Initial commit

Change-Id: I6a4444e3c193dae437cd7929f4c39aba7b749efa
diff --git a/CMakeLists.txt b/CMakeLists.txt
new file mode 100644
index 0000000..d41c645
--- /dev/null
+++ b/CMakeLists.txt
@@ -0,0 +1,112 @@
+# This file is the source for generating the Makefile for the project, using cmake tool (cmake.org)
+
+# Name of the project
+PROJECT("freeDiameter")
+
+# Informations to display in daemon's help
+SET(FD_PROJECT_NAME freeDiameter)
+SET(FD_PROJECT_BINARY freeDiameterd)
+SET(FD_PROJECT_COPYRIGHT "Copyright (c) 2008-2015, WIDE Project (www.wide.ad.jp) and NICT (www.nict.go.jp)")
+
+# Version of the source code
+SET(FD_PROJECT_VERSION_MAJOR 1)
+SET(FD_PROJECT_VERSION_MINOR 2)
+SET(FD_PROJECT_VERSION_REV 1)
+
+# Version of the API with the library
+SET(FD_PROJECT_VERSION_API 6)
+
+# The test framework, using CTest and CDash.
+INCLUDE(CTest)
+
+# CMake version
+CMAKE_MINIMUM_REQUIRED(VERSION 2.6)
+
+# Location of additional CMake modules
+SET(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake/Modules/")
+
+# The default directories
+SET(DEFAULT_CONF_PATH ${CMAKE_INSTALL_PREFIX}/etc/freeDiameter CACHE PATH "Default location of freeDiameter configuration files")
+
+IF (NOT DEFINED LIB_INSTALL_DIR)
+SET(LIB_INSTALL_DIR lib CACHE PATH "Default library path name on the system, to accomodate RPM-based systems that use lib64")
+ENDIF (NOT DEFINED LIB_INSTALL_DIR)
+
+SET(INSTALL_HEADERS_SUFFIX 		include/freeDiameter 	CACHE PATH "Directory where the headers are installed (relative to CMAKE_INSTALL_PREFIX).")
+SET(INSTALL_DAEMON_SUFFIX 		bin 			CACHE PATH "Directory where the daemon binary is installed (relative to CMAKE_INSTALL_PREFIX).")
+SET(INSTALL_LIBRARY_SUFFIX 		${LIB_INSTALL_DIR} 			CACHE PATH "Directory where the freeDiameter libraries are installed (relative to CMAKE_INSTALL_PREFIX).")
+SET(INSTALL_EXTENSIONS_SUFFIX 	${LIB_INSTALL_DIR}/freeDiameter	CACHE PATH "Directory where the extensions are installed / searched (relative to CMAKE_INSTALL_PREFIX).")
+
+# All source code should be POSIX 200112L compatible, but some other extensions might be used, so:
+ADD_DEFINITIONS(-D_GNU_SOURCE)
+
+# Set a default build type if none was specified
+if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
+  message(STATUS "Setting build type to 'Debug' as none was specified.")
+  set(CMAKE_BUILD_TYPE Debug CACHE STRING "Choose the type of build." FORCE)
+  # Set the possible values of build type for cmake-gui
+  set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS "Debug" "Release"
+    "MinSizeRel" "RelWithDebInfo" "Profiling" "MaxPerformance" "DebianPackage" "DebugValgrind")
+endif()
+
+# Add a "Profiling" build type
+# SET(CMAKE_BUILD_TYPE Profiling)
+SET(CMAKE_C_FLAGS_PROFILING "-fprofile-arcs -ftest-coverage -fstack-protector -g -Wall")
+
+# Add a "MaxPerformance" build type -- this is very silent...
+# SET(CMAKE_BUILD_TYPE MaxPerformance)
+SET(CMAKE_C_FLAGS_MAXPERFORMANCE "${CMAKE_C_FLAGS_RELEASE} -DSTRIP_DEBUG_CODE")
+
+# Add a "DebianPackage" build type used when creating the Debian packages
+SET(CMAKE_C_FLAGS_DEBIANPACKAGE "${CMAKE_C_FLAGS_RELWITHDEBINFO}")
+
+# Set the "Debug" flags
+SET(CMAKE_C_FLAGS_DEBUG "-Wall -g -O0")
+
+# Add a "DebugValgrind" build type used for checking execution with Valgrind tool
+SET(CMAKE_C_FLAGS_DEBUGVALGRIND "-Wall -g -O0")
+
+# Set the DEBUG flag for Debug and Profiling builds
+IF (CMAKE_BUILD_TYPE MATCHES "Debug|Profiling|DebugValgrind")
+  SET(DEBUG 1)
+ENDIF (CMAKE_BUILD_TYPE MATCHES "Debug|Profiling|DebugValgrind")
+
+# some subfolders use yacc and lex parsers
+SET(BISON_GENERATE_DEFINES TRUE)
+SET(BISON_PREFIX_OUTPUTS TRUE)
+INCLUDE(CMakeUserUseBison)
+SET(FLEX_PREFIX_OUTPUTS TRUE)
+INCLUDE(CMakeUserUseFlex)
+IF( NOT BISON_EXECUTABLE OR NOT FLEX_EXECUTABLE )
+  MESSAGE( SEND_ERROR "Bison and Flex are required" )
+ENDIF( NOT BISON_EXECUTABLE OR NOT FLEX_EXECUTABLE )
+# Check that flex is at least 2.5.20 to support bison-bridge
+# how to do the check with cmake???
+
+# Add this to workaround an apparent bug in FreeBSD cmake (already defined in Linux)
+SET(CMAKE_SHARED_LIBRARY_LINK_C_FLAGS "-rdynamic")
+
+# For Darwin systems
+IF(APPLE)
+   SET(CMAKE_SHARED_MODULE_CREATE_C_FLAGS "${CMAKE_SHARED_MODULE_CREATE_C_FLAGS} -flat_namespace -undefined dynamic_lookup")
+   SET(CMAKE_SHARED_MODULE_CREATE_CXX_FLAGS "${CMAKE_SHARED_MODULE_CREATE_CXX_FLAGS} -flat_namespace -undefined dynamic_lookup")
+ENDIF(APPLE) 
+
+# Location for the include files
+INCLUDE_DIRECTORIES(include)
+INCLUDE_DIRECTORIES(${CMAKE_CURRENT_BINARY_DIR}/include)
+SUBDIRS(include/freeDiameter)
+
+# Location for the source code
+SUBDIRS(libfdproto)
+SUBDIRS(libfdcore)
+SUBDIRS(freeDiameterd)
+
+# Extensions (there is no use of freeDiameter without any extension)
+SUBDIRS(extensions)
+
+# The unary tests directory
+IF ( BUILD_TESTING )
+	SUBDIRS(tests)
+ENDIF ( BUILD_TESTING )
+
diff --git a/CTestConfig.cmake b/CTestConfig.cmake
new file mode 100644
index 0000000..61fef33
--- /dev/null
+++ b/CTestConfig.cmake
@@ -0,0 +1,10 @@
+# Configuration for sumitting the test result.
+# Check http://www.freediameter.net/CDash for detail.
+
+set(CTEST_PROJECT_NAME "freeDiameter")
+set(CTEST_NIGHTLY_START_TIME "00:00:00 JST")
+
+set(CTEST_DROP_METHOD "http")
+set(CTEST_DROP_SITE "www.freediameter.net")
+set(CTEST_DROP_LOCATION "/CDash/submit.php?project=freeDiameter")
+set(CTEST_DROP_SITE_CDASH TRUE)
diff --git a/INSTALL b/INSTALL
new file mode 100644
index 0000000..f2bcb8e
--- /dev/null
+++ b/INSTALL
@@ -0,0 +1,39 @@
+This package uses CMake (cmake.org) as building system. You'll need the cmake tool in order 
+to generate the Makefiles for your platform. You can also select which extensions must be built
+with cmake. After the initial cmake configuration, you will need several tools such as make, a 
+C compiler (tested mostly with gcc), flex (> 2.5.4), bison, ...
+
+You may retrieve the source package in several ways:
+ - as a pre-packaged version for your platform. Check the website for supported platforms.
+ - as a tarball containing the source.
+ - directly from the repository using Mercurial tool:
+      hg clone http://www.freediameter.net/hg/freeDiameter
+   In order to update later:
+      hg pull -u
+
+Building in a separate directory is recommended:
+# mkdir build
+# cd build
+# cmake ../
+# make
+
+You can pass options to instruct cmake about which components to compile on the command-line.
+You can also use a CMake front-end (for example ccmake or cmake-gui). 
+If your cmake installation is recent, the edit_cache target is a good help as well:
+# mkdir build
+# cd build
+# cmake ../
+# make help
+# make edit_cache
+# make
+
+You can disable the unit tests by doing:
+# cmake -DBUILD_TESTING:BOOL=OFF ../
+# make
+
+When the tests are enabled, you can run them with:
+# make test
+
+See the INSTALL.* files for additional platform-specific information.
+Note that the most up-to-date INSTALL file is the Ubuntu one. You may want to read there
+in addition to your own platform file.
diff --git a/INSTALL.Fedora b/INSTALL.Fedora
new file mode 100644
index 0000000..3c881c2
--- /dev/null
+++ b/INSTALL.Fedora
@@ -0,0 +1,37 @@
+### Very short install notes for Fedora (tested on Fedora 13 and 14)
+# Please refer to other INSTALL files for more detailed instructions (e.g. extension-specific notes).
+
+
+Dependencies on Fedora 13 (from minimal system):
+# yum install cmake make gcc gcc-c++ flex bison lksctp-tools-devel gnutls-devel libgcrypt-devel libidn-devel
+
+In addition, if you have not already retrieved the latest source:
+# yum install mercurial
+
+Following dependencies are optional, depending on which extensions you plan to compile
+ app_acct:
+	# yum install postgresql-devel
+	optional:
+	# yum install postgresql-server
+
+ app_sip:
+ app_diameap:
+	# yum install mysql-devel
+	optional:
+	# yum install mysql-server 
+	
+ dict_legacy_xml:
+	# yum install libxml2 libxml2-devel
+	
+ dbg_interactive:
+	# yum install swig python-devel
+
+
+NOTE: You may need to change something in SELinux to allow binding the SCTP socket on Diameter port.
+The following command is the very naive way to do it, you can probably do better (feedback appreciated!)
+# setenforce Permissive
+
+
+There is currently no Fedora-specific package for freeDiameter.
+You are welcome to contribute packaging scripts. 
+Please contact dev@freediameter.net for more details.
diff --git a/INSTALL.FreeBSD b/INSTALL.FreeBSD
new file mode 100644
index 0000000..4625d8a
--- /dev/null
+++ b/INSTALL.FreeBSD
@@ -0,0 +1,125 @@
+See INSTALL file for general instructions on building freeDiameter.
+
+------------------
+QUICK INSTRUCTIONS
+------------------
+
+On FreeBSD-8.0 at least the following ports packages were required (should be same on FreeBSD-7.x):
+ cmake flex bison gnutls
+
+Then the cmake command had to look like:
+ cmake -DFLEX_EXECUTABLE:FILEPATH=/usr/local/bin/flex -DSCTP_USE_MAPPED_ADDRESSES:BOOL=ON ...
+
+
+---------------------
+COMPLETE INSTRUCTIONS
+---------------------
+
+1) If you don't have freeBSD yet:
+   Install minimal system + ports using initial installer /usr/sbin/sysinstall
+
+
+2) Install 'cmake'
+
+ a) from sources:
+    # cd /usr/ports/devel/cmake
+    # make install
+    
+ b) or from package (don't forget to set your PACKAGEROOT appropriately. Ex: set PACKAGEROOT=ftp://ftp.jp.freebsd.org):
+    # pkg_add -v -r cmake
+	
+ 
+3) Install 'mercurial' (optional)
+  (replace 'cmake' by 'mercurial' in the previous command) 
+
+4) Install 'flex' and 'bison', same way.
+
+5) Install 'gnutls' and 'libidn', same way also.
+
+6) Retrieve freeDiameter source code:
+   # cd ~
+   # /usr/local/bin/hg clone http://www.freediameter.net/hg/freeDiameter/
+   
+6b) Make a build directory
+   # mkdir fD-build
+   # cd fD-build
+   
+7) Run cmake for freeDiameter (add other flags as you see fit, see INSTALL for more details)
+   # /usr/local/bin/cmake -DFLEX_EXECUTABLE:FILEPATH=/usr/local/bin/flex -DSCTP_USE_MAPPED_ADDRESSES:BOOL=ON ../freeDiameter
+
+8) Compile, optionnaly test
+   # make
+   # make test
+
+9) Install
+   # make install
+   
+10) Run (the install path can be changed during cmake step):
+   # /usr/local/bin/freeDiameterd --help
+
+
+------------------------------
+app_acct test ADDITIONAL STEPS
+------------------------------
+Here is additional steps in order to run the test for app_acct
+
+1) Install the required packages
+  # pkg_add -v -r postgresql84-client
+  # pkg_add -v -r postgresql84-server
+
+2) Prepare access to the database:
+  # echo postgresql_enable=YES >> /etc/rc.conf
+  # /usr/local/etc/rc.d/postgresql initdb
+  # su - pgsql
+  > /usr/local/bin/pg_ctl -D /usr/local/pgsql/data -l logfile start
+  > /usr/local/bin/createuser root
+  Shall the new user be allowed to create databases? (y/n) y
+  > logout
+  # /usr/local/bin/createdb root
+  # /usr/local/bin/psql root
+  root=# CREATE TABLE incoming_test (
+  root(# recorded_on timestamp with time zone NOT NULL,
+  root(# "Accounting-Record-Type" integer,
+  root(# "Session-Id" bytea,
+  root(# "Accounting-Record-Number" integer,
+  root(# "Route-Record1" bytea,
+  root(# "Route-Record2" bytea,
+  root(# "Route-Record3" bytea,
+  root(# "Route-Record4" bytea );
+  root=# \q
+
+3) configure the sources
+  # make edit_cache
+   BUILD_APP_ACCT:BOOL=ON
+   TEST_APP_ACCT:BOOL=ON
+   TEST_APP_ACCT_CONNINFO:STRING="user=root dbname=root"
+   
+4) run the test
+  # tests/testappacct -d
+  or
+  # make test
+  
+  
+----------------------------------
+Segmentation fault on program exit
+----------------------------------
+
+In case you encounter a segmentation fault on program termination like this:
+  [...]
+  freeDiameterd framework is terminated.
+  Segmentation fault: 11 (core dumped)
+
+with a backtrace like this:
+  #0  0x0000000801a414a0 in ?? ()
+  #1  0x0000000800f99274 in __cxa_finalize () from /lib/libc.so.7
+  #2  0x0000000800f460b7 in exit () from /lib/libc.so.7
+  
+You may try to add the following compilation directive in cmake:
+  -DSKIP_DLCLOSE:BOOL=ON
+
+Note: this segmentation fault was experienced with:
+ - FreeBSD 8.1
+ - 64 bits architecture only.
+ - Profiling mode only.
+
+
diff --git a/INSTALL.OSX b/INSTALL.OSX
new file mode 100644
index 0000000..1e6dc65
--- /dev/null
+++ b/INSTALL.OSX
@@ -0,0 +1,85 @@
+See INSTALL file for general instructions on building freeDiameter.
+
+------------------
+QUICK INSTRUCTIONS
+------------------
+
+Starting from version 1.1.5, freeDiameter is available through Homebrew:
+
+1) Install Homebrew
+   a) Install Command Line Tools for Xcode or Xcode:
+      - Command Line Tools (your OS X Version) for Xcode:
+         https://developer.apple.com/downloads (Free Apple Developer ID Registration Required)
+      - or Xcode:
+         https://itunes.apple.com/us/app/xcode/id497799835 (Free App Store Account Required)
+
+   b) Install Homebrew
+     $ ruby -e "$(curl -fsSkL raw.github.com/mxcl/homebrew/go)"
+
+2) Install freeDiameter:
+     $ brew install freediameter
+
+   After installation is done "Caveats" section will provide information
+   how to start freeDiameterd through launchd at system startup.
+
+   To view this information again:
+     $ brew info freediameter
+
+   To learn more about freeDiameter configuration options, read:
+      http://www.freediameter.net/trac/wiki/Configuration
+
+   For more information on available extension and how to configure them, read:
+      http://www.freediameter.net/trac/wiki/Extensions
+
+------------
+FROM SOURCES
+------------
+
+1) Install Homebrew:
+   See QUICK INSTRUCTIONS Step #1 above.
+
+2) Install dependencies:
+    $ brew install mercurial cmake gnutls libgcrypt postgres mysql libidn
+
+   Notes:
+    * GNU IDN (libidn) is optional, see below
+    * When libusrsctp package is available, you can use it as well.
+        However, it requires some rework on the source code as libusrsctp is not fully
+        compliant with the other SCTP stack.
+
+3) Retrieve source code:
+    $ hg clone http://www.freediameter.net/hg/freeDiameter
+
+4) Enter source folder:
+    $ cd freeDiameter
+
+5) Create build folder:
+    $ mkdir freeDiameter-build
+
+6) Enter build folder:
+    $ cd freeDiameter-build
+
+7) Configure:
+    $ cmake .. -DDISABLE_SCTP:BOOL=ON
+
+   or for ncurses-based configuration:
+    $ ccmake .. -DDISABLE_SCTP:BOOL=ON
+
+   Notes:
+    * GNU IDN (Support for International Domain Names) can be disabled with:
+       -DDIAMID_IDNA_IGNORE=ON or -DDIAMID_IDNA_REJECT=ON
+    * For more information on available configuration options, read:
+       http://www.freediameter.net/trac/wiki/Installation
+
+8) Compile:
+    $ make
+
+9) Install (might require to be root):
+    $ make install
+
+------------------------------------------------
+
+These instructions have been tested on OS X:
+   - 10.6.8 (Snow Leopard)
+   - 10.7.5 (Lion)
+   - 10.8.2 (Mountain Lion)
diff --git a/INSTALL.OpenSUSE b/INSTALL.OpenSUSE
new file mode 100644
index 0000000..67af742
--- /dev/null
+++ b/INSTALL.OpenSUSE
@@ -0,0 +1,29 @@
+### Very short install notes for OpenSUSE (tested on OpenSUSE 11.3)
+# Please refer to other INSTALL files for more detailed instructions (e.g. extension-specific notes).
+
+
+Dependencies on OpenSUSE 11.3 (from minimal server system installation):
+# zypper install cmake make gcc gcc-c++ flex bison lksctp-tools-devel libgnutls-devel libgcrypt-devel libidn-devel
+# zypper install mercurial
+
+Following dependencies are optional, depending on which extensions you plan to compile
+ app_acct:
+	# zypper install postgresql-server postgresql-devel
+
+ app_sip:
+ app_diameap:
+ 	# zypper install libmysqlclient-devel 
+	(would also need a server, not sure which package is appropriate)
+	
+ dict_legacy_xml:
+	# zypper install libxml2 libxml2-devel
+	
+ dbg_interactive:
+	# zypper install swig python-devel
+
+ sample:
+	# zypper install gcc-c++
+
+There is currently no OpenSUSE-specific package for freeDiameter.
+You are welcome to contribute packaging scripts! Please contact with
+dev@freediameter.net for more details.
diff --git a/INSTALL.OpenWRT b/INSTALL.OpenWRT
new file mode 100644
index 0000000..bc9f997
--- /dev/null
+++ b/INSTALL.OpenWRT
@@ -0,0 +1,3 @@
+There is a package script available for the OpenWRT platform.
+
+Please refer to contrib/OpenWRT/HOWTO for more information.
diff --git a/INSTALL.Ubuntu b/INSTALL.Ubuntu
new file mode 100644
index 0000000..d063335
--- /dev/null
+++ b/INSTALL.Ubuntu
@@ -0,0 +1,123 @@
+See http://www.freediameter.net/trac/wiki/DebRepository for instructions on how to
+install freeDiameter from existing package.
+
+See INSTALL file for general instructions on building freeDiameter from sources.
+
+The remaining of this file contains specific instructions for building the freeDiameter 
+package files for Debian and Ubuntu systems.
+
+
+
+
+freeDiameter is shipped with the necessary files to generate the Debian package. 
+All related files are in the directory "contrib/debian" of the distribution.
+As a first step, you have to link this directory from your top-level dir:
+  ln -s contrib/debian
+ 
+============================================
+
+The following packages are required to compile freeDiameter from source:
+ cmake make gcc g++ flex bison libsctp1 libsctp-dev libgnutls-dev libgcrypt-dev libidn11-dev
+ 
+(note that libidn and libsctp can be avoided by defining DISABLE_SCTP and DIAMID_IDNA_REJECT)
+ 
+Additionnaly, these ones may be useful:
+ mercurial gdb
+ 
+Extensions additional dependencies:
+ app_acct:
+	libpq-dev
+
+ app_sip:
+ app_diameap:
+ 	libmysqlclient-dev
+	
+ dict_legacy_xml:
+ 	libxml2-dev
+	
+ dbg_interactive:
+ 	swig python-dev
+	
+============================================
+
+If your debhelper environment is recent (> 7.3.9 for cmake support), 
+the following commands should generate the freeDiameter packages for you:
+
+# Install the dependencies for building the source:
+sudo apt-get -y install mercurial cmake make gcc g++ bison flex libsctp-dev libgnutls-dev libgcrypt-dev libidn11-dev ssl-cert debhelper fakeroot \
+   libpq-dev libmysqlclient-dev libxml2-dev swig python-dev
+
+# Retrieve the latest version of the source package
+cd 
+hg clone http://www.freediameter.net/hg/freeDiameter
+cd freeDiameter
+
+# Prepare for Debian package
+ln -s contrib/debian
+
+# Build the packages
+fakeroot dh binary
+
+# Install the packages
+cd ..
+sudo dpkg -i *.deb
+
+
+# The following lines may help you getting started.... (execute as root)
+ln -s /etc/ssl/certs/ssl-cert-snakeoil.pem /etc/ssl/certs/freeDiameter.pem
+ln -s /etc/ssl/private/ssl-cert-snakeoil.key /etc/ssl/private/freeDiameter.key
+zcat /usr/share/doc/freediameter-daemon/examples/freediameter.conf.sample.gz > /etc/freeDiameter/freeDiameter.conf
+echo "Identity=\"localhost.localdomain\";" >> /etc/freeDiameter/freeDiameter.conf
+freeDiameterd
+
+===========================================
+
+freeDiameter is tested regularly on all current Ubuntu distributions since Intrepid (compiled from source as described below)
+Ubuntu Hardy support is known to be broken.
+
+The Debian package has been generated with success on Debian (>=Squeeze) and Ubuntu (>=Karmic).
+
+
+===========================================-
+Step by step instructions without using the debhelper tools:
+
+1) Install all packages dependencies
+# sudo apt-get install mercurial cmake make gcc g++ bison flex libsctp-dev libgnutls-dev libgcrypt-dev libidn11-dev
+
+2) (OPTION) If you will compile modules that require postgresql, also install:
+# sudo apt-get install libpq-dev
+   and for mysql:
+# sudo apt-get install libmysqlclient-dev
+
+3) (OPTION) If you want a more user-friendly interface, install this:
+# sudo apt-get install cmake-curses-gui
+
+4) Retrieve the source files
+# hg clone http://www.freediameter.net/hg/freeDiameter
+
+5) Create a build directory, and enter it
+# mkdir fDbuild
+# cd fDbuild
+
+6) Configure and generate the Makefiles
+# cmake ../freeDiameter
+# make edit_cache
+
+7) Compile all files:
+# make
+
+8) (OPTION) See available targets:
+# make help
+
+9) (OPTION) Check the software has a correct basic behavior on your environment. -- only if you did not disable the tests in step 6
+# make test
+
+10) (OPTION) Install the software in configured locations:
+# sudo make install
+
+
+===========================================
+
+Note: On Ubuntu Quantal Quetzal, you may have to force use of python 2.7 
+library for the dbg_interactive extension, as on some systems CMake selects the 3.2 library
+by default.
diff --git a/INSTALL.pkgsrc b/INSTALL.pkgsrc
new file mode 100644
index 0000000..34df9b5
--- /dev/null
+++ b/INSTALL.pkgsrc
@@ -0,0 +1,21 @@
+The simplest way to install on NetBSD, DragonFly, MirBSD or other
+pkgsrc platforms is:
+	pkg_add freeDiameter
+
+If no binary package exists:
+	cd /usr/pkgsrc/net/freeDiameter
+	make install
+
+If you want to build and install freeDiameter from the repository,
+you'll need to install:
+	pkg_add bison pkg-config libidn gnutls libgcrypt mercurial
+and follow the usual installation note.
+
+NetBSD does not support SCTP, so you have to add
+	-DDISABLE_SCTP:BOOL=ON
+to the cmake command line.
+
+For the optional extensions, you need mysql*-client, postgres*-client,
+libxml2.  For the debugging extensions, you also need swig and a
+python -- install as usual.
+
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..71d50a8
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,51 @@
+Unless specified otherwise, this software package is copyrighted under the terms of the BSD license, as follow:
+
+Software License Agreement (BSD License)
+
+Copyright (c) 2008-2011, WIDE Project and NICT
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms, with or without modification, are 
+permitted provided that the following conditions are met:
+
+* Redistributions of source code must retain the above 
+  copyright notice, this list of conditions and the 
+  following disclaimer.
+   
+* Redistributions in binary form must reproduce the above 
+  copyright notice, this list of conditions and the 
+  following disclaimer in the documentation and/or other
+  materials provided with the distribution.
+
+* Neither the name of the WIDE Project or NICT nor the 
+  names of its contributors may be used to endorse or 
+  promote products derived from this software without 
+  specific prior written permission of WIDE Project and 
+  NICT.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED 
+WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 
+PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR 
+TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 
+ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+
+The following authors have contributed the following files. See source files for copyright information.
+
+ * Alexandre Westfahl:
+  extensions/dict_sip/*
+  extensions/app_sip/*
+  extensions/app_radgw/rgwx_sip.c
+
+ * Souheil Ben Ayed:
+  extensions/app_diameap/*
+
+ * Francois Bard:
+  extensions/dict_mip6a/*
+  extensions/dict_mip6i/*
+  extensions/dict_nas_mipv6/*
+  extensions/dict_rfc5777/*
diff --git a/NEWS b/NEWS
new file mode 100644
index 0000000..d21bf18
--- /dev/null
+++ b/NEWS
@@ -0,0 +1,5 @@
+The digested changelog can be found under:
+ contrib/debian/changelog
+ 
+You can also find the exhaustive list of change using mercurial history, 
+or at the following URL: http://www.freediameter.net/hg/freeDiameter/shortlog
diff --git a/PREREQUISITES b/PREREQUISITES
new file mode 100644
index 0000000..ac687c6
--- /dev/null
+++ b/PREREQUISITES
@@ -0,0 +1 @@
+sudo apt-get install cmake cmake-curses-gui make gcc g++ bison flex libsctp-dev libgnutls-dev libgcrypt-dev libidn11-dev
diff --git a/README b/README
new file mode 100644
index 0000000..2855ec5
--- /dev/null
+++ b/README
@@ -0,0 +1,43 @@
+freeDiameter is an implementation of the Diameter protocol.
+
+Diameter is a protocol designed to carry Authentication, Authorization and
+Accounting (AAA) payload. It is an evolution of the RADIUS protocol (as the 
+name suggests).
+
+Diameter is an extensible protocol. RFC3588 (currently under revision) defines the
+Base Protocol that all Diameter nodes must support, while other documents define
+the additional protocol support for specific applications. Such applications include 
+for example Network Access Servers (RFC4005), EAP (RFC4072), ...
+
+
+The implementation consists in several components:
+ - libfdproto : this shared library provides the functions to manipulate Diameter
+      messages and dictionary. This library is meant to be re-used by other projects
+      that would require parsing or manipulating Diameter messages.
+      
+ - libfdcore : this shared library contains the core of the framework. It establishes 
+      the network connections with other Diameter peers and performs the tasks described 
+      in Diameter Base Protocol, such as watchdogs, basic routing, ... It also handles 
+      the loading of extensions (see below).
+      
+ - freeDiameterd : this simple daemon parses the command line and initializes the
+      freeDiameter framework. Use it for your Diameter server & agent components.
+      In case of Diameter clients, you probably will prefer linking the libfdcore 
+      directly with your client application that must be made Diameter-aware.
+      
+ - extensions : the extensions provide the mean to augment the features of the
+      freeDiameterd framework. Extensions can provide the handling of a Diameter 
+      server application, but also advanced routing features, peer management, etc.
+
+
+See http://www.freediameter.net/ for more information on the project.
+
+freeDiameter was previously known as the "waaad" project (WIDE AAA Daemon)
+
+This project is not related to the "freediameter" project from Sun on sourceforge.
+
+Author: Sebastien Decugis.
+
+See LICENSE file for legal information on this software.
+
+See INSTALL for information on building and using this software.
diff --git a/cmake/Modules/CMakeUserUseBison.cmake b/cmake/Modules/CMakeUserUseBison.cmake
new file mode 100644
index 0000000..9257545
--- /dev/null
+++ b/cmake/Modules/CMakeUserUseBison.cmake
@@ -0,0 +1,72 @@
+# - Look for GNU Bison, the parser generator
+# Based off a news post from Andy Cedilnik at Kitware
+# Defines the following:
+#  BISON_EXECUTABLE - path to the bison executable
+#  BISON_FILE - parse a file with bison
+#  BISON_PREFIX_OUTPUTS - Set to true to make BISON_FILE produce prefixed
+#                         symbols in the generated output based on filename.
+#                         So for ${filename}.y, you'll get ${filename}parse(), etc.
+#                         instead of yyparse().
+#  BISON_GENERATE_DEFINES - Set to true to make BISON_FILE output the matching
+#                           .h file for a .c file. You want this if you're using
+#                           flex.
+
+IF(NOT DEFINED BISON_PREFIX_OUTPUTS)
+ SET(BISON_PREFIX_OUTPUTS FALSE)
+ENDIF(NOT DEFINED BISON_PREFIX_OUTPUTS)
+
+IF(NOT DEFINED BISON_GENERATE_DEFINES)
+ SET(BISON_GENERATE_DEFINES FALSE)
+ENDIF(NOT DEFINED BISON_GENERATE_DEFINES)
+
+IF(NOT BISON_EXECUTABLE)
+ MESSAGE(STATUS "Looking for bison")
+ FIND_PROGRAM(BISON_EXECUTABLE bison)
+ IF(BISON_EXECUTABLE)
+   MESSAGE(STATUS "Looking for bison -- ${BISON_EXECUTABLE}")
+ ENDIF(BISON_EXECUTABLE)
+ MARK_AS_ADVANCED(BISON_EXECUTABLE)
+ENDIF(NOT BISON_EXECUTABLE)
+
+IF(BISON_EXECUTABLE)
+ MACRO(BISON_FILE FILENAME)
+   GET_FILENAME_COMPONENT(PATH "${FILENAME}" PATH)
+   IF("${PATH}" STREQUAL "")
+     SET(PATH_OPT "")
+   ELSE("${PATH}" STREQUAL "")
+     SET(PATH_OPT "/${PATH}")
+   ENDIF("${PATH}" STREQUAL "")
+   GET_FILENAME_COMPONENT(HEAD "${FILENAME}" NAME_WE)
+   IF(NOT EXISTS "${CMAKE_CURRENT_BINARY_DIR}${PATH_OPT}")
+     FILE(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}${PATH_OPT}")
+   ENDIF(NOT EXISTS "${CMAKE_CURRENT_BINARY_DIR}${PATH_OPT}")
+   IF(BISON_PREFIX_OUTPUTS)
+     SET(PREFIX "${HEAD}")
+   ELSE(BISON_PREFIX_OUTPUTS)
+     SET(PREFIX "yy")
+   ENDIF(BISON_PREFIX_OUTPUTS)
+   SET(OUTFILE "${CMAKE_CURRENT_BINARY_DIR}${PATH_OPT}/${HEAD}.tab.c")
+   IF(BISON_GENERATE_DEFINES)
+     SET(HEADER "${CMAKE_CURRENT_BINARY_DIR}${PATH_OPT}/${HEAD}.tab.h")
+     ADD_CUSTOM_COMMAND(
+       OUTPUT "${OUTFILE}" "${HEADER}"
+       COMMAND "${BISON_EXECUTABLE}"
+       ARGS "--name-prefix=${PREFIX}"
+       "--defines"
+       "--output-file=${OUTFILE}"
+       "${CMAKE_CURRENT_SOURCE_DIR}/${FILENAME}"
+       DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/${FILENAME}")
+     SET_SOURCE_FILES_PROPERTIES("${OUTFILE}" "${HEADER}" PROPERTIES GENERATED TRUE)
+     SET_SOURCE_FILES_PROPERTIES("${HEADER}" PROPERTIES HEADER_FILE_ONLY TRUE)
+   ELSE(BISON_GENERATE_DEFINES)
+     ADD_CUSTOM_COMMAND(
+       OUTPUT "${OUTFILE}"
+       COMMAND "${BISON_EXECUTABLE}"
+       ARGS "--name-prefix=${PREFIX}"
+       "--output-file=${OUTFILE}"
+       "${CMAKE_CURRENT_SOURCE_DIR}/${FILENAME}"
+       DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/${FILENAME}")
+     SET_SOURCE_FILES_PROPERTIES("${OUTFILE}" PROPERTIES GENERATED TRUE)
+   ENDIF(BISON_GENERATE_DEFINES)
+ ENDMACRO(BISON_FILE) 
+ENDIF(BISON_EXECUTABLE)
diff --git a/cmake/Modules/CMakeUserUseFlex.cmake b/cmake/Modules/CMakeUserUseFlex.cmake
new file mode 100644
index 0000000..7d0394f
--- /dev/null
+++ b/cmake/Modules/CMakeUserUseFlex.cmake
@@ -0,0 +1,47 @@
+# - Look for GNU flex, the lexer generator.
+# Defines the following:
+#  FLEX_EXECUTABLE - path to the flex executable
+#  FLEX_FILE - parse a file with flex
+#  FLEX_PREFIX_OUTPUTS - Set to true to make FLEX_FILE produce outputs of
+#                        lex.${filename}.c, not lex.yy.c . Passes -P to flex. 
+
+IF(NOT DEFINED FLEX_PREFIX_OUTPUTS)
+  SET(FLEX_PREFIX_OUTPUTS FALSE)
+ENDIF(NOT DEFINED FLEX_PREFIX_OUTPUTS) 
+
+IF(NOT FLEX_EXECUTABLE)
+  MESSAGE(STATUS "Looking for flex")
+  FIND_PROGRAM(FLEX_EXECUTABLE flex)
+  IF(FLEX_EXECUTABLE)
+    MESSAGE(STATUS "Looking for flex -- ${FLEX_EXECUTABLE}")
+  ENDIF(FLEX_EXECUTABLE)
+ MARK_AS_ADVANCED(FLEX_EXECUTABLE)
+ENDIF(NOT FLEX_EXECUTABLE) 
+
+IF(FLEX_EXECUTABLE)
+  MACRO(FLEX_FILE FILENAME)
+    GET_FILENAME_COMPONENT(PATH "${FILENAME}" PATH)
+    IF("${PATH}" STREQUAL "")
+      SET(PATH_OPT "")
+    ELSE("${PATH}" STREQUAL "")
+      SET(PATH_OPT "/${PATH}")
+    ENDIF("${PATH}" STREQUAL "")
+    IF(NOT EXISTS "${CMAKE_CURRENT_BINARY_DIR}${PATH_OPT}")
+      FILE(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}${PATH_OPT}")
+    ENDIF(NOT EXISTS "${CMAKE_CURRENT_BINARY_DIR}${PATH_OPT}")
+    IF(FLEX_PREFIX_OUTPUTS)
+      GET_FILENAME_COMPONENT(PREFIX "${FILENAME}" NAME_WE)
+    ELSE(FLEX_PREFIX_OUTPUTS)
+      SET(PREFIX "yy")
+    ENDIF(FLEX_PREFIX_OUTPUTS)
+    SET(OUTFILE "${CMAKE_CURRENT_BINARY_DIR}${PATH_OPT}/lex.${PREFIX}.c")
+    ADD_CUSTOM_COMMAND(
+      OUTPUT "${OUTFILE}"
+      COMMAND "${FLEX_EXECUTABLE}"
+      ARGS "-P${PREFIX}"
+      "-o${OUTFILE}"
+      "${CMAKE_CURRENT_SOURCE_DIR}/${FILENAME}"
+      DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/${FILENAME}")
+    SET_SOURCE_FILES_PROPERTIES("${OUTFILE}" PROPERTIES GENERATED TRUE)
+  ENDMACRO(FLEX_FILE)
+ENDIF(FLEX_EXECUTABLE)
diff --git a/cmake/Modules/FindGcrypt.cmake b/cmake/Modules/FindGcrypt.cmake
new file mode 100644
index 0000000..fd4517d
--- /dev/null
+++ b/cmake/Modules/FindGcrypt.cmake
@@ -0,0 +1,36 @@
+# - Find gnutls
+# Find the native GCRYPT includes and library
+#
+#  GCRYPT_FOUND - True if gnutls found.
+#  GCRYPT_INCLUDE_DIR - where to find gnutls.h, etc.
+#  GCRYPT_LIBRARIES - List of libraries when using gnutls.
+
+if (GCRYPT_INCLUDE_DIR AND GCRYPT_LIBRARIES)
+  set(GCRYPT_FIND_QUIETLY TRUE)
+endif (GCRYPT_INCLUDE_DIR AND GCRYPT_LIBRARIES)
+
+# Include dir
+find_path(GCRYPT_INCLUDE_DIR
+	NAMES
+	  gcrypt.h
+)
+
+# Library
+find_library(GCRYPT_LIBRARY 
+  NAMES gcrypt
+)
+
+# handle the QUIETLY and REQUIRED arguments and set GCRYPT_FOUND to TRUE if 
+# all listed variables are TRUE
+INCLUDE(FindPackageHandleStandardArgs)
+FIND_PACKAGE_HANDLE_STANDARD_ARGS(GCRYPT DEFAULT_MSG GCRYPT_LIBRARY GCRYPT_INCLUDE_DIR)
+
+IF(GCRYPT_FOUND)
+  SET( GCRYPT_LIBRARIES ${GCRYPT_LIBRARY} )
+ELSE(GCRYPT_FOUND)
+  SET( GCRYPT_LIBRARIES )
+ENDIF(GCRYPT_FOUND)
+
+# Lastly make it so that the GCRYPT_LIBRARY and GCRYPT_INCLUDE_DIR variables
+# only show up under the advanced options in the gui cmake applications.
+MARK_AS_ADVANCED( GCRYPT_LIBRARY GCRYPT_INCLUDE_DIR )
diff --git a/cmake/Modules/FindGnuTLS.cmake b/cmake/Modules/FindGnuTLS.cmake
new file mode 100644
index 0000000..19c4fff
--- /dev/null
+++ b/cmake/Modules/FindGnuTLS.cmake
@@ -0,0 +1,64 @@
+# - Find gnutls
+# Find the native GNUTLS includes and library
+#
+#  GNUTLS_FOUND - True if gnutls found.
+#  GNUTLS_INCLUDE_DIR - where to find gnutls.h, etc.
+#  GNUTLS_LIBRARIES - List of libraries when using gnutls.
+#  GNUTLS_VERSION_210 - true if GnuTLS version is >= 2.10.0 (does not require additional separate gcrypt initialization)
+#  GNUTLS_VERSION_212 - true if GnuTLS version is >= 2.12.0 (supports gnutls_transport_set_vec_push_function)
+#  GNUTLS_VERSION_300 - true if GnuTLS version is >= 3.00.0 (x509 verification functions changed)
+#  GNUTLS_VERSION_310 - true if GnuTLS version is >= 3.01.0 (stabilization branch with new APIs)
+
+if (GNUTLS_INCLUDE_DIR AND GNUTLS_LIBRARIES)
+  set(GNUTLS_FIND_QUIETLY TRUE)
+endif (GNUTLS_INCLUDE_DIR AND GNUTLS_LIBRARIES)
+
+# Include dir
+find_path(GNUTLS_INCLUDE_DIR
+	NAMES
+	  gnutls.h
+	  gnutls/gnutls.h
+)
+
+# Library
+find_library(GNUTLS_LIBRARY 
+  NAMES gnutls
+)
+
+# handle the QUIETLY and REQUIRED arguments and set GNUTLS_FOUND to TRUE if 
+# all listed variables are TRUE
+INCLUDE(FindPackageHandleStandardArgs)
+FIND_PACKAGE_HANDLE_STANDARD_ARGS(GNUTLS DEFAULT_MSG GNUTLS_LIBRARY GNUTLS_INCLUDE_DIR)
+
+IF(GNUTLS_FOUND)
+  SET( GNUTLS_LIBRARIES ${GNUTLS_LIBRARY} )
+ELSE(GNUTLS_FOUND)
+  SET( GNUTLS_LIBRARIES )
+ENDIF(GNUTLS_FOUND)
+
+# Lastly make it so that the GNUTLS_LIBRARY and GNUTLS_INCLUDE_DIR variables
+# only show up under the advanced options in the gui cmake applications.
+MARK_AS_ADVANCED( GNUTLS_LIBRARY GNUTLS_INCLUDE_DIR )
+
+# Now check if the library is recent. gnutls_hash was added in 2.10.0.
+# Also test library is even more recent. gnutls_x509_trust_list_verify_crt was added in 3.00.0.
+IF(GNUTLS_FOUND)
+  IF( NOT( "${GNUTLS_VERSION_TEST_FOR}" STREQUAL "${GNUTLS_LIBRARY}" ))
+    INCLUDE (CheckLibraryExists) 
+    MESSAGE(STATUS "Checking GNUTLS version")
+    UNSET(GNUTLS_VERSION_210)
+    UNSET(GNUTLS_VERSION_210 CACHE)
+    UNSET(GNUTLS_VERSION_212)
+    UNSET(GNUTLS_VERSION_212 CACHE)
+    UNSET(GNUTLS_VERSION_300)
+    UNSET(GNUTLS_VERSION_300 CACHE)
+    UNSET(GNUTLS_VERSION_310)
+    UNSET(GNUTLS_VERSION_310 CACHE)
+    GET_FILENAME_COMPONENT(GNUTLS_PATH ${GNUTLS_LIBRARY} PATH)
+    CHECK_LIBRARY_EXISTS(gnutls gnutls_hash ${GNUTLS_PATH} GNUTLS_VERSION_210) 
+    CHECK_LIBRARY_EXISTS(gnutls gnutls_transport_set_vec_push_function ${GNUTLS_PATH} GNUTLS_VERSION_212) 
+    CHECK_LIBRARY_EXISTS(gnutls gnutls_x509_trust_list_verify_crt ${GNUTLS_PATH} GNUTLS_VERSION_300) 
+    CHECK_LIBRARY_EXISTS(gnutls gnutls_handshake_set_timeout ${GNUTLS_PATH} GNUTLS_VERSION_310) 
+    SET( GNUTLS_VERSION_TEST_FOR ${GNUTLS_LIBRARY} CACHE INTERNAL "Version the test was made against" )
+  ENDIF (NOT( "${GNUTLS_VERSION_TEST_FOR}" STREQUAL "${GNUTLS_LIBRARY}" ))
+ENDIF(GNUTLS_FOUND)
diff --git a/cmake/Modules/FindIDNA.cmake b/cmake/Modules/FindIDNA.cmake
new file mode 100644
index 0000000..e5463b4
--- /dev/null
+++ b/cmake/Modules/FindIDNA.cmake
@@ -0,0 +1,40 @@
+# - Try to find GNU IDN library and headers
+# Once done, this will define
+#
+#  IDNA_FOUND - system has IDNA
+#  IDNA_INCLUDE_DIR - the IDNA include directories (<idna.h>)
+#  IDNA_LIBRARIES - link these to use IDNA (idna_to_ascii_8z)
+
+if (IDNA_INCLUDE_DIR AND IDNA_LIBRARIES)
+  set(IDNA_FIND_QUIETLY TRUE)
+endif (IDNA_INCLUDE_DIR AND IDNA_LIBRARIES)
+
+# Include dir
+find_path(IDNA_INCLUDE_DIR
+  NAMES idna.h
+)
+
+# Library
+find_library(IDNA_LIBRARY
+  NAMES idn
+)
+
+
+# handle the QUIETLY and REQUIRED arguments and set IDNA_FOUND to TRUE if
+# all listed variables are TRUE
+INCLUDE(FindPackageHandleStandardArgs)
+FIND_PACKAGE_HANDLE_STANDARD_ARGS(IDNA DEFAULT_MSG IDNA_LIBRARY IDNA_INCLUDE_DIR)
+
+# If we successfully found the idn library then add the library to the
+# IDNA_LIBRARIES cmake variable otherwise set IDNA_LIBRARIES to nothing.
+IF(IDNA_FOUND)
+   SET( IDNA_LIBRARIES ${IDNA_LIBRARY} )
+ELSE(IDNA_FOUND)
+   SET( IDNA_LIBRARIES )
+ENDIF(IDNA_FOUND)
+
+
+# Lastly make it so that the IDNA_LIBRARY and IDNA_INCLUDE_DIR variables
+# only show up under the advanced options in the gui cmake applications.
+MARK_AS_ADVANCED( IDNA_LIBRARY IDNA_INCLUDE_DIR )
+
diff --git a/cmake/Modules/FindLibXml2.cmake b/cmake/Modules/FindLibXml2.cmake
new file mode 100644
index 0000000..e18dc2e
--- /dev/null
+++ b/cmake/Modules/FindLibXml2.cmake
@@ -0,0 +1,53 @@
+# - Try to find the LibXml2 xml processing library
+# Once done this will define
+#
+#  LIBXML2_FOUND - System has LibXml2
+#  LIBXML2_INCLUDE_DIR - The LibXml2 include directory
+#  LIBXML2_LIBRARIES - The libraries needed to use LibXml2
+#  LIBXML2_DEFINITIONS - Compiler switches required for using LibXml2
+#  LIBXML2_XMLLINT_EXECUTABLE - The XML checking tool xmllint coming with LibXml2
+
+#=============================================================================
+# Copyright 2006-2009 Kitware, Inc.
+# Copyright 2006 Alexander Neundorf <neundorf@kde.org>
+#
+# Distributed under the OSI-approved BSD License (the "License");
+# see accompanying file Copyright.txt for details.
+#
+# This software is distributed WITHOUT ANY WARRANTY; without even the
+# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+# See the License for more information.
+#=============================================================================
+# (To distributed this file outside of CMake, substitute the full
+#  License text for the above reference.)
+
+# use pkg-config to get the directories and then use these values
+# in the FIND_PATH() and FIND_LIBRARY() calls
+FIND_PACKAGE(PkgConfig)
+PKG_CHECK_MODULES(PC_LIBXML libxml-2.0)
+SET(LIBXML2_DEFINITIONS ${PC_LIBXML_CFLAGS_OTHER})
+
+FIND_PATH(LIBXML2_INCLUDE_DIR NAMES libxml/xpath.h
+   HINTS
+   ${PC_LIBXML_INCLUDEDIR}
+   ${PC_LIBXML_INCLUDE_DIRS}
+   PATH_SUFFIXES libxml2
+   )
+
+FIND_LIBRARY(LIBXML2_LIBRARIES NAMES xml2 libxml2
+   HINTS
+   ${PC_LIBXML_LIBDIR}
+   ${PC_LIBXML_LIBRARY_DIRS}
+   )
+
+FIND_PROGRAM(LIBXML2_XMLLINT_EXECUTABLE xmllint)
+# for backwards compat. with KDE 4.0.x:
+SET(XMLLINT_EXECUTABLE "${LIBXML2_XMLLINT_EXECUTABLE}")
+
+# handle the QUIETLY and REQUIRED arguments and set LIBXML2_FOUND to TRUE if 
+# all listed variables are TRUE
+INCLUDE(FindPackageHandleStandardArgs)
+FIND_PACKAGE_HANDLE_STANDARD_ARGS(LibXml2 DEFAULT_MSG LIBXML2_LIBRARIES LIBXML2_INCLUDE_DIR)
+
+MARK_AS_ADVANCED(LIBXML2_INCLUDE_DIR LIBXML2_LIBRARIES LIBXML2_XMLLINT_EXECUTABLE)
+
diff --git a/cmake/Modules/FindMySQL.cmake b/cmake/Modules/FindMySQL.cmake
new file mode 100644
index 0000000..c27222b
--- /dev/null
+++ b/cmake/Modules/FindMySQL.cmake
@@ -0,0 +1,56 @@
+# - Find mysqlclient
+#
+# -*- cmake -*-
+#
+# Find the native MySQL includes and library
+#
+#  MySQL_INCLUDE_DIR - where to find mysql.h, etc.
+#  MySQL_LIBRARIES   - List of libraries when using MySQL.
+#  MySQL_FOUND       - True if MySQL found.
+
+IF (MySQL_INCLUDE_DIR AND MySQL_LIBRARY)
+  # Already in cache, be silent
+  SET(MySQL_FIND_QUIETLY TRUE)
+ENDIF (MySQL_INCLUDE_DIR AND MySQL_LIBRARY)
+
+# Include dir
+FIND_PATH(MySQL_INCLUDE_DIR 
+  NAMES mysql.h
+  PATH_SUFFIXES mysql
+)
+
+# Library
+#SET(MySQL_NAMES mysqlclient mysqlclient_r)
+#SET(MySQL_NAMES mysqlclient_r)
+SET(MySQL_NAMES mysqlclient_r mysqlclient)
+FIND_LIBRARY(MySQL_LIBRARY
+  NAMES ${MySQL_NAMES}
+  PATHS /usr/lib /usr/local/lib
+  PATH_SUFFIXES mysql
+)
+
+IF (MySQL_INCLUDE_DIR AND MySQL_LIBRARY)
+  SET(MySQL_FOUND TRUE)
+  SET( MySQL_LIBRARIES ${MySQL_LIBRARY} )
+ELSE (MySQL_INCLUDE_DIR AND MySQL_LIBRARY)
+  SET(MySQL_FOUND FALSE)
+  SET( MySQL_LIBRARIES )
+ENDIF (MySQL_INCLUDE_DIR AND MySQL_LIBRARY)
+
+
+IF (MySQL_FOUND)
+  IF (NOT MySQL_FIND_QUIETLY)
+    MESSAGE(STATUS "Found MySQL: ${MySQL_LIBRARY}")
+  ENDIF (NOT MySQL_FIND_QUIETLY)
+ELSE (MySQL_FOUND)
+  IF (MySQL_FIND_REQUIRED)
+    MESSAGE(STATUS "Looked for MySQL libraries named ${MySQL_NAMES}.")
+    MESSAGE(FATAL_ERROR "Could NOT find MySQL library")
+  ENDIF (MySQL_FIND_REQUIRED)
+ENDIF (MySQL_FOUND)
+
+MARK_AS_ADVANCED(
+  MySQL_LIBRARY
+  MySQL_INCLUDE_DIR
+  )
+
diff --git a/cmake/Modules/FindPostgreSQL.cmake b/cmake/Modules/FindPostgreSQL.cmake
new file mode 100644
index 0000000..a639a26
--- /dev/null
+++ b/cmake/Modules/FindPostgreSQL.cmake
@@ -0,0 +1,36 @@
+# - Find PostgreSQL library
+#
+# This module defines:
+#  POSTGRESQL_FOUND - True if the package is found
+#  POSTGRESQL_INCLUDE_DIR - containing libpq-fe.h
+#  POSTGRESQL_LIBRARIES - Libraries to link to use PQ functions.
+
+if (POSTGRESQL_INCLUDE_DIR AND POSTGRESQL_LIBRARIES)
+  set(POSTGRESQL_FIND_QUIETLY TRUE)
+endif (POSTGRESQL_INCLUDE_DIR AND POSTGRESQL_LIBRARIES)
+
+# Include dir
+find_path(POSTGRESQL_INCLUDE_DIR 
+	NAMES libpq-fe.h
+	PATH_SUFFIXES pgsql postgresql
+)
+
+# Library
+find_library(POSTGRESQL_LIBRARY 
+  NAMES pq
+)
+
+# handle the QUIETLY and REQUIRED arguments and set POSTGRESQL_FOUND to TRUE if 
+# all listed variables are TRUE
+INCLUDE(FindPackageHandleStandardArgs)
+FIND_PACKAGE_HANDLE_STANDARD_ARGS(POSTGRESQL DEFAULT_MSG POSTGRESQL_LIBRARY POSTGRESQL_INCLUDE_DIR)
+
+IF(POSTGRESQL_FOUND)
+  SET( POSTGRESQL_LIBRARIES ${POSTGRESQL_LIBRARY} )
+ELSE(POSTGRESQL_FOUND)
+  SET( POSTGRESQL_LIBRARIES )
+ENDIF(POSTGRESQL_FOUND)
+
+# Lastly make it so that the POSTGRESQL_LIBRARY and POSTGRESQL_INCLUDE_DIR variables
+# only show up under the advanced options in the gui cmake applications.
+MARK_AS_ADVANCED( POSTGRESQL_LIBRARY POSTGRESQL_INCLUDE_DIR )
diff --git a/cmake/Modules/FindSCTP.cmake b/cmake/Modules/FindSCTP.cmake
new file mode 100644
index 0000000..de8e878
--- /dev/null
+++ b/cmake/Modules/FindSCTP.cmake
@@ -0,0 +1,46 @@
+# - Try to find SCTP library and headers
+# Once done, this will define
+#
+#  SCTP_FOUND - system has SCTP
+#  SCTP_INCLUDE_DIR - the SCTP include directories
+#  SCTP_LIBRARIES - link these to use SCTP
+
+if (SCTP_INCLUDE_DIR AND SCTP_LIBRARIES)
+  set(SCTP_FIND_QUIETLY TRUE)
+endif (SCTP_INCLUDE_DIR AND SCTP_LIBRARIES)
+
+# Include dir
+find_path(SCTP_INCLUDE_DIR
+  NAMES netinet/sctp.h
+)
+
+# Library
+find_library(SCTP_LIBRARY
+  NAMES sctp
+)
+
+# Set the include dir variables and the libraries and let libfind_process do the rest.
+# NOTE: Singular variables for this library, plural for libraries this this lib depends on.
+#set(SCTP_PROCESS_INCLUDES SCTP_INCLUDE_DIR)
+#set(SCTP_PROCESS_LIBS SCTP_LIBRARY)
+#libfind_process(SCTP)
+
+
+# handle the QUIETLY and REQUIRED arguments and set SCTP_FOUND to TRUE if
+# all listed variables are TRUE
+INCLUDE(FindPackageHandleStandardArgs)
+FIND_PACKAGE_HANDLE_STANDARD_ARGS(SCTP DEFAULT_MSG SCTP_LIBRARY SCTP_INCLUDE_DIR)
+
+# If we successfully found the sctp library then add the library to the
+# SCTP_LIBRARIES cmake variable otherwise set SCTP_LIBRARIES to nothing.
+IF(SCTP_FOUND)
+   SET( SCTP_LIBRARIES ${SCTP_LIBRARY} )
+ELSE(SCTP_FOUND)
+   SET( SCTP_LIBRARIES )
+ENDIF(SCTP_FOUND)
+
+
+# Lastly make it so that the SCTP_LIBRARY and SCTP_INCLUDE_DIR variables
+# only show up under the advanced options in the gui cmake applications.
+MARK_AS_ADVANCED( SCTP_LIBRARY SCTP_INCLUDE_DIR )
+
diff --git a/cmake/Modules/GetVersionWithHg.cmake b/cmake/Modules/GetVersionWithHg.cmake
new file mode 100644
index 0000000..9fcf392
--- /dev/null
+++ b/cmake/Modules/GetVersionWithHg.cmake
@@ -0,0 +1,23 @@
+# This file is called at build time. It regenerates the version.h file based on the hg version.
+
+EXECUTE_PROCESS(
+	COMMAND ${HGCOMMAND} id -i
+	WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
+	RESULT_VARIABLE reshash
+	OUTPUT_VARIABLE verhash
+	ERROR_QUIET
+	OUTPUT_STRIP_TRAILING_WHITESPACE)
+EXECUTE_PROCESS(
+	COMMAND ${HGCOMMAND} id -n
+	WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
+	RESULT_VARIABLE resval
+	OUTPUT_VARIABLE verval
+	ERROR_QUIET
+	OUTPUT_STRIP_TRAILING_WHITESPACE)
+	
+if (reshash EQUAL 0) 
+	SET(FD_PROJECT_VERSION_HG "${verval}(${verhash})")
+ 	message(STATUS "Source version: ${FD_PROJECT_VERSION_HG}")
+endif (reshash EQUAL 0)
+
+CONFIGURE_FILE(${SRC} ${DST})
diff --git a/contrib/CxDx/README b/contrib/CxDx/README
new file mode 100644
index 0000000..9554e44
--- /dev/null
+++ b/contrib/CxDx/README
@@ -0,0 +1,17 @@
+Date: Thu, 13 Oct 2011 14:01:40 -0300
+From: "Norberto R. de Goes Jr." <norberto@cpqd.com.br>
+To: help@freediameter.net
+Subject: [Help] Cx dictionary (samples "c" and "xml")
+
+Hi.
+
+Just a contribution, they were not tested.
+Best regards,
+
+--
+Norberto R. de Goes Jr.
+CPqD - DRC
+Tel.: +55 19 3705-4241 / Fax: +55 19 3705-6125
+norberto@cpqd.com.br
+www.cpqd.com.br
+
diff --git a/contrib/CxDx/dict_cxdx.c b/contrib/CxDx/dict_cxdx.c
new file mode 100644
index 0000000..dd58c8d
--- /dev/null
+++ b/contrib/CxDx/dict_cxdx.c
@@ -0,0 +1,1724 @@
+/*********************************************************************************************************
+ * Software License Agreement (BSD License)                                                               *
+ * Author: Norberto R. de Goes Jr. 						 *
+ *													 *
+ * Copyright (c) 2011, Norberto R. de Goes Jr..                                                      	 *
+ *										 *
+ * All rights reserved.											 *
+ * 													 *
+ * Redistribution and use of this software in source and binary forms, with or without modification, are  *
+ * permitted provided that the following conditions are met:						 *
+ * 													 *
+ * * Redistributions of source code must retain the above 						 *
+ *   copyright notice, this list of conditions and the 							 *
+ *   following disclaimer.										 *
+ *    													 *
+ * * Redistributions in binary form must reproduce the above 						 *
+ *   copyright notice, this list of conditions and the 							 *
+ *   following disclaimer in the documentation and/or other						 *
+ *   materials provided with the distribution.								 *
+ * 													 *
+ * * Neither the name of the Teraoka Laboratory nor the 							 *
+ *   names of its contributors may be used to endorse or 						 *
+ *   promote products derived from this software without 						 *
+ *   specific prior written permission of Teraoka Laboratory 						 *
+ *   													 *
+ * 													 *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED *
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR *
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 	 *
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 	 *
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR *
+ * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF   *
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.								 *
+ *********************************************************************************************************/
+
+
+/*********************************************************************************************************
+
+ === CpqD/DRC  -  Projeto ADRIMS  -  Mar/2011 ===
+ === Dicionario Dx/Cx ===
+ Baseado no "dict_sip" do FreeDiameter (www.freediameter.net) 
+                                                                                 Norberto R Goes Jr
+*********************************************************************************************************/
+
+
+#include <freeDiameter/extension.h>
+
+
+
+/* The content of this file follows the same structure as dict_base_proto.c */
+
+#define CHECK_dict_new( _type, _data, _parent, _ref )			\
+  CHECK_FCT(  fd_dict_new( fd_g_config->cnf_dict, (_type), (_data), (_parent), (_ref))  );
+
+#define CHECK_dict_search( _type, _criteria, _what, _result )		\
+  CHECK_FCT(  fd_dict_search( fd_g_config->cnf_dict, (_type), (_criteria), (_what), (_result), ENOENT) );
+
+
+struct local_rules_definition 
+{
+  char 			*avp_name;
+  enum rule_position	 position;
+  int 			 min;
+  int			 max;
+};
+
+/*==================================================================*/
+
+#define RULE_ORDER( _position ) ((((_position) == RULE_FIXED_HEAD) || ((_position) == RULE_FIXED_TAIL)) ? 1 : 0 )
+
+/*==================================================================*/
+
+#define PARSE_loc_rules( _rulearray, _parent, _avp_search_flag) {	\
+    int __ar;								\
+    for (__ar=0; __ar < sizeof(_rulearray) / sizeof((_rulearray)[0]); __ar++) {	\
+      struct dict_rule_data __data = { NULL,				\
+				       (_rulearray)[__ar].position,	\
+				       0,				\
+				       (_rulearray)[__ar].min,		\
+				       (_rulearray)[__ar].max};		\
+      __data.rule_order = RULE_ORDER(__data.rule_position);		\
+                                                                        \
+      CHECK_FCT(  fd_dict_search(					\
+				 fd_g_config->cnf_dict,			\
+				 DICT_AVP,				\
+				 _avp_search_flag,			\
+				 (_rulearray)[__ar].avp_name,		\
+				 &__data.rule_avp, 0 ) );		\
+      if ( !__data.rule_avp ) {						\
+	TRACE_DEBUG(INFO, "AVP Not found: '%s'", (_rulearray)[__ar].avp_name );	\
+	return ENOENT;							\
+      }									\
+                                                                        \
+      CHECK_FCT_DO( fd_dict_new( fd_g_config->cnf_dict, DICT_RULE, &__data, _parent, NULL), \
+		    {							\
+		      TRACE_DEBUG(INFO, "Error on rule with AVP '%s'",	\
+				  (_rulearray)[__ar].avp_name );	\
+		      return EINVAL;					\
+		    } );						\
+    }									\
+  }
+
+#define enumval_def_u32( _val_, _str_ )		\
+  { _str_, 		{ .u32 = _val_ }}
+
+#define enumval_def_os( _len_, _val_, _str_ )				\
+  { _str_, 		{ .os = { .data = (unsigned char *)_val_, .len = _len_ }}}
+
+
+/*==================================================================*/
+/*==================================================================*/
+/*==================================================================*/
+/*==================================================================*/
+
+int cxdx_dict_init(char * conffile)
+{
+
+#define VENDOR_3GPP_Id  10415
+
+
+  struct dict_object * vendor_dict;
+  {
+    struct dict_vendor_data vendor_data = { VENDOR_3GPP_Id, "3GPP" };
+    CHECK_dict_new (DICT_VENDOR, &vendor_data, NULL, &vendor_dict);
+  }
+
+
+  struct dict_object * cxdx_dict;
+  {
+    struct dict_application_data data  = { 16777216 /* NRGJ */, "Diameter CxDx Application"	};
+    CHECK_dict_new (DICT_APPLICATION, &data, vendor_dict, &cxdx_dict);
+  }
+
+
+  /* ##### AVP section #################################### */
+  {
+    struct dict_object * UTF8String_type;
+    struct dict_object * DiameterURI_type;
+
+    CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "UTF8String",  &UTF8String_type);
+    CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "DiameterURI", &DiameterURI_type);
+
+    /* Digest AVPs:  */
+
+    /* Visited-Network-Identifier */
+    {
+      struct dict_avp_data data = 
+	{ 
+	  600, 					/* Code */
+	  VENDOR_3GPP_Id,  			/* Vendor */
+	  "Visited-Network-Identifier",         /* Name */
+	  AVP_FLAG_MANDATORY | AVP_FLAG_VENDOR, /* Fixed flags */
+	  AVP_FLAG_MANDATORY | AVP_FLAG_VENDOR, /* Fixed flag values */
+	  AVP_TYPE_OCTETSTRING 			/* base type of data */
+	};
+      CHECK_dict_new( DICT_AVP, &data , UTF8String_type, NULL);
+    }
+
+    /* Public-Identity */
+    {
+      struct dict_avp_data data = 
+	{ 
+	  601, 					/* Code */
+	  VENDOR_3GPP_Id,			/* Vendor */
+	  "Public-Identity", 		        /* Name */
+	  AVP_FLAG_MANDATORY | AVP_FLAG_VENDOR, /* Fixed flags */
+	  AVP_FLAG_MANDATORY | AVP_FLAG_VENDOR,	/* Fixed flag values */
+	  AVP_TYPE_OCTETSTRING 			/* base type of data */
+	};
+      CHECK_dict_new( DICT_AVP, &data , UTF8String_type, NULL);
+    }
+
+
+    /* Server-Name */
+    {
+      struct dict_avp_data data = 
+	{ 
+	  602, 					/* Code */
+	  VENDOR_3GPP_Id,			/* Vendor */
+	  "Server-Name", 		        /* Name */
+	  AVP_FLAG_MANDATORY | AVP_FLAG_VENDOR, /* Fixed flags */
+	  AVP_FLAG_MANDATORY | AVP_FLAG_VENDOR,	/* Fixed flag values */
+	  AVP_TYPE_OCTETSTRING 			/* base type of data */
+	};
+      CHECK_dict_new( DICT_AVP, &data , DiameterURI_type/*UTF8String_type*/, NULL);
+    }
+
+
+    /* Optional-Capability */
+    {
+      struct dict_avp_data data = 
+	{ 
+	  605, 					/* Code */
+	  VENDOR_3GPP_Id,			/* Vendor */
+	  "Optional-Capability",	        /* Name */
+	  AVP_FLAG_MANDATORY | AVP_FLAG_VENDOR, /* Fixed flags */
+	  AVP_FLAG_MANDATORY | AVP_FLAG_VENDOR,	/* Fixed flag values */
+	  AVP_TYPE_UNSIGNED32 			/* base type of data */
+	};
+      CHECK_dict_new( DICT_AVP, &data , NULL, NULL);
+    }
+
+
+    /* Feature-List-ID */
+    {
+      struct dict_avp_data data = 
+	{ 
+	  629, 					/* Code */
+	  VENDOR_3GPP_Id,			/* Vendor */
+	  "Feature-List-ID", 		        /* Name */
+	  AVP_FLAG_VENDOR,                      /* Fixed flags */
+	  AVP_FLAG_VENDOR,	                /* Fixed flag values */
+	  AVP_TYPE_UNSIGNED32 			/* base type of data */
+	};
+      CHECK_dict_new( DICT_AVP, &data , NULL, NULL);
+    }
+
+
+    /* Feature-List */
+    {
+      struct dict_avp_data data = 
+	{ 
+	  630, 					/* Code */
+	  VENDOR_3GPP_Id,			/* Vendor */
+	  "Feature-List", 		        /* Name */
+	  AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, /* Fixed flags */
+	  AVP_FLAG_MANDATORY,		 	/* Fixed flag values */
+	  AVP_TYPE_UNSIGNED32 			/* base type of data */
+	};
+      CHECK_dict_new( DICT_AVP, &data , NULL, NULL);
+    }
+
+    /* Server-Capabilities */
+    {
+      struct dict_object * avp;
+      struct dict_avp_data data = 
+	{ 
+	  603, 					/* Code */
+	  VENDOR_3GPP_Id,			/* Vendor */
+	  "Server-Capabilities", 		/* Name */
+	  AVP_FLAG_MANDATORY | AVP_FLAG_VENDOR, /* Fixed flags */
+	  AVP_FLAG_MANDATORY | AVP_FLAG_VENDOR,	/* Fixed flag values */
+	  AVP_TYPE_GROUPED 			/* base type of data */
+	};
+
+      struct local_rules_definition rules[] = 
+	{ 
+	  {  "Vendor-Id", 	 RULE_REQUIRED, -1, 1 },
+	  {  "Feature-List-ID",  RULE_REQUIRED, -1, 1 },
+	  {  "Feature-List", 	 RULE_REQUIRED, -1, 1 }
+	};
+
+      CHECK_dict_new (DICT_AVP, &data , NULL, &avp);
+      PARSE_loc_rules(rules, avp, AVP_BY_NAME_ALL_VENDORS );
+    }
+
+
+
+    /* User-Authorization-Type */
+    {
+      struct dict_avp_data data = 
+	{ 
+	  623, 					/* Code */
+	  VENDOR_3GPP_Id, 			/* Vendor */
+	  "User-Authorization-Type", 		/* Name */
+	  AVP_FLAG_MANDATORY | AVP_FLAG_VENDOR, /* Fixed flags */
+	  AVP_FLAG_MANDATORY | AVP_FLAG_VENDOR,	/* Fixed flag values */
+	  AVP_TYPE_OCTETSTRING 			/* base type of data */
+	};
+      CHECK_dict_new( DICT_AVP, &data , UTF8String_type, NULL);
+    }
+
+
+    /* Supported-Features */
+    {
+      struct dict_object * avp;
+      struct dict_avp_data data = 
+	{ 
+	  628, 					/* Code */
+	  VENDOR_3GPP_Id,			/* Vendor */
+	  "Supported-Features", 		/* Name */
+	  AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, /* Fixed flags */
+	  AVP_FLAG_MANDATORY,		 	/* Fixed flag values */
+	  AVP_TYPE_GROUPED 			/* base type of data */
+	};
+
+      struct local_rules_definition rules[] = 
+	{ 
+	  {  "Vendor-Id", 	 RULE_REQUIRED, -1, 1 },
+	  {  "Feature-List-ID",  RULE_REQUIRED, -1, 1 },
+	  {  "Feature-List", 	 RULE_REQUIRED, -1, 1 }
+	};
+
+      CHECK_dict_new (DICT_AVP, &data , NULL, &avp);
+      PARSE_loc_rules(rules, avp, AVP_BY_NAME_ALL_VENDORS );
+    }
+  
+
+
+
+  } /* end AVP section */
+
+
+
+  /* ### Command section ############################# */
+  {
+    /* User-Authorization-Request (UAR) Command */
+    {
+      /*
+	The User-Authorization-Request (UAR) is indicated by the Command-Code
+	set to 283 and the Command Flags' 'R' bit set.  The Diameter client
+	in a SIP server sends this command to the Diameter server to request
+	authorization for the SIP User Agent to route a SIP REGISTER request.
+	Because the SIP REGISTER request implicitly carries a permission to
+	bind an AOR to a contact address, the Diameter client uses the
+	Diameter UAR as a first authorization request towards the Diameter
+	server to authorize the registration.  For instance, the Diameter
+	server can verify that the AOR is a legitimate user of the realm.
+
+	The Diameter client in the SIP server requests authorization for one
+	of the possible values defined in the SIP-User-Authorization-Type AVP
+	(Section 9.10).
+
+	The user name used for authentication of the user is conveyed in a
+	User-Name AVP (defined in the Diameter base protocol, RFC 3588
+	[RFC3588]).  The location of the authentication user name in the SIP
+	REGISTER request varies depending on the authentication mechanism.
+	When the authentication mechanism is HTTP Digest as defined in RFC
+	2617 [RFC2617], the authentication user name is found in the
+	"username" directive of the SIP Authorization header field value.
+	This Diameter SIP application only provides support for HTTP Digest
+	authentication in SIP; other authentication mechanisms are not
+	currently supported.
+
+	The SIP or SIPS URI to be registered is conveyed in the SIP-AOR AVP
+	(Section 9.8).  Typically this SIP or SIPS URI is found in the To
+	header field value of the SIP REGISTER request that triggered the
+	Diameter UAR message.
+
+	The SIP-Visited-Network-Id AVP indicates the network that is
+	providing SIP services (e.g., SIP proxy functionality or any other
+	kind of services) to the SIP User Agent.
+
+	The Message Format of the UAR command is as follows:
+
+
+	< UAR> ::=< Diameter Header: 300, REQ, PXY, 16777216 >
+	< Session-Id >
+	{ Vendor-Specific-Application-Id }
+	{ Auth-Session-State }
+	{ Origin-Host }
+	{ Origin-Realm }
+	[ Destination-Host ]
+	{ Destination-Realm }
+	{ User-Name }
+	*[ Supported-Features ]
+	{ Public-Identity }
+	{ Visited-Network-Identifier }
+	[ User-Authorization-Type ]
+	[ UAR-Flags ]
+	*[ AVP ]
+	*[ Proxy-Info ]
+	*[ Route-Record ]
+	*/
+
+      struct dict_object   * cmd;
+      struct dict_cmd_data   data = 
+	{ 
+	  300,                   	/* Code */
+	  "User-Authorization-Request", /* Name */
+	  CMD_FLAG_REQUEST | CMD_FLAG_PROXIABLE | CMD_FLAG_ERROR, /* Fixed flags */
+	  CMD_FLAG_REQUEST | CMD_FLAG_PROXIABLE  /* Fixed flag values */
+	};
+
+      struct local_rules_definition rules[] = 
+	{
+	  {  "Session-Id", 			RULE_FIXED_HEAD, -1,  1 },
+	  {  "Vendor-Specific-Application-Id",	RULE_REQUIRED,   -1,  1 },
+	  {  "Auth-Session-State", 		RULE_REQUIRED,   -1,  1 },
+	  {  "Origin-Host", 			RULE_REQUIRED,   -1,  1 },
+	  {  "Origin-Realm", 			RULE_REQUIRED,   -1,  1 },
+	  //	  {  "Destination-Host", 		RULE_OPTIONAL,   -1,  1 },
+	  {  "Destination-Realm", 		RULE_REQUIRED,   -1,  1 },
+	  {  "User-Name", 			RULE_REQUIRED,   -1,  1 },
+	  //	  {  "Supported-Features", 		RULE_OPTIONAL,   -1, -1 },
+	  {  "Public-Identity", 		RULE_REQUIRED,   -1,  1 },
+	  {  "Visited-Network-Identifier",      RULE_REQUIRED,   -1,  1 },
+	  //	  {  "UAR-Flags",                       RULE_OPTIONAL,   -1,  1 },
+	  //	  {  "User-Authorization-Type", 	RULE_OPTIONAL,   -1,  1 },
+	  //	  {  "Proxy-Info", 			RULE_OPTIONAL,   -1, -1 },
+	  //	  {  "Route-Record", 			RULE_OPTIONAL,   -1, -1 }
+	};
+			
+      CHECK_dict_new( DICT_COMMAND, &data , cxdx_dict, &cmd);
+      PARSE_loc_rules( rules, cmd, AVP_BY_NAME_ALL_VENDORS);
+    }
+
+    /* User-Authorization-Answer (UAA) Command */
+    {
+      /*
+	The User-Authorization-Answer (UAA) is indicated by the Command-Code
+	set to 283 and the Command Flags' 'R' bit cleared.  The Diameter
+	server sends this command in response to a previously received
+	Diameter User-Authorization-Request (UAR) command.  The Diameter
+	server indicates the result of the requested registration
+	authorization.  Additionally, the Diameter server may indicate a
+	collection of SIP capabilities that assists the Diameter client to
+	select a SIP proxy to the AOR under registration.
+
+
+	In addition to the values already defined in RFC 3588 [RFC3588], the
+	Result-Code AVP may contain one of the values defined in
+	Section 10.1.
+
+	Whenever the Diameter server fails to process the Diameter UAR
+	message, it MUST stop processing and return the relevant error in the
+	Diameter UAA message.  When there is success in the process, the
+	Diameter server MUST set the code to DIAMETER_SUCCESS in the Diameter
+	UAA message.
+
+	If the Diameter server requires a User-Name AVP value to process the
+	Diameter UAR request, but the Diameter UAR message did not contain a
+	User-Name AVP value, the Diameter server MUST set the Result-Code AVP
+	value to DIAMETER_USER_NAME_REQUIRED (see Section 10.1.2) and return
+	it in a Diameter UAA message.  Upon reception of this Diameter UAA
+	message with the Result-Code AVP value set to
+	DIAMETER_USER_NAME_REQUIRED, the SIP server typically requests
+	authentication by sending a SIP 401 (Unauthorized) or SIP 407 (Proxy
+	Authentication Required) response back to the originator.
+
+	When the authorization procedure succeeds, the Diameter server
+	constructs a User-Authorization-Answer (UAA) message that MUST
+	include (1) the address of the SIP server already assigned to the
+	user name, (2) the capabilities needed by the SIP server (Diameter
+	client) to select another SIP server for the user, or (3) a
+	combination of the previous two options.
+
+	If the Diameter server is already aware of a SIP server allocated to
+	the user, the Diameter UAA message contains the address of that SIP
+	server.
+
+	The Diameter UAA message contains the capabilities required by a SIP
+	server to trigger and execute services.  It is required that these
+	capabilities are present in the Diameter UAA message due to the
+	possibility that the Diameter client (in the SIP server) allocates a
+	different SIP server to trigger and execute services for that
+	particular user.
+
+	If a User-Name AVP is present in the Diameter UAR message, then the
+	Diameter server MUST verify the existence of the user in the realm,
+	i.e., the User-Name AVP value is a valid user within that realm.  If
+	the Diameter server does not recognize the user name received in the
+	User-Name AVP, the Diameter server MUST build a Diameter User-
+	Authorization-Answer (UAA) message and MUST set the Result-Code AVP
+	to DIAMETER_ERROR_USER_UNKNOWN.
+
+
+	If a User-Name AVP is present in the Diameter UAR message, then the
+	Diameter server MUST authorize that User-Name AVP value is able to
+	register the SIP or SIPS URI included in the SIP-AOR AVP.  If this
+	authorization fails, the Diameter server must set the Result-Code AVP
+	to DIAMETER_ERROR_IDENTITIES_DONT_MATCH and send it in a Diameter
+	User-Authorization-Answer (UAA) message.
+
+	Note: Correlation between User-Name and SIP-AOR AVP values is
+	required in order to avoid registration of a SIP-AOR allocated to
+	another user.
+
+	If there is a SIP-Visited-Network-Id AVP in the Diameter UAR message,
+	and the SIP-User-Authorization-Type AVP value received in the
+	Diameter UAR message is set to REGISTRATION or REGISTRATION&
+	CAPABILITIES, then the Diameter server SHOULD verify whether the user
+	is allowed to roam into the network specified in the
+	SIP-Visited-Network-Id AVP in the Diameter UAR message.  If the user
+	is not allowed to roam into that network, the Diameter AAA server
+	MUST set the Result-Code AVP value in the Diameter UAA message to
+	DIAMETER_ERROR_ROAMING_NOT_ALLOWED.
+
+	If the SIP-User-Authorization-Type AVP value received in the Diameter
+	UAR message is set to REGISTRATION or REGISTRATION&CAPABILITIES, then
+	the Diameter server SHOULD verify whether the SIP-AOR AVP value is
+	authorized to register in the Home Realm.  Where the SIP AOR is not
+	authorized to register in the Home Realm, the Diameter server MUST
+	set the Result-Code AVP to DIAMETER_AUTHORIZATION_REJECTED and send
+	it in a Diameter UAA message.
+
+	When the SIP-User-Authorization-Type AVP is not present in the
+	Diameter UAR message, or when it is present and its value is set to
+	REGISTRATION, then:
+
+	o  If the Diameter server is not aware of any previous registration
+	of the user name (including registrations of other SIP AORs
+	allocated to the same user name), then the Diameter server does
+	not know of any SIP server allocated to the user.  In this case,
+	the Diameter server MUST set the Result-Code AVP value to
+	DIAMETER_FIRST_REGISTRATION in the Diameter UAA message, and the
+	Diameter server SHOULD include the required SIP server
+	capabilities in the SIP-Server-Capabilities AVP value in the
+	Diameter UAA message.  The SIP-Server-Capabilities AVP assists the
+	Diameter client (SIP server) to select an appropriate SIP server
+	for the user, according to the required capabilities.
+
+	o  In some cases, the Diameter server is aware of a previously
+	assigned SIP server for the same or different SIP AORs allocated
+	to the same user name.  In these cases, re-assignment of a new SIP
+	server may or may not be needed, depending on the capabilities of
+	the SIP server.  The Diameter server MUST always include the
+	allocated SIP server URI in the SIP-Server-URI AVP of the UAA
+	message.  If the Diameter server does not return the SIP
+	capabilities, the Diameter server MUST set the Result-Code AVP in
+	the Diameter UAA message to DIAMETER_SUBSEQUENT_REGISTRATION.
+	Otherwise (i.e., if the Diameter server includes a
+	SIP-Server-Capabilities AVP), then the Diameter server MUST set
+	the Result-Code AVP in the Diameter UAA message to
+	DIAMETER_SERVER_SELECTION.  Then the Diameter client determines,
+	based on the received information, whether it needs to select a
+	new SIP server.
+
+	When the SIP-User-Authorization-Type AVP value received in the
+	Diameter UAR message is set to REGISTRATION&CAPABILITIES, then
+	Diameter Server MUST return the list of capabilities in the
+	SIP-Server-Capabilities AVP value of the Diameter UAA message, it
+	MUST set the Result-Code to DIAMETER_SUCCESS, and it MUST NOT return
+	a SIP-Server-URI AVP.  The SIP-Server-Capabilities AVP enables the
+	SIP server (Diameter client) to select another appropriate SIP server
+	for invoking and executing services for the user, depending on the
+	required capabilities.  The Diameter server MAY leave the list of
+	capabilities empty to indicate that any SIP server can be selected.
+
+	When the SIP-User-Authorization-Type AVP value received in the
+	Diameter UAR message is set to DEREGISTRATION, then:
+
+	o  If the Diameter server is aware of a SIP server assigned to the
+	SIP AOR under deregistration, the Diameter server MUST set the
+	Result-Code AVP to DIAMETER_SUCCESS and MUST set the
+	SIP-Server-URI AVP value to the known SIP server, and return them
+	in the Diameter UAA message.
+
+	o  If the Diameter server is not aware of a SIP server assigned to
+	the SIP AOR under deregistration, then the Diameter server MUST
+	set the Result-Code AVP in the Diameter UAA message to
+	DIAMETER_ERROR_IDENTITY_NOT_REGISTERED.
+
+	The Message Format of the UAA command is as follows:
+
+	<UAA> ::= < Diameter Header: 283, PXY >
+	< Session-Id >
+	{ Auth-Application-Id }
+	{ Auth-Session-State }
+	{ Result-Code }
+	{ Origin-Host }
+	{ Origin-Realm }
+	[ SIP-Server-URI ]
+	[ SIP-Server-Capabilities ]
+	[ Authorization-Lifetime ]
+	[ Auth-Grace-Period ]
+	[ Redirect-Host ]
+	[ Redirect-Host-Usage ]
+	[ Redirect-Max-Cache-Time ]
+	* [ Proxy-Info ]
+	* [ Route-Record ]
+	* [ AVP ]
+
+
+	*/
+      struct dict_object * cmd;
+      struct dict_cmd_data data = 
+	{ 
+	  300, 					/* Code */
+	  "User-Authorization-Answer", 		/* Name */
+	  CMD_FLAG_REQUEST | CMD_FLAG_PROXIABLE | CMD_FLAG_ERROR, /* Fixed flags */
+	  CMD_FLAG_PROXIABLE 					  /* Fixed flag values */
+	};
+
+      struct local_rules_definition rules[] = 
+	{ 	 
+	  {  "Session-Id", 		RULE_FIXED_HEAD, -1,  1 },
+	  {  "Auth-Application-Id", 	RULE_REQUIRED,   -1,  1 },
+	  {  "Auth-Session-State", 	RULE_REQUIRED,   -1,  1 },
+	  {  "Result-Code", 		RULE_REQUIRED,   -1,  1 },
+	  {  "Origin-Host", 		RULE_REQUIRED,   -1,  1 },
+	  {  "Origin-Realm", 		RULE_REQUIRED,   -1,  1 },
+	  {  "Proxy-Info", 		RULE_OPTIONAL,   -1, -1 },
+	  {  "Route-Record", 		RULE_OPTIONAL,   -1, -1 }
+	};
+
+      CHECK_dict_new( DICT_COMMAND, &data , cxdx_dict, &cmd);
+      PARSE_loc_rules( rules, cmd, AVP_BY_NAME );
+    }
+
+
+
+
+
+#if 0   /* TODO - NRGJ :   alterar conforme RFC-3GPP : */
+		
+    /* Multimedia-Auth-Request (MAR) Command */
+    {
+      /*		
+			The Multimedia-Auth-Request (MAR) command is indicated by the
+			Command-Code set to 286 and the Command Flags' 'R' bit set.  The
+			Diameter client in a SIP server sends this command to the Diameter
+			server to request that the Diameter server authenticate and authorize
+			a user attempt to use some SIP service (in this context, SIP service
+			can be something as simple as a SIP subscription or using the proxy
+			services for a SIP request).
+
+			The MAR command may also register the SIP server's own URI to the
+			Diameter server, so that future LIR/LIA messages can return this URI.
+			If the SIP server is acting as a SIP registrar (see examples in
+			Sections 6.2 and 6.3), its Diameter client MUST include a SIP-
+			Server-URI AVP in the MAR command.  In any other cases (see example
+			in Section 6.4), its Diameter client MUST NOT include a SIP-Server-
+			URI AVP in the MAR command.
+
+			The SIP-Method AVP MUST include the SIP method name of the SIP
+			request that triggered this Diameter MAR message.  The Diameter
+			server can use this AVP to authorize some SIP requests depending on
+			the method.
+
+			The Diameter MAR message MUST include a SIP-AOR AVP.  The SIP-AOR AVP
+			indicates the target of the SIP request.  The value of the AVP is
+			extracted from different places in SIP request, depending on the
+			semantics of the SIP request.  For SIP REGISTER messages the SIP-AOR
+			AVP value indicates the intended public user identity under
+			registration, and it is the SIP or SIPS URI populated in the To
+			header field value (addr-spec as per RFC 3261 [RFC3261]) of the SIP
+			REGISTER request.  For other types of SIP requests, such as INVITE,
+			SUBSCRIBE, MESSAGE, etc., the SIP-AOR AVP value indicates the
+			intended destination of the request.  This is typically populated in
+			the Request-URI of the SIP request.  Extracting the SIP-AOR AVP value
+			from the proper SIP header field is the Diameter client's
+			responsibility.  Extensions to SIP (new SIP methods or new semantics)
+			may require the SIP-AOR to be extracted from other parts of the
+			request.
+
+			If the SIP request includes some sort of authentication information,
+			the Diameter client MUST include the user name, extracted from the
+			authentication information of the SIP request, in the User-Name AVP
+			value.
+
+			The Message Format of the MAR command is as follows:
+
+			<MAR> ::= < Diameter Header: 286, REQ, PXY >
+			< Session-Id >
+			{ Auth-Application-Id }
+			{ Auth-Session-State }
+			{ Origin-Host }
+			{ Origin-Realm }
+			{ Destination-Realm }
+			{ SIP-AOR }
+			{ SIP-Method }
+			[ Destination-Host ]
+			[ User-Name ]
+			[ SIP-Server-URI ]
+			[ SIP-Number-Auth-Items ]
+			[ SIP-Auth-Data-Item ]
+			* [ Proxy-Info ]
+			* [ Route-Record ]
+			* [ AVP ]
+
+			*/
+
+      struct dict_object * cmd;
+      struct dict_cmd_data data = 
+	{ 
+	  303, 				/* Code */
+	  "Multimedia-Auth-Request", 	/* Name */
+	  CMD_FLAG_REQUEST | CMD_FLAG_PROXIABLE | CMD_FLAG_ERROR, 	/* Fixed flags */
+	  CMD_FLAG_REQUEST | CMD_FLAG_PROXIABLE 			/* Fixed flag values */
+	};
+
+      struct local_rules_definition rules[] = 
+	{ 	 {  "Session-Id", 		RULE_FIXED_HEAD, -1, 1 }
+		 ,{  "Auth-Application-Id", 	RULE_REQUIRED,   -1, 1 }
+		 ,{  "Auth-Session-State", 	RULE_REQUIRED,   -1, 1 }
+		 ,{  "Origin-Host", 		RULE_REQUIRED,   -1, 1 }
+		 ,{  "Origin-Realm", 		RULE_REQUIRED,   -1, 1 }
+		 ,{  "Destination-Realm",	RULE_REQUIRED,   -1, 1 }
+		 ,{  "SIP-AOR", 		RULE_REQUIRED,   -1, 1 }
+		 ,{  "SIP-Method", 		RULE_REQUIRED,   -1, 1 }
+		 ,{  "Destination-Host", 	RULE_OPTIONAL,   -1, 1 }
+		 ,{  "User-Name", 		RULE_OPTIONAL,   -1, 1 }
+		 ,{  "SIP-Server-URI", 		RULE_OPTIONAL,   -1, 1 }
+		 ,{  "SIP-Number-Auth-Items", 	RULE_OPTIONAL,   -1, 1 }
+		 ,{  "SIP-Auth-Data-Item", 	RULE_OPTIONAL,   -1, 1 }
+		 ,{  "Proxy-Info", 		RULE_OPTIONAL,   -1, -1 }
+		 ,{  "Route-Record", 		RULE_OPTIONAL,   -1, -1 }
+
+	};
+			
+      CHECK_dict_new( DICT_COMMAND, &data , cxdx_dict, &cmd);
+      PARSE_loc_rules( rules, cmd, AVP_BY_NAME );
+    }
+    /* Multimedia-Auth-Answer (MAA) Command */
+    {
+      /*
+			
+	The Multimedia-Auth-Answer (MAA) is indicated by the Command-Code set
+	to 286 and the Command Flags' 'R' bit cleared.  The Diameter server
+	sends this command in response to a previously received Diameter
+	Multimedia-Auth-Request (MAR) command.
+
+	In addition to the values already defined in RFC 3588 [RFC3588], the
+	Result-Code AVP may contain one of the values defined in
+	Section 10.1.
+
+	If the Diameter server requires a User-Name AVP value to process the
+	Diameter MAR request, but the Diameter MAR message did not contain a
+	User-Name AVP value, the Diameter server MUST set the Result-Code AVP
+	value to DIAMETER_USER_NAME_REQUIRED (see Section 10.1.2) and return
+	it in a Diameter MAA message.  The Diameter server MAY include a
+	SIP-Number-Auth-Items AVP and one or more SIP-Auth-Data-Item AVPs
+	with authentication information (e.g., a challenge).  Upon reception
+	of this Diameter MAA message with the Result-Code AVP value set to
+	DIAMETER_USER_NAME_REQUIRED, the SIP server typically requests
+	authentication by generating a SIP 401 (Unauthorized) or SIP 407
+	(Proxy Authentication Required) response back to the originator.
+
+	If the User-Name AVP is present in the Diameter MAR message, the
+	Diameter server MUST verify the existence of the user in the realm,
+	i.e., the User-Name AVP value is a valid user within that realm.  If
+	the Diameter server does not recognize the user name received in the
+	User-Name AVP, the Diameter server MUST build a Diameter
+	Multimedia-Auth-Answer (MAA) message and MUST set the Result-Code AVP
+	to DIAMETER_ERROR_USER_UNKNOWN.
+
+	If the SIP-Methods AVP value of the Diameter MAR message is set to
+	REGISTER and a User-Name AVP is present, then the Diameter server
+	MUST authorize that User-Name AVP value is able to use the URI
+	included in the SIP-AOR AVP.  If this authorization fails, the
+	Diameter server must set the Result-Code AVP to
+	DIAMETER_ERROR_IDENTITIES_DONT_MATCH and send it in a Diameter
+	Multimedia-Auth-Answer (MAA) message.
+
+	Note: Correlation between User-Name and SIP-AOR AVP values is only
+	required for SIP REGISTER request, to prevent a user from
+	registering a SIP-AOR allocated to another user.  In other types
+	of SIP requests (e.g., INVITE), the SIP-AOR indicates the intended
+	destination of the request, rather than the originator of it.
+
+	The Diameter server MUST verify whether the authentication scheme
+	(SIP-Authentication-Scheme AVP value) indicated in the grouped
+	SIP-Auth-Data-Item AVP is supported or not.  If that authentication
+	scheme is not supported, then the Diameter server MUST set the
+	Result-Code AVP to DIAMETER_ERROR_AUTH_SCHEME_NOT_SUPPORTED and send
+	it in a Diameter Multimedia-Auth-Answer (MAA) message.
+
+	If the SIP-Number-Auth-Items AVP is present in the Diameter MAR
+	message, it indicates the number of authentication data items that
+	the Diameter client is requesting.  It is RECOMMENDED that the
+	Diameter server, when building the Diameter MAA message, includes a
+	number of SIP-Auth-Data-Item AVPs that are a subset of the
+	authentication data items requested by the Diameter client in the
+	SIP-Number-Auth-Items AVP value of the Diameter MAR message.
+
+	If the SIP-Server-URI AVP is present in the Diameter MAR message,
+	then the Diameter server MUST compare the stored SIP server (assigned
+	to the user) with the SIP-Server-URI AVP value (received in the
+	Diameter MAR message).  If they don't match, the Diameter server MUST
+	temporarily save the newly received SIP server assigned to the user,
+	and MUST set an "authentication pending" flag for the user.  If they
+	match, the Diameter server shall clear the "authentication pending"
+	flag for the user.
+
+	In any other situation, if there is a success in processing the
+	Diameter MAR command and the Diameter server stored the
+	SIP-Server-URI, the Diameter server MUST set the Result-Code AVP
+	value to DIAMETER_SUCCESS and return it in a Diameter MAA message.
+
+	If there is a success in processing the Diameter MAR command, but the
+	Diameter server does not store the SIP-Server-URI because the AVP was
+	not present in the Diameter MAR command, then the Diameter server
+	MUST set the Result-Code AVP value to either:
+
+	1.  DIAMETER_SUCCESS_AUTH_SENT_SERVER_NOT_STORED, if the Diameter
+	server is sending authentication credentials to create a
+	challenge.
+
+	2.  DIAMETER_SUCCESS_SERVER_NAME_NOT_STORED, if the Diameter server
+	successfully authenticated the user and authorized the SIP server
+	to proceed with the SIP request.
+
+	Otherwise, the Diameter server MUST set the Result-Code AVP value to
+	DIAMETER_UNABLE_TO_COMPLY, and it MUST NOT include any
+	SIP-Auth-Data-Item AVP.
+
+	The Message Format of the MAA command is as follows:
+
+	<MAA> ::= < Diameter Header: 286, PXY >
+	< Session-Id >
+	{ Auth-Application-Id }
+	{ Result-Code }
+	{ Auth-Session-State }
+	{ Origin-Host }
+	{ Origin-Realm }
+	[ User-Name ]
+	[ SIP-AOR ]
+	[ SIP-Number-Auth-Items ]
+	* [ SIP-Auth-Data-Item ]
+	[ Authorization-Lifetime ]
+	[ Auth-Grace-Period ]
+	[ Redirect-Host ]
+	[ Redirect-Host-Usage ]
+	[ Redirect-Max-Cache-Time ]
+	* [ Proxy-Info ]
+	* [ Route-Record ]
+	* [ AVP ]
+
+	*/
+      struct dict_object * cmd;
+      struct dict_cmd_data data = { 
+	286, 					/* Code */
+	"Multimedia-Auth-Answer", 		/* Name */
+	CMD_FLAG_REQUEST | CMD_FLAG_PROXIABLE | CMD_FLAG_ERROR, 	/* Fixed flags */
+	CMD_FLAG_PROXIABLE 						/* Fixed flag values */
+      };
+      struct local_rules_definition rules[] = 
+	{ 	 {  "Session-Id", 		RULE_FIXED_HEAD, -1, 1 }
+		 ,{  "Auth-Application-Id", 	RULE_REQUIRED,   -1, 1 }
+		 ,{  "Result-Code", 		RULE_REQUIRED,   -1, 1 }
+		 ,{  "Auth-Session-State", 	RULE_REQUIRED,   -1, 1 }
+		 ,{  "Origin-Host", 		RULE_REQUIRED,   -1, 1 }
+		 ,{  "Origin-Realm", 		RULE_REQUIRED,   -1, 1 }
+		 ,{  "User-Name", 		RULE_OPTIONAL,   -1, 1 }
+		 ,{  "SIP-AOR", 			RULE_OPTIONAL,   -1, 1 }
+		 ,{  "SIP-Number-Auth-Items", 	RULE_OPTIONAL,   -1, 1 }
+		 ,{  "SIP-Auth-Data-Item", 	RULE_OPTIONAL,   -1, -1 }
+		 ,{  "Authorization-Lifetime", 	RULE_OPTIONAL,   -1, 1 }
+		 ,{  "Auth-Grace-Period", 	RULE_OPTIONAL,   -1, 1 }
+		 ,{  "Redirect-Host", 		RULE_OPTIONAL,   -1, 1 }
+		 ,{  "Redirect-Host-Usage", 	RULE_OPTIONAL,   -1, 1 }
+		 ,{  "Redirect-Max-Cache-Time", 	RULE_OPTIONAL,   -1, 1 }
+		 ,{  "Proxy-Info", 		RULE_OPTIONAL,   -1, -1 }
+		 ,{  "Route-Record", 		RULE_OPTIONAL,   -1, -1 }
+
+	};
+			
+      CHECK_dict_new( DICT_COMMAND, &data , cxdx_dict, &cmd);
+      PARSE_loc_rules( rules, cmd, AVP_BY_NAME );
+    }
+    /* Server-Assignment-Request (SAR) Command */
+    {
+      /*
+			
+	The Server-Assignment-Request (SAR) command is indicated by the
+	Command-Code set to 284 and the Command Flags' 'R' bit set.  The
+	Diameter client in a SIP server sends this command to the Diameter
+	server to indicate the completion of the authentication process and
+	to request that the Diameter server store the URI of the SIP server
+	that is currently serving the user.  The main functions of the
+	Diameter SAR command are to inform the Diameter server of the URI of
+	the SIP server allocated to the user, and to store or clear it from
+	the Diameter server.  Additionally, the Diameter client can request
+	to download the user profile or part of it.
+
+	During the registration procedure, a SIP server becomes assigned to
+	the user.  The Diameter client in the assigned SIP server MUST
+	include its own URI in the SIP-Server-URI AVP of the
+	Server-Assignment-Request (SAR) Diameter message and send it to the
+	Diameter server.  The Diameter server then becomes aware of the
+	allocation of the SIP server to the user name and the server's URI.
+
+	The Diameter client in the SIP server MAY send a Diameter SAR message
+	because of other reasons.  These reasons are identified in the
+	SIP-Server-Assignment-Type AVP (Section 9.4) value.  For instance, a
+	Diameter client in a SIP server may contact the Diameter server to
+	request deregistration of a user, to inform the Diameter server of an
+	authentication failure, or just to download the user profile.  For a
+	complete description of all the SIP-Server-Assignment-Type AVP
+	values, see Section 9.4.
+
+	Typically the reception of a SIP REGISTER request in a SIP server
+	will trigger the Diameter client in the SIP server to send the
+	Diameter SAR message.  However, if a SIP server is receiving other
+	SIP request, such as INVITE, and the SIP server does not have the
+	user profile, the Diameter client in the SIP server may send the
+	Diameter SAR message to the Diameter server in order to download the
+	user profile and make the Diameter server aware of the SIP server
+	assigned to the user.
+	The user profile is an important piece of information that dictates
+	the behavior of the SIP server when triggering or providing services
+	for the user.  Typically the user profile is divided into:
+
+	o  Services to be rendered to the user when the user is registered
+	and initiates a SIP request.
+
+	o  Services to be rendered to the user when the user is registered
+	and a SIP request destined to that user arrives to the SIP proxy.
+
+	o  Services to be rendered to the user when the user is not
+	registered and a SIP request destined to that user arrives to the
+	SIP proxy.
+
+	The SIP-Server-Assignment-Type AVP indicates the reason why the
+	Diameter client (SIP server) contacted the Diameter server.  If the
+	Diameter client sets the SIP-Server-Assignment-Type AVP value to
+	REGISTRATION, RE_REGISTRATION, UNREGISTERED_USER, NO_ASSIGNMENT,
+	AUTHENTICATION_FAILURE or AUTHENTICATION_TIMEOUT, the Diameter client
+	MUST include exactly one SIP-AOR AVP in the Diameter SAR message.
+
+	The SAR message MAY contain zero or more SIP-Supported-User-Data-Type
+	AVPs.  Each of them contains a type of user data understood by the
+	SIP server.  This allows the Diameter client to provide an indication
+	to the Diameter server of the different format of user data
+	understood by the SIP server.  The Diameter server uses this
+	information to select one or more SIP-User-Data AVPs that will be
+	included in the SAA message.
+
+	The Message Format of the SAR command is as follows:
+
+	<SAR> ::= < Diameter Header: 284, REQ, PXY >
+	< Session-Id >
+	{ Auth-Application-Id }
+	{ Auth-Session-State }
+	{ Origin-Host }
+	{ Origin-Realm }
+	{ Destination-Realm }
+	{ SIP-Server-Assignment-Type }
+	{ SIP-User-Data-Already-Available }
+	[ Destination-Host ]
+	[ User-Name ]
+	[ SIP-Server-URI ]
+	* [ SIP-Supported-User-Data-Type ]
+	* [ SIP-AOR ]
+	* [ Proxy-Info ]
+	* [ Route-Record ]
+	* [ AVP ]
+	*/
+      struct dict_object * cmd;
+      struct dict_cmd_data data = { 
+	284, 					/* Code */
+	"Server-Assignment-Request", 		/* Name */
+	CMD_FLAG_REQUEST | CMD_FLAG_PROXIABLE | CMD_FLAG_ERROR, 	/* Fixed flags */
+	CMD_FLAG_REQUEST | CMD_FLAG_PROXIABLE 						/* Fixed flag values */
+      };
+      struct local_rules_definition rules[] = 
+	{ 	 {  "Session-Id", 			RULE_FIXED_HEAD, -1, 1 }
+		 ,{  "Auth-Application-Id", 		RULE_REQUIRED,   -1, 1 }
+		 ,{  "Auth-Session-State", 		RULE_REQUIRED,   -1, 1 }
+		 ,{  "Origin-Host", 			RULE_REQUIRED,   -1, 1 }
+		 ,{  "Origin-Realm", 			RULE_REQUIRED,   -1, 1 }
+		 ,{  "Destination-Realm",		RULE_REQUIRED,   -1, 1 }
+		 ,{  "SIP-Server-Assignment-Type", 	RULE_REQUIRED,   -1, 1 }
+		 ,{  "SIP-User-Data-Already-Available", 	RULE_REQUIRED,   -1, 1 }
+		 ,{  "Destination-Host", 		RULE_OPTIONAL,   -1, 1 }
+		 ,{  "User-Name", 			RULE_OPTIONAL,   -1, 1 }
+		 ,{  "SIP-Server-URI", 			RULE_OPTIONAL,   -1, 1 }
+		 ,{  "SIP-Supported-User-Data-Type", 	RULE_OPTIONAL,   -1, -1 }
+		 ,{  "SIP-AOR", 				RULE_OPTIONAL,   -1, -1 }
+		 ,{  "Proxy-Info", 			RULE_OPTIONAL,   -1, -1 }
+		 ,{  "Route-Record", 			RULE_OPTIONAL,   -1, -1 }
+
+	};
+			
+      CHECK_dict_new( DICT_COMMAND, &data , cxdx_dict, &cmd);
+      PARSE_loc_rules( rules, cmd, AVP_BY_NAME );
+    }
+    /* Server-Assignment-Answer (SAA) Command */
+    {
+      /*
+			
+	The Server-Assignment-Answer (SAA) is indicated by the Command-Code
+	set to 284 and the Command Flags' 'R' bit cleared.  The Diameter
+	server sends this command in response to a previously received
+	Diameter Server-Assignment-Request (SAR) command.  The response may
+	include the user profile or part of it, if requested.
+
+	In addition to the values already defined in RFC 3588 [RFC3588], the
+	Result-Code AVP may contain one of the values defined in
+	Section 10.1.
+
+	The Result-Code AVP value in the Diameter SAA message may indicate a
+	success or an error in the execution of the Diameter SAR command.  If
+	Result-Code AVP value in the Diameter SAA message does not contain an
+	error code, the SAA message MAY include one or more SIP-User-Data
+	AVPs that typically contain the profile of the user, indicating
+	services that the SIP server can provide to that user.
+
+	The Diameter server MAY include one or more
+	SIP-Supported-User-Data-Type AVPs, each one identifying a type of
+	user data format supported in the Diameter server.  If there is not a
+	common supported user data type between the Diameter client and the
+	Diameter server, the Diameter server SHOULD declare its list of
+	supported user data types by including one or more
+	SIP-Supported-User-Data-Type AVPs in a Diameter SAA message.  This
+	indication is merely for debugging reasons, since there is not a
+	fallback mechanism that allows the Diameter client to retrieve the
+	profile in a supported format.
+
+	If the Diameter server requires a User-Name AVP value to process the
+	Diameter SAR request, but the Diameter SAR message did not contain a
+	User-Name AVP value, the Diameter server MUST set the Result-Code AVP
+	value to DIAMETER_USER_NAME_REQUIRED (see Section 10.1.2) and return
+	it in a Diameter SAA message.  Upon reception of this Diameter SAA
+	message with the Result-Code AVP value set to
+	DIAMETER_USER_NAME_REQUIRED, the SIP server typically requests
+	authentication by generating a SIP 401 (Unauthorized) or SIP 407
+	(Proxy Authentication Required) response back to the originator.
+
+	If the User-Name AVP is included in the Diameter SAR message, upon
+	reception of the Diameter SAR message, the Diameter server MUST
+	verify the existence of the user in the realm, i.e., the User-Name
+	AVP value is a valid user within that realm.  If the Diameter server
+	does not recognize the user name received in the User-Name AVP, the
+	Diameter server MUST build a Diameter Server-Assignment-Answer (SAA)
+	message and MUST set the Result-Code AVP to
+	DIAMETER_ERROR_USER_UNKNOWN.
+	Then the Diameter server MUST authorize that User-Name AVP value is a
+	valid authentication name for the SIP or SIPS URI included in the
+	SIP-AOR AVP of the Diameter SAR message.  If this authorization
+	fails, the Diameter server must set the Result-Code AVP to
+	DIAMETER_ERROR_IDENTITIES_DONT_MATCH and send it in a Diameter
+	Server-Assignment-Answer (SAA) message.
+
+	After successful execution of the Diameter SAR command, the Diameter
+	server MUST clear the "authentication pending" flag and SHOULD move
+	the temporarily stored SIP server URI to permanent storage.
+
+	The actions of the Diameter server upon reception of the Diameter SAR
+	message depend on the value of the SIP-Server-Assignment-Type:
+
+	o  If the SIP-Server-Assignment-Type AVP value in the Diameter SAR
+	message is set to REGISTRATION or RE_REGISTRATION, the Diameter
+	server SHOULD verify that there is only one SIP-AOR AVP.
+	Otherwise, the Diameter server MUST answer with a Diameter SAA
+	message with the Result-Code AVP value set to
+	DIAMETER_AVP_OCCURS_TOO_MANY_TIMES and MUST NOT include any
+	SIP-User-Data AVP.  If there is only one SIP-AOR AVP and if the
+	SIP-User-Data-Already-Available AVP value is set to
+	USER_DATA_NOT_AVAILABLE, then the Diameter server SHOULD include
+	one or more user profile data with the SIP or SIPS URI (SIP-AOR
+	AVP) and all other SIP identities associated with that AVP in the
+	SIP-User-Data AVP value of the Diameter SAA message.  On selecting
+	the type of user data, the Diameter server SHOULD take into
+	account the supported formats at the SIP server
+	(SIP-Supported-User-Data-Type AVP in the SAR message) and the
+	local policy.  Additionally, the Diameter server MUST set the
+	Result-Code AVP value to DIAMETER_SUCCESS in the Diameter SAA
+	message.  The Diameter server considers the SIP AOR authenticated
+	and registered.
+
+	o  If the SIP-Server-Assignment-Type AVP value in the Diameter SAR
+	message is set to UNREGISTERED_USER, then the Diameter server MUST
+	store the SIP server address included in the SIP-Server-URI AVP
+	value.  The Diameter server will return the SIP server address in
+	Diameter Location-Info-Answer (LIA) messages.  If the
+	SIP-User-Data-Already-Available AVP value is set to
+	USER_DATA_NOT_AVAILABLE, then the Diameter server SHOULD include
+	one or more user profile data associated with the SIP or SIPS URI
+	(SIP-AOR AVP) and associated identities in the SIP-User-Data AVP
+	value of the Diameter SAA message.  On selecting the type of user
+	data, the Diameter server SHOULD take into account the supported
+	formats at the SIP server (SIP-Supported-User-Data-Type AVP in the
+	SAR message) and the local policy.  The Diameter server MUST set
+	the Result-Code AVP value to DIAMETER_SUCCESS.  The Diameter
+	server considers the SIP AOR UNREGISTERED, but with a SIP server
+	allocated to trigger and provide services for unregistered users.
+	Note that in case of UNREGISTERED_USER (SIP-Server-Assignment-Type
+	AVP), the Diameter server MUST verify that there is only one
+	SIP-AOR AVP.  Otherwise, the Diameter server MUST answer the
+	Diameter SAR message with a Diameter SAA message, and it MUST set
+	the Result-Code AVP value to DIAMETER_AVP_OCCURS_TOO_MANY_TIMES
+	and MUST NOT include any SIP-User-Data AVP.
+	If the User-Name AVP was not present in the Diameter SAR message
+	and the SIP-AOR is not known for the Diameter server, the Diameter
+	server MUST NOT include a User-Name AVP in the Diameter SAA
+	message and MUST set the Result-Code AVP value to
+	DIAMETER_ERROR_USER_UNKNOWN.
+
+	o  If the SIP-Server-Assignment-Type AVP value in the Diameter SAR
+	message is set to TIMEOUT_DEREGISTRATION, USER_DEREGISTRATION,
+	DEREGISTRATION_TOO_MUCH_DATA, or ADMINISTRATIVE_DEREGISTRATION,
+	the Diameter server MUST clear the SIP server address associated
+	with all SIP AORs indicated in each of the SIP-AOR AVP values
+	included in the Diameter SAR message.  The Diameter server
+	considers all of these SIP AORs as not registered.  The Diameter
+	server MUST set the Result-Code AVP value to DIAMETER_SUCCESS in
+	the Diameter SAA message.
+
+	o  If the SIP-Server-Assignment-Type AVP value in the Diameter SAR
+	message is set to TIMEOUT_DEREGISTRATION_STORE_SERVER_NAME or
+	USER_DEREGISTRATION_STORE_SERVER_NAME, the Diameter server MAY
+	keep the SIP server address associated with the SIP AORs included
+	in the SIP-AOR AVP values of the Diameter SAR message, even though
+	the SIP AORs become unregistered.  This feature allows a SIP
+	server to request that the Diameter server remain an assigned SIP
+	server for those SIP AORs (SIP-AOR AVP values) allocated to the
+	same user name, and avoid SIP server assignment.  The Diameter
+	server MUST consider all these SIP AORs as not registered.  If the
+	Diameter server honors the request of the Diameter client (SIP
+	server) to remain as an allocated SIP server, then the Diameter
+	server MUST keep the SIP server assigned to those SIP AORs
+	allocated to the username and MUST set the Result-Code AVP value
+	to DIAMETER_SUCCESS in the Diameter SAA message.  Otherwise, when
+	the Diameter server does not honor the request of the Diameter
+	client (SIP server) to remain as an allocated SIP server, the
+	Diameter server MUST clear the SIP server name assigned to those
+	SIP AORs and it MUST set the Result-Code AVP value to
+	DIAMETER_SUCCESS_SERVER_NAME_NOT_STORED in the Diameter SAA
+	message.
+	o  If the SIP-Server-Assignment-Type AVP value in the Diameter SAR
+	message is set to NO_ASSIGNMENT, the Diameter server SHOULD first
+	verify that the SIP-Server-URI AVP value in the Diameter SAR
+	message is the same URI as the one assigned to the SIP-AOR AVP
+	value.  If they differ, then the Diameter server MUST set the
+	Result-Code AVP value to DIAMETER_UNABLE_TO_COMPLY in the Diameter
+	SAA message.  Otherwise, if the SIP-User-Data-Already-Available
+	AVP value is set to USER_DATA_NOT_AVAILABLE, then the Diameter
+	server SHOULD include the user profile data with the SIP or SIPS
+	URI (SIP-AOR AVP) and all other SIP identities associated with
+	that AVP in the SIP-User-Data AVP value of the Diameter SAA
+	message.  On selecting the type of user data, the Diameter server
+	SHOULD take into account the supported formats at the SIP server
+	(SIP-Supported-User-Data-Type AVP in the SAR message) and the
+	local policy.
+
+	o  If the SIP-Server-Assignment-Type AVP value in the Diameter SAR
+	message is set to AUTHENTICATION_FAILURE or
+	AUTHENTICATION_TIMEOUT, the Diameter server MUST verify that there
+	is exactly one SIP-AOR AVP in the Diameter SAR message.  If the
+	number of occurrences of the SIP-AOR AVP is not exactly one, the
+	Diameter server MUST set the Result-Code AVP value to
+	DIAMETER_AVP_OCCURS_TOO_MANY_TIMES in the Diameter SAA message,
+	and SHOULD not take further actions.  If there is exactly one
+	SIP-AOR AVP in the Diameter SAR message, the Diameter server MUST
+	clear the address of the SIP server assigned to the SIP AOR
+	allocated to the user name, and the Diameter server MUST set the
+	Result-Code AVP value to DIAMETER_SUCCESS in the Diameter SAA
+	message.  The Diameter server MUST consider the SIP AOR as not
+	registered.
+
+	The Message Format of the SAA command is as follows:
+
+	<SAA> ::= < Diameter Header: 284, PXY >
+	< Session-Id >
+	{ Auth-Application-Id }
+	{ Result-Code }
+	{ Auth-Session-State }
+	{ Origin-Host }
+	{ Origin-Realm }
+	* [ SIP-User-Data ]
+	[ SIP-Accounting-Information ]
+	* [ SIP-Supported-User-Data-Type ]
+	[ User-Name ]
+	[ Auth-Grace-Period ]
+	[ Authorization-Lifetime ]
+	[ Redirect-Host ]
+	[ Redirect-Host-Usage ]
+	[ Redirect-Max-Cache-Time ]
+	* [ Proxy-Info ]
+	* [ Route-Record ]
+	* [ AVP ]
+
+
+
+
+	*/
+      struct dict_object * cmd;
+      struct dict_cmd_data data = { 
+	284, 					/* Code */
+	"Server-Assignment-Answer", 		/* Name */
+	CMD_FLAG_REQUEST | CMD_FLAG_PROXIABLE | CMD_FLAG_ERROR, 	/* Fixed flags */
+	CMD_FLAG_PROXIABLE 						/* Fixed flag values */
+      };
+      struct local_rules_definition rules[] = 
+	{ 	 {  "Session-Id", 			RULE_FIXED_HEAD, -1, 1 }
+		 ,{  "Auth-Application-Id", 		RULE_REQUIRED,   -1, 1 }
+		 ,{  "Result-Code", 			RULE_REQUIRED,   -1, 1 }
+		 ,{  "Auth-Session-State", 		RULE_REQUIRED,   -1, 1 }
+		 ,{  "Origin-Host", 			RULE_REQUIRED,   -1, 1 }
+		 ,{  "Origin-Realm", 			RULE_REQUIRED,   -1, 1 }
+		 ,{  "SIP-User-Data",			RULE_OPTIONAL,   -1, -1 }
+		 ,{  "SIP-Accounting-Information", 	RULE_OPTIONAL,   -1, 1 }
+		 ,{  "SIP-Supported-User-Data-Type", 	RULE_OPTIONAL,   -1, -1 }
+		 ,{  "User-Name", 			RULE_OPTIONAL,   -1, 1 }
+		 ,{  "Auth-Grace-Period", 		RULE_OPTIONAL,   -1, 1 }
+		 ,{  "Authorization-Lifetime", 		RULE_OPTIONAL,   -1, 1 }
+		 ,{  "Redirect-Host", 			RULE_OPTIONAL,   -1, 1 }
+		 ,{  "Redirect-Host-Usage", 		RULE_OPTIONAL,   -1, 1 }
+		 ,{  "Redirect-Max-Cache-Time", 		RULE_OPTIONAL,   -1, 1 }
+		 ,{  "Proxy-Info", 			RULE_OPTIONAL,   -1, -1 }
+		 ,{  "Route-Record", 			RULE_OPTIONAL,   -1, -1 }
+
+	};
+			
+      CHECK_dict_new( DICT_COMMAND, &data , cxdx_dict, &cmd);
+      PARSE_loc_rules( rules, cmd, AVP_BY_NAME );
+    }
+    /* Location-Info-Request (LIR) Command */
+    {
+      /*
+			
+	The Location-Info-Request (LIR) is indicated by the Command-Code set
+	to 285 and the Command Flags' 'R' bit set.  The Diameter client in a
+	SIP server sends this command to the Diameter server to request
+	routing information, e.g., the URI of the SIP server assigned to the
+	SIP-AOR AVP value allocated to the users.
+
+	The Message Format of the LIR command is as follows:
+
+	<LIR> ::= < Diameter Header: 285, REQ, PXY >
+	< Session-Id >
+	{ Auth-Application-Id }
+	{ Auth-Session-State }
+	{ Origin-Host }
+	{ Origin-Realm }
+	{ Destination-Realm }
+	{ SIP-AOR }
+	[ Destination-Host ]
+	* [ Proxy-Info ]
+	* [ Route-Record ]
+	* [ AVP ]
+	*/
+      struct dict_object * cmd;
+      struct dict_cmd_data data = { 
+	285, 					/* Code */
+	"Location-Info-Request", 		/* Name */
+	CMD_FLAG_REQUEST | CMD_FLAG_PROXIABLE | CMD_FLAG_ERROR, 	/* Fixed flags */
+	CMD_FLAG_REQUEST | CMD_FLAG_PROXIABLE 						/* Fixed flag values */
+      };
+      struct local_rules_definition rules[] = 
+	{ 	 {  "Session-Id", 		RULE_FIXED_HEAD, -1, 1 }
+		 ,{  "Auth-Application-Id", 	RULE_REQUIRED,   -1, 1 }
+		 ,{  "Auth-Session-State", 	RULE_REQUIRED,   -1, 1 }
+		 ,{  "Origin-Host", 		RULE_REQUIRED,   -1, 1 }
+		 ,{  "Origin-Realm", 		RULE_REQUIRED,   -1, 1 }
+		 ,{  "Destination-Realm",	RULE_REQUIRED,   -1, 1 }
+		 ,{  "SIP-AOR", 			RULE_REQUIRED,   -1, 1 }
+		 ,{  "Destination-Host", 	RULE_OPTIONAL,   -1, 1 }
+		 ,{  "Proxy-Info", 		RULE_OPTIONAL,   -1, -1 }
+		 ,{  "Route-Record", 		RULE_OPTIONAL,   -1, -1 }
+
+	};
+			
+      CHECK_dict_new( DICT_COMMAND, &data , cxdx_dict, &cmd);
+      PARSE_loc_rules( rules, cmd, AVP_BY_NAME );
+    }
+    /* Location-Info-Answer (LIA) Command */
+    {
+      /*
+	The Location-Info-Answer (LIA) is indicated by the Command-Code set
+	to 285 and the Command Flags' 'R' bit cleared.  The Diameter server
+	sends this command in response to a previously received Diameter
+	Location-Info-Request (LIR) command.
+
+	In addition to the values already defined in RFC 3588 [RFC3588], the
+	Result-Code AVP may contain one of the values defined in
+	Section 10.1.  When the Diameter server finds an error in processing
+	the Diameter LIR message, the Diameter server MUST stop the process
+	of the message and answer with a Diameter LIA message that includes
+	the appropriate error code in the Result-Code AVP value.  When there
+	is no error, the Diameter server MUST set the Result-Code AVP value
+	to DIAMETER_SUCCESS in the Diameter LIA message.
+
+	One of the errors that the Diameter server may find is that the
+	SIP-AOR AVP value is not a valid user in the realm.  In such cases,
+	the Diameter server MUST set the Result-Code AVP value to
+	DIAMETER_ERROR_USER_UNKNOWN and return it in a Diameter LIA message.
+
+	If the Diameter server cannot process the Diameter LIR command, e.g.,
+	due to a database error, the Diameter server MUST set the Result-Code
+	AVP value to DIAMETER_UNABLE_TO_COMPLY and return it in a Diameter
+	LIA message.  The Diameter server MUST NOT include any SIP-Server-URI
+	or SIP-Server-Capabilities AVP in the Diameter LIA message.
+
+	The Diameter server may or may not be aware of a SIP server assigned
+	to the SIP-AOR AVP value included in the Diameter LIR message.  If
+	the Diameter server is aware of a SIP server allocated to that
+	particular user, the Diameter server MUST include the URI of such SIP
+	server in the SIP-Server-URI AVP and return it in a Diameter LIA
+	message.  This is typically the situation when the user is either
+	registered, or unregistered but a SIP server is still assigned to the
+	user.
+
+	When the Diameter server is not aware of a SIP server allocated to
+	the user (typically the case when the user unregistered), the
+	Result-Code AVP value in the Diameter LIA message depends on whether
+	the Diameter server is aware that the user has services defined for
+	unregistered users:
+
+	o  Those users who have services defined for unregistered users may
+	require the allocation of a SIP server to trigger and perhaps
+	execute those services.  Therefore, when the Diameter server is
+	not aware of an assigned SIP server, but the user has services
+	defined for unregistered users, the Diameter server MUST set the
+	Result-Code AVP value to DIAMETER_UNREGISTERED_SERVICE and return
+	it in a Diameter LIA message.  The Diameter server MAY also
+	include a SIP-Server-Capabilities AVP to facilitate the SIP server
+	(Diameter client) with the selection of an appropriate SIP server
+	with the required capabilities.  Absence of the SIP-Server-
+	Capabilities AVP indicates to the SIP server (Diameter client)
+	that any SIP server is suitable to be allocated for the user.
+
+	o  Those users who do not have service defined for unregistered users
+	do not require further processing.  The Diameter server MUST set
+	the Result-Code AVP value to
+	DIAMETER_ERROR_IDENTITY_NOT_REGISTERED and return it to the
+	Diameter client in a Diameter LIA message.  The SIP server
+	(Diameter client) may return the appropriate SIP response (e.g.,
+	480 (Temporarily unavailable)) to the original SIP request.
+
+	The Message Format of the LIA command is as follows:
+
+	<LIA> ::= < Diameter Header: 285, PXY >
+	< Session-Id >
+	{ Auth-Application-Id }
+	{ Result-Code }
+	{ Auth-Session-State }
+	{ Origin-Host }
+	{ Origin-Realm }
+	[ SIP-Server-URI ]
+	[ SIP-Server-Capabilities ]
+	[ Auth-Grace-Period ]
+	[ Authorization-Lifetime ]
+	[ Redirect-Host ]
+	[ Redirect-Host-Usage ]
+	[ Redirect-Max-Cache-Time ]
+	* [ Proxy-Info ]
+	* [ Route-Record ]
+	* [ AVP ]
+	*/
+      struct dict_object * cmd;
+      struct dict_cmd_data data = { 
+	285, 					/* Code */
+	"Location-Info-Answer", 		/* Name */
+	CMD_FLAG_REQUEST | CMD_FLAG_PROXIABLE | CMD_FLAG_ERROR, 	/* Fixed flags */
+	CMD_FLAG_PROXIABLE 						/* Fixed flag values */
+      };
+      struct local_rules_definition rules[] = 
+	{ 	 {  "Session-Id", 		RULE_FIXED_HEAD, -1, 1 }
+		 ,{  "Auth-Application-Id", 	RULE_REQUIRED,   -1, 1 }
+		 ,{  "Result-Code", 		RULE_REQUIRED,   -1, 1 }
+		 ,{  "Auth-Session-State", 	RULE_REQUIRED,   -1, 1 }
+		 ,{  "Origin-Host", 		RULE_REQUIRED,   -1, 1 }
+		 ,{  "Origin-Realm", 		RULE_REQUIRED,   -1, 1 }
+		 ,{  "SIP-Server-URI",		RULE_OPTIONAL,   -1, 1 }
+		 ,{  "SIP-Server-Capabilities", 	RULE_OPTIONAL,   -1, 1 }
+		 ,{  "Auth-Grace-Period", 	RULE_OPTIONAL,   -1, 1 }
+		 ,{  "Authorization-Lifetime", 	RULE_OPTIONAL,   -1, 1 }
+		 ,{  "Redirect-Host", 		RULE_OPTIONAL,   -1, 1 }
+		 ,{  "Redirect-Host-Usage", 	RULE_OPTIONAL,   -1, 1 }
+		 ,{  "Redirect-Max-Cache-Time", 	RULE_OPTIONAL,   -1, 1 }
+		 ,{  "Proxy-Info", 		RULE_OPTIONAL,   -1, -1 }
+		 ,{  "Route-Record", 		RULE_OPTIONAL,   -1, -1 }
+
+	};
+			
+      CHECK_dict_new( DICT_COMMAND, &data , cxdx_dict, &cmd);
+      PARSE_loc_rules( rules, cmd, AVP_BY_NAME );
+    }
+    /* Registration-Termination-Request (RTR) Command */
+    {
+      /*
+	The Registration-Termination-Request (RTR) command is indicated by
+	the Command-Code set to 287 and the Command Flags' 'R' bit set.  The
+	Diameter server sends this command to the Diameter client in a SIP
+	server to indicate to the SIP server that one or more SIP AORs have
+	to be deregistered.  The command allows an operator to
+	administratively cancel the registration of a user from a centralized
+	Diameter server.
+
+	The Diameter server has the capability to initiate the deregistration
+	of a user and inform the SIP server by means of the Diameter RTR
+	command.  The Diameter server can decide whether only one SIP AOR is
+	going to be deregistered, a list of SIP AORs, or all the SIP AORs
+	allocated to the user.
+
+	The absence of a SIP-AOR AVP in the Diameter RTR message indicates
+	that all the SIP AORs allocated to the user identified by the
+	User-Name AVP are being deregistered.
+
+	The Diameter server MUST include a SIP-Deregistration-Reason AVP
+	value to indicate the reason for the deregistration.
+
+	The Message Format of the RTR command is as follows:
+
+	<RTR> ::= < Diameter Header: 287, REQ, PXY >
+	< Session-Id >
+	{ Auth-Application-Id }
+	{ Auth-Session-State }
+	{ Origin-Host }
+	{ Origin-Realm }
+	{ Destination-Host }
+	{ SIP-Deregistration-Reason }
+	[ Destination-Realm ]
+	[ User-Name ]
+	* [ SIP-AOR ]
+	* [ Proxy-Info ]
+	* [ Route-Record ]
+	* [ AVP ]
+
+	*/
+
+      struct dict_object * cmd;
+      struct dict_cmd_data data = 
+	{ 
+	  287, 					/* Code */
+	  "Registration-Termination-Request", 		/* Name */
+	  CMD_FLAG_REQUEST | CMD_FLAG_PROXIABLE | CMD_FLAG_ERROR, 	/* Fixed flags */
+	  CMD_FLAG_REQUEST | CMD_FLAG_PROXIABLE 			/* Fixed flag values */
+	};
+
+      struct local_rules_definition rules[] = 
+	{  
+	  { "Session-Id",               RULE_FIXED_HEAD, -1,  1 },
+	  { "Auth-Application-Id", 	RULE_REQUIRED,   -1,  1 },
+	  { "Auth-Session-State", 	RULE_REQUIRED,   -1,  1 },
+	  { "Origin-Host", 		RULE_REQUIRED,   -1,  1 },
+	  { "Origin-Realm", 		RULE_REQUIRED,   -1,  1 },
+	  { "Destination-Host", 	RULE_REQUIRED,   -1,  1 },
+	  { "SIP-Deregistration-Reason",RULE_REQUIRED,   -1,  1 },	
+	  { "Destination-Realm",	RULE_OPTIONAL,   -1,  1 },
+	  { "User-Name", 		RULE_OPTIONAL,   -1,  1 },
+	  { "SIP-AOR", 		        RULE_REQUIRED,   -1, -1 },
+	  { "Proxy-Info", 		RULE_OPTIONAL,   -1, -1 },
+	  { "Route-Record", 		RULE_OPTIONAL,   -1, -1 }
+	};
+      
+      CHECK_dict_new( DICT_COMMAND, &data , cxdx_dict, &cmd);
+      PARSE_loc_rules( rules, cmd, AVP_BY_NAME );
+    }
+    /* Registration-Termination-Answer (RTA) Command */
+    {
+      /*
+	The Registration-Termination-Answer (RTA) is indicated by the
+	Command-Code set to 287 and the Command Flags' 'R' bit cleared.  The
+	Diameter client sends this command in response to a previously
+	received Diameter Registration-Termination-Request (RTR) command.
+
+	In addition to the values already defined in RFC 3588 [RFC3588], the
+	Result-Code AVP may contain one of the values defined in
+	Section 10.1.
+
+	If the SIP server (Diameter client) requires a User-Name AVP value to
+	process the Diameter RTR request, but the Diameter RTR message did
+	not contain a User-Name AVP value, the Diameter client MUST set the
+	Result-Code AVP value to DIAMETER_USER_NAME_REQUIRED (see Section
+	10.1.2) and return it in a Diameter RTA message.
+
+	The SIP server (Diameter client) applies the administrative
+	deregistration to each of the URIs included in each of the SIP-AOR
+	AVP values, or, if there is no SIP-AOR AVP present in the Diameter
+	RTR request, to all the URIs allocated to the User-Name AVP value.
+
+	The value of the SIP-Deregistration-Reason AVP in the Diameter RTR
+	command has an effect on the actions performed at the SIP server
+	(Diameter client):
+
+	o  If the value is set to PERMANENT_TERMINATION, then the user has
+	terminated his/her registration to the realm.  If informing the
+	interested parties (e.g., subscribers to the "reg" event
+	[RFC3680]) about the administrative deregistration is supported
+	through SIP procedures, the SIP server (Diameter client) will do
+	so.  The Diameter Client in the SIP Server SHOULD NOT request a
+	new user registration.  The SIP server clears the registration
+	state of the deregistered AORs.
+
+	o  If the value is set to NEW_SIP_SERVER_ASSIGNED, the Diameter
+	server informs the SIP server (Diameter client) that a new SIP
+	server has been allocated to the user, due to some reason.  The
+	SIP server, if supported through SIP procedures, will inform the
+	interested parties (e.g., subscribers to the "reg" event
+	[RFC3680]) about the administrative deregistration at this SIP
+	server.  The Diameter client in the SIP server SHOULD NOT request
+	a new user registration.  The SIP server clears the registration
+	state of the deregistered SIP AORs.
+
+	o  If the value is set to SIP_SERVER_CHANGE, the Diameter server
+	informs the SIP server (Diameter client) that a new SIP server has
+	to be allocated to the user, e.g., due to user's capabilities
+	requiring a new SIP server, or not enough resources in the current
+	SIP server.  If informing the interested parties about the
+	administrative deregistration is supported through SIP procedures
+	(e.g., subscriptions to the "reg" event [RFC3680]), the SIP server
+	will do so.  The Diameter client in the SIP Server SHOULD NOT
+	request a new user registration.  The SIP server clears the
+	registration state of the deregistered SIP AORs.
+
+	o  If the value is set to REMOVE_SIP_SERVER, the Diameter server
+	informs the SIP server (Diameter client) that the SIP server will
+	no longer be bound in the Diameter server with that user.  The SIP
+	server can delete all data related to the user.
+
+	The Message Format of the RTA command is as follows:
+
+	<RTA> ::= < Diameter Header: 287, PXY >
+	< Session-Id >
+	{ Auth-Application-Id }
+	{ Result-Code }
+	{ Auth-Session-State }
+	{ Origin-Host }
+	{ Origin-Realm }
+	[ Authorization-Lifetime ]
+	[ Auth-Grace-Period ]
+	[ Redirect-Host ]
+	[ Redirect-Host-Usage ]
+	[ Redirect-Max-Cache-Time ]
+	* [ Proxy-Info ]
+	* [ Route-Record ]
+	* [ AVP ]
+
+	*/
+      struct dict_object * cmd;
+      struct dict_cmd_data data = { 
+	287, 					/* Code */
+	"Registration-Termination-Answer", 		/* Name */
+	CMD_FLAG_REQUEST | CMD_FLAG_PROXIABLE | CMD_FLAG_ERROR, 	/* Fixed flags */
+	CMD_FLAG_PROXIABLE 						/* Fixed flag values */
+      };
+      struct local_rules_definition rules[] = 
+	{ 	 {  "Session-Id", 		RULE_FIXED_HEAD, -1, 1 }
+		 ,{  "Auth-Application-Id", 	RULE_REQUIRED,   -1, 1 }
+		 ,{  "Result-Code", 		RULE_REQUIRED,   -1, 1 }
+		 ,{  "Auth-Session-State", 	RULE_REQUIRED,   -1, 1 }
+		 ,{  "Origin-Host", 		RULE_REQUIRED,   -1, 1 }
+		 ,{  "Origin-Realm", 		RULE_REQUIRED,   -1, 1 }
+		 ,{  "Authorization-Lifetime",	RULE_OPTIONAL,   -1, 1 }
+		 ,{  "Auth-Grace-Period", 	RULE_OPTIONAL,   -1, 1 }
+		 ,{  "Redirect-Host", 		RULE_OPTIONAL,   -1, 1 }
+		 ,{  "Redirect-Host-Usage", 	RULE_OPTIONAL,   -1, 1 }
+		 ,{  "Redirect-Max-Cache-Time", 	RULE_OPTIONAL,   -1, 1 }
+		 ,{  "Proxy-Info", 		RULE_OPTIONAL,   -1, -1 }
+		 ,{  "Route-Record", 		RULE_OPTIONAL,   -1, -1 }
+
+	};
+			
+      CHECK_dict_new( DICT_COMMAND, &data , cxdx_dict, &cmd);
+      PARSE_loc_rules( rules, cmd, AVP_BY_NAME );
+    }
+		
+    /* Push-Profile-Request (PPR) Command */
+    {
+      /*
+	The Push-Profile-Request (PPR) command is indicated by the
+	Command-Code set to 288 and the Command Flags' 'R' bit set.  The
+	Diameter server sends this command to the Diameter client in a SIP
+	server to update either the user profile of an already registered
+	user in that SIP server or the SIP accounting information.  This
+	allows an operator to modify the data of a user profile or the
+	accounting information and push it to the SIP server where the user
+	is registered.
+
+	Each user has a user profile associated with him/her and other
+	accounting information.  The profile or the accounting information
+	may change with time, e.g., due to addition of new services to the
+	user.  When the user profile or the accounting information changes,
+	the Diameter server sends a Diameter Push-Profile-Request (PPR)
+	command to the Diameter client in a SIP server, in order to start
+	applying those new services.
+
+	A PPR command MAY contain a SIP-Accounting-Information AVP that
+	updates the addresses of the accounting servers.  Changes in the
+	addresses of the accounting servers take effect immediately.  The
+	Diameter client SHOULD close any existing accounting session with the
+	existing server and start providing accounting information to the
+	newly acquired accounting server.
+
+	A PPR command MAY contain zero or more SIP-User-Data AVP values
+	containing the new user profile.  On selecting the type of user data,
+	the Diameter server SHOULD take into account the supported formats at
+	the SIP server (SIP-Supported-User-Data-Type AVP sent in a previous
+	SAR message) and the local policy.
+
+	The User-Name AVP indicates the user to whom the profile is
+	applicable.
+
+	The Message Format of the PPR command is as follows:
+
+	<PPR> ::= < Diameter Header: 288, REQ, PXY >
+	< Session-Id >
+	{ Auth-Application-Id }
+	{ Auth-Session-State }
+	{ Origin-Host }
+	{ Origin-Realm }
+	{ Destination-Realm }
+	{ User-Name }
+	* [ SIP-User-Data ]
+	[ SIP-Accounting-Information ]
+	[ Destination-Host ]
+	[ Authorization-Lifetime ]
+	[ Auth-Grace-Period ]
+	* [ Proxy-Info ]
+	* [ Route-Record ]
+	* [ AVP ]
+
+	*/
+      struct dict_object * cmd;
+      struct dict_cmd_data data = { 
+	288, 					/* Code */
+	"Push-Profile-Request", 		/* Name */
+	CMD_FLAG_REQUEST | CMD_FLAG_PROXIABLE | CMD_FLAG_ERROR, 	/* Fixed flags */
+	CMD_FLAG_REQUEST | CMD_FLAG_PROXIABLE 						/* Fixed flag values */
+      };
+      struct local_rules_definition rules[] = 
+	{ 	 {  "Session-Id", 			RULE_FIXED_HEAD, -1, 1 }
+		 ,{  "Auth-Application-Id", 		RULE_REQUIRED,   -1, 1 }
+		 ,{  "Auth-Session-State", 		RULE_REQUIRED,   -1, 1 }
+		 ,{  "Origin-Host", 			RULE_REQUIRED,   -1, 1 }
+		 ,{  "Origin-Realm", 			RULE_REQUIRED,   -1, 1 }
+		 ,{  "Destination-Realm",		RULE_REQUIRED,   -1, 1 }
+		 ,{  "User-Name", 			RULE_REQUIRED,   -1, 1 }
+		 ,{  "SIP-User-Data", 			RULE_OPTIONAL,   -1, -1 }
+		 ,{  "SIP-Accounting-Information", 	RULE_OPTIONAL,   -1, 1 }
+		 ,{  "Destination-Host", 		RULE_OPTIONAL,   -1, 1 }
+		 ,{  "Authorization-Lifetime", 		RULE_OPTIONAL,   -1, 1 }
+		 ,{  "Auth-Grace-Period", 		RULE_OPTIONAL,   -1, 1 }
+		 ,{  "Proxy-Info", 			RULE_OPTIONAL,   -1, -1 }
+		 ,{  "Route-Record", 			RULE_OPTIONAL,   -1, -1 }
+
+	};
+			
+      CHECK_dict_new( DICT_COMMAND, &data , cxdx_dict, &cmd);
+      PARSE_loc_rules( rules, cmd, AVP_BY_NAME );
+    }
+    /* Push-Profile-Answer (PPA) Command */
+    {
+      /*
+			
+			
+	The Push-Profile-Answer (PPA) is indicated by the Command-Code set to
+	288 and the Command Flags' 'R' bit cleared.  The Diameter client
+	sends this command in response to a previously received Diameter
+	Push-Profile-Request (PPR) command.
+
+	In addition to the values already defined in RFC 3588 [RFC3588], the
+	Result-Code AVP may contain one of the values defined in
+	Section 10.1.
+
+	If there is no error when processing the received Diameter PPR
+	message, the SIP server (Diameter client) MUST download the received
+	user profile from the SIP-User-Data AVP values in the Diameter PPR
+	message and store it associated with the user specified in the
+	User-Name AVP value.
+
+	If the SIP server does not recognize or does not support some of the
+	data transferred in the SIP-User-Data AVP values, the Diameter client
+	in the SIP server MUST return a Diameter PPA message that includes a
+	Result-Code AVP set to the value DIAMETER_ERROR_NOT_SUPPORTED_USER_DATA.
+
+	If the SIP server (Diameter client) receives a Diameter PPR message
+	with a User-Name AVP that is unknown, the Diameter client MUST set
+	the Result-Code AVP value to DIAMETER_ERROR_USER_UNKNOWN and MUST
+	return it to the Diameter server in a Diameter PPA message.
+
+	If the SIP server (Diameter client) receives in the
+	SIP-User-Data-Content AVP value (of the grouped SIP-User-Data AVP)
+	more data than it can accept, it MUST set the Result-Code AVP value
+	to DIAMETER_ERROR_TOO_MUCH_DATA and MUST return it to the Diameter
+	server in a Diameter PPA message.  The SIP server MUST NOT override
+	the existing user profile with the one received in the PPR message.
+
+	If the Diameter server receives the Result-Code AVP value set to
+	DIAMETER_ERROR_TOO_MUCH_DATA in a Diameter PPA message, it SHOULD
+	force a new re-registration of the user by sending to the Diameter
+	client a Diameter Registration-Termination-Request (RTR) with the
+	SIP-Deregistration-Reason AVP value set to SIP_SERVER_CHANGE.  This
+	will force a re-registration of the user and will trigger a selection
+	of a new SIP server.
+
+	If the Diameter client is not able to honor the command, for any
+	other reason, it MUST set the Result-Code AVP value to
+	DIAMETER_UNABLE_TO_COMPLY and it MUST return it in a Diameter PPA
+	message.
+
+	The Message Format of the PPA command is as follows:
+
+	<PPA> ::= < Diameter Header: 288, PXY >
+	< Session-Id >
+	{ Auth-Application-Id }
+	{ Result-Code }
+	{ Auth-Session-State }
+	{ Origin-Host }
+	{ Origin-Realm }
+	[ Redirect-Host ]
+	[ Redirect-Host-Usage ]
+	[ Redirect-Max-Cache-Time ]
+	* [ Proxy-Info ]
+	* [ Route-Record ]
+	* [ AVP ]
+
+
+
+	*/
+      struct dict_object * cmd;
+      struct dict_cmd_data data = { 
+	288, 					/* Code */
+	"Push-Profile-Answer", 		/* Name */
+	CMD_FLAG_REQUEST | CMD_FLAG_PROXIABLE | CMD_FLAG_ERROR, 	/* Fixed flags */
+	CMD_FLAG_PROXIABLE 						/* Fixed flag values */
+      };
+      struct local_rules_definition rules[] = 
+	{ 	 {  "Session-Id", 		RULE_FIXED_HEAD, -1, 1 }
+		 ,{  "Auth-Application-Id", 	RULE_REQUIRED,   -1, 1 }
+		 ,{  "Result-Code", 		RULE_REQUIRED,   -1, 1 }
+		 ,{  "Auth-Session-State", 	RULE_REQUIRED,   -1, 1 }
+		 ,{  "Origin-Host", 		RULE_REQUIRED,   -1, 1 }
+		 ,{  "Origin-Realm", 		RULE_REQUIRED,   -1, 1 }
+		 ,{  "Redirect-Host",		RULE_OPTIONAL,   -1, 1 }
+		 ,{  "Redirect-Host-Usage", 	RULE_OPTIONAL,   -1, 1 }
+		 ,{  "Redirect-Max-Cache-Time", 	RULE_OPTIONAL,   -1, 1 }
+		 ,{  "Proxy-Info", 		RULE_OPTIONAL,   -1, -1 }
+		 ,{  "Route-Record", 		RULE_OPTIONAL,   -1, -1 }
+
+	};
+			
+      CHECK_dict_new( DICT_COMMAND, &data , cxdx_dict, &cmd);
+      PARSE_loc_rules( rules, cmd, AVP_BY_NAME );
+    }
+
+#endif /* TODO - NRGJ */
+
+  }  /* end Command section */
+
+
+	
+  TRACE_DEBUG(INFO, "Extension 'Dictionary CxDx' initialized");
+  return 0;
+}
+
+
+EXTENSION_ENTRY("dict_cxdx", cxdx_dict_init);
+
diff --git a/contrib/CxDx/dict_cxdx.xml b/contrib/CxDx/dict_cxdx.xml
new file mode 100644
index 0000000..9956c21
--- /dev/null
+++ b/contrib/CxDx/dict_cxdx.xml
@@ -0,0 +1,407 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE dictionary SYSTEM "dictionary.dtd">
+
+
+<!--**************************************************************************************
+
+ === CpqD/DRC  -  Projeto ADRIMS  -  Mar/2011 ===
+ === Dicionario Dx/Cx ===
+ Baseado no "dict_sip" do FreeDiameter (www.freediameter.net) 
+                                                                      Norberto R Goes Jr
+**************************************************************************************-->
+
+
+<dictionary>
+
+  <!-- ******************************************************** -->
+  <!-- ********************* Vendors ************************** -->
+  <!-- ******************************************************** -->
+
+  <vendor id="13019" name="ETSI" />
+
+  <vendor id="10415" name="3GPP" />
+  
+  <!-- ******************************************************** -->
+  <!-- ***************** CxDx Application *********************-->
+  <!-- ******************************************************** -->
+
+  <application id="16777216" name="Diameter CxDx Application" 
+	       uri="http://www.cpqd.com.br">
+    
+    <!-- ******************************************************** -->
+    <!-- ******************** Commands ************************** -->
+    <!-- ******************************************************** -->
+ 
+    <command name="User-Authorization" code="300" >
+
+      <requestrules>
+        <fixed>
+	  <avprule name="Session-Id" minimum="1" maximum="1"/>
+	</fixed>
+	
+        <required>
+	  <avprule name="Vendor-Specific-Application-Id" maximum="1" />
+	  <avprule name="Auth-Session-State" maximum="1" />
+	  <avprule name="Origin-Host" maximum="1" />
+	  <avprule name="Origin-Realm" maximum="1" />
+	  <avprule name="Destination-Realm" maximum="1" />
+	  <avprule name="User-Name" maximum="1" />
+	  <avprule name="Public-Identity" maximum="1" />
+	  <avprule name="Visited-Network-Identifier" maximum="1" />
+	</required>
+	
+        <optional>
+	  <avprule name="Destination-Host" maximum="1"/>
+	  <avprule name="Supported-Features" />
+	  <avprule name="User-Authorization-Type" maximum="1"/>
+	  <avprule name="UAR-Flags" maximum="1" />
+	  <avprule name="AVP" />
+	  <avprule name="Proxy-Info" />
+	  <avprule name="Route-Record" />
+        </optional>
+      </requestrules>
+      
+      
+      <answerrules>
+        <fixed>
+	  <avprule name="Session-Id"  minimum="1" maximum="1"/>
+	</fixed>
+	
+        <required>
+	  <avprule name="Vendor-Specific-Application-Id" maximum="1" />
+	  <avprule name="Auth-Session-State" maximum="1" />
+	  <avprule name="Origin-Host" maximum="1" />
+	  <avprule name="Origin-Realm" maximum="1"/>
+	  
+	</required>
+	
+        <optional>
+	  <avprule name="Result-Code" maximum="1"/>
+	  <avprule name="Experimental-Result" maximum="1"/>
+	  <avprule name="Supported-Features" />
+	  <avprule name="Server-Name" maximum="1"/>
+	  <avprule name="Server-Capabilities" maximum="1"/>
+	  <avprule name="Wildcarded-IMPU" maximum="1"/>
+	  <avprule name="AVP" />
+	  <avprule name="Failed-AVP" />
+	  <avprule name="Proxy-Info" />
+	  <avprule name="Route-Record" />
+        </optional>
+	
+      </answerrules>
+      
+    </command>
+    
+
+
+    <command name="Server-Assignment" code="301" >
+
+      <requestrules>
+        <fixed>
+	  <avprule name="Session-Id" minimum="1" maximum="1"/>
+	</fixed>
+	
+        <required>
+	  <avprule name="Vendor-Specific-Application-Id" maximum="1" />
+	  <avprule name="Auth-Session-State" maximum="1" />
+	  <avprule name="Origin-Host" maximum="1" />
+	  <avprule name="Origin-Realm" maximum="1" />
+	  <avprule name="Destination-Realm" maximum="1" />
+	  <avprule name="Server-Name" maximum="1"/>
+	  <avprule name="Server-Assignment-Type" maximum="1" />
+	  <avprule name="User-Data-Already-Available" maximum="1" />
+	</required>
+	
+        <optional>
+	  <avprule name="Destination-Host" maximum="1"/>
+	  <avprule name="User-Name" maximum="1" />
+	  <avprule name="Supported-Features" />
+	  <avprule name="Public-Identity" />
+	  <avprule name="Wildcarded-PSI" maximum="1"/>
+	  <avprule name="Wildcarded-IMPU" maximum="1"/>
+	  <!-- avprule name="SCSCF-Restoration-Info" maximum="1"/> -->
+	  <!-- avprule name="Multiple-Registration-Indication" maximum="1"/> -->
+	  <!--avprule name="Session-Priority" maximum="1"/> -->
+	  <avprule name="AVP" />
+	  <avprule name="Proxy-Info" />
+	  <avprule name="Route-Record" />
+        </optional>
+      </requestrules>    
+
+
+      <answerrules>
+        <fixed>
+	  <avprule name="Session-Id"  minimum="1" maximum="1"/>
+	</fixed>
+	
+        <required>
+	  <avprule name="Vendor-Specific-Application-Id" maximum="1" />
+	  <avprule name="Auth-Session-State" maximum="1" />
+	  <avprule name="Origin-Host" maximum="1" />
+	  <avprule name="Origin-Realm" maximum="1"/>
+	</required>
+	
+        <optional>
+	  <avprule name="Result-Code" maximum="1"/>
+	  <avprule name="Experimental-Result" maximum="1"/>
+	  <avprule name="User-Name" maximum="1" />
+	  <avprule name="Supported-Features" />
+	  <!--avprule name="User-Data" maximum="1"/> -->
+	  <!--avprule name="Charging-Information" maximum="1"/> -->
+	  <!--avprule name="Associated-Identities" maximum="1"/> -->
+	  <!--avprule name="Loose-Route-Indication" maximum="1"/> -->
+	  <!--avprule name="SCSCF-Restoration-Info" /> -->
+	  <!--avprule name="Associated-Registered-Identities " maximum="1"/> -->
+	  <avprule name="AVP" />
+	  <avprule name="Server-Name" maximum="1"/>
+	  <avprule name="Failed-AVP" />
+	  <avprule name="Proxy-Info" />
+	  <avprule name="Route-Record" />
+   
+        </optional>
+	
+      </answerrules>
+      
+    </command>
+    
+
+
+
+
+    <!-- ******************************************************** -->
+    <!-- *********************** AVPs *************************** -->
+    <!-- ******************************************************** -->
+	
+    <avp name="Visited-Network-Identifier" code="600" vendor-id="10415" mandatory="must"
+	 may-encrypt="no">
+      <type type-name="OctetString" />
+    </avp>
+   
+    <avp name="Public-Identity" code="601" vendor-id="10415"  mandatory="must"
+	 may-encrypt="no">
+      <type type-name="UTF8String" />
+    </avp>
+  
+    <avp name="Server-Name" code="602" vendor-id="10415"  mandatory="must"
+	 may-encrypt="no">
+      <type type-name="UTF8String" />
+    </avp>
+
+    <!-- "Server-Capabilites" (603) usa as duas AVPs a seguir :    -->
+    <avp name="Feature-List-ID" code="629" vendor-id="10415"  mandatory="must"
+	 may-encrypt="no">  <!-- verificar flags / NRGJ -->
+      <type type-name="Unsigned32" />
+    </avp>
+
+    <avp name="Feature-List" code="630" vendor-id="10415"  mandatory="must"
+	 may-encrypt="no"> <!-- verificar flags / NRGJ -->
+      <type type-name="Unsigned32" />
+    </avp>    
+
+    <avp name="Server-Capabilities" code="603" vendor-id="10415" mandatory="must"
+	 may-encrypt="no">
+      <grouped>
+	<optional>
+	  <avprule name="Vendor-Id" maximum="1" />
+	  <avprule name="Feature-List-ID" maximum="1" />
+	  <avprule name="Feature-List" maximum="1" />
+	</optional>
+      </grouped>
+    </avp>
+
+    <avp name="Mandatory-Capability" code="604" vendor-id="10415" mandatory="must"
+	 may-encrypt="no">
+      <type type-name="Unsigned32" />
+    </avp>
+  
+    <avp name="Optional-Capability" code="605" vendor-id="10415" mandatory="must"
+	 may-encrypt="no">
+      <type type-name="Unsigned32" />
+    </avp>
+  
+    <avp name="User-Data" code="606" vendor-id="10415" mandatory="must"
+	 may-encrypt="no">
+      <type type-name="OctetString" />
+    </avp>
+  
+    <avp name="SIP-Number-Auth-Items" code="607" vendor-id="10415" mandatory="must"
+	 may-encrypt="no">
+      <type type-name="Unsigned32" />
+    </avp>
+  
+    <avp name="SIP-Authentication-Scheme" code="608" vendor-id="10415" mandatory="must"
+	 may-encrypt="no">
+      <type type-name="UTF8String" />
+    </avp>
+  
+    <avp name="SIP-Authenticate" code="609" vendor-id="10415" mandatory="must"
+	 may-encrypt="no">
+      <type type-name="OctetString" />
+    </avp>
+  
+    <avp name="SIP-Authorization" code="610" vendor-id="10415" mandatory="must"
+	 may-encrypt="no">
+      <type type-name="OctetString" />
+    </avp>
+ 
+    <avp name="SIP-Authentication-Context" code="611" vendor-id="10415" mandatory="must"
+	 may-encrypt="no">
+      <type type-name="OctetString" />
+    </avp>
+  
+
+
+    <!-- "SIP-Auth-Data-Item" (612) usa as AVPs a seguir :    -->
+
+    <avp name="SIP-Item-Number" code="613" vendor-id="10415" mandatory="must"
+	 may-encrypt="no">
+      <type type-name="Unsigned32" />
+    </avp>
+  
+    <avp name="Confidentiality-Key" code="625" vendor-id="10415" mandatory="must"
+	 may-encrypt="no">
+      <type type-name="OctetString" />
+    </avp>
+  
+    <avp name="Integrity-Key" code="626" vendor-id="10415" mandatory="must"
+	 may-encrypt="no">
+      <type type-name="OctetString" />
+    </avp>
+  
+    <avp name="Digest-Realm" code="104" vendor-id="10415" mandatory="must"
+	 may-encrypt="no"> <!-- verificar flags / NRGJ -->
+      <type type-name="UTF8String" />
+    </avp>
+ 
+   <avp name="Digest-Algorithm" code="111" vendor-id="10415" mandatory="must"
+	 may-encrypt="no"> <!-- verificar flags / NRGJ -->
+      <type type-name="UTF8String" />
+    </avp>
+
+   <avp name="Digest-QoP" code="110" vendor-id="10415" mandatory="must"
+	 may-encrypt="no"> <!-- verificar flags / NRGJ -->
+      <type type-name="UTF8String" />
+    </avp>
+  
+   <avp name="Digest-HA1" code="121" vendor-id="10415" mandatory="must"
+	 may-encrypt="no"> <!-- verificar flags / NRGJ -->
+      <type type-name="UTF8String" />
+    </avp>
+     
+
+    <avp name="SIP-Digest-Authenticate" code="635" vendor-id="10415" 
+	 may-encrypt="no"> <!-- verificar flags / NRGJ -->
+      <grouped>
+	<required>
+	  <avprule name="Digest-Realm" minimum="1" maximum="1" />
+	</required>
+	<optional>
+	  <avprule name="Digest-Algorithm" maximum="1" />
+	  <avprule name="Digest-QoP" maximum="1" />
+	  <avprule name="Digest-HA1" maximum="1" />
+	  <avprule name="AVP" />
+	</optional>
+      </grouped>
+
+    </avp>
+    
+    <avp name="Line-Identifier" code="500" vendor-id="13019" mandatory="must"
+	 may-encrypt="no"> <!-- verificar flags / NRGJ -->
+      <type type-name="OctetString" />
+    </avp>
+    
+    <avp name="SIP-Auth-Data-Item" code="612" vendor-id="10415" mandatory="must"
+	 may-encrypt="no">
+      <grouped>
+	<optional>
+	  <avprule name="SIP-Item-Number" maximum="1" />
+	  <avprule name="SIP-Authentication-Scheme" maximum="1" />
+	  <avprule name="SIP-Authenticate" maximum="1" />
+	  <avprule name="SIP-Authorization" maximum="1" />
+	  <avprule name="SIP-Authentication-Context" maximum="1" />
+	  <avprule name="Confidentiality-Key" maximum="1" />
+	  <avprule name="Integrity-Key" maximum="1" />
+	  <avprule name="SIP-Digest-Authenticate" maximum="1" />
+	  <avprule name="Framed-IP-Address" maximum="1" />
+	  <avprule name="Framed-IPv6-Prefix" maximum="1" />
+	  <avprule name="Framed-Interface-Id" maximum="1" />
+	  <avprule name="Line-Identifier" />
+	  <avprule name="AVP" />
+	</optional>
+      </grouped>
+    </avp>
+  
+
+
+
+    <avp name="Server-Assignment-Type" code="614" mandatory="must"
+	 may-encrypt="no">
+      <type type-name="Enumerated"/>
+      <enum name="NO_ASSIGNMENT" code="0"/>
+      <enum name="REGISTRATION" code="1"/>
+      <enum name="RE_REGISTRATION" code="2"/>
+      <enum name="UNREGISTERED_USER" code="3"/>
+      <enum name="TIMEOUT_DEREGISTRATION" code="4"/>
+      <enum name="USER_DEREGISTRATION" code="5"/>
+      <enum name="TIMEOUT_DEREGISTRATION_STORE_SERVER_NAME" code="6"/>
+      <enum name="USER_DEREGISTRATION_STORE_SERVER_NAME" code="7"/>
+      <enum name="ADMINISTRATIVE_DEREGISTRATION " code="8"/>
+      <enum name="AUTHENTICATION_FAILURE" code="9"/>
+      <enum name="AUTHENTICATION_TIMEOUT" code="10"/>
+      <enum name="DEREGISTRATION_TOO_MUCH_DATA" code="11"/>
+      <enum name="AAA_USER_DATA_REQUEST" code="12"/>
+      <enum name="PGW_UPDATE " code="13"/>
+    </avp>
+
+
+    <avp name="User-Data-Already-Available" code="624" mandatory="must"
+	 may-encrypt="no">
+      <type type-name="Enumerated"/>
+      <enum name="USER_DATA_NOT_AVAILABLE" code="0"/>
+      <enum name="USER_DATA_ALREADY_AVAILABLE" code="1"/>
+    </avp>
+  
+
+    <avp name="Wildcarded-PSI" code="634" vendor-id="10415"
+	 may-encrypt="no">
+      <type type-name="UTF8String" />
+    </avp>
+   
+  
+    <avp name="User-Authorization-Type" code="623" vendor-id="10415" mandatory="must"
+	 may-encrypt="no">
+      <type type-name="UTF8String" />
+    </avp>
+   
+
+  
+   <avp name="Wildcarded-IMPU" code="636" vendor-id="10415" mandatory="must"
+	may-encrypt="no">
+      <type type-name="UTF8String" />
+    </avp>
+
+    <avp name="UAR-Flags" code="637" vendor-id="10415"  mandatory="must"
+	 may-encrypt="no">
+      <type type-name="Unsigned32" />
+    </avp>
+  
+    
+    <avp name="Supported-Features" code="628" vendor-id="10415"
+	 may-encrypt="no">
+      <grouped>
+	<optional>
+	  <avprule name="Vendor-Id" maximum="1" />
+	  <avprule name="Feature-List-ID" maximum="1" />
+	  <avprule name="Feature-List" maximum="1" />
+	</optional>
+      </grouped>
+    </avp>
+ 
+
+
+  </application>
+
+
+</dictionary>
+
+
diff --git a/contrib/OpenWRT/HOWTO b/contrib/OpenWRT/HOWTO
new file mode 100644
index 0000000..af07b43
--- /dev/null
+++ b/contrib/OpenWRT/HOWTO
@@ -0,0 +1,305 @@
+#####################
+#  !! IMPORTANT !!  #
+#####################
+
+The uClibc library that is shipped with OpenWRT lacks support for several POSIX thread
+features, such as pthread_cleanup_{push,pop}, that are required by the freeDiameter
+framework.
+
+Until these features are included in the base OpenWRT system, the framework will not 
+behave correctly on this platform.
+
+Therefore, the OpenWRT port is NOT usable properly at this moment with uClibc.
+
+A test software is included in test_required for checking if new uClibc distributions 
+support the required features. You'll have to adapt the Makefile according to your environment.
+
+An alternative choice if your hardware allows it is to use (e)glibc in your openwrt image.
+
+#####################
+
+
+
+This HOWTO describes how to generate a set of ipkg modules for 
+providing support of freeDiameter in an OpenWRT system.
+
+This HOWTO is written for OpenWRT 10.03 (BackFire) and no guarantee is provided
+that it will work for you. Be prepared to eventually brick your routeur...
+
+Table of contents:
+0) Quick HOWTO: optimistic step-by-step instructions.
+1) Prerequisites: get the OpenWRT development environment ready.
+2) Supplied packages: use the existing packages when possible (gnutls, ...)
+3) Other dependencies: provide for additional missing dependencies (sctp ...)
+4) freediameter package: now create the freeDiameter package
+5) Configuration: how to set the configuration on the router.
+
+This HOWTO will NOT cover how to install OpenWRT on your access device, nor 
+its basic configuration. Please refer to OpenWRT website for this type of HOWTOs.
+
+
+==============================================
+0) Quick HOWTO
+==============================================
+The following instructions should allow you to put freeDiameter on your OpenWRT-compatible router.
+In case something goes wrong, you should follow the detailed instructions in the remaining of 
+this file.
+
+Be warned: playing with the software in your router may brick it, i.e. make it unusable forever. 
+Do it at your own risk.
+
+1) Get the OpenWRT environment:
+$ git clone git://nbd.name/openwrt.git
+$ cd openwrt
+
+2) Get the feeds
+$ cp feeds.conf.default feeds.conf
+$ echo "src-hg freediameter http://www.freediameter.net/hg/fD-OWRT-packages" >> feeds.conf
+$ scripts/feeds update
+$ scripts/feeds install freeDiameter
+
+3) Configure your image
+$ make menuconfig
+(set Target System and Target Profile as needed for your equipment)
+
+- Network --->
+   freeDiameter (M)
+   freeDiameter-test (M)
+   wpad (*)
+   wpad-mini ( )
+   
+
+4) Set the C library to glibc instead of uClibc (broken support, see #26)
+
+- Advanced configuration options (for developers) --->
+  - Toolchain Options ---->
+    C Library implementation (Use eglibc)
+
+
+5) Build the image and packages, this takes a while
+$ make world
+
+6) Export the bin/* directory through a webserver. 
+   We assume it is available at http://192.168.1.25/owrt
+   
+7) Flash the router with your new image -- THIS DESTROYS ALL CONFIG ON THE ROUTER!
+$ ssh root@192.168.1.1
+# cd /tmp
+# wget http://192.168.1.25/owrt/openwrt-brcm47xx-squashfs.trx
+    ;; change the file name with yours
+# mtd -r write openwrt-brcm47xx-squashfs.trx linux
+    ;; wait for reboot
+$ telnet 192.168.1.1
+# passwd
+# sync
+# exit
+
+8) Update the opkg router's config to get your new packages
+ssh root@192.168.1.1
+# echo "src/gz localrepo http://192.168.1.25/owrt/packages" >> /etc/opkg.conf 
+# opkg update
+
+9) Install freeDiameter, you're done. Optionnaly, install also certtool on the router before, to 
+   generate the TLS certificate automatically.
+# opkg install freeDiameter
+
+==============================================
+1) Prerequisites:
+==============================================
+
+We will first need a working OpenWRT toolchain environment. You can retrieve
+pre-compiled binaries of such toolchains ("Image builder") on the OpenWRT website. Anyway,
+in case the architecture you are interested in is not listed, you can build
+the full toolchain from source. This is the path we are following in this HOWTO.
+
+a) Retrieve the latest OpenWRT source, using subversion or git.
+Since I have to go through a proxy, I use the later here, svn being quite annoying with proxies.
+Note, the following commands must not be run as root.
+$ git clone git://nbd.name/openwrt.git
+ (Note: you might instead use "backfire.git" if you want to stick with an OpenWRT release.)
+$ cd openwrt
+$ cp feeds.conf.default feeds.conf
+
+b) If you are using git, you have to edit the feeds.conf file to use git as well for packages.
+Do the following modifications in this case:
+$ vi feeds.conf
+ Comment out this line:
+src-svn packages https://svn.openwrt.org/openwrt/packages
+ Add this line instead:
+src-git packages git://nbd.name/packages.git
+
+ You can leave uncommented the luci (for GNUTLS) and Xwrt (webif) repositories. Since these repositories
+use svn over http, you can use subversion even if you are behind a proxy.
+
+c) Then issue the following command to update the package list:
+$ scripts/feeds update
+
+d) Now, let's already create the toolchain and basic image.
+$ make menuconfig
+
+This will open a menu for you. You must select the target you are building for.
+See http://wiki.openwrt.org/toh/start for the table of hardware and associated information.
+In my case, I am using a Buffalo WZR-HP-G300NH router. I therefore select these options:
+- Target System --->
+   Atheros AR71xx/AR7240/AR913x
+- Target Profile --->
+   Buffalo WZR-HP-G300NH
+   
+For many routeurs, the recommended kernel is a 2.4x version. I have NOT tried with such kernel,
+and the SCTP support is likely to be different in this generation of kernels. I strongly recommend
+to go with a 2.6x kernel, whenever possible. 
+   
+e) As per freeDiameter ticket #26, you also need to change the library to glibc instead of uClibc.
+Change the option as follow:
+
+- Advanced configuration options (for developers) --->
+  - Toolchain Options ---->
+    C Library implementation (Use eglibc)
+
+f) Once configured, create the toolchain and default image (this takes a while):
+$ make world
+
+After this command completes successfully, your build environment is ready.
+The resulting image and packages are stored in the "bin/" subdirectory.
+It is very convenient if you make this repository available in http to your routeur.
+
+You should probably try at this early stage to flash your device with the image you have generated.
+If the default basic image does not work, it is probably not worth adding new problems on top of it.
+
+For troubleshooting, please consult OpenWRT documentation directly.
+"make prereq" may help you building the initial image also.
+See http://downloads.openwrt.org/docs/buildroot-documentation.html for additional information
+concerning this step.
+
+You should now be able to login on your routeur with telnet (first time) or ssh (after setting a password).
+
+==============================================
+2) Supplied packages:
+==============================================
+
+There are some dependencies of freeDiameter already available in the OpenWRT packages repository. 
+You can check for the available packages with the script:
+$ ./scripts/feeds search <package>
+
+We will now describe how to install these dependencies. At the time this HOWTO is written, 
+the OpenWRT repositories contains packages for sctp, ipv6, gnutls, pthreads and hostapd. 
+Follow these instructions to build them.
+
+Alternatively, you can find these packages pre-compiled in the OpenWRT packages repository.
+
+a) Add the packages
+$ scripts/feeds install libgnutls
+$ scripts/feeds install sctp
+
+b) Select the following components in the menu:
+$ make menuconfig
+- Base system --->
+   libpthread (M)
+   
+- Network --->
+   sctp (M)
+   hostapd (M)
+   wpad-mini ( )
+
+- Libraries --->
+   SSL --->
+     libgnutls (M)
+   
+- Kernel modules --->
+   Network Support --->
+     kmod-ipv6 (M)
+     
+Quit and save the new config, then:
+$ make world
+
+This will add a bunch of modules in your bin directory that will be required for freeDiameter.
+Since we are removing the wpad-mini daemon from the base image, this image (trx or bin file) is also recompiled.
+
+Note that if you are setting your device as WPA supplicant also (wireless client), you must select wpad instead of hostapd.
+(in any case, the -mini version is not suitable since we will use the RADIUS authentication).
+
+
+You should now reflash your routeur with the new firmware image. The simplest way to achieve if your routeur has enough
+flash memory is to:
+- copy the new trx image to your routeur's /tmp (using wget or scp)
+- run this command (on the device) -- replace <newfile.trx> with your actual filename:
+ root@OpenWrt:~# mtd -r write <newfile.trx> linux
+
+WARNING: this will erase your existing configuration on the routeur. 
+In case you need to save it, you may try the sysupgrade command instead.
+
+This will reboot the device after writing the new image file.
+Afterwards, if you have set up the http server on your development machine properly 
+(let's assume it has IP address 192.168.1.25)
+you can run the following command on your router:
+ root@OpenWrt:~# echo "src/gz mydev http://192.168.1.25/packages" >> /etc/opkg.conf 
+ root@OpenWrt:~# opkg update
+
+Install the newly compiled packages with:
+ root@OpenWrt:~# opkg install kmod-ipv6 hostapd libpthread sctp
+
+==============================================
+3) Missing packages:
+==============================================
+
+UPDATE: Starting from revision r22917, sctp and kmod-sctp are included in the OpenWRT distribution, and have been removed
+from freeDiameter package. One may consider using a freeDiameter package prior to 2010/09/05 in order to get the sctp 
+package, or a more recent OpenWRT environment. 
+
+PREVIOUS SITUATION: If you are using components prior to 2010/09/05, the following applies:
+P: 
+P: There are other dependencies for freeDiameter that are not provided by OpenWRT packages. 
+P: For convenience, we include these meta-packages in the freeDiameter distribution -- but they
+P: might not be up-to-date.
+P: 
+P: a) Adding the contributed directory to the feeds
+P:   Add the following line in your feeds.conf file:
+P: src-link freediameter /path/to/freediameter/contrib/OpenWRT/packages/
+P: 
+P: Then run: 
+P: $ scripts/feeds update
+P: 
+P: This should allow you to install the missing dependencies as follow:
+P: 
+P: 
+P: b) SCTP library (note: you might alternatively compile freeDiameter without SCTP support).
+P: $ scripts/feeds install sctp
+P: 
+P: 
+P: c) Select these components in the menu:
+P: $ make menuconfig
+P: - Libraries --->
+P:    sctp (M)
+P: 
+P: Quit and save the new config, then:
+P: $ make world
+P: 
+P: 
+P: d) Install this on the router as well:
+P:  root@OpenWrt:~# opkg update
+P:  root@OpenWrt:~# opkg install sctp
+
+
+==============================================
+4) freediameter package:
+==============================================
+
+Now, your environment should be ready to compile the freeDiameter ipkg package.
+$ scripts/feeds install freeDiameter
+
+Note that in order to build this package, you need to have cmake & flex on your compilation machine.
+
+$ make menuconfig
+- Network --->
+   freeDiameter (M)
+   freeDiameter-test (M)
+   
+Quit and save the new config, then:
+$ make world
+
+On your router, run:
+# opkg update
+# opkg install freeDiameter
+
+
+
diff --git a/contrib/OpenWRT/others/D-Link_DIR-330_netconfig.patch b/contrib/OpenWRT/others/D-Link_DIR-330_netconfig.patch
new file mode 100644
index 0000000..a35556a
--- /dev/null
+++ b/contrib/OpenWRT/others/D-Link_DIR-330_netconfig.patch
@@ -0,0 +1,35 @@
+diff --git a/target/linux/brcm47xx/base-files/etc/init.d/netconfig b/target/linux/brcm47xx/base-files/etc/init.d/netconfig
+index d7839b6..6446483 100755
+--- a/target/linux/brcm47xx/base-files/etc/init.d/netconfig
++++ b/target/linux/brcm47xx/base-files/etc/init.d/netconfig
+@@ -150,6 +150,30 @@ start() {
+ 				}
+ 			}
+ 		}
++                if (model == "D-Link DIR-330") { # boardtype is 0x0472, so we need to reset the parameters
++		   # The switch is on eth1, this script defaults to switch on eth0, so we write the values directly instead.
++                       print "#### DIR-330: eth1 must be up for configuring the switch "
++                       print "config interface switchport"
++                       print " option ifname \"eth1\""
++                       print " option proto none"
++                       print ""
++		        print "config switch eth1"
++                       print " option enable   1"
++                       print ""
++                       print "config switch_vlan eth1_0"
++                       print " option device   \"eth1\""
++                       print " option vlan     0"
++                       print " option ports    \"0 1 2 3 5t\""
++                       print ""
++                       print "config switch_vlan eth1_1"
++                       print " option device   \"eth1\""
++                       print " option vlan     1"
++                       print " option ports    \"4 5t\""
++                       print ""
++                        c["lan_ifname"] = "eth0.0"
++                        c["wan_ifname"] = "eth0.1"
++                }
++
+ 		# Buffalo WBR-B11 and Buffalo WBR-G54
+ 		if (nvram["boardtype"] == "bcm94710ap") {
+ 			c["vlan0ports"] = "0 1 2 3 4 5u"
diff --git a/contrib/OpenWRT/packages/freeDiameter/Makefile b/contrib/OpenWRT/packages/freeDiameter/Makefile
new file mode 100644
index 0000000..d06502c
--- /dev/null
+++ b/contrib/OpenWRT/packages/freeDiameter/Makefile
@@ -0,0 +1,241 @@
+#
+# Software License Agreement (BSD License)
+#
+# Copyright (c) 2013, WIDE Project and NICT
+# All rights reserved.
+#
+# See LICENSE file from freeDiameter source package for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=freeDiameter
+PKG_REV:=696
+PKG_VERSION:=r$(PKG_REV)
+PKG_RELEASE:=1
+
+PKG_SOURCE_PROTO:=hg
+PKG_SOURCE_VERSION:=$(PKG_REV)
+PKG_SOURCE_SUBDIR:=$(PKG_NAME)-$(PKG_VERSION)
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
+PKG_SOURCE_URL:=http://www.freediameter.net/hg/freeDiameter
+# PKG_MD5SUM:=
+
+PKG_FIXUP:=libtool
+PKG_INSTALL:=1
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/freeDiameter
+  SECTION:=freeDiameter
+  CATEGORY:=Network
+  TITLE:=freeDiameter
+  URL:=http://www.freediameter.net
+  DEPENDS:=+sctp +libgnutls +libpthread +kmod-ipv6
+endef
+
+define Package/freeDiameter-test
+  SECTION:=freeDiameter
+  CATEGORY:=Network
+  TITLE:=freeDiameter-test
+  URL:=http://www.freediameter.net
+  DEPENDS:=+freeDiameter
+endef
+
+define Package/freeDiameter/description
+ freeDiameter + RADIUS/Diameter gateway extension package.
+endef
+
+define Package/freeDiameter-test/description
+ The app_test.fdx extension for freeDiameter, useful only to perform some
+tests between freeDiameter peers (ping-like for Diameter).
+endef
+
+define Package/freeDiameter/conffiles
+/etc/freeDiameter/freeDiameter.conf
+/etc/freeDiameter/rgw.conf
+endef
+
+define Build/Configure
+    IN_OPENWRT=1 \
+    AR="$(TARGET_CROSS)ar" \
+    AS="$(TARGET_CC) -c $(TARGET_CFLAGS)" \
+    LD="$(TARGET_CROSS)ld" \
+    NM="$(TARGET_CROSS)nm" \
+    CC="$(TARGET_CC)" \
+    GCC="$(TARGET_CC)" \
+    CXX="$(TARGET_CROSS)g++" \
+    RANLIB="$(TARGET_CROSS)ranlib" \
+    STRIP="$(TARGET_CROSS)strip" \
+    OBJCOPY="$(TARGET_CROSS)objcopy" \
+    OBJDUMP="$(TARGET_CROSS)objdump" \
+    TARGET_CPPFLAGS="$(TARGET_CPPFLAGS)" \
+    TARGET_CFLAGS="$(TARGET_CFLAGS)" \
+    TARGET_LDFLAGS="$(TARGET_LDFLAGS)" \
+    cmake \
+		-DCMAKE_PREFIX_PATH:PATH=$(STAGING_DIR)/usr \
+    		-DCMAKE_INSTALL_PREFIX:PATH=/usr \
+                -DDIAMID_IDNA_REJECT:BOOL=ON \
+                -DBUILD_TESTING:BOOL=OFF \
+		-DCMAKE_BUILD_TYPE:STRING=DebianPackage \
+		-DDEFAULT_CONF_PATH:PATH=/etc/freeDiameter \
+		-DBUILD_APP_RADGW:BOOL=ON \
+		-DBUILD_DBG_MONITOR:BOOL=ON \
+		-DBUILD_TEST_APP:BOOL=ON \
+		VERBOSE=1 \
+	$(PKG_BUILD_DIR)/CMakeLists.txt 
+endef
+
+TARGET_LDFLAGS := -L$(STAGING_DIR)/usr/lib $(TARGET_LDFLAGS)
+define Package/freeDiameter/install
+	# binaries
+	$(INSTALL_DIR) $(1)/usr/bin
+	$(CP) \
+		$(PKG_INSTALL_DIR)/usr/bin/freeDiameterd* \
+		$(1)/usr/bin/
+	# libraries & extensions
+	$(INSTALL_DIR) $(1)/usr/lib/
+	$(CP) \
+		$(PKG_INSTALL_DIR)/usr/lib/* \
+		$(1)/usr/lib/
+	# Remove the test_app from the main package (see freeDiameter-test)
+	$(RM) $(1)/usr/lib/freeDiameter/test_app*
+	
+	# configuration files
+	$(INSTALL_DIR) $(1)/etc/freeDiameter
+	$(INSTALL_CONF) \
+		$(PKG_BUILD_DIR)/doc/freediameter.conf.sample \
+		$(1)/etc/freeDiameter/freeDiameter.conf
+	$(SED) 's,TLS_Cred,#TLS_Cred,g' 		   $(1)/etc/freeDiameter/freeDiameter.conf
+	echo "" 					>> $(1)/etc/freeDiameter/freeDiameter.conf
+	echo "### OPENWRT specific"		 	>> $(1)/etc/freeDiameter/freeDiameter.conf
+	echo "TLS_Cred = \"/etc/freeDiameter/freeDiameter.pem\", \"/etc/freeDiameter/freeDiameter.key\";" \
+							>> $(1)/etc/freeDiameter/freeDiameter.conf
+	echo "TLS_CA = \"/etc/freeDiameter/freeDiameter.ca.pem\";" \
+							>> $(1)/etc/freeDiameter/freeDiameter.conf
+	echo "TLS_DH_File = \"/etc/freeDiameter/dh.pem\";" \
+				 			>> $(1)/etc/freeDiameter/freeDiameter.conf
+	echo "SCTP_streams = 3;"			>> $(1)/etc/freeDiameter/freeDiameter.conf
+	echo "LoadExtension = \"dict_nasreq.fdx\";" 	>> $(1)/etc/freeDiameter/freeDiameter.conf
+	echo "LoadExtension = \"dict_eap.fdx\";" 	>> $(1)/etc/freeDiameter/freeDiameter.conf
+	echo "LoadExtension = \"app_radgw.fdx\":\"rgw.conf\";" \
+							>> $(1)/etc/freeDiameter/freeDiameter.conf
+	echo "# test_app.fdx provided in freeDiameter-test package:" \
+							>> $(1)/etc/freeDiameter/freeDiameter.conf
+	echo "# LoadExtension = \"test_app.fdx\";"	>> $(1)/etc/freeDiameter/freeDiameter.conf
+	echo "## Add overrides below this point" 	>> $(1)/etc/freeDiameter/freeDiameter.conf
+
+	
+	$(INSTALL_CONF) \
+		$(PKG_BUILD_DIR)/doc/app_radgw.conf.sample \
+		$(1)/etc/freeDiameter/rgw.conf
+	$(SED) 's,RGWX,#RGWX,g' 		  	   $(1)/etc/freeDiameter/rgw.conf
+	echo "" 					>> $(1)/etc/freeDiameter/rgw.conf
+	echo "### OPENWRT specific"		 	>> $(1)/etc/freeDiameter/rgw.conf
+	echo "  RGWX = \"auth.rgwx\" : auth;"		>> $(1)/etc/freeDiameter/rgw.conf
+	echo "  RGWX = \"acct.rgwx\" : acct;"		>> $(1)/etc/freeDiameter/rgw.conf
+	echo "" 					>> $(1)/etc/freeDiameter/rgw.conf
+	echo "  cli = 127.0.0.1 / \"secret key\" ;" 	>> $(1)/etc/freeDiameter/rgw.conf
+	echo "  auth_server_ip4 = 127.0.0.1;" 		>> $(1)/etc/freeDiameter/rgw.conf
+	echo "  auth_server_ip6 = ::1 ;" 		>> $(1)/etc/freeDiameter/rgw.conf
+	echo "  acct_server_ip4 = 127.0.0.1;" 		>> $(1)/etc/freeDiameter/rgw.conf
+	echo "  acct_server_ip6 = ::1 ;" 		>> $(1)/etc/freeDiameter/rgw.conf
+endef
+
+define Package/freeDiameter-test/install
+	# Only the test_app extension
+	$(INSTALL_DIR) $(1)/usr/lib/freeDiameter/
+	$(CP) $(PKG_INSTALL_DIR)/usr/lib/freeDiameter/test_app* \
+		$(1)/usr/lib/freeDiameter/
+endef
+
+define Package/freeDiameter/postinst
+#!/bin/sh
+
+# Test if the configuration file contains the local identity already
+localid=`sed -n -r -e "s/^[[:space:]]*Identity[[:space:]]*=[[:space:]]*\"([^\"]*)\"[[:space:]]*;/\1/p" /etc/freeDiameter/freeDiameter.conf`
+if [ -z "$$localid" ]; then
+   # Ask for the local name
+   echo -n "Full name of your access point? (openwrt.localdomain) : "
+   read localid
+   if [ -z "$$localid" ]; then
+      localid="openwrt.localdomain"
+   fi
+   echo "Identity = \"$$localid\";" >> /etc/freeDiameter/freeDiameter.conf
+fi
+
+# Is there already a ConnectPeer directive?
+grep -q -E -e "^[[:space:]]*ConnectPeer[[:space:]]*=" /etc/freeDiameter/freeDiameter.conf
+if [ "$$?" -eq "1" ]; then
+   echo -n "Diameter Identity of your Diameter server: "
+   read serverid
+   if [ -z "$$serverid" ]; then
+      echo "Skipped. Please add ConnectPeer directive to your /etc/freeDiameter/freeDiameter.conf file later."
+   else
+      echo -n "IP or IPv6 address of your Diameter server? (leave blank for dynamic resolution) "
+      read serverip
+      connstr=""
+      if [ -n "$$serverip" ]; then
+        connstr=" { ConnectTo = \"$$serverip\"; }"
+      fi
+      echo "ConnectPeer = \"$$serverid\"$$connstr;" >> /etc/freeDiameter/freeDiameter.conf
+   fi
+fi
+
+# Certificate configuration    
+if [ ! -f "/usr/bin/certtool" ]; then
+   echo "certtool is not installed, skipping creation of default certificate and DH parameters."
+   echo "The following files are expected by freeDiameter:"
+   echo "  /etc/freeDiameter/freeDiameter.key"
+   echo "  /etc/freeDiameter/freeDiameter.pem"
+   echo "  /etc/freeDiameter/freeDiameter.ca.pem"
+   echo "  /etc/freeDiameter/dh.pem"
+   exit 0
+fi
+if [ ! -f "/etc/freeDiameter/freeDiameter.key" ]; then 
+   echo "Creating a new private key for freeDiameter, please wait"
+   certtool -p --outfile /etc/freeDiameter/freeDiameter.key
+fi
+if [ ! -f "/etc/freeDiameter/freeDiameter.pem" ]; then
+   echo "organization = freeDiameter"		> /tmp/template.cnf
+   echo "unit = OpenWRT"			>>/tmp/template.cnf
+   echo "state = internet"			>>/tmp/template.cnf
+   echo "country = net"				>>/tmp/template.cnf
+   echo "cn = $$localid"			>>/tmp/template.cnf
+   echo "expiration_days = 3650"		>>/tmp/template.cnf
+   echo "signing_key"				>>/tmp/template.cnf
+   echo "encryption_key"			>>/tmp/template.cnf
+   if [ ! -f "/etc/freeDiameter/freeDiameter.csr" ]; then 
+      echo "Creating a new CSR (use if you have a separate CA)"
+      certtool -q --load-privkey /etc/freeDiameter/freeDiameter.key \
+               --outfile /etc/freeDiameter/freeDiameter.csr \
+	       --template /tmp/template.cnf
+   fi
+   echo "Creating a new certificate for freeDiameter"
+   certtool -s --load-privkey /etc/freeDiameter/freeDiameter.key \
+               --outfile /etc/freeDiameter/freeDiameter.pem \
+	       --template /tmp/template.cnf
+   rm -f /tmp/template.cnf
+   cat /etc/freeDiameter/freeDiameter.pem >> /etc/freeDiameter/freeDiameter.ca.pem
+   echo "Done."
+   echo "========================================================================"
+   echo "To enable TLS communication, you should either:"
+   echo "  - use a real certificate signed by your server's CA:"
+   echo "      Use the CSR provided in /etc/freeDiameter/freeDiameter.csr"
+   echo "      Save the new certificate as /etc/freeDiameter/freeDiameter.pem"
+   echo "      Replace the contents of /etc/freeDiameter/freeDiameter.ca.pem with your CA's certificate"
+   echo "  - or, declare the certificates as trusted as follow: "
+   echo "      Add your server's CA certificate into /etc/freeDiameter/freeDiameter.ca.pem"
+   echo "      Add the content of /etc/freeDiameter/freeDiameter.pem into your server's trusted CA file"
+   echo "========================================================================"
+fi
+if [ ! -f "/etc/freeDiameter/dh.pem" ]; then
+   echo "Creating new Diffie-Hellman parameters file. This operation takes a while..."
+   certtool --generate-dh-params --outfile /etc/freeDiameter/dh.pem
+   echo "Done."
+fi
+echo "freeDiameter configuration completed and stored in /etc/freeDiameter/."
+endef
+
+$(eval $(call BuildPackage,freeDiameter))
+$(eval $(call BuildPackage,freeDiameter-test))
diff --git a/contrib/OpenWRT/packages/freeDiameter/patches/01-freeDiameter-OpenWRT.patch b/contrib/OpenWRT/packages/freeDiameter/patches/01-freeDiameter-OpenWRT.patch
new file mode 100644
index 0000000..6f43c8d
--- /dev/null
+++ b/contrib/OpenWRT/packages/freeDiameter/patches/01-freeDiameter-OpenWRT.patch
@@ -0,0 +1,19 @@
+diff -Nur freeDiameter/CMakeLists.txt freeDiameter-OpenWRT/CMakeLists.txt
+--- freeDiameter/CMakeLists.txt	2010-08-13 16:19:35.000000000 +0900
++++ freeDiameter-OpenWRT/CMakeLists.txt	2010-08-13 16:21:32.000000000 +0900
+@@ -51,6 +51,14 @@
+   SET(DEBUG 1)
+ ENDIF (CMAKE_BUILD_TYPE MATCHES "Debug|Profiling|DebugValgrind")
+ 
++# OpenWRT
++SET(IN_OPENWRT $ENV{IN_OPENWRT})
++IF (IN_OPENWRT)
++  ADD_DEFINITIONS("$ENV{TARGET_LDFLAGS}" "$ENV{TARGET_CPPFLAGS}" "$ENV{TARGET_CFLAGS}")
++  INCLUDE_DIRECTORIES("$ENV{TARGET_LDFLAGS}" "$ENV{TARGET_CPPFLAGS}" "$ENV{TARGET_CFLAGS}")
++ENDIF(IN_OPENWRT)
++
++
+ # some subfolders use yacc and lex parsers
+ SET(BISON_GENERATE_DEFINES TRUE)
+ SET(BISON_PREFIX_OUTPUTS TRUE)
+Binary files freeDiameter/.hg/dirstate and freeDiameter-OpenWRT/.hg/dirstate differ
diff --git a/contrib/OpenWRT/test_required/Makefile b/contrib/OpenWRT/test_required/Makefile
new file mode 100644
index 0000000..d13cc91
--- /dev/null
+++ b/contrib/OpenWRT/test_required/Makefile
@@ -0,0 +1,15 @@
+OWRT_ENV_ROOT=/root/openwrt-env/openwrt
+STAGING_UCLIBC_ROOT=$(OWRT_ENV_ROOT)/staging_dir/target-mipsel_uClibc-0.9.31
+STAGING_GCC_ROOT=$(OWRT_ENV_ROOT)/staging_dir/toolchain-mipsel_gcc-4.3.3+cs_uClibc-0.9.31
+
+CFLAGS=-Os -pipe -mips32 -mtune=mips32 -funit-at-a-time -fhonour-copts -msoft-float  -I$(STAGING_UCLIBC_ROOT)/usr/include -I$(STAGING_UCLIBC_ROOT)/include -I$(STAGING_GCC_ROOT)/usr/include -I$(STAGING_GCC_ROOT)/include 
+LDFLAGS=-L$(STAGING_UCLIBC_ROOT)/usr/lib -L$(STAGING_UCLIBC_ROOT)/lib -L$(STAGING_GCC_ROOT)/usr/lib -L$(STAGING_GCC_ROOT)/lib 
+
+GCC=mipsel-openwrt-linux-uclibc-gcc
+PATH:=$(STAGING_GCC_ROOT)/bin/:$(PATH)
+
+testcase:	testcase.o
+	$(GCC) $(LDFLAGS) -lpthread testcase.o -o testcase
+
+testcase.o:	testcase.c
+	$(GCC) $(CFLAGS) -o testcase.o -c testcase.c
diff --git a/contrib/OpenWRT/test_required/testcase.c b/contrib/OpenWRT/test_required/testcase.c
new file mode 100644
index 0000000..11d7882
--- /dev/null
+++ b/contrib/OpenWRT/test_required/testcase.c
@@ -0,0 +1,90 @@
+#include <pthread.h>
+#include <stdio.h>
+#include <strings.h>
+#include <assert.h>
+
+static pthread_barrier_t bar;
+static pthread_mutex_t mtx = PTHREAD_MUTEX_INITIALIZER;
+static pthread_cond_t cnd = PTHREAD_COND_INITIALIZER;
+static int called = 0;
+
+#ifndef ASSERT
+#define ASSERT(x) assert(x)
+#endif /* ASSERT */
+
+static void cleanupmutex(void * arg)
+{
+	printf("cancelation cleanup handler called\n");
+	if (arg) {
+		ASSERT( pthread_mutex_unlock((pthread_mutex_t *)arg) == 0 );
+		called++;
+	}
+	
+}
+
+static void * mythread(void * a)
+{
+	int ret;
+	
+	/* lock mutex */
+	ASSERT( pthread_mutex_lock(&mtx) == 0 );
+		
+	/* Push cleanup */
+	pthread_cleanup_push(cleanupmutex, &mtx);
+	
+	printf("thread synchronization (mutex acquired)\n");
+	
+	/* Wake the other thread */
+	ret = pthread_barrier_wait(&bar);
+	ASSERT( (ret == 0) || (ret == PTHREAD_BARRIER_SERIAL_THREAD) );
+	
+	/* Now wait for the condition, this unlocks the mutex */
+	do {
+		printf("thread waiting cond\n");
+		ASSERT( pthread_cond_wait(&cnd, &mtx) == 0);
+		printf("thread woken\n");
+	} while (1);
+	
+	/* Cleanup, never reached */
+	pthread_cleanup_pop(1);
+	return NULL;
+}
+
+int main(int argc, char * argv[])
+{
+	int ret;
+	pthread_t thr;
+	void * dummy;
+	
+	/* initialize the barrier */
+	ASSERT( pthread_barrier_init(&bar, NULL, 2) == 0 );
+	
+	printf("Creating thread\n");
+	
+	/* Create the thread */
+	ASSERT( pthread_create(&thr, NULL, mythread, NULL) == 0 );
+	
+	printf("main synchronization\n");
+	ret = pthread_barrier_wait(&bar);
+	ASSERT( (ret == 0) || (ret == PTHREAD_BARRIER_SERIAL_THREAD) );
+	
+	ASSERT( pthread_mutex_lock(&mtx) == 0 );
+	printf("main: thread is now waiting for condvar\n");
+	
+	/* Cancel the thread */
+	ASSERT( pthread_cancel(thr) == 0 );
+	
+	/* Now, unlock, so that the thread can actually really exit */
+	ASSERT( pthread_mutex_unlock(&mtx) == 0 );
+	
+	/* Release thread resources */
+	ASSERT( pthread_join(thr, &dummy) == 0 );
+	
+	if (called == 1)
+		printf("Test successful!\n");
+	else
+		printf("Test failed! Cleanup was not called (& lock not released)\n");
+	
+	return 0;
+	
+}
diff --git a/contrib/PKI/ca_script/Makefile b/contrib/PKI/ca_script/Makefile
new file mode 100644
index 0000000..70476d4
--- /dev/null
+++ b/contrib/PKI/ca_script/Makefile
@@ -0,0 +1,149 @@
+#!/usr/bin/make -s
+#
+# This file is designed to automatize the CA tasks such as:
+#  -> init  : create the initial CA tree and the CA root certificate.
+#  -> newcsr: create a new private key and csr. $name and $email must be set. C, ST, L, O, OU may be overwitten (example: make newcsr C=FR)
+#  -> cert  : sign a pending CSR and generate the certificate. $name must be provided.
+#  -> revoke: revoke a certificate. $name must be provided.
+#  -> gencrl: update/create the CRL.
+#
+# The file should be located in the directory STATIC_DIR as defined below.
+# The DIR directory will contain the data of the CA. It might be placed in /var.
+# The DIR should also be configured in openssl.cnf file under [ CA_default ]->dir.
+#
+# Here are the steps to install the CA scripts in default environment:
+## mkdir /etc/openssl-ca.static
+## cp Makefile openssl.cnf /etc/openssl-ca.static
+# ( configure the default parameters of your CA in /etc/openssl-ca/openssl.cnf ) ##
+## mkdir /etc/openssl-ca
+## make -f /etc/openssl-ca.static/Makefile destroy force=y
+## cd /etc/openssl-ca
+## make init
+## make help
+
+DIR = /home/thedoc/testbed.aaa/ca
+STATIC_DIR = /home/thedoc/testbed.aaa/ca
+CONFIG = -config $(DIR)/openssl.cnf
+
+#Defaults for new CSR
+C = JP
+ST = Tokyo
+L = Koganei
+O = WIDE
+OU = "AAA WG"
+
+#Default lifetime
+DAYS = 365
+
+#Values for the CA
+CA_CN = mgr.testbed.aaa
+CA_mail = sdecugis@freediameter.net
+
+#Disable "make destroy"
+force = 
+
+
+# Default: print the help
+all:	help
+
+# Help message
+help:
+	@echo "\n\
+Default values (can be overwritten on command-line):\n\
+   [C=$(C)] [ST=$(ST)] [L=$(L)] [O=$(O)] [OU=$(OU)]\n\
+   [CA_CN=$(CA_CN)] [CA_mail=$(CA_mail)]\n\n\
+Available commands:\n\
+   make init\n\
+       Creates the initial CA structure in $(DIR)\n\
+   make gencrl\n\
+       Regenerates the CRL. Should be run at least once a month.\n\
+   make newcsr name=foo email=b@r [type=ca]\n\
+       Create private key and csr in clients subdir (named foo.*)\n\
+   make cert name=foo\n\
+       Signs the CSR foo.csr and creates the certificate foo.cert.\n\
+   make revoke name=foo\n\
+       Revokes the certificate foo.cert and regenerates the CRL.\n\
+\n\
+Notes:\n\
+   Content from public-www should be available from Internet. \n\
+   The URL to CRL should be set in openssl.cnf.\n\
+   A cron job should execute make gencrl once a month.\n\
+";
+
+# Destroy the CA completely. Use with care.
+destroy:
+	@if [ -z "$(force)" ]; then echo "Restart disabled, use: make destroy force=y"; exit 1; fi
+	@if [ ! -d $(STATIC_DIR) ]; then echo "Error in setup"; exit 1; fi
+	@echo "Removing everything (for debug purpose)..."
+	@rm -rf $(DIR)/*
+	@ln -sf $(STATIC_DIR)/Makefile $(DIR)
+	@ln -sf $(STATIC_DIR)/openssl.cnf $(DIR)
+
+# Initialize the CA structure and keys.
+init:
+	@if [ -d $(DIR)/private ]; then echo "CA already initialized."; exit 1; fi
+	@echo "Creating CA structure..."
+	@mkdir $(DIR)/crl
+	@mkdir $(DIR)/certs
+	@mkdir $(DIR)/newcerts
+	@mkdir $(DIR)/public-www
+	@mkdir $(DIR)/private
+	@chmod 700 $(DIR)/private
+	@mkdir $(DIR)/clients
+	@mkdir $(DIR)/clients/privkeys
+	@mkdir $(DIR)/clients/csr
+	@mkdir $(DIR)/clients/certs
+	@echo "01" > $(DIR)/serial
+	@touch $(DIR)/index.txt
+	@openssl req $(CONFIG) -new -batch -x509 -days 3650 -nodes -newkey rsa:2048 -out $(DIR)/public-www/cacert.pem \
+		-keyout $(DIR)/private/cakey.pem -subj /C=$(C)/ST=$(ST)/L=$(L)/O=$(O)/OU=$(OU)/CN=$(CA_CN)/emailAddress=$(CA_mail)
+	@ln -s $(DIR)/public-www/cacert.pem $(DIR)/certs/`openssl x509 -noout -hash < $(DIR)/public-www/cacert.pem`.0
+	@$(MAKE) -f $(DIR)/Makefile gencrl
+
+# Regenerate the Certificate Revocation List.
+# This list should be available publicly
+gencrl:
+	@openssl ca $(CONFIG) -gencrl -out $(DIR)/public-www/crl.pem
+	@ln -sf $(DIR)/public-www/crl.pem $(DIR)/crl/`openssl crl -noout -hash < $(DIR)/public-www/crl.pem`.r0
+
+# Create a new private key and a CSR, in case the client does not provide the CSR by another mean.
+# Usage is: make newcsr name=peer.client.fqdn email=admin@client.fqdn
+newcsr:
+	@if [ -z "$(name)" -o -z "$(email)" ]; then echo "Please provide certificate name and email address: make newcsr name=mn.nautilus.org email=you@mail.com"; exit 1; fi
+	@if [ -e $(DIR)/clients/csr/$(name).csr ]; then echo "There is already a pending csr for this name."; exit 1; fi
+	@if [ ! -e $(DIR)/clients/privkeys/$(name).key.pem ]; \
+		then echo "Generating a private key for $(name) ..."; \
+		openssl genrsa -out $(DIR)/clients/privkeys/$(name).key.pem 1024; \
+		fi;
+	@echo "Creating the CSR in $(DIR)/clients/csr/$(name).csr";
+	@openssl req $(CONFIG) -new -batch -out $(DIR)/clients/csr/$(name).csr \
+		-key $(DIR)/clients/privkeys/$(name).key.pem \
+		-subj /C=$(C)/ST=$(ST)/L=$(L)/O=$(O)/OU=$(OU)/CN=$(name)/emailAddress=$(email)
+
+# Process a CSR to create a x509 certificate. The certificate is valid for 1 year. 
+# It should be sent to the client by any mean.
+cert:
+	@if [ -z "$(name)" ]; then echo "name must be provided: make cert name=mn.n6.org"; exit 1; fi
+	@if [ ! -e $(DIR)/clients/csr/$(name).csr ]; then echo "Could not find CSR in $(DIR)/clients/csr/$(name).csr."; exit 1; fi
+	@if [ -e $(DIR)/clients/certs/$(name).cert ]; \
+		then echo "Revoking old certificate..."; \
+		$(MAKE) revoke name=$(name); \
+		fi;
+	@openssl ca $(CONFIG) -in $(DIR)/clients/csr/$(name).csr \
+		-out $(DIR)/clients/certs/$(name).cert \
+		-days $(DAYS) \
+		-batch
+	@ln -s $(DIR)/clients/certs/$(name).cert $(DIR)/certs/`openssl x509 -noout -hash < $(DIR)/clients/certs/$(name).cert`.0
+
+# Revoke a certificate.
+revoke:
+	@if [ -z "$(name)" ]; then echo "name must be provided: make revoke name=mn.n6.org"; exit 1; fi
+	@if [ ! -e $(DIR)/clients/certs/$(name).cert ]; \
+		then echo "$(DIR)/clients/certs/$(name).cert not found"; \
+		exit 1; \
+		fi;
+	@openssl ca $(CONFIG) -revoke $(DIR)/clients/certs/$(name).cert;
+	@rm -f $(DIR)/certs/`openssl x509 -noout -hash < $(DIR)/clients/certs/$(name).cert`.0
+	@$(MAKE) gencrl
+
+# End of file...
diff --git a/contrib/PKI/ca_script/openssl.cnf b/contrib/PKI/ca_script/openssl.cnf
new file mode 100644
index 0000000..e4671d8
--- /dev/null
+++ b/contrib/PKI/ca_script/openssl.cnf
@@ -0,0 +1,315 @@
+#
+# OpenSSL example configuration file.
+# This is mostly being used for generation of certificate requests.
+#
+
+# This definition stops the following lines choking if HOME isn't
+# defined.
+HOME			= .
+RANDFILE		= $ENV::HOME/.rnd
+
+# Extra OBJECT IDENTIFIER info:
+#oid_file		= $ENV::HOME/.oid
+oid_section		= new_oids
+
+# To use this configuration file with the "-extfile" option of the
+# "openssl x509" utility, name here the section containing the
+# X.509v3 extensions to use:
+# extensions		= 
+# (Alternatively, use a configuration file that has only
+# X.509v3 extensions in its main [= default] section.)
+
+[ new_oids ]
+
+# We can add new OIDs in here for use by 'ca' and 'req'.
+# Add a simple OID like this:
+# testoid1=1.2.3.4
+# Or use config file substitution like this:
+# testoid2=${testoid1}.5.6
+
+####################################################################
+[ ca ]
+default_ca	= CA_default		# The default ca section
+
+####################################################################
+[ CA_default ]
+
+dir		= /etc/openssl-ca	# Where everything is kept
+certs		= $dir/certs		# Where the issued certs are kept
+crl_dir		= $dir/crl		# Where the issued crl are kept
+database	= $dir/index.txt	# database index file.
+#unique_subject	= no			# Set to 'no' to allow creation of
+					# several ctificates with same subject.
+new_certs_dir	= $dir/newcerts		# default place for new certs.
+
+certificate	= $dir/public-www/cacert.pem 	# The CA certificate
+serial		= $dir/serial 		# The current serial number
+# crlnumber	= $dir/crlnumber	# the current crl number
+					# must be commented out to leave a V1 CRL
+crl		= $dir/public-www/crl.pem 		# The current CRL
+private_key	= $dir/private/cakey.pem# The private key
+RANDFILE	= $dir/private/.rand	# private random number file
+
+x509_extensions	= usr_cert		# The extentions to add to the cert
+
+# Comment out the following two lines for the "traditional"
+# (and highly broken) format.
+name_opt 	= ca_default		# Subject Name options
+cert_opt 	= ca_default		# Certificate field options
+
+# Extension copying option: use with caution.
+# copy_extensions = copy
+
+# Extensions to add to a CRL. Note: Netscape communicator chokes on V2 CRLs
+# so this is commented out by default to leave a V1 CRL.
+# crlnumber must also be commented out to leave a V1 CRL.
+# crl_extensions	= crl_ext
+
+default_days	= 365			# how long to certify for
+default_crl_days= 30			# how long before next CRL
+default_md	= sha1			# which md to use.
+preserve	= no			# keep passed DN ordering
+
+# A few difference way of specifying how similar the request should look
+# For type CA, the listed attributes must be the same, and the optional
+# and supplied fields are just that :-)
+# policy		= policy_match
+policy			= policy_anything
+
+# For the CA policy
+[ policy_match ]
+countryName		= match
+stateOrProvinceName	= match
+organizationName	= match
+organizationalUnitName	= optional
+commonName		= supplied
+emailAddress		= optional
+
+# For the 'anything' policy
+# At this point in time, you must list all acceptable 'object'
+# types.
+[ policy_anything ]
+countryName		= optional
+stateOrProvinceName	= optional
+localityName		= optional
+organizationName	= optional
+organizationalUnitName	= optional
+commonName		= supplied
+emailAddress		= optional
+
+####################################################################
+[ req ]
+default_bits		= 1024
+default_keyfile 	= privkey.pem
+distinguished_name	= req_distinguished_name
+attributes		= req_attributes
+x509_extensions	= v3_ca	# The extentions to add to the self signed cert
+
+# Passwords for private keys if not present they will be prompted for
+# input_password = fdsecret
+# output_password = fdsecret
+
+# This sets a mask for permitted string types. There are several options. 
+# default: PrintableString, T61String, BMPString.
+# pkix	 : PrintableString, BMPString.
+# utf8only: only UTF8Strings.
+# nombstr : PrintableString, T61String (no BMPStrings or UTF8Strings).
+# MASK:XXXX a literal mask value.
+# WARNING: current versions of Netscape crash on BMPStrings or UTF8Strings
+# so use this option with caution!
+string_mask = utf8only
+
+# req_extensions = v3_req # The extensions to add to a certificate request
+
+[ req_distinguished_name ]
+countryName			= Country Name (2 letter code)
+countryName_default		= JP
+countryName_min			= 2
+countryName_max			= 2
+
+stateOrProvinceName		= State or Province Name (full name)
+stateOrProvinceName_default	= Tokyo
+
+localityName			= Locality Name (eg, city)
+localityName_default		= Koganei
+
+0.organizationName		= Organization Name (eg, company)
+0.organizationName_default	= WIDE
+
+# we can do this but it is not needed normally :-)
+1.organizationName		= Second Organization Name (eg, company)
+1.organizationName_default	= NICT
+
+organizationalUnitName		= Organizational Unit Name (eg, section)
+organizationalUnitName_default	= AAA WG
+
+commonName			= Common Name (i.e. Diameter Agent hostname)
+commonName_max			= 64
+
+emailAddress			= Email Address (i.e. Diameter agent administrator)
+emailAddress_max		= 64
+
+# SET-ex3			= SET extension number 3
+
+[ req_attributes ]
+challengePassword		= A challenge password
+challengePassword_min		= 0
+challengePassword_max		= 20
+
+unstructuredName		= An optional company name
+
+[ usr_cert ]
+
+# These extensions are added when 'ca' signs a request.
+
+# This goes against PKIX guidelines but some CAs do it and some software
+# requires this to avoid interpreting an end user certificate as a CA.
+
+basicConstraints=CA:FALSE
+
+# Here are some examples of the usage of nsCertType. If it is omitted
+# the certificate can be used for anything *except* object signing.
+
+# This is OK for an SSL server.
+# nsCertType			= server
+
+# For an object signing certificate this would be used.
+# nsCertType = objsign
+
+# For normal client use this is typical
+# nsCertType = client, email
+
+# and for everything including object signing:
+# nsCertType = client, email, objsign
+
+# This is typical in keyUsage for a client certificate.
+# keyUsage = nonRepudiation, digitalSignature, keyEncipherment
+
+# This will be displayed in Netscape's comment listbox.
+nsComment			= "OpenSSL Generated Certificate"
+
+# PKIX recommendations harmless if included in all certificates.
+subjectKeyIdentifier=hash
+authorityKeyIdentifier=keyid,issuer
+
+# This stuff is for subjectAltName and issuerAltname.
+# Import the email address.
+# subjectAltName=email:copy
+# An alternative to produce certificates that aren't
+# deprecated according to PKIX.
+# subjectAltName=email:move
+
+# Copy subject details
+# issuerAltName=issuer:copy
+
+#nsCaRevocationUrl		= http://www.domain.dom/ca-crl.pem
+#nsBaseUrl
+#nsRevocationUrl
+#nsRenewalUrl
+#nsCaPolicyUrl
+#nsSslServerName
+
+[ v3_req ]
+
+# Extensions to add to a certificate request
+
+basicConstraints = CA:FALSE
+keyUsage = nonRepudiation, digitalSignature, keyEncipherment
+
+[ v3_ca ]
+
+
+# Extensions for a typical CA
+
+
+# PKIX recommendation.
+
+subjectKeyIdentifier=hash
+
+authorityKeyIdentifier=keyid:always,issuer:always
+
+# This is what PKIX recommends but some broken software chokes on critical
+# extensions.
+#basicConstraints = critical,CA:true
+# So we do this instead.
+basicConstraints = CA:true
+
+# Key usage: this is typical for a CA certificate. However since it will
+# prevent it being used as an test self-signed certificate it is best
+# left out by default.
+# keyUsage = cRLSign, keyCertSign
+
+# Some might want this also
+# nsCertType = sslCA, emailCA
+
+# Include email address in subject alt name: another PKIX recommendation
+# subjectAltName=email:copy
+# Copy issuer details
+# issuerAltName=issuer:copy
+
+# DER hex encoding of an extension: beware experts only!
+# obj=DER:02:03
+# Where 'obj' is a standard or added object
+# You can even override a supported extension:
+# basicConstraints= critical, DER:30:03:01:01:FF
+
+[ crl_ext ]
+
+# CRL extensions.
+# Only issuerAltName and authorityKeyIdentifier make any sense in a CRL.
+
+# issuerAltName=issuer:copy
+authorityKeyIdentifier=keyid:always,issuer:always
+
+[ proxy_cert_ext ]
+# These extensions should be added when creating a proxy certificate
+
+# This goes against PKIX guidelines but some CAs do it and some software
+# requires this to avoid interpreting an end user certificate as a CA.
+
+basicConstraints=CA:FALSE
+
+# Here are some examples of the usage of nsCertType. If it is omitted
+# the certificate can be used for anything *except* object signing.
+
+# This is OK for an SSL server.
+# nsCertType			= server
+
+# For an object signing certificate this would be used.
+# nsCertType = objsign
+
+# For normal client use this is typical
+# nsCertType = client, email
+
+# and for everything including object signing:
+# nsCertType = client, email, objsign
+
+# This is typical in keyUsage for a client certificate.
+# keyUsage = nonRepudiation, digitalSignature, keyEncipherment
+
+# This will be displayed in Netscape's comment listbox.
+nsComment			= "OpenSSL Generated Certificate"
+
+# PKIX recommendations harmless if included in all certificates.
+subjectKeyIdentifier=hash
+authorityKeyIdentifier=keyid,issuer:always
+
+# This stuff is for subjectAltName and issuerAltname.
+# Import the email address.
+# subjectAltName=email:copy
+# An alternative to produce certificates that aren't
+# deprecated according to PKIX.
+# subjectAltName=email:move
+
+# Copy subject details
+# issuerAltName=issuer:copy
+
+#nsCaRevocationUrl		= http://www.domain.dom/ca-crl.pem
+#nsBaseUrl
+#nsRevocationUrl
+#nsRenewalUrl
+#nsCaPolicyUrl
+#nsSslServerName
+
+# This really needs to be in place for it to be a proxy certificate.
+proxyCertInfo=critical,language:id-ppl-anyLanguage,pathlen:3,policy:foo
diff --git a/contrib/PKI/ca_script2/Makefile b/contrib/PKI/ca_script2/Makefile
new file mode 100644
index 0000000..845176e
--- /dev/null
+++ b/contrib/PKI/ca_script2/Makefile
@@ -0,0 +1,178 @@
+#!/usr/bin/make -s
+#
+# This file is inspired from freeDiameter's contrib/ca_script and
+# improved to handle multiple CA in a hierarchical fashion.
+# Warning: the directory structure is flat, does not reflect the CA hierarchy
+
+SCRIPT_DIR = .
+DATA_DIR = ./ca_data
+
+CONFIG = -config $(SCRIPT_DIR)/openssl.cnf
+REMAKE = $(MAKE) -f $(SCRIPT_DIR)/Makefile
+
+#Disable "make destroy" -- overwrite on command line
+force = 
+
+#RSA key sizes, can be overwritten on command line
+cakeysize = 2048
+keysize = 1024
+
+# Save current date
+DATE=`date +%Y%m%d-%H%M%S`
+
+# Default: print the help
+all:	help
+
+# Help message
+help:
+	@echo "\n\
+Available commands:\n\
+   make init topca=name\n\
+       Creates the initial top-level CA structure\n\
+   make newca name=newcaname ca=parentca\n\
+       Creates a new sub-CA that can be used for certificates later.\n\
+   make newcert name=foo ca=parentca\n\
+       Create private key and csr, then issue the certificate (named foo.*)\n\
+   make p12 name=foo ca=parentca\n\
+       Same as newcert, but additionnaly creates a pkcs12 file to ship client certificate to Windows or Mac\n\
+   make ship name=foo ca=parentca\n\
+       Create an archive with the data for the client (useful for freeDiameter peers)\n\
+   make revoke name=foo ca=parentca\n\
+       Revokes the certificate foo.cert issued by parentca and regenerates the CRL.\n\
+   make gencrl ca=caname\n\
+       Regenerates the CRL of CA caname. Should be run periodically.\n\
+\n\
+";
+
+# Destroy the CA hierarchy completely. Use with care.
+destroy:
+	@if [ -z "$(force)" ]; then echo "Destroy disabled, use: make destroy force=y"; exit 1; fi
+	@if [ ! -d $(SCRIPT_DIR) ]; then echo "Error in setup"; exit 1; fi
+	@echo "Removing everything (for debug purpose)..."
+	@rm -rf $(DATA_DIR)/*
+
+# Initialize the CA structure
+structure:
+	@if [ -z "$(caname)" ]; then echo "Internal error: caname is missing"; exit 1; fi
+	@if [ -d $(DATA_DIR)/$(caname) ]; then echo "CA $(caname) already exists."; exit 1; fi
+	# Creating CA structure
+	@mkdir -p $(DATA_DIR)/$(caname)
+	@mkdir $(DATA_DIR)/$(caname)/public
+	@mkdir $(DATA_DIR)/$(caname)/public/crl
+	@mkdir $(DATA_DIR)/$(caname)/private
+	@chmod 700 $(DATA_DIR)/$(caname)/private
+	@mkdir $(DATA_DIR)/$(caname)/clients
+	@echo "01" > $(DATA_DIR)/$(caname)/serial
+	@echo "01" > $(DATA_DIR)/$(caname)/crlnumber
+	@touch $(DATA_DIR)/$(caname)/index.txt
+
+# Initialize the top-level CA structure and keys.
+init:
+	@if [ -z "$(topca)" ]; then echo "Please specify the name of the root CA. Ex: make init topca=rootca.testbed.aaa"; exit 1; fi
+	# Create the folder hierarchy
+	@$(REMAKE) structure caname=$(topca)
+	# Generate the self-signed certificate
+	@CA_ROOT_DIR=$(DATA_DIR)/$(topca) openssl req $(CONFIG) -new -batch -x509 -days 3650 -nodes -newkey rsa:$(cakeysize) -out $(DATA_DIR)/$(topca)/public/cacert.pem \
+		-keyout $(DATA_DIR)/$(topca)/private/cakey.pem -extensions ca_cert -subj /CN=$(topca)
+	@ln -s cacert.pem $(DATA_DIR)/$(topca)/public/`openssl x509 -noout -hash < $(DATA_DIR)/$(topca)/public/cacert.pem`.0
+	@touch $(DATA_DIR)/$(topca)/public/cachain.pem
+	@ln -s ../../$(topca)/public/cacert.pem $(DATA_DIR)/$(topca)/public/caroot.pem 
+	@$(REMAKE) gencrl ca=$(topca)
+
+# Create a secondary CA
+newca:
+	@if [ -z "$(name)" -o -z "$(ca)" ]; then echo "Missing parameter. Ex: make newca name=subca.testbed.aaa ca=rootca.testbed.aaa"; exit 1; fi
+	@if [ ! -e $(DATA_DIR)/$(ca)/private/cakey.pem ]; then echo "The parent CA $(ca) does not exist."; exit 1; fi
+	@if [ ! -d $(DATA_DIR)/$(name) ]; then $(REMAKE) structure caname=$(name); fi
+	# Generate the private key and CSR for the new CA if needed
+	@if [ ! -e $(DATA_DIR)/$(name)/private/cakey.pem ]; then \
+		openssl genrsa -out $(DATA_DIR)/$(name)/private/cakey.pem $(cakeysize) ; fi
+	@if [ ! -e $(DATA_DIR)/$(name)/private/cacsr.pem ]; then \
+		CA_ROOT_DIR=$(DATA_DIR)/$(name) openssl req $(CONFIG) -new -batch -out $(DATA_DIR)/$(name)/private/cacsr.pem \
+			-key $(DATA_DIR)/$(name)/private/cakey.pem \
+			-subj /CN=$(name) -reqexts v3_req_ca; fi
+	# Revoke a previous certificate for this CA if any
+	@if [ -e $(DATA_DIR)/$(name)/public/cacert.pem ]; then \
+		echo "Revoking previous certificate ..."; \
+		$(REMAKE) revoke name=$(name) ca=$(ca); \
+		mv $(DATA_DIR)/$(name)/public/cacert.pem $(DATA_DIR)/$(name)/public/cacert-$(DATE).pem; fi
+	# Issue the new CA certificate
+	@CA_ROOT_DIR=$(DATA_DIR)/$(ca) openssl ca $(CONFIG) -in $(DATA_DIR)/$(name)/private/cacsr.pem \
+		-out $(DATA_DIR)/$(name)/public/cacert.pem \
+		-batch -extensions ca_cert
+	# Hash and link to parent
+	@ln -s cacert.pem $(DATA_DIR)/$(ca)/public/`openssl x509 -noout -hash < $(DATA_DIR)/$(name)/public/cacert.pem`.0
+	@rm -f $(DATA_DIR)/$(name)/parent
+	@ln -s ../$(ca) $(DATA_DIR)/$(name)/parent
+	@cat $(DATA_DIR)/$(name)/public/cacert.pem $(DATA_DIR)/$(ca)/public/cachain.pem > $(DATA_DIR)/$(name)/public/cachain.pem
+	@ln -s ../../$(ca)/public/caroot.pem $(DATA_DIR)/$(name)/public/caroot.pem
+	@for CRLFILE in `cd $(DATA_DIR)/$(ca)/public/crl && ls -1`; do ln -sf ../../../$(ca)/public/crl/$$CRLFILE $(DATA_DIR)/$(name)/public/crl/$$CRLFILE; done
+	@$(REMAKE) gencrl ca=$(name)
+
+# Create a new certificate for use in TLS communications and other terminal usages
+newcert:
+	@if [ -z "$(name)" -o -z "$(ca)" ]; then echo "Missing parameter. Ex: make newcert name=service.testbed.aaa ca=ca.testbed.aaa"; exit 1; fi
+	@if [ ! -e $(DATA_DIR)/$(ca)/private/cakey.pem ]; then echo "The parent CA $(ca) does not exist."; exit 1; fi
+	@if [ ! -d $(DATA_DIR)/$(ca)/clients/$(name) ]; then mkdir $(DATA_DIR)/$(ca)/clients/$(name); fi
+	# Create a private key if needed
+	@if [ ! -e $(DATA_DIR)/$(ca)/clients/$(name)/privkey.pem ]; then \
+		openssl genrsa -out $(DATA_DIR)/$(ca)/clients/$(name)/privkey.pem $(keysize); fi
+	# Create a CSR if needed
+	@if [ ! -e $(DATA_DIR)/$(ca)/clients/$(name)/csr.pem ]; then \
+		CA_ROOT_DIR=$(DATA_DIR)/$(ca) openssl req $(CONFIG) -new -batch -out $(DATA_DIR)/$(ca)/clients/$(name)/csr.pem \
+			-key $(DATA_DIR)/$(ca)/clients/$(name)/privkey.pem \
+			-subj /CN=$(name); fi
+	# Revoke a previous certificate if any
+	@if [ -e $(DATA_DIR)/$(ca)/clients/$(name)/cert.pem ]; then \
+		$(REMAKE) revoke name=$(name) ca=$(ca); \
+		mv $(DATA_DIR)/$(ca)/clients/$(name)/cert.pem $(DATA_DIR)/$(ca)/clients/$(name)/cert-$(DATE).pem; fi
+	# Now sign the new certificate with the CA key
+	@CA_ROOT_DIR=$(DATA_DIR)/$(ca) openssl ca $(CONFIG) -in $(DATA_DIR)/$(ca)/clients/$(name)/csr.pem \
+		-out $(DATA_DIR)/$(ca)/clients/$(name)/cert.pem \
+		-batch
+	# Hash
+	@ln -sf `cat $(DATA_DIR)/$(ca)/serial.old`.pem $(DATA_DIR)/$(ca)/public/`openssl x509 -noout -hash < $(DATA_DIR)/$(ca)/clients/$(name)/cert.pem`.0
+	# Compiled informations for the client
+	@cat $(DATA_DIR)/$(ca)/clients/$(name)/cert.pem $(DATA_DIR)/$(ca)/public/cachain.pem > $(DATA_DIR)/$(ca)/clients/$(name)/certchain.pem
+	@ln -sf ../../public/crl $(DATA_DIR)/$(ca)/clients/$(name)/crl
+	@ln -sf ../../public/caroot.pem $(DATA_DIR)/$(ca)/clients/$(name)/ca.pem
+
+# Create a PKCS#12 file containing the client's information
+p12:	newcert
+	# Create the PKCS#12 file
+	@cat 	$(DATA_DIR)/$(ca)/clients/$(name)/privkey.pem \
+		$(DATA_DIR)/$(ca)/clients/$(name)/certchain.pem \
+		$(DATA_DIR)/$(ca)/clients/$(name)/ca.pem \
+		| openssl pkcs12 -export -out $(DATA_DIR)/$(ca)/clients/$(name)/$(name).p12
+	@echo "Client certificate is created in $(DATA_DIR)/$(ca)/clients/$(name)/$(name).p12"
+
+# Create an archive to send the data to the client node
+ship:
+	@if [ -z "$(name)" -o -z "$(ca)" ]; then echo "Missing parameter. Ex: make ship name=service.testbed.aaa ca=ca.testbed.aaa"; exit 1; fi
+	@if [ ! -e $(DATA_DIR)/$(ca)/private/cakey.pem ]; then echo "The parent CA $(ca) does not exist."; exit 1; fi
+	@if [ ! -e  $(DATA_DIR)/$(ca)/clients/$(name)/privkey.pem ]; then echo "The client $(name) does not exist, use 'make newcert' first."; exit 1; fi
+	# Ship the data
+	@tar -c -C $(DATA_DIR)/$(ca)/clients/$(name) -z -f $(ca)_$(name).tar.gz -h .
+	@echo "The files have been packaged into archive: $(ca)_$(name).tar.gz"
+
+# Revoke a certificate
+revoke:
+	@if [ -z "$(name)" -o -z "$(ca)" ]; then echo "Missing parameter. Ex: make revoke name=service.testbed.aaa ca=ca.testbed.aaa"; exit 1; fi
+	@if [ ! -e $(DATA_DIR)/$(ca)/private/cakey.pem ]; then echo "The parent CA $(ca) does not exist."; exit 1; fi
+	@if [ ! -e $(DATA_DIR)/$(ca)/clients/$(name)/cert.pem ]; \
+		then echo "$(DATA_DIR)/$(ca)/clients/$(name)/cert.pem not found"; \
+		exit 1; \
+		fi;
+	# Revoke the certificate
+	@CA_ROOT_DIR=$(DATA_DIR)/$(ca) openssl ca $(CONFIG) -revoke $(DATA_DIR)/$(ca)/clients/$(name)/cert.pem;
+	@$(REMAKE) gencrl ca=$(ca)
+
+# Regenerate the Certificate Revocation List.
+gencrl:
+	@if [ -z "$(ca)" ]; then echo "Missing parameter. Ex: make gencrl ca=ca.testbed.aaa"; exit 1; fi
+	# Create the CRL
+	@CA_ROOT_DIR=$(DATA_DIR)/$(ca) openssl ca $(CONFIG) -gencrl -out $(DATA_DIR)/$(ca)/public/crl/$(ca).pem
+	@ln -s crl/$(ca).pem $(DATA_DIR)/$(ca)/public/local.pem
+	@ln -s local.pem $(DATA_DIR)/$(ca)/public/`openssl crl -noout -hash < $(DATA_DIR)/$(ca)/public/crl/$(ca).pem`.r0
+
+# End of file...
diff --git a/contrib/PKI/ca_script2/openssl.cnf b/contrib/PKI/ca_script2/openssl.cnf
new file mode 100644
index 0000000..2202209
--- /dev/null
+++ b/contrib/PKI/ca_script2/openssl.cnf
@@ -0,0 +1,120 @@
+# Note: for this file to be working, an environment var CA_ROOT_DIR = directory 
+# must be defined and pointing to the CA top-level directory.
+
+HOME			= .
+RANDFILE		= $ENV::HOME/.rnd
+
+oid_section		= new_oids
+
+[ new_oids ]
+
+
+####################################################################
+[ req ]
+default_bits		= 1024
+# default_keyfile 	= privkey.pem
+string_mask 		= utf8only
+
+distinguished_name	= req_distinguished_name
+attributes		= req_attributes
+req_extensions 		= v3_req    # overwrite with -reqexts
+x509_extensions		= ca_cert   # overwrite with -extensions; used for self-signed keys only
+
+[ req_distinguished_name ]
+countryName			= Country Name (2 letter code)
+countryName_default		= JP
+countryName_min			= 2
+countryName_max			= 2
+stateOrProvinceName		= State or Province Name (full name)
+stateOrProvinceName_default	= Tokyo
+localityName			= Locality Name (eg, city)
+localityName_default		= Koganei
+0.organizationName		= Organization Name (eg, company)
+0.organizationName_default	= WIDE
+1.organizationName		= Second Organization Name (eg, company)
+1.organizationName_default	= NICT
+organizationalUnitName		= Organizational Unit Name (eg, section)
+organizationalUnitName_default	= AAA WG testbed
+
+[ req_attributes ]
+challengePassword		= A challenge password
+challengePassword_min		= 0
+challengePassword_max		= 20
+unstructuredName		= An optional company name
+
+[ v3_req ]
+# Extensions to add to a certificate request
+basicConstraints = CA:FALSE
+keyUsage = nonRepudiation, digitalSignature, keyEncipherment
+
+[ v3_req_ca ]
+# Extensions to add to a certificate request for CA
+basicConstraints = CA:TRUE
+
+
+####################################################################
+[ ca ]
+default_ca	= CA_default		# The default ca section
+
+[ CA_default ]
+
+dir		= $ENV::CA_ROOT_DIR	# Where everything is kept
+certs		= $dir/public		# Where the issued certs are kept
+crl_dir		= $dir/public		# Where the issued crl are kept
+database	= $dir/index.txt	# database index file.
+#unique_subject	= no			# Set to 'no' to allow creation of
+					# several ctificates with same subject.
+new_certs_dir	= $dir/public		# default place for new certs.
+
+certificate	= $dir/public/cacert.pem 	# The CA certificate
+serial		= $dir/serial 		# The current serial number
+crlnumber	= $dir/crlnumber	# the current crl number
+crl		= $dir/public/local.pem 		# The current CRL
+private_key	= $dir/private/cakey.pem	# The private key
+x509_extensions	= usr_cert		# The extentions to add to the cert
+					# overwrite with -extensions
+name_opt 	= ca_default		# Subject Name options
+cert_opt 	= ca_default		# Certificate field options
+crl_extensions	= crl_ext
+
+default_days	= 3650			# how long to certify for
+default_crl_days= 365			# how long before next CRL
+default_md	= sha1			# which md to use.
+preserve	= no			# keep passed DN ordering
+
+# We accept to sign anything, but a real deployment would limit to proper domain etc...
+policy			= policy_anything
+
+[ policy_anything ]
+countryName		= optional
+stateOrProvinceName	= optional
+localityName		= optional
+organizationName	= optional
+organizationalUnitName	= optional
+commonName		= supplied
+emailAddress		= optional
+
+[ usr_cert ]
+basicConstraints=CA:FALSE
+# This is typical in keyUsage for a client certificate.
+keyUsage = nonRepudiation, digitalSignature, keyEncipherment
+subjectKeyIdentifier=hash
+authorityKeyIdentifier=keyid,issuer
+
+[ ca_cert ]
+# Extensions for a typical CA
+subjectKeyIdentifier=hash
+authorityKeyIdentifier=keyid:always,issuer:always
+basicConstraints = critical,CA:true  # Remove "critical," in case of problems
+keyUsage = cRLSign, keyCertSign
+# subjectAltName=email:copy
+# Copy issuer details
+# issuerAltName=issuer:copy
+
+[ crl_ext ]
+# CRL extensions.
+# Only issuerAltName and authorityKeyIdentifier make any sense in a CRL.
+# issuerAltName=issuer:copy
+authorityKeyIdentifier=keyid:always,issuer:always
+
+
diff --git a/contrib/PKI/phpki-0.82.patch b/contrib/PKI/phpki-0.82.patch
new file mode 100644
index 0000000..e954d88
--- /dev/null
+++ b/contrib/PKI/phpki-0.82.patch
@@ -0,0 +1,284 @@
+diff -Nur phpki-0.82/ca/main.php phpki-0.82-fD/ca/main.php
+--- phpki-0.82/ca/main.php	2005-11-17 10:17:20.000000000 +0900
++++ phpki-0.82-fD/ca/main.php	2010-05-27 17:04:44.000000000 +0900
+@@ -36,7 +36,7 @@
+         else {
+                 ?>
+                 <font color=#ff0000>
+-                <h2>There was an error updating the Certificate Revocation List.</h2></font><br>
++                <h2>There was an error updating the Certificate Revocation List.</h2></font><br />
+                 <blockquote>
+                 <h3>Debug Info:</h3>
+                 <pre><?=$errtxt?></pre>
+@@ -53,8 +53,11 @@
+ default:
+ 	printHeader('ca');
+ 	?>
+-	<br>
+-	<br>
++	<br />
++	<br />
++
++	<center><h3>For <span style="color: #FF0000;">freeDiameter</span> specific instructions, scroll down this page...</h3></center><br />
++
+ 	<center>
+ 	<table class=menu width=600><th class=menu colspan=2><big>CERTIFICATE MANAGEMENT MENU</big></th>
+ 
+@@ -89,7 +92,57 @@
+ 
+ 	</table>
+ 	</center>
+-	<br><br>
++	<br /><br />
++	<center>
++	<table class=menu width=900><th class=menu colspan=2><big>FREEDIAMETER INSTRUCTIONS</big></th>
++        <tr><td style="text-align: center; vertical-align: middle; font-weight: bold;">
++        Create a new certificate</td>
++
++	<td>Use the <strong><cite>Create a New Certificate</cite></strong> link in previous table to request a new certificate. Fill the form as follow:
++	<ul>
++	  <li><strong>Common Name</strong>: use your new freeDiameter identity (usually the FQDN).</li>
++	  <li><strong>E-mail Address</strong>: Provide your address so that you can be contacted in case of inquiry.</li>
++	  <li><strong>Organization</strong>: use "freeDiameter testbed" for example.</li>
++          <li><strong>Certificate Password</strong>: Do not loose the password you provide, you'll need it in the next step. <br />
++		The password must be >= 8 chars.</li>
++	  <li>The other fields can be filled at your taste.</li>
++	</ul>
++	Once you have validated, you can check the values, and then proceed to download the new certificate and private key.
++	You will receive a file in PEM format. Let's call this file <em>mycertprotected.pem</em>.
++        It contains:
++        <ul>
++          <li>Your password-protected RSA private key.</li>
++          <li>Your certificate in PEM format.</li>
++          <li>The CA certificate.</li>
++        </ul></td></tr>
++
++        <tr><td style="text-align: center; vertical-align: middle; font-weight: bold;">
++        Split the file</td>
++	
++	<td>In order to use the information with freeDiameter daemon, you must transform the data as follow:
++	<ul>
++	  <li><strong>Decode the private key</strong>: <br />
++		<code>openssl rsa -in <em>mycertprotected.pem</em> -out /etc/ssl/private/freeDiameter.key</code><br />
++	OpenSSL will ask for the password you entered when creating the certificate.</li>
++	  <li><strong>Extract your certificate</strong>: <br />
++                <code>openssl x509 -in <em>mycertprotected.pem</em> > /etc/ssl/certs/freeDiameter.pem</code></li>
++          <li><strong>Get the CA certificate</strong>: <br />
++                <code>wget --no-check-certificate "$config[base_url]index.php?stage=dl_root" -O /etc/ssl/certs/freeDiameter_testbed_CA.pem</code></li>
++	</ul>
++	Note: for the last step, you could also extract it directly from the PEM file you received.<br />
++	Note: the CRL is also available from the website, but this feature is not tested yet.</td></tr>
++
++	<tr><td style="text-align: center; vertical-align: middle; font-weight: bold;">
++        Configure freeDiameter</td>
++
++        <td>Here is the configuration related to TLS that you should set in your <em>/etc/freeDiameter/freeDiameter.conf</em> file:
++	<blockquote>TLS_Cred = "/etc/ssl/certs/freeDiameter.pem", "/etc/ssl/private/freeDiameter.key";<br />
++TLS_CA = "/etc/ssl/certs/freeDiameter_testbed_CA.pem";</blockquote></td></tr>
++
++
++        </table>
++        </center>
++	<br /><br />	
+ 	<?
+ 	printFooter();
+ }
+diff -Nur phpki-0.82/ca/request_cert.php phpki-0.82-fD/ca/request_cert.php
+--- phpki-0.82/ca/request_cert.php	2007-01-04 14:45:09.000000000 +0900
++++ phpki-0.82-fD/ca/request_cert.php	2010-05-27 16:59:16.000000000 +0900
+@@ -197,6 +197,7 @@
+ 
+                 switch($cert_type) {
+                 case 'server':
++                case 'freediameter':
+                         upload(array("$config[private_dir]/$serial-key.pem","$config[new_certs_dir]/$serial.pem",$config['cacert_pem']), "$common_name ($email).pem",'application/pkix-cert');
+                         break;
+                 case 'email':
+@@ -225,7 +226,7 @@
+ 	if (! $email)         $email = "";
+ 	if (! $expiry)        $expiry = 1;
+ 	if (! $keysize)       $keysize = 1024;
+-	if (! $cert_type)     $cert_type = 'email';
++	if (! $cert_type)     $cert_type = 'freediameter';
+ 
+ 	printHeader();
+ 	?>
+@@ -302,13 +303,14 @@
+ 	<td>Certificate Use: </td>
+ 	<td><select name=cert_type>
+ 	<?
+-	print '<option value="email" '.($cert_type=='email'?'selected':'').'>E-mail, SSL Client</option>';
+-	print '<option value="email_signing" '.($cert_type=='email_signing'?'selected':'').'>E-mail, SSL Client, Code Signing</option>';
+-	print '<option value="server" '.($cert_type=='server'?'selected':'').'>SSL Server</option>';
+-	print '<option value="vpn_client" '.($cert_type=='vpn_client'?'selected':'').'>VPN Client Only</option>';
+-	print '<option value="vpn_server" '.($cert_type=='vpn_server'?'selected':'').'>VPN Server Only</option>';
+-	print '<option value="vpn_client_server" '.($cert_type=='vpn_client_server'?'selected':'').'>VPN Client, VPN Server</option>';
+-	print '<option value="time_stamping" '.($cert_type=='time_stamping'?'selected':'').'>Time Stamping</option>';
++	print '<option value="email" disabled '.($cert_type=='email'?'selected':'').'>E-mail, SSL Client</option>';
++	print '<option value="email_signing" disabled '.($cert_type=='email_signing'?'selected':'').'>E-mail, SSL Client, Code Signing</option>';
++	print '<option value="server" disabled '.($cert_type=='server'?'selected':'').'>SSL Server</option>';
++	print '<option value="freediameter" '.($cert_type=='freediameter'?'selected':'').'>freeDiameter node</option>';
++	print '<option value="vpn_client" disabled '.($cert_type=='vpn_client'?'selected':'').'>VPN Client Only</option>';
++	print '<option value="vpn_server" disabled '.($cert_type=='vpn_server'?'selected':'').'>VPN Server Only</option>';
++	print '<option value="vpn_client_server" disabled '.($cert_type=='vpn_client_server'?'selected':'').'>VPN Client, VPN Server</option>';
++	print '<option value="time_stamping" disabled '.($cert_type=='time_stamping'?'selected':'').'>Time Stamping</option>';
+ 	?>
+ 	</select></td>
+ 	</tr>
+diff -Nur phpki-0.82/include/openssl_functions.php phpki-0.82-fD/include/openssl_functions.php
+--- phpki-0.82/include/openssl_functions.php	2007-01-04 15:47:57.000000000 +0900
++++ phpki-0.82-fD/include/openssl_functions.php	2010-05-27 16:59:57.000000000 +0900
+@@ -69,6 +69,13 @@
+ default_days           = 365
+ policy                 = policy_supplied
+ 
++[ freediameter_cert ]
++x509_extensions        = freediameter_ext
++default_days           = 730
++policy                 = policy_supplied
++
++
++
+ [ vpn_cert ]
+ x509_extensions        = vpn_client_server_ext
+ default_days           = 365
+@@ -152,6 +159,24 @@
+ nsRevocationUrl         = ns_revoke_query.php?
+ nsCaPolicyUrl           = $config[base_url]policy.html
+ 
++[ freediameter_ext ]
++basicConstraints        = CA:false
++keyUsage                = critical, digitalSignature, keyEncipherment
++extendedKeyUsage        = critical, serverAuth, clientAuth
++nsCertType              = critical, server, client
++subjectKeyIdentifier    = hash
++authorityKeyIdentifier  = keyid:always, issuer:always
++subjectAltName          = DNS:$common_name,email:copy
++issuerAltName           = issuer:copy
++crlDistributionPoints   = URI:$config[base_url]index.php?stage=dl_crl
++nsComment               = \"PHPki/OpenSSL Generated Secure Certificate for freeDiameter\"
++nsBaseUrl                       = $config[base_url]
++nsRevocationUrl             = ns_revoke_query.php?
++nsCaPolicyUrl           = $config[base_url]policy.html
++
++
++
++
+ [ time_stamping_ext ]
+ basicConstraints       = CA:false
+ keyUsage               = critical, nonRepudiation, digitalSignature
+diff -Nur phpki-0.82/openssl.cnf phpki-0.82-fD/openssl.cnf
+--- phpki-0.82/openssl.cnf	2006-07-23 00:33:34.000000000 +0900
++++ phpki-0.82-fD/openssl.cnf	2010-05-27 17:00:33.000000000 +0900
+@@ -39,6 +39,11 @@
+ default_days           = 365
+ policy                 = policy_supplied
+ 
++[ freediameter_cert ]
++x509_extensions        = freediameter_ext
++default_days           = 730
++policy                 = policy_supplied
++
+ [ vpn_cert ]
+ x509_extensions        = vpn_client_server_ext
+ default_days           = 365
+@@ -115,6 +120,23 @@
+ nsRevocationUrl		= ns_revoke_query.php?
+ nsCaPolicyUrl           = http://www.somewhere.com/phpki/policy.html
+ 
++[ freediameter_ext ]
++basicConstraints        = CA:false
++keyUsage                = critical, digitalSignature, keyEncipherment
++extendedKeyUsage        = critical, serverAuth, clientAuth
++nsCertType              = critical, server, client
++subjectKeyIdentifier    = hash
++authorityKeyIdentifier  = keyid:always, issuer:always
++subjectAltName          = DNS:$common_name,email:copy
++issuerAltName           = issuer:copy
++crlDistributionPoints   = URI:$config[base_url]index.php?stage=dl_crl
++nsComment               = "PHPki/OpenSSL Generated Secure Certificate for freeDiameter"
++nsBaseUrl                       = $config[base_url]
++nsRevocationUrl             = ns_revoke_query.php?
++nsCaPolicyUrl           = $config[base_url]policy.html
++
++
++
+ [ vpn_client_ext ]
+ basicConstraints        = critical, CA:false
+ keyUsage                = critical, digitalSignature
+diff -Nur phpki-0.82/setup.php phpki-0.82-fD/setup.php
+--- phpki-0.82/setup.php	2007-07-22 23:34:08.000000000 +0900
++++ phpki-0.82-fD/setup.php	2010-05-27 17:01:41.000000000 +0900
+@@ -339,6 +339,11 @@
+ default_days           = 365
+ policy                 = policy_supplied
+ 
++[ freediameter_cert ]
++x509_extensions        = freediameter_ext
++default_days           = 730
++policy                 = policy_supplied
++
+ [ vpn_cert ]
+ x509_extensions        = vpn_client_server_ext
+ default_days           = 365
+@@ -418,6 +423,22 @@
+ nsRevocationUrl		    = ns_revoke_query.php?
+ nsCaPolicyUrl           = $config[base_url]policy.html
+ 
++[ freediameter_ext ]
++basicConstraints        = CA:false
++keyUsage                = critical, digitalSignature, keyEncipherment
++extendedKeyUsage        = critical, serverAuth, clientAuth
++nsCertType              = critical, server, client
++subjectKeyIdentifier    = hash
++authorityKeyIdentifier  = keyid:always, issuer:always
++subjectAltName          = DNS:$common_name,email:copy
++issuerAltName           = issuer:copy
++crlDistributionPoints   = URI:$config[base_url]index.php?stage=dl_crl
++nsComment               = "PHPki/OpenSSL Generated Secure Certificate for freeDiameter"
++nsBaseUrl		        = $config[base_url]
++nsRevocationUrl		    = ns_revoke_query.php?
++nsCaPolicyUrl           = $config[base_url]policy.html
++
++
+ [ time_stamping_ext ]
+ basicConstraints       = CA:false
+ keyUsage               = critical, nonRepudiation, digitalSignature
+diff -Nur phpki-0.82/setup.php-presetup phpki-0.82-fD/setup.php-presetup
+--- phpki-0.82/setup.php-presetup	2007-07-22 23:34:08.000000000 +0900
++++ phpki-0.82-fD/setup.php-presetup	2010-05-27 17:01:41.000000000 +0900
+@@ -339,6 +339,11 @@
+ default_days           = 365
+ policy                 = policy_supplied
+ 
++[ freediameter_cert ]
++x509_extensions        = freediameter_ext
++default_days           = 730
++policy                 = policy_supplied
++
+ [ vpn_cert ]
+ x509_extensions        = vpn_client_server_ext
+ default_days           = 365
+@@ -418,6 +423,22 @@
+ nsRevocationUrl		    = ns_revoke_query.php?
+ nsCaPolicyUrl           = $config[base_url]policy.html
+ 
++[ freediameter_ext ]
++basicConstraints        = CA:false
++keyUsage                = critical, digitalSignature, keyEncipherment
++extendedKeyUsage        = critical, serverAuth, clientAuth
++nsCertType              = critical, server, client
++subjectKeyIdentifier    = hash
++authorityKeyIdentifier  = keyid:always, issuer:always
++subjectAltName          = DNS:$common_name,email:copy
++issuerAltName           = issuer:copy
++crlDistributionPoints   = URI:$config[base_url]index.php?stage=dl_crl
++nsComment               = "PHPki/OpenSSL Generated Secure Certificate for freeDiameter"
++nsBaseUrl		        = $config[base_url]
++nsRevocationUrl		    = ns_revoke_query.php?
++nsCaPolicyUrl           = $config[base_url]policy.html
++
++
+ [ time_stamping_ext ]
+ basicConstraints       = CA:false
+ keyUsage               = critical, nonRepudiation, digitalSignature
diff --git a/contrib/README b/contrib/README
new file mode 100644
index 0000000..678d30b
--- /dev/null
+++ b/contrib/README
@@ -0,0 +1,61 @@
+This file describes the content of the "contrib" directory. 
+For information about the freeDiameter project, please refer
+to top-level README file.
+
+- update_copyright.sh : This script will simply update the copyright information
+        in all source files in the freeDiameter mercurial repository, based
+	on the last modification time. Thought I might share it if other people find
+	it useful for their own project...
+
+
+- debian : This directory contains the packaging information to create native Debian / Ubuntu 
+	packages. It requires debhelper >= 7.3.9 (support for cmake). To use, simply link the
+	debian folder from the main freeDiameter folder, then use your building script as
+	usual ('dh binary' or 'pdebuild' or ...).
+	If you simply intend to use freeDiameter package, the relevant information is located
+	at: http://www.freediameter.net/trac/wiki/DebRepository
+
+
+- PKI : This directory contains useful material related to establishing a 
+        Public Key Infrastructure (PKI) for deploying x509 certificates 
+	and use these for TLS authentication of the freeDiameter nodes.
+	
+        IMPORTANT: Please note that these solutions are NOT suitable 
+	for use in a production environment! It allows easy deployment of 
+	certificates for tests, and that is their sole purpose.
+    
+        The directory contains:
+	
+    - ca_script: a simple Makefile allowing you to generate a self-signed certificate (root)
+                and then issue new certificates and private keys for your users.
+		Run "make" without argument to get the help.
+		
+    - ca_script2: An evolution of the previous Makefile. This one allows you
+    		to create a hierarchy of CA and certificates. 
+
+    - phpki-0.82.patch : This patch is to be applied to PHPki to customize the use for freeDiameter.
+                PHPki (http://sourceforge.net/projects/phpki/) is a PHP-based web interface
+		that provides more or less the same services as ca_script.
+
+
+- OpenWRT : This directory contains the scripts and documentation related to 
+	the integration of freeDiameter RADIUS/Diameter gateway component in the openWRT
+	distribution (http://openwrt.org) -- the goal is to give the access point the 
+	ability to "talk" Diameter instead of RADIUS.
+				
+
+- nightly_tests : This directory contains the scripts and documentation for the nightly 
+	tests run on freeDiameter. The results are published at the following URL:
+	http://www.freediameter.net/CDash/index.php?project=freeDiameter
+
+
+- dict_legacy: XML and DTD files for the dict_legacy_xml.fdx extension.
+
+- dict_dcca: partial implementations of the DCCA dictionary
+
+- dict_gx: untested implementation of the Gx interface.
+
+- test_Gx: a responder on the Gx interface that always send SUCCESS status.
+
+- wireshark: This contains some information on how to use Wireshark to monitor Diameter
+	exchange protected with TLS. It involves patching the wireshark software.
diff --git a/contrib/RPM/build_rpm.txt b/contrib/RPM/build_rpm.txt
new file mode 100755
index 0000000..53eb77f
--- /dev/null
+++ b/contrib/RPM/build_rpm.txt
@@ -0,0 +1,6 @@
+[krum@ThinkPad DelMe]$ cp freeDiameter.spec /home/krum/rpmbuild/SPECS/
+[krum@ThinkPad DelMe]$ cd /home/krum/rpmbuild/SOURCES/
+[krum@ThinkPad ~]$ cd /home/krum/rpmbuild/SOURCES/
+[krum@ThinkPad SOURCES]$ wget http://www.freediameter.net/hg/freeDiameter/archive/1.1.6.tar.gz
+[krum@ThinkPad SOURCES]$ cd ../SPECS/
+[krum@ThinkPad SPECS]$ rpmbuild -ba freeDiameter.spec
diff --git a/contrib/RPM/freeDiameter.spec b/contrib/RPM/freeDiameter.spec
new file mode 100755
index 0000000..7f492db
--- /dev/null
+++ b/contrib/RPM/freeDiameter.spec
@@ -0,0 +1,78 @@
+
+Name: freeDiameter		
+Version: 1.1.6 	
+Release: 1%{?dist}
+Packager: krum.boy4ev@gmail.com
+Summary: freeDiameter is an implementation of the Diameter protocol. 	
+Group: Development/Libraries		
+License: BSD License	
+URL: http://www.freediameter.net		
+Source0: http://www.freediameter.net/hg/freeDiameter/archive/1.1.6.tar.gz	
+
+BuildRequires: cmake make gcc gcc-c++ flex bison lksctp-tools-devel 
+BuildRequires: gnutls-devel libgcrypt-devel libidn-devel
+BuildRequires: mercurial	
+Requires: lksctp-tools	
+
+%description
+freeDiameter is an implementation of the Diameter protocol.
+	
+Diameter is a protocol designed to carry Authentication, Authorization and
+Accounting (AAA) payload. It is an evolution of the RADIUS protocol (as the
+name suggests).
+
+See http://www.freediameter.net/ for more information on the project.
+	
+freeDiameter was previously known as the "waaad" project (WIDE AAA Daemon)
+This project is not related to the "freediameter" project from Sun on sourceforge.
+	
+Author: Sebastien Decugis.
+
+%package daemon
+Summary:  Simple daemon parses the command line and initializes the freeDiameter framework.
+Group: Development/Libraries
+Requires: freeDiameter
+
+%description daemon
+freeDiameterd : this simple daemon parses the command line and initializes the
+freeDiameter framework. Use it for your Diameter server & agent components.
+In case of Diameter clients, you probably will prefer linking the libfdcore
+directly with your client application that must be made Diameter-aware.
+
+
+%prep
+%setup -qn %{name}-%{version}
+
+
+%build
+mkdir -p build
+cd build
+cmake ../
+
+make %{?_smp_mflags}
+
+
+%install
+rm -rf $RPM_BUILD_ROOT
+cd build
+make install DESTDIR=$RPM_BUILD_ROOT
+make test
+
+%post daemon
+echo "/usr/local/lib/" > /etc/ld.so.conf.d/%{name}.conf 
+/sbin/ldconfig
+
+%files
+%defattr(-,root,root,-)
+/usr/local/include/
+/usr/local/lib/
+
+%files daemon
+%defattr(-,root,root,-)
+/usr/local/bin/
+
+
+
+%changelog
+ * Sat Jul 5 2013 Krum Boychev <krum.boy4ev@gmail.com> - 1.1.6-1
+ - initial version
diff --git a/contrib/app_acct_tools/README b/contrib/app_acct_tools/README
new file mode 100644
index 0000000..4728f15
--- /dev/null
+++ b/contrib/app_acct_tools/README
@@ -0,0 +1,47 @@
+This folder contains several tools to use and parse the data from the app_acct.fdx extension.
+
+- database.sql :
+    An example database format for use with the scripts in this folder.
+    
+- app_acct.conf :
+    The part of app_acct.conf that is relevant to this database schema.
+
+- purge_to_file.php : 
+    This PHP script is used to take the records from the incoming table (stored by app_acct.fdx 
+  extension) and save these records in a file in SQL format. This is similar to pg_dump 
+  command, except that all the records that have been saved in the file are removed from 
+  the table. This can be used in cron jobs for example to maintain a reasonable size of 
+  the incoming table and move the data to another host for off-line processing. It can 
+  also be useful to aggregate the data from different hosts, if you are load-balancing your
+  accounting servers for example (granted that all app_acct.fdx use identical table format
+  on all the servers). See the top of the file for configuration parameters.
+    
+- process_records.php :
+    This PHP script processes the records pertaining to users sessions, as follow:
+  * when a session is complete (STOP record received), it stores a session summary
+  into the processed records table (see process_database.sql file for format). 
+  * It optionally archives the processed records into a different table, before deleting them.
+  * It can also move records of unterminated sessions that are older than a configurable time 
+  to an orphan_records table, so that they are not re-processed every time. 
+  This orphans table must have the same structure as the "incoming" table.
+  
+- display_results.php, display_self.php, display_stats.php :
+   These scripts give a few examples of how to display the processed data.
+  
+USAGE:
+ *) Initial: create your database using database.sql file
+ *) Configure the app_acct.fdx extension using tips from app_acct.conf
+
+  The following processing can be run for example as cron jobs.
+ 1) On each accounting server for the realm, configure the app_acct.fdx extension to
+   dump the records in a local database (all servers must use the same database format).
+   The table would typically be "incoming".
+ 2) Run the purge_to_file.php script on each server regularly, then move the generated
+   files onto a single server for processing. This server only needs the other tables.
+ 3) Add the data from the files into the database in this server by running:
+   psql < file.sql
+    Each file that has been added should then be archived and removed so that it is not 
+   re-added later.
+ 4) Run the process_records.php script on this processing server. Now, the database
+   contains the aggregated data that can be visualized with display_*.php scripts.
+   
diff --git a/contrib/app_acct_tools/app_acct.conf b/contrib/app_acct_tools/app_acct.conf
new file mode 100644
index 0000000..0c9cdb8
--- /dev/null
+++ b/contrib/app_acct_tools/app_acct.conf
@@ -0,0 +1,68 @@
+
+# This is the configuration for use with the database created by 'database.sql' file.
+# One should take care of configuring the ConnInfo properly.
+ConnInfo = "";
+
+# The table and special fields names:
+Table = "incoming";
+Timestamp_field = "recorded_on";
+Server_name_field = "recorded_serv";
+
+# The AVPs that are saved in the table:
+"Origin-Host";
+"Origin-Realm";
+"Destination-Realm";
+"Destination-Host";
+"Session-Id";
+"Origin-State-Id"; 
+"Accounting-Record-Type";
+"Accounting-Record-Number";
+"User-Name";
+"Event-Timestamp"; 
+"Acct-Application-Id";
+"Accounting-Sub-Session-Id";
+"Acct-Session-Id";
+"Acct-Multi-Session-Id";
+"Origin-AAA-Protocol";
+"Acct-Delay-Time"; 
+"NAS-Identifier";
+"NAS-IP-Address";
+"NAS-IPv6-Address";
+"NAS-Port";
+"NAS-Port-Id";
+"NAS-Port-Type";
+"Service-Type";
+"Termination-Cause"; 
+"Accounting-Input-Octets";
+"Accounting-Input-Packets";
+"Accounting-Output-Octets";
+"Accounting-Output-Packets";
+"Acct-Authentic";
+"Acct-Link-Count";
+"Acct-Session-Time"; 
+"Acct-Tunnel-Connection";
+"Acct-Tunnel-Packets-Lost"; 
+"Callback-Id";
+"Callback-Number";
+"Called-Station-Id";
+"Calling-Station-Id"; 
+"Connect-Info";
+"Originating-Line-Info"; 
+"Authorization-Lifetime";
+"Session-Timeout";
+"Idle-Timeout";
+"Port-Limit";
+"Accounting-Realtime-Required"; 
+"Acct-Interim-Interval";
+"Filter-Id";
+"NAS-Filter-Rule";
+"QoS-Filter-Rule"; 
+"Login-IP-Host";
+"Login-IPv6-Host";
+"Login-LAT-Group";
+"Login-LAT-Node";
+"Login-LAT-Port"; 
+"Login-LAT-Service";
+"Login-Service";
+"Login-TCP-Port"; 
+"Route-Record" = { multi=5; };
diff --git a/contrib/app_acct_tools/database.sql b/contrib/app_acct_tools/database.sql
new file mode 100644
index 0000000..c3a3072
--- /dev/null
+++ b/contrib/app_acct_tools/database.sql
@@ -0,0 +1,227 @@
+-- database.sql
+-- Script to create the tables for process_records.php script to perform.
+-- IMPORTANT NOTE: No constraint and almost no index are created by this script. 
+-- One should consider adding the appropriate indexes according to their utilization of the data.
+
+-- Incoming table table.
+--  This table is used by app_acct.fdx to store the Accounting records.
+CREATE TABLE incoming (
+    "Origin-Host" bytea NOT NULL,
+    "Origin-Realm" bytea NOT NULL,
+    "Destination-Realm" bytea,
+    "Destination-Host" bytea,
+    "Session-Id" bytea NOT NULL,
+    "Origin-State-Id" integer,
+    "Accounting-Record-Type" integer NOT NULL,
+    "Accounting-Record-Number" integer NOT NULL,
+    "User-Name" bytea,
+    "Event-Timestamp" bytea,
+    "Acct-Application-Id" integer,
+    "Accounting-Sub-Session-Id" bigint,
+    "Acct-Session-Id" bytea,
+    "Acct-Multi-Session-Id" bytea,
+    "Origin-AAA-Protocol" integer,
+    "Acct-Delay-Time" integer,
+    "NAS-Identifier" bytea,
+    "NAS-IP-Address" bytea,
+    "NAS-IPv6-Address" bytea,
+    "NAS-Port" integer,
+    "NAS-Port-Id" bytea,
+    "NAS-Port-Type" integer,
+    "Service-Type" integer,
+    "Termination-Cause" integer,
+    "Accounting-Input-Octets" bigint,
+    "Accounting-Input-Packets" bigint,
+    "Accounting-Output-Octets" bigint,
+    "Accounting-Output-Packets" bigint,
+    "Acct-Authentic" integer,
+    "Acct-Link-Count" integer,
+    "Acct-Session-Time" integer,
+    "Acct-Tunnel-Connection" bytea,
+    "Acct-Tunnel-Packets-Lost" integer,
+    "Callback-Id" bytea,
+    "Callback-Number" bytea,
+    "Called-Station-Id" bytea,
+    "Calling-Station-Id" bytea,
+    "Connect-Info" bytea,
+    "Originating-Line-Info" bytea,
+    "Authorization-Lifetime" integer,
+    "Session-Timeout" integer,
+    "Idle-Timeout" integer,
+    "Port-Limit" integer,
+    "Accounting-Realtime-Required" integer,
+    "Acct-Interim-Interval" integer,
+    "Filter-Id" bytea,
+    "NAS-Filter-Rule" bytea,
+    "QoS-Filter-Rule" bytea,
+    "Login-IP-Host" bytea,
+    "Login-IPv6-Host" bytea,
+    "Login-LAT-Group" bytea,
+    "Login-LAT-Node" bytea,
+    "Login-LAT-Port" bytea,
+    "Login-LAT-Service" bytea,
+    "Login-Service" integer,
+    "Login-TCP-Port" integer,
+    "Route-Record1" bytea,
+    "Route-Record2" bytea,
+    "Route-Record3" bytea,
+    "Route-Record4" bytea,
+    "Route-Record5" bytea,
+    "recorded_on" timestamp with time zone NOT NULL,
+    "recorded_serv" bytea
+ );
+
+
+-- Accounting Data.
+--  This is is the processed data that is used also by display_results.php
+CREATE TABLE processed (
+    user_name bytea,
+    user_device bytea,
+    nas_info bytea,
+    sess_start timestamp with time zone,
+    sess_duration interval,
+    downl_bytes bigint,
+    upl_bytes bigint,
+    downl_packets bigint,
+    upl_packets bigint
+ );
+CREATE INDEX un_index ON processed (user_name);
+
+
+
+-- Orphans table.
+--  This is optional, and it must match the structure of your incoming table.
+CREATE TABLE orphans (
+    "Origin-Host" bytea NOT NULL,
+    "Origin-Realm" bytea NOT NULL,
+    "Destination-Realm" bytea,
+    "Destination-Host" bytea,
+    "Session-Id" bytea NOT NULL,
+    "Origin-State-Id" integer,
+    "Accounting-Record-Type" integer NOT NULL,
+    "Accounting-Record-Number" integer NOT NULL,
+    "User-Name" bytea,
+    "Event-Timestamp" bytea,
+    "Acct-Application-Id" integer,
+    "Accounting-Sub-Session-Id" bigint,
+    "Acct-Session-Id" bytea,
+    "Acct-Multi-Session-Id" bytea,
+    "Origin-AAA-Protocol" integer,
+    "Acct-Delay-Time" integer,
+    "NAS-Identifier" bytea,
+    "NAS-IP-Address" bytea,
+    "NAS-IPv6-Address" bytea,
+    "NAS-Port" integer,
+    "NAS-Port-Id" bytea,
+    "NAS-Port-Type" integer,
+    "Service-Type" integer,
+    "Termination-Cause" integer,
+    "Accounting-Input-Octets" bigint,
+    "Accounting-Input-Packets" bigint,
+    "Accounting-Output-Octets" bigint,
+    "Accounting-Output-Packets" bigint,
+    "Acct-Authentic" integer,
+    "Acct-Link-Count" integer,
+    "Acct-Session-Time" integer,
+    "Acct-Tunnel-Connection" bytea,
+    "Acct-Tunnel-Packets-Lost" integer,
+    "Callback-Id" bytea,
+    "Callback-Number" bytea,
+    "Called-Station-Id" bytea,
+    "Calling-Station-Id" bytea,
+    "Connect-Info" bytea,
+    "Originating-Line-Info" bytea,
+    "Authorization-Lifetime" integer,
+    "Session-Timeout" integer,
+    "Idle-Timeout" integer,
+    "Port-Limit" integer,
+    "Accounting-Realtime-Required" integer,
+    "Acct-Interim-Interval" integer,
+    "Filter-Id" bytea,
+    "NAS-Filter-Rule" bytea,
+    "QoS-Filter-Rule" bytea,
+    "Login-IP-Host" bytea,
+    "Login-IPv6-Host" bytea,
+    "Login-LAT-Group" bytea,
+    "Login-LAT-Node" bytea,
+    "Login-LAT-Port" bytea,
+    "Login-LAT-Service" bytea,
+    "Login-Service" integer,
+    "Login-TCP-Port" integer,
+    "Route-Record1" bytea,
+    "Route-Record2" bytea,
+    "Route-Record3" bytea,
+    "Route-Record4" bytea,
+    "Route-Record5" bytea,
+    "recorded_on" timestamp with time zone NOT NULL,
+    "recorded_serv" bytea
+ );
+
+-- Archives table.
+--  This is also optional, and it must match the structure of your incoming table.
+CREATE TABLE archived (
+    "Origin-Host" bytea NOT NULL,
+    "Origin-Realm" bytea NOT NULL,
+    "Destination-Realm" bytea,
+    "Destination-Host" bytea,
+    "Session-Id" bytea NOT NULL,
+    "Origin-State-Id" integer,
+    "Accounting-Record-Type" integer NOT NULL,
+    "Accounting-Record-Number" integer NOT NULL,
+    "User-Name" bytea,
+    "Event-Timestamp" bytea,
+    "Acct-Application-Id" integer,
+    "Accounting-Sub-Session-Id" bigint,
+    "Acct-Session-Id" bytea,
+    "Acct-Multi-Session-Id" bytea,
+    "Origin-AAA-Protocol" integer,
+    "Acct-Delay-Time" integer,
+    "NAS-Identifier" bytea,
+    "NAS-IP-Address" bytea,
+    "NAS-IPv6-Address" bytea,
+    "NAS-Port" integer,
+    "NAS-Port-Id" bytea,
+    "NAS-Port-Type" integer,
+    "Service-Type" integer,
+    "Termination-Cause" integer,
+    "Accounting-Input-Octets" bigint,
+    "Accounting-Input-Packets" bigint,
+    "Accounting-Output-Octets" bigint,
+    "Accounting-Output-Packets" bigint,
+    "Acct-Authentic" integer,
+    "Acct-Link-Count" integer,
+    "Acct-Session-Time" integer,
+    "Acct-Tunnel-Connection" bytea,
+    "Acct-Tunnel-Packets-Lost" integer,
+    "Callback-Id" bytea,
+    "Callback-Number" bytea,
+    "Called-Station-Id" bytea,
+    "Calling-Station-Id" bytea,
+    "Connect-Info" bytea,
+    "Originating-Line-Info" bytea,
+    "Authorization-Lifetime" integer,
+    "Session-Timeout" integer,
+    "Idle-Timeout" integer,
+    "Port-Limit" integer,
+    "Accounting-Realtime-Required" integer,
+    "Acct-Interim-Interval" integer,
+    "Filter-Id" bytea,
+    "NAS-Filter-Rule" bytea,
+    "QoS-Filter-Rule" bytea,
+    "Login-IP-Host" bytea,
+    "Login-IPv6-Host" bytea,
+    "Login-LAT-Group" bytea,
+    "Login-LAT-Node" bytea,
+    "Login-LAT-Port" bytea,
+    "Login-LAT-Service" bytea,
+    "Login-Service" integer,
+    "Login-TCP-Port" integer,
+    "Route-Record1" bytea,
+    "Route-Record2" bytea,
+    "Route-Record3" bytea,
+    "Route-Record4" bytea,
+    "Route-Record5" bytea,
+    "recorded_on" timestamp with time zone NOT NULL,
+    "recorded_serv" bytea
+ );
+
diff --git a/contrib/app_acct_tools/display_results.php b/contrib/app_acct_tools/display_results.php
new file mode 100644
index 0000000..f84d3d2
--- /dev/null
+++ b/contrib/app_acct_tools/display_results.php
@@ -0,0 +1,141 @@
+<?php
+
+# The copyright of this file is the same as the freeDiameter project. Licence is BSD.
+
+# This file should no be called directly; 
+# instead it should be included from another script that sets its parameters as described below.
+
+## $USERS  
+# An array of the user names to display; the empty array will display all users.
+# This parameter MUST be set.
+if (!isset($USERS))
+	die('Do not call this file directly');
+
+## $START_TIME:
+# If set, this restricts the displayed data to sessions starting after $START
+
+## $END_TIME:
+# If set, this restricts the displayed data to sessions starting before $END
+
+## $LIMIT:
+## $LIMIT_OFFSET:
+# If set, these limit the number of accounting records displayed (for pagination purpose)
+
+#------------------------------------------------------------------------------------------
+# DATABASE:
+
+/* The Connection String used to access that database:
+  Example: "host=localhost dbname=app_acct user=freediameter password=foo" */
+$CONNSTR=""; 
+
+/* The name of the table containing the processed data (from process_records.php script) */
+$PROCESSED="processed";
+
+#------------------------------------------------------------------------------------------
+
+
+/* Connect to the database */
+$dbconn = pg_connect($CONNSTR)
+    or die('Could not connect: ' . pg_last_error() . "\n");
+    
+/* Function to format download size (from php.net) */
+function human_readable( $size )
+{
+   $count = 0;
+   $format = array("B","KB","MB","GB","TB","PB","EB","ZB","YB");
+   while(($size/1024)>1 && $count<8)
+   {
+       $size=$size/1024;
+       $count++;
+   }
+   if( $size >= 100 ) $decimals = 0;
+   elseif ($size >= 10 ) $decimals = 1;
+   else  $decimals = 2;
+   $return = number_format($size,$decimals,'.',' ')." ".$format[$count];
+   return $return;
+}
+    
+/* Build the SQL query */
+$sql = 'SELECT *, to_char(sess_start, \'YYYY-MM-DD&nbsp;HH24:MI:SS&nbsp;(TZ)\') as fmt_sess_start FROM "'.$PROCESSED.'"';
+$where=0;
+if ($USERS) {
+	$USERS = array_map(pg_escape_bytea, $USERS);
+	$sql .= " WHERE user_name IN ('". join("', '", array_values($USERS))."') ";
+	$where = 1;
+}
+
+if ($START_TIME) {
+	$START_TIME = pg_escape_string($START_TIME);
+	if ($where++)
+		$sql .= " AND ";
+	else
+		$sql .= " WHERE ";
+	$sql .= "sess_start >= '".$START_TIME."'";
+}
+if ($END_TIME) {
+	$END_TIME = pg_escape_string($END_TIME);
+	if ($where++)
+		$sql .= " AND ";
+	else
+		$sql .= " WHERE ";
+	$sql .= "sess_start <= '".$END_TIME."'";
+}
+
+$sql .= " ORDER BY sess_start, sess_duration";
+
+if ($LIMIT)
+	$sql .= " LIMIT $LIMIT";
+if ($LIMIT_OFFSET)
+	$sql .= " OFFSET $LIMIT_OFFSET";
+
+/* Execute the query */
+$result = pg_query($dbconn, $sql) or die('Query failed: ' . pg_last_error() . "\n");
+$recs = pg_num_rows($result);
+if ($recs == 0) {
+	echo "<p><em>Sorry, no data is available in this selection.</em></p>\n";
+} else {
+	echo "<p><strong>$recs</strong> records found.</p>\n";
+?>
+  <table>
+    <tr>
+      <th>Device identifier</th>
+      <th>Access Device information</th>
+      <th>Session started on</th>
+      <th>Duration</th>
+      <th>Downloaded</th>
+      <th>Uploaded</th>
+    </tr>
+<?php
+	while ($record = pg_fetch_array($result, null, PGSQL_ASSOC)) {
+		echo "    <tr title='".htmlentities(pg_unescape_bytea($record["user_name"]))."'>\n";
+		echo "      <td>";
+		echo htmlentities(pg_unescape_bytea($record["user_device"]));
+		echo "</td>\n";
+		echo "      <td>";
+		echo htmlentities(pg_unescape_bytea($record["nas_info"]));
+		echo "</td>\n";
+		echo "      <td>";
+		echo $record["fmt_sess_start"];
+		echo "</td>\n";
+		echo "      <td>";
+		echo htmlentities($record["sess_duration"]);
+		echo "</td>\n";
+		echo "      <td>";
+		echo human_readable( $record["downl_bytes"] )." (".$record["downl_packets"]."pckts)";
+		echo "</td>\n";
+		echo "      <td>";
+		echo human_readable( $record["upl_bytes"] )." (".$record["upl_packets"]."pckts)";
+		echo "</td>\n";
+		echo "    </tr>\n";
+	
+	}
+}
+pg_free_result($result);
+
+
+/* Closing connection */
+pg_close($dbconn);
+
+
+
+?>
diff --git a/contrib/app_acct_tools/display_self.php b/contrib/app_acct_tools/display_self.php
new file mode 100644
index 0000000..906cb0a
--- /dev/null
+++ b/contrib/app_acct_tools/display_self.php
@@ -0,0 +1,139 @@
+<?php
+
+# This file is an example wrapper around display_results.php.
+
+# It relies on clients authentication based on certificate usage 
+# (it must be the same certificate as used during AAA access, so that the User-Name matches).
+# See your web server documentation for details.
+# Example for apache2:
+#  (+ detail in http://httpd.apache.org/docs/2.0/ssl/ssl_howto.html#allclients )
+# - in vhost definition file, refence the CA chain of your users certificates:
+#  SSLCACertificateFile /var/www/conf/ssl.crt/ca.crt
+# - in vhost file or .htaccess file (adjust Depth to your setup):
+#  <IfModule mod_ssl.c>
+#  SSLVerifyClient require
+#  SSLVerifyDepth 2
+#  </IfModule>
+
+/* Check the client is correctly SSL authenticated with his server */
+if (!isset($_SERVER["SSL_CLIENT_VERIFY"]) || $_SERVER["SSL_CLIENT_VERIFY"] != "SUCCESS")
+	die("SSL authentication failed, the webserver is probably not configured correctly.\n");
+	
+/* Force some parameters to integer values */
+if ($_GET["t_limit"])
+	$_GET["t_limit"] = (int) $_GET["t_limit"];
+if ($_GET["t_offset"])
+	$_GET["t_offset"] = (int) $_GET["t_offset"];
+	
+/* Default form values */
+if (!isset($_GET["Submit"])) {
+	$_GET["t_limit"] = 50;
+	$_GET["c_limit"] = 1;
+	$_GET["t_offset"] = 0;
+}
+
+/* Output the form */
+?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<html lang="en-US">
+<head>
+    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+
+    <title>Accounting Data</title>
+    <meta name="description" content="This page gives you access to your personal accounting data.">
+    <meta name="keywords" content="accounting">
+
+    <style type="text/css">
+        body { text-align:center; }
+	table { border-collapse:collapse; margin-left:auto; margin-right:auto; }
+	table, td, th { border:1px solid green; padding-left:.5em; padding-right:.5em;}
+	th { background-color:green; color:white; }
+    </style>
+</head>
+
+<body >
+ <h1>Accounting data</h1>
+  <p>Note well: this page displays only data about <em>terminated</em> sessions.</p>
+  <form method="GET">
+  <table>
+    <tr>
+      <th colspan="3">
+        Filtering parameters
+      </th>
+    </tr>
+    <tr>
+      <td><input type="checkbox" name="c_starttime"<?php if (isset($_GET["c_starttime"])) echo " checked"; ?>></td>
+      <td>Show only sessions starting from (<a href="http://www.postgresql.org/docs/8.4/static/datatype-datetime.html">YYYY-MM-DD HH:MM:SS</a>):</td>
+      <td><input type="text" name="t_starttime"<?php if (isset($_GET["t_starttime"])) echo 'value="'.$_GET["t_starttime"].'"'; ?>></td>
+    </tr>
+    <tr>
+      <td><input type="checkbox" name="c_endtime"<?php if (isset($_GET["c_endtime"])) echo " checked"; ?>></td>
+      <td>Show only sessions starting until (<a href="http://www.postgresql.org/docs/8.4/static/datatype-datetime.html">YYYY-MM-DD HH:MM:SS</a>):</td>
+      <td><input type="text" name="t_endtime"<?php if (isset($_GET["t_endtime"])) echo 'value="'.$_GET["t_endtime"].'"'; ?>></td>
+    </tr>
+    <tr>
+      <td><input type="checkbox" name="c_limit"<?php if (isset($_GET["c_limit"])) echo " checked"; ?>></td>
+      <td>Show only this number of records:</td>
+      <td><input type="text" name="t_limit"<?php if (isset($_GET["t_limit"])) echo 'value="'.$_GET["t_limit"].'"'; ?>></td>
+    </tr>
+    <tr>
+      <td><input type="checkbox" name="c_offset"<?php if (isset($_GET["c_offset"])) echo " checked"; ?>></td>
+      <td>Starting from record:</td>
+      <td><input type="text" name="t_offset"<?php if (isset($_GET["t_offset"])) echo 'value="'.$_GET["t_offset"].'"'; ?>></td>
+    </tr>
+    <tr>
+      <th colspan="3">
+        Apply this filter: <input type="submit" name="Submit">
+      </th>
+    </tr>
+  </table>
+  </form>
+  
+<p>
+   Currently displaying user <em><?php echo htmlentities($_SERVER["SSL_CLIENT_S_DN_CN"]); ?></em><?php
+
+/* Search user by CN or Email since some OS use the later during EAP-TLS authentication */
+$USERS = array($_SERVER["SSL_CLIENT_S_DN_CN"], $_SERVER["SSL_CLIENT_S_DN_Email"]);
+
+/* If the start time boundary was specified... */
+if ($_GET["c_starttime"] && $_GET["t_starttime"]) {
+	$START_TIME=$_GET["t_starttime"];
+}
+if ($_GET["c_endtime"] && $_GET["t_endtime"]) {
+	$END_TIME=$_GET["t_endtime"];
+}
+
+/* idem with end time */
+if ($START_TIME && $END_TIME) {
+	echo ", sessions starting between $START_TIME and $END_TIME";
+} elseif ($START_TIME) {
+	echo ", sessions starting after $START_TIME";
+} elseif ($END_TIME) {
+	echo ", sessions starting before $END_TIME";
+}
+
+/* Pagination */
+if ($_GET["c_limit"] && $_GET["t_limit"]) {
+	$LIMIT=$_GET["t_limit"];
+}
+if ($_GET["c_offset"] && $_GET["t_offset"]) {
+	$LIMIT_OFFSET=$_GET["t_offset"];
+}
+if ($LIMIT) {
+	echo ", limited to ".$LIMIT." records";
+	if ($LIMIT_OFFSET)
+		echo " starting at ".$LIMIT_OFFSET;
+} else if ($LIMIT_OFFSET) {
+	echo " starting at record ".$LIMIT_OFFSET;
+}
+echo ".\n";
+?>
+</p>
+
+<?php
+/* This file will generate the array of data matching the selection */
+require("display_results.php");
+
+?>
+</body>
+</html>
diff --git a/contrib/app_acct_tools/display_stats.php b/contrib/app_acct_tools/display_stats.php
new file mode 100644
index 0000000..31beb12
--- /dev/null
+++ b/contrib/app_acct_tools/display_stats.php
@@ -0,0 +1,269 @@
+<?php
+
+# The copyright of this file is the same as the freeDiameter project. Licence is BSD.
+
+#------------------------------------------------------------------------------------------
+# DATABASE:
+
+/* The Connection String used to access that database:
+  Example: "host=localhost dbname=app_acct user=freediameter password=foo" */
+$CONNSTR=""; 
+
+/* The name of the table containing the processed data (from process_records.php script) */
+$PROCESSED="processed";
+
+#------------------------------------------------------------------------------------------
+
+?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<html lang="en-US">
+<head>
+    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+
+    <title>Accounting Data</title>
+    <meta name="description" content="This page gives you access to your personal accounting data.">
+    <meta name="keywords" content="accounting">
+
+    <style type="text/css">
+        body { text-align:center; }
+	table.colored { border-collapse:collapse; margin-left:auto; margin-right:auto; }
+	table.colored td, table.colored th { border:1px solid green; padding-left:.5em; padding-right:.5em;}
+	.colored th { background-color:green; color:white; }
+	hr { width:15px; margin-top:2em;margin-bottom:2em; }
+    </style>
+</head>
+
+<body >
+ <h1>Statistical accounting data</h1>
+  <form method="GET">
+  <table class="colored">
+    <tr>
+      <th colspan="3">
+        Filtering options
+      </th>
+    </tr>
+    <tr>
+      <td><input type="checkbox" name="c_starttime"<?php if (isset($_GET["c_starttime"])) echo " checked"; ?>></td>
+      <td>Limit to sessions starting from (<a href="http://www.postgresql.org/docs/8.4/static/datatype-datetime.html">hint</a>):</td>
+      <td><input type="text" title="YYYY-MM-DD HH:MM:SS" name="t_starttime"<?php if (isset($_GET["t_starttime"])) echo 'value="'.$_GET["t_starttime"].'"'; ?>></td>
+    </tr>
+    <tr>
+      <td><input type="checkbox" name="c_endtime"<?php if (isset($_GET["c_endtime"])) echo " checked"; ?>></td>
+      <td>Limit to sessions starting until (<a href="http://www.postgresql.org/docs/8.4/static/datatype-datetime.html">hint</a>):</td>
+      <td><input type="text" title="YYYY-MM-DD HH:MM:SS" name="t_endtime"<?php if (isset($_GET["t_endtime"])) echo 'value="'.$_GET["t_endtime"].'"'; ?>></td>
+    </tr>
+    <tr>
+      <th colspan="3">
+        Apply this filter: <input type="submit" name="Submit">
+      </th>
+    </tr>
+  </table>
+  </form>
+  <p>Note well: this page displays only data about <em>terminated</em> sessions.</p>
+<?php
+
+/* Connect to the database */
+$dbconn = pg_connect($CONNSTR)
+    or die('Could not connect: ' . pg_last_error() . "\n");
+    
+if ($_GET["c_starttime"] && $_GET["t_starttime"]) {
+	$START_TIME=$_GET["t_starttime"];
+}
+if ($_GET["c_endtime"] && $_GET["t_endtime"]) {
+	$END_TIME=$_GET["t_endtime"];
+}
+$sql_cond="";
+if ($START_TIME) {
+	$sql_cond = "sess_start >= '".pg_escape_string($START_TIME)."'";
+}
+if ($END_TIME) {
+	if ($sql_cond)
+		$sql_cond .= " AND ";
+	$sql_cond .= "sess_start =< '".pg_escape_string($END_TIME)."'";
+}
+
+
+/* Function to format download size (from php.net) */
+function human_readable( $size )
+{
+   $count = 0;
+   $format = array("B","KB","MB","GB","TB","PB","EB","ZB","YB");
+   while(($size/1024)>1 && $count<8)
+   {
+       $size=$size/1024;
+       $count++;
+   }
+   if( $size >= 100 ) $decimals = 0;
+   elseif ($size >= 10 ) $decimals = 1;
+   else  $decimals = 2;
+   $return = number_format($size,$decimals,'.',' ')." ".$format[$count];
+   return $return;
+}
+
+?>
+  
+  <hr />
+  
+<?php
+    
+/* First query: global data */
+$sql = 'SELECT SUM(downl_bytes) as total_down, SUM(upl_bytes) as total_up,';
+$sql .= ' to_char(min(sess_start), \'YYYY-MM-DD&nbsp;HH24:MI:SS&nbsp;TZ\') as first_sess,';
+$sql .= ' to_char(max(sess_start), \'YYYY-MM-DD&nbsp;HH24:MI:SS&nbsp;TZ\') as last_sess,';
+$sql .= ' count(distinct user_name) as nb_users,';
+$sql .= ' count(distinct nas_info) as nb_ap';
+$sql .= ' FROM "'.$PROCESSED.'"';
+if ($sql_cond)
+	$sql .= ' WHERE '.$sql_cond;
+
+/* Execute the query */
+$result = pg_query($dbconn, $sql) or die('Query failed: ' . pg_last_error() . "\n");
+if (pg_num_rows($result) == 0) {
+	echo "<p><em>No data is available in the selected period.</em></p>\n";
+	die("</body></html>\n");
+} 
+
+$data = pg_fetch_array($result, null, PGSQL_ASSOC);
+?>
+  <table class="colored">
+    <tr>
+      <th colspan="2">Total accounted data</th>
+    </tr>
+<?php
+echo "    <tr><td>First session started:</td><td>".$data["first_sess"]."</td></tr>\n";
+echo "    <tr><td>Last session started:</td><td>".$data["last_sess"]."</td></tr>\n";
+echo "    <tr><td>Total data downloaded:</td><td><strong>".human_readable($data["total_down"])."</strong></td></tr>\n";
+echo "    <tr><td>Total data uploaded:</td><td><strong>".human_readable($data["total_up"])."</strong></td></tr>\n";
+echo "    <tr><td>Number of users who connected at least once:</td><td>".$data["nb_users"]."</td></tr>\n";
+echo "    <tr><td>Number of access points involved:</td><td>".$data["nb_ap"]."</td></tr>\n";
+echo "  </tr>\n";
+echo " </table>\n";
+
+pg_free_result($result);
+
+?>
+  
+  <hr />
+  
+  <table class="colored">
+    <tr>
+      <th colspan="2">Top-5 <strong>downloading</strong> users</th>
+    </tr>
+<?php
+    
+/* Now, get the top 5 downloaders */
+$sql = 'SELECT SUM(downl_bytes) as total_down, user_name';
+$sql .= ' FROM "'.$PROCESSED.'"';
+if ($sql_cond)
+	$sql .= ' WHERE '.$sql_cond;
+$sql .= ' GROUP BY user_name';
+$sql .= ' ORDER BY total_down desc, user_name';
+$sql .= ' LIMIT 5';
+
+/* Execute the query */
+$result = pg_query($dbconn, $sql) or die('Query failed: ' . pg_last_error() . "\n");
+while ($data = pg_fetch_array($result, null, PGSQL_ASSOC)) {
+	echo "    <tr>\n";
+	echo "      <td>".htmlentities(pg_unescape_bytea($data["user_name"]))."</td>\n";
+	echo "      <td>".human_readable($data["total_down"])."</td>\n";
+	echo "    </tr>\n";
+}
+pg_free_result($result);
+?>
+  </table>
+  
+  <hr />
+  
+  <table class="colored">
+    <tr>
+      <th colspan="2">Top-5 <strong>uploading</strong> users</th>
+    </tr>
+<?php
+    
+/* Now, get the top 5 downloaders */
+$sql = 'SELECT SUM(upl_bytes) as total_up, user_name';
+$sql .= ' FROM "'.$PROCESSED.'"';
+if ($sql_cond)
+	$sql .= ' WHERE '.$sql_cond;
+$sql .= ' GROUP BY user_name';
+$sql .= ' ORDER BY total_up desc, user_name';
+$sql .= ' LIMIT 5';
+
+/* Execute the query */
+$result = pg_query($dbconn, $sql) or die('Query failed: ' . pg_last_error() . "\n");
+while ($data = pg_fetch_array($result, null, PGSQL_ASSOC)) {
+	echo "    <tr>\n";
+	echo "      <td>".htmlentities(pg_unescape_bytea($data["user_name"]))."</td>\n";
+	echo "      <td>".human_readable($data["total_up"])."</td>\n";
+	echo "    </tr>\n";
+}
+pg_free_result($result);
+?>
+  </table>
+
+  <hr />
+  
+  <table class="colored">
+    <tr>
+      <th colspan="2">Top-8 access devices (by number of users)</th>
+    </tr>
+<?php
+    
+/* Now, get the top 5 downloaders */
+$sql = 'SELECT count(distinct user_name) as unc, nas_info';
+$sql .= ' FROM "'.$PROCESSED.'"';
+if ($sql_cond)
+	$sql .= ' WHERE '.$sql_cond;
+$sql .= ' GROUP BY nas_info';
+$sql .= ' ORDER BY unc desc, nas_info';
+$sql .= ' LIMIT 8';
+
+/* Execute the query */
+$result = pg_query($dbconn, $sql) or die('Query failed: ' . pg_last_error() . "\n");
+while ($data = pg_fetch_array($result, null, PGSQL_ASSOC)) {
+	echo "    <tr>\n";
+	echo "      <td>".htmlentities(pg_unescape_bytea($data["nas_info"]))."</td>\n";
+	echo "      <td>".$data["unc"]."</td>\n";
+	echo "    </tr>\n";
+}
+pg_free_result($result);
+?>
+  </table>
+
+  <hr />
+  
+  <table class="colored">
+    <tr>
+      <th colspan="2">Top-8 access devices (by traffic: up+down)</th>
+    </tr>
+<?php
+    
+/* Now, get the top 5 downloaders */
+$sql = 'SELECT SUM(upl_bytes) + SUM(downl_bytes) as traffic, nas_info';
+$sql .= ' FROM "'.$PROCESSED.'"';
+if ($sql_cond)
+	$sql .= ' WHERE '.$sql_cond;
+$sql .= ' GROUP BY nas_info';
+$sql .= ' ORDER BY traffic desc, nas_info';
+$sql .= ' LIMIT 8';
+
+/* Execute the query */
+$result = pg_query($dbconn, $sql) or die('Query failed: ' . pg_last_error() . "\n");
+while ($data = pg_fetch_array($result, null, PGSQL_ASSOC)) {
+	echo "    <tr>\n";
+	echo "      <td>".htmlentities(pg_unescape_bytea($data["nas_info"]))."</td>\n";
+	echo "      <td>".human_readable($data["traffic"])."</td>\n";
+	echo "    </tr>\n";
+}
+pg_free_result($result);
+?>
+  </table>
+
+  <hr />
+<?php
+/* Closing connection */
+pg_close($dbconn);
+?>
+<p><small>Data generated by scripts from the <a href="http://www.freediameter.net">freeDiameter</a> project.</small></p>
+</body>
+</html>
diff --git a/contrib/app_acct_tools/process_records.php b/contrib/app_acct_tools/process_records.php
new file mode 100644
index 0000000..c64e1d6
--- /dev/null
+++ b/contrib/app_acct_tools/process_records.php
@@ -0,0 +1,205 @@
+<?php
+# This file may be called either from CLI or web PHP installation.
+# The copyright is the same as the freeDiameter project. Licence is BSD.
+
+# IMPORTANT: This script is highly experimental, PLEASE KEEP A COPY OF YOUR ACCOUNTING DATA 
+# if this data has any importance.
+
+/*-------------------------------------------------------*/
+
+/* This script supports only one database where all tables are kept. 
+  The Connection String used to access that database:
+  Example: "host=localhost dbname=app_acct user=freediameter password=foo" */
+$CONNSTR=""; 
+
+
+/**** 1 : Incoming records (output of app_acct.fdx) ****/
+/* The name of the table were the raw records are saved (from app_acct.conf) */
+$INCOMING="incoming";
+
+/* Note: For this script, this table MUST contain the following fields (with these names): 
+ Session-Id, User-Name, Accounting-Record-Type, Accounting-Record-Number, Acct-Session-Id, 
+ Accounting-{In,Out}put-{Octets,Packets},
+ NAS-Identifier, Called-Station-Id, Calling-Station-Id, recorded_on.
+ */
+
+
+/**** 2 : Processed records (output of this script, input for display_results.php) ****/
+/* The name of the table */
+$PROCESSED="processed";
+
+/* See process_database.sql for command to create this database */
+
+/**** 3 : Orphan records (optional) ****/
+/* The script can move records belonging to an unterminated session that has not received any new
+  record for more than $ORPHAN_DELAY (based on recorded_on field) into an $ORPHANED_TABLE table, so that
+  these records are not re-processed everytime the script runs. 
+  If $ORPHANED_TABLE is empty, this feature is disabled.  */
+$ORPHANED_TABLE="orphans";
+$ORPHAN_DELAY = "2 days";
+
+
+/**** 4 : Archived records (optional) ****/
+/* When data has been processed successfully, the records can be saved into an archive table before being deleted. */
+/* This table also must have the same structure as $INCOMING */
+$ARCHIVES_TABLE="archived";
+
+/*-------------------------------------------------------*/
+
+/* Connect to the database */
+$dbconn = pg_connect($CONNSTR)
+    or die('Could not connect: ' . pg_last_error() . "\n");
+
+/* Handle orphans first */
+if ($ORPHANED_TABLE) {
+	$orphans_sql = 'SELECT * FROM "'.$INCOMING.'" ';
+	$orphans_sql.= 'WHERE "Acct-Session-Id" IN (';
+	$orphans_sql.= '   SELECT data.asid ';
+	$orphans_sql.= '   FROM (';
+	$orphans_sql.= '       SELECT "Acct-Session-Id" as asid, MAX("recorded_on") as latest, bool_or("Accounting-Record-Type" = 2) as got_start, bool_or("Accounting-Record-Type" = 4) as got_stop  ';
+	$orphans_sql.= '       FROM "'.$INCOMING.'"';
+	$orphans_sql.= '       GROUP BY "Acct-Session-Id") ';
+	$orphans_sql.= '   as data';
+	$orphans_sql.= '   WHERE data.latest < current_timestamp - interval \''. $ORPHAN_DELAY .'\' AND NOT ( got_start AND got_stop )';
+	$orphans_sql.= ');';
+	
+	/* Execute, move the orphaned records to the appropriate table. */
+	$result = pg_query($dbconn, $orphans_sql) or die('Query failed: ' . pg_last_error() . "\n");
+	if (pg_num_rows($result) > 0) {
+		$i = 0;
+		while ($orphan = pg_fetch_array($result, null, PGSQL_ASSOC)) {
+			$i++;
+			
+			// this doesn't work: pg_insert( $dbconn, $ORPHANED_TABLE, $orphan ) or die('Insert failed: ' . pg_last_error() . "\n");
+			$sql  = "INSERT INTO \"$ORPHANED_TABLE\" ";
+			$sql .= '("';
+			$sql .= join('", "', array_keys($orphan));
+			$sql .= '") VALUES (';
+			for($c = 0; $c < count($orphan); $c++)
+			  $sql .= ($c ? ', ' : '').'$'.($c+1);
+			$sql .= ')';
+			pg_query_params($dbconn, $sql, array_values($orphan)) or die('Insert failed: ' . pg_last_error() . "\n");
+						
+			// This also doesn't work: pg_delete( $dbconn, $INCOMING, $orphan ) or die('Removing orphan failed: ' . pg_last_error() . "\n");
+			$sql  = "DELETE FROM \"$INCOMING\" WHERE ";
+			$sql .= '"Acct-Session-Id" = $1 AND "recorded_on" = $2';
+			pg_query_params($dbconn, $sql, array($orphan["Acct-Session-Id"], $orphan["recorded_on"])) or die('Removing orphan failed: ' . pg_last_error() . "\n");
+		}
+		echo $i." orphans have been moved to '".$ORPHANED_TABLE."'\n";
+	}
+	pg_free_result($result);
+}
+
+/* Delete duplicate records (which might have been received by different servers on different time, but are identical otherwise */
+$duplicate_sql  = ' SELECT * FROM (SELECT count(*) as cnt, min("recorded_on") as first, "Session-Id", "Acct-Session-Id", "Accounting-Record-Type", "Accounting-Record-Number"';
+$duplicate_sql .= ' FROM "'.$INCOMING.'" GROUP BY "Session-Id", "Acct-Session-Id", "Accounting-Record-Type", "Accounting-Record-Number") as qry WHERE qry.cnt > 1';
+$result = pg_query($dbconn, $orphans_sql) or die('Query failed: ' . pg_last_error() . "\n");
+if (pg_num_rows($result) > 0) {
+	/* We have some duplicates to delete */
+	$i=0;
+	while ($dup = pg_fetch_array($result, null, PGSQL_ASSOC)) {
+		$i++;
+		$sql  = "DELETE FROM \"$INCOMING\" WHERE ";
+		$sql .= '"Session-Id" = $1 AND "Acct-Session-Id" = $2 AND "Accounting-Record-Type" = $3 AND "Accounting-Record-Number" = $4 AND "recorded_on" <> $5';
+		$params = array($dup["Session-Id"], $dup["Acct-Session-Id"], $dup["Accounting-Record-Type"], $dup["Accounting-Record-Number"], $dup["first"]);
+		pg_query_params($dbconn, $sql, $params) or die('Removing duplicates failed: ' . pg_last_error() . "\n");
+	}
+	echo $i." duplicate records have been deleted from '".$INCOMING."'\n";
+}
+pg_free_result($result);
+
+
+/* Now, find Acct-Session-Id of completed sessions */
+$completed_sql  = ' SELECT "Session-Id", "Acct-Session-Id" FROM (';
+$completed_sql .= '     SELECT "Session-Id", "Acct-Session-Id", bool_or("Accounting-Record-Type" = 2) as got_start, bool_or("Accounting-Record-Type" = 4) as got_stop ';
+$completed_sql .= '     FROM "'.$INCOMING.'" GROUP BY "Session-Id", "Acct-Session-Id"';
+$completed_sql .= '    ) as input';
+$completed_sql .= ' WHERE got_start AND got_stop';
+
+$sids = pg_query($dbconn, $completed_sql) or die('Query failed: ' . pg_last_error() . "\n");
+if (pg_num_rows($sids) > 0) {
+	while ($sids_line = pg_fetch_array($sids, null, PGSQL_ASSOC)) {
+		$sid  = $sids_line["Session-Id"];
+		$asid = $sids_line["Acct-Session-Id"];
+		echo "Processing Acct-Session-Id '".$asid."', Session-Id '".$sid ."'... ";
+		
+		$data=array();
+		
+		/* We simply ignore the interim record(s) in this first version, since they contain only cumulative data. It could be used in later version to draw the session details for example. */
+		
+		$result = pg_query_params($dbconn, 'SELECT *, "recorded_on" - CAST(textcat(text("Acct-Session-Time"), text(\' seconds\')) as INTERVAL) as start_time FROM "'.$INCOMING.
+						   '" WHERE "Session-Id" = $1 AND "Acct-Session-Id" = $2 AND "Accounting-Record-Type" = 4 ORDER BY "recorded_on"', 
+						   array($sid, $asid)) or die('Query failed: ' . pg_last_error() . "\n");
+		$record = pg_fetch_array($result, null, PGSQL_ASSOC) or die('Internal error, got_stop is true but no record was returned');
+		
+		$data[/* "user_name" */] = $record["User-Name"];
+		$data[/* "user_device" */] = $record["Calling-Station-Id"];
+		
+		$nas_id= ($record["NAS-Identifier"] ?: $record["Origin-Host"]) ?: "<unidentified NAS>";
+		$ip = $record["NAS-IP-Address"] ?: $record["NAS-IPv6-Address"];
+		$nas_ip= $ip ? inet_ntop(pg_unescape_bytea($ip)) : "<unknown NAS IP>";
+		$nas_csi = $record["Called-Station-Id"];
+		$data[/* "nas_info" */] = $nas_id . " (".$nas_ip.")" . ($nas_csi ? " - Called Station: ".$nas_csi : "");
+		
+		/* Is it possible to infer the session start time from this record only? */
+		if ($record["Acct-Session-Time"]) {
+			/* Yes, let's go */
+			$data[/* "sess_start" */] = $record["start_time"];
+			$data[/* "sess_duration" */] = $record["Acct-Session-Time"]." seconds";
+		} else {
+			/* No the information is missing, let's compute the approx value with the START record timestamp */
+			$res = pg_query_params($dbconn, 'SELECT t_start."recorded_on" as begining, t_end."recorded_on" - t_start."recorded_on" as duration'.
+							' FROM (SELECT "recorded_on" FROM "'.$INCOMING.'"  WHERE "Session-Id" = $1 AND "Acct-Session-Id" = $2 AND "Accounting-Record-Type" = 4 ORDER BY "recorded_on" LIMIT 1) as t_end, '.
+							'      (SELECT "recorded_on" FROM "'.$INCOMING.'"  WHERE "Session-Id" = $1 AND "Acct-Session-Id" = $2 AND "Accounting-Record-Type" = 2 ORDER BY "Accounting-Record-Number", "recorded_on" LIMIT 1) as t_start',
+							array($sid, $asid)) or die('Query failed: ' . pg_last_error() . "\n");
+			$vals = pg_fetch_array($result, null, PGSQL_ASSOC) or die('Internal error, unable to compute session time');
+			$data[/* "sess_start" */] = $vals["begining"];
+			$data[/* "sess_duration" */] = $vals["duration"];
+			pg_free_result($res);
+		}
+		
+		$data[/* "downl_bytes" */] = $record["Accounting-Output-Octets"];
+		$data[/* "downl_packets" */] = $record["Accounting-Output-Packets"];
+		$data[/* "upl_bytes" */] = $record["Accounting-Input-Octets"];
+		$data[/* "upl_packets" */] = $record["Accounting-Input-Packets"];
+		pg_free_result($result);
+		
+		$result = pg_query_params($dbconn, 
+			'INSERT INTO "'.$PROCESSED.'" (user_name, user_device, nas_info, sess_start, sess_duration, downl_bytes, downl_packets, upl_bytes, upl_packets) '.
+			'VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9)', $data) or die('Query failed: ' . pg_last_error() . "\n");
+		pg_free_result($result);
+		echo "Data stored into '$PROCESSED'... ";
+		
+		/* Now that we have processed it, move these records to the $ARCHIVES_TABLE table. */
+		if ($ARCHIVES_TABLE) {
+			$result = pg_query_params($dbconn, 'SELECT * FROM "'.$INCOMING.'" WHERE "Session-Id" = $1 AND "Acct-Session-Id" = $2', array($sid, $asid)) or die('Query failed: ' . pg_last_error() . "\n");
+			$i = 0;
+			while ($rec = pg_fetch_array($result, null, PGSQL_ASSOC)) {
+				$i++;
+
+				$sql  = "INSERT INTO \"$ARCHIVES_TABLE\" ";
+				$sql .= '("';
+				$sql .= join('", "', array_keys($rec));
+				$sql .= '") VALUES (';
+				for($c = 0; $c < count($rec); $c++)
+				  $sql .= ($c ? ', ' : '').'$'.($c+1);
+				$sql .= ')';
+				pg_query_params($dbconn, $sql, array_values($rec)) or die('Insert failed: ' . pg_last_error() . "\n");
+			}
+			echo $i." records archived into '".$ARCHIVES_TABLE."'";
+			pg_free_result($result);
+		}
+		echo "\n";
+		$result = pg_query_params($dbconn, 'DELETE FROM "'.$INCOMING.'" WHERE "Session-Id" = $1 AND "Acct-Session-Id" = $2', array($sid, $asid)) or die('Query failed: ' . pg_last_error() . "\n");
+		pg_free_result($result);
+	}
+}
+pg_free_result($sids);
+
+echo "Operation completed with success!\n";
+
+/* Closing connection */
+pg_close($dbconn);
+
+
+?>
diff --git a/contrib/app_acct_tools/purge_to_file.php b/contrib/app_acct_tools/purge_to_file.php
new file mode 100644
index 0000000..0fc9f29
--- /dev/null
+++ b/contrib/app_acct_tools/purge_to_file.php
@@ -0,0 +1,157 @@
+<?php
+# This file may be called either from CLI or web PHP installation.
+
+# The copyright is the same as the freeDiameter project. Licence is BSD.
+
+/*-------------------------------------------------------*/
+
+/* -- These parameters must match the app_acct.conf file -- */
+
+/* The Connection String used to access the database.
+  Example: "host=localhost dbname=app_acct user=freediameter password=foo" */
+$CONNSTR=""; 
+
+/* The name of the table were the records are saved by app_acct.fdx */
+$TABLE="incoming";
+
+
+/* -- These parameters are specific to this script -- */
+
+/* Name of the dump file to create. It can be relative or absolute. 
+   The script fails if this file already exists.
+   Use for example "data-".date("Ymdhis").".sql" to avoid collisions. */
+$DUMPFILE="incoming_data.sql";
+
+/* Does the script also echoes an HTML TABLE of the data processed? */
+$DISPLAY_HTML=FALSE; // it would be better to detect if we are called through Web or CLI...
+/* In addition, issue a full HTML page (including headers) ? */
+$HTML_HEADERS=TRUE;
+
+/*-------------------------------------------------------*/
+
+/* Connect to the database */
+$dbconn = pg_connect($CONNSTR)
+    or die('Could not connect: ' . pg_last_error() . "\n");
+    
+/* Check if the file exists */
+$file = fopen($DUMPFILE, "xb")
+    or die("The file '$DUMPFILE' already exists or cannot be created, aborting.\n");
+
+/* First, query the table format */
+$format_sql =   "SELECT ".
+		"   a.attname AS field,".
+		"   t.typname AS type,".
+/*		"   a.attlen AS length,". */
+		"   a.atttypmod AS lengthvar,".
+		"   a.attnotnull AS notnull".
+		" FROM".
+		"   pg_class c,".
+		"   pg_attribute a,".
+		"   pg_type t".
+		" WHERE".
+		"   c.relname = '" . $TABLE . "'".
+		"   AND a.attnum > 0".
+		"   AND a.attrelid = c.oid".
+		"   AND a.atttypid = t.oid".
+		"   ORDER BY a.attnum";
+$result = pg_query($dbconn, $format_sql) or die('Query failed: ' . pg_last_error() . "\n");
+
+/* app_acct.fdx only uses a few different fields types: */
+$conv_types = array(
+    "timestamptz" => "timestamp with time zone", /* recorded on */
+    "bytea" => "bytea",   /* octet string */
+    "int4" => "integer",  /* unsigned32, integer32, float32 */
+    "int8" => "bigint"    /* unsigned64, integer64, float64 */
+    );
+    
+$fields_types=array();
+
+fwrite($file, " -- Data purged on ".date(DATE_RFC822)."\n\n");
+fwrite($file, " -- Format of the table it was extracted from:\n");
+fwrite($file, " -- CREATE TABLE \"".$TABLE."\" (\n");
+$i = 0;
+while ($field = pg_fetch_array($result, null, PGSQL_ASSOC)) {
+	if ($i++)
+		fwrite($file, ",\n");
+	fwrite($file, " --    \"".$field["field"]."\" ");
+	if (array_key_exists($field["type"], $conv_types))
+		$fields_types[$field["field"]] = $conv_types[$field["type"]];
+	else
+		$fields_types[$field["field"]] = $field["type"];
+	fwrite($file, $fields_types[$field["field"]]);
+	if ($field["lengthvar"] != "-1")
+		fwrite($file, "(".$field["lengthvar"].")");
+	if ($field["notnull"] == "t")
+		fwrite($file, " NOT NULL");
+}
+fwrite($file, "\n -- );\n\n");
+pg_free_result($result);
+
+/* Now, the data */
+$result = pg_query($dbconn, "SELECT * FROM \"".$TABLE."\"") or die('Query failed: ' . pg_last_error() . "\n");
+if (pg_num_rows($result) > 0) {
+	fwrite($file, "INSERT INTO \"".$TABLE."\"\n (\n");
+	$i = pg_num_fields($result);
+	if ($DISPLAY_HTML && $HTML_HEADERS) echo "<HTML>\n<HEAD><TITLE>Purge</TITLE></HEAD>\n<BODY>\n";
+	if ($DISPLAY_HTML) echo "<TABLE>\n  <TR>\n";
+	for ($j = 0; $j < $i; $j++) {
+	      fwrite($file, ($j ? ", " : "") . "\"" . pg_escape_string(pg_field_name($result, $j)). "\"");
+	      if ($DISPLAY_HTML) echo "    <TD>".htmlentities(pg_field_name($result, $j))."</TD>\n";
+	}
+	fwrite($file, "\n )\n VALUES \n");
+	if ($DISPLAY_HTML) echo "  </TR>\n";
+	$i = 0;
+	while ($line = pg_fetch_array($result, null, PGSQL_ASSOC)) {
+		if ($i++)
+			fwrite($file, ",\n");
+		fwrite($file, " ( ");
+		
+		if ($DISPLAY_HTML) echo "  <TR>\n";
+		$j = 0;
+		$sql = "";
+		foreach ($line as $f => $v) {
+			if (!is_null($v))
+				switch ($fields_types[$f]) {
+					case "bytea":
+						$v = "E'".pg_escape_bytea(pg_unescape_bytea($v))."'";
+						break;
+					case "timestamp with time zone":
+						$v = "E'".pg_escape_string($v)."'";
+						break;
+				}
+			else
+				$v = "NULL";
+			
+	      		if ($DISPLAY_HTML) echo "    <TD>".htmlentities(print_r($line[$f], TRUE))."</TD>\n";
+
+			fwrite($file, ($j ? ", " : "") . $v);
+			$sql .= ($j ? " AND " : "") . "\"".pg_escape_string($f)."\" ";
+			if (is_null($line[$f]))
+				$sql .= " IS NULL";
+			else 
+				$sql .= " = " . $v;
+			$j++;
+		}
+		fwrite($file, ")");
+		if ($DISPLAY_HTML) echo "  </TR>\n";
+		$res = pg_query( "DELETE FROM \"".$TABLE."\" WHERE ".$sql) or die('DELETE query failed: ' . pg_last_error() . "\n");
+		pg_free_result($res);
+	}
+	fwrite($file, "\n;\n");
+	if ($DISPLAY_HTML) echo "</TABLE>\n";
+	if ($DISPLAY_HTML && $HTML_HEADERS) echo "</BODY>\n</HTML>\n";
+        else echo $i." records have been successfully written to '".$DUMPFILE."' and removed from database.\n";
+} else {
+	if ($DISPLAY_HTML) echo "<p><em>No new record in the database</em></p>\n";
+        else echo "No new record in the database, the generated file is empty.\n";
+}
+pg_free_result($result);
+
+/* Closing connection */
+pg_close($dbconn);
+
+/* Closing the file */
+fclose($file);
+
+
+?>
diff --git a/contrib/debian/changelog b/contrib/debian/changelog
new file mode 100644
index 0000000..526d9ef
--- /dev/null
+++ b/contrib/debian/changelog
@@ -0,0 +1,209 @@
+freediameter (1.2.1) UNRELEASED; urgency=low
+
+  * New extension: rt_randomize (load-balancing on possible destinations)
+  * New contrib: Gx extension.
+  * rt_redirect.fdx and rt_load_balance.fdx improvement: use a hash table. Thanks Thomas.
+  * New hook HOOK_MESSAGE_SENDING to give a last chance to edit messages before they are sent.
+    This will be mostly used for enforcing interoperability constraints on non-compliant peers.
+  * Simplified log output. Old output can be recovered with DEBUG_WITH_META build option.
+  * Updated the internal counters for finer control on the load.
+  * Fixes in message expiry mechanism.
+  * Bug fixes in error messages generation and various parts.
+  * Improvements on shutdown sequence handling.
+  * Improvements to the dict_dcca_* extensions.
+  * Improved default CMake configuration.
+  * Improved build for MacOSX
+  * Fixes for a few newer operating systems compatibility.
+  * Fixed default secure Diameter port number 5868 instead of5658 (errata of RFC 6733)
+
+ -- Sebastien Decugis <sdecugis@freediameter.net>  Sat, 30 Jan 2016 23:38:03 +0800
+
+freediameter (1.2.0) UNRELEASED; urgency=low
+
+  * Major changes in the logging system to be more syslog and production friendly
+  * New extension: dict_dcca_3gpp
+  * New extension: dict_dcca_starent (Starent DCCA vendor-specific AVPs)
+  * New extension: rt_ignore_dh (hide network topology by proxying Destination-Host).
+  * New extension: rt_load_balance (load balancer based on pending queue size).
+  * New extension: rt_busypeers. See doc/rt_busypeers.conf.sample.
+  * New extension: dbg_msg_timings. Measures timing of message operations.
+  * New extension: dbg_msg_dumps. Use to control hooks display.
+  * New API (fd_hook_*) for extensions to control messages logging & profiling
+  * New API (fd_stats_*) for extensions to monitor framework state (e.g. SNMP implem)
+  * API change: all the fd_*_dump functions now return malloc'd strings instead of logging directly.
+  * API change: callback parameter of fd_rt_out_register had its signature updated.
+  * Updated dbg_monitoring extension to use the new API
+  * New script to generate dictionary extensions from org file (see contrib/tools)
+  * New compilation option: WORKAROUND_ACCEPT_INVALID_VSAI to improve compatibility
+    with invalid Vendor-Specific-Application-Id AVPs received from some equipments (e.g. Cisco).
+  * New compilation option: DISABLE_PEER_EXPIRY for use in test environments.
+  * Extensions are now also searched in LD_LIBRARY_PATH.
+  * Copy Proxy-Info AVP automatically in new answers.
+  * Port value 0 allowed in configuration to disable local server (e.g. disable non-secure port).
+  * API change: fd_msg_send_timeout now takes a separate callback for timeout situation.
+  * Function changes: fd_msg_dump_* now split in three different type of output.
+  * New test testmesg_stress to measure message parser performance
+  * Fix termination of the framework to avoid failures.
+  * Fix invalid timespec value in peer PSM appearing randomly (leading to crash).
+  * Return DIAMETER_LOOP_DETECTED if local peer in the Route-Record list of a message.
+  * Allow running without TLS configuration.
+  * Upgraded SCTP code to comply with RFC 6458
+  * Using default secure Diameter port number 5658 as per RFC 6733
+  * Updated TLS code for performance improvements with new GNU TLS.
+  * Fix interlocking problem when large number of requests were failed over.
+  * New option in test_app.fdx extension for long messages payload.
+  * Performance improvement in message sending code path.
+
+ -- Sebastien Decugis <sdecugis@freediameter.net>  Sat, 14 Sep 2013 18:08:07 +0800
+
+freediameter (1.1.6) UNRELEASED; urgency=low
+
+  * Fix major issue in 1.1.5 preventing to send answers to a received message.
+  * New command-line option: --enable_msg_log=( DROPPED | RECEIVED | SENT | NODELIVER | TIMING )
+  * Improved parsing error handling and Failed-AVP generation.
+  * Added support for some timings measurements in freeDiameter (in the logs)
+  * Fix port handling when using non-default port.
+  * Some cleanups in several dictionary files.
+  * New option to fd_dict_search: AVP_BY_STRUCT
+  * Improved compatibility with C++ compilers.
+  * Cleanups in sessions creation/destruction to avoid memory corruption under stress.
+  * Add support for "include" directive in freeDiameter.conf file.
+
+ -- Sebastien Decugis <sdecugis@freediameter.net>  Sun, 03 Mar 2013 07:40:43 +0100
+
+freediameter (1.1.5) UNRELEASED; urgency=low
+
+  * Added compatibility with MAC OS X
+  * Fix behavior of timeout whe nsending messages to allow re-send.
+  * Several cleanups and new contributions included.
+  * Added dependency on C++ compiler for CMakeLists.txt
+
+ -- Sebastien Decugis <sdecugis@freediameter.net>  Sat, 03 Nov 2012 17:58:11 +0100
+
+freediameter (1.1.4) UNRELEASED; urgency=low
+
+  * Compatibility with GnuTLS 3.x versions / updated packaging files accordingly
+  * Fix crash on Sparc 64 (possibly other 64b machines)
+  * Updated dict_dcca in extensions and contrib (thanks Konstantin)
+  * Changed dumping of messages to avoid interleaved information
+
+ -- Sebastien Decugis <sdecugis@freediameter.net>  Fri, 24 Aug 2012 00:17:05 +0200
+
+freediameter (1.1.3) UNRELEASED; urgency=low
+
+  * Fixed a memory leak
+  * Clean-up of some extensions
+
+ -- Sebastien Decugis <sdecugis@freediameter.net>  Tue, 03 Jul 2012 08:15:49 +0200
+
+freediameter (1.1.2) UNRELEASED; urgency=low
+
+  * FIFO queues are now capped to avoid memory exhaustion.
+  * Cleanups in MIPv6 dictionaries.
+  * app_acct upgraded: enabled vendor-specific AVP logging, thread-safe version.
+  * New function: fd_dict_getlistof to list dictionary contents.
+  * New function: fd_dict_delete to remove an entry (dangerous function!)
+  * New function: fd_sess_getcount to get count of session objects.
+  * A few additional bug fixes, check hg log for details.
+
+ -- Sebastien Decugis <sdecugis@freediameter.net>  Tue, 21 Feb 2012 18:38:10 +0100
+
+freediameter (1.1.1) UNRELEASED; urgency=low
+
+  * Bug fix release
+  * Supports newer GNUTLS versions
+  * Allow empty OctetString AVPs (l=0)
+  * Allow two instances of freeDiameter on a single host.
+
+ -- Sebastien Decugis <sdecugis@nict.go.jp>  Fri, 30 Sep 2011 21:56:50 +0200
+
+freediameter (1.1.0) UNRELEASED; urgency=low
+
+  * Source package restructured. Most of the 
+    framework now contained in the libfdcore library.
+    libfreeDiameter renamed as libfdproto.
+    This closes #15.
+  * API version bumped to version 4.
+  * Improved fd_dict_new() when the same object already exists.
+  * Improvements to dict_legacy_xml extension.
+  * Cleanups in links to shared libraries
+  * (app_radgw.fdx) Better handling conversion of DEA with error status
+    to RADIUS (closes #25)
+  * Allow default signals such as SIGTSTP (ctrl-z) to be used with
+    freeDiameterd
+  * Improved DiameterIdentity handling (esp. interationalization issues), 
+    and improve efficiency of some string operations in peers, sessions, 
+    and dictionary modules (closes #7)
+  * Cleanup in the session module to free only unreferenced sessions (#16)
+  * Removed fd_cpu_flush_cache(), replaced by more robust alternatives.
+  * Improved peer state machine algorithm to counter SCTP multistream race 
+    condition.
+  * New extension rt_redirect.fdx that handles the Diameter Redirect errors.
+  * New extension app_redirect that allows sending Redirect indications to 
+    other peers. See doc/app_redirect.conf.sample for more information.
+  * Added incomplete dictionary extension for rfc4006 (DCCA), courtesy
+    of Konstantin Chekushin <koch@lmt.lv>
+
+ -- Sebastien Decugis <sdecugis@freediameter.net>  Tue, 29 Mar 2011 10:41:19 +0900
+
+freediameter (1.0.4) UNRELEASED; urgency=low
+
+  * Added new API to specify timeout on receiving answer (#10) 
+  * Bumped API version number accordingly.
+  * New test_netemul extension (simple network emulator proxy)
+  * Improved API compatibility to C++ compilers
+
+ -- Sebastien Decugis <sdecugis@nict.go.jp>  Tue, 11 Jan 2011 12:28:22 +0900
+
+freediameter (1.0.3) UNRELEASED; urgency=low
+
+  * Fixed a couple of issues for portability (#21, #22, #23)
+  * Fixed issue with ListenOn bit ordering (#20)
+  * Added dictionary support for MIPv6 application objects.
+  * Added dictionary support for legacy XML files.
+  * Added python interface dbg_interactive (experimental). 
+  * Added parameters to fd_disp_register() and fd_sess_handler_create(),
+    Bumped API version number accordingly.
+
+ -- Sebastien Decugis <sdecugis@nict.go.jp>  Tue, 14 Dec 2010 11:39:29 +0900
+
+freediameter (1.0.2) UNRELEASED; urgency=low
+
+  * Fix an issue in app_diameap.fdx with user names (#18)
+  * Allow DH parameters loaded from a file (#17) 
+  * Fixed a few compilation warnings on 64bits architectures.
+  * New ALL_EXTENSIONS build option.
+
+ -- Sebastien Decugis <sdecugis@nict.go.jp>  Wed, 27 Oct 2010 11:17:32 +0900
+
+freediameter (1.0.1) UNRELEASED; urgency=low
+
+  * app_acct.fdx: new set of PHP scripts available in source
+    contrib/app_acct_tools
+  * app_acct.fdx: new directive 'Server_name_field' in the
+    configuration.
+  * app_radgw.fdx: new directive 'nonai' in acct and auth plugins to
+    disable NAI processing.
+  * app_radgw.fdx: New support for RADIUS proxies.
+  * app_radgw.fdx: many bug fixes.
+  * daemon: Check the local certificate is valid during TLS
+    initialization.
+  * daemon: Fixed issue for IP addresses in the form x.x.x.235
+  * daemon: new option --dbg_gnutls to get GNUTLS debug messages.
+  * debian: some cleanups in the packaging (dependencies, meta-data)
+  * rt_ereg.fdx: New routing extension based on regular expression
+    matching in package freediameter-daemon.
+
+ -- Sebastien Decugis <sdecugis@nict.go.jp>  Wed, 15 Sep 2010 18:30:28 +0900
+
+freediameter (1.0.0-2) experimental; urgency=low
+
+  * Official release 1.0.0 
+
+ -- Sebastien Decugis <sdecugis@nict.go.jp>  Thu, 29 Jul 2010 17:27:13 +0900
+
+freediameter (1.0.0-1) experimental; urgency=low
+
+  * Initial Release.
+  
+ -- Sebastien Decugis <sdecugis@nict.go.jp>  Wed, 19 May 2010 15:36:54 +0900
diff --git a/contrib/debian/compat b/contrib/debian/compat
new file mode 100644
index 0000000..7f8f011
--- /dev/null
+++ b/contrib/debian/compat
@@ -0,0 +1 @@
+7
diff --git a/contrib/debian/control b/contrib/debian/control
new file mode 100644
index 0000000..919e10e
--- /dev/null
+++ b/contrib/debian/control
@@ -0,0 +1,229 @@
+Source: freediameter
+Section: contrib/net
+Priority: extra
+Maintainer: Sebastien Decugis <sdecugis@freediameter.net>
+Build-Depends: debhelper ( >= 7.3.9),
+ cmake, make, gcc, g++, bison, flex,
+ libsctp-dev, libgnutls-dev | gnutls-dev, libidn11-dev,
+ libpq-dev, libmysqlclient-dev, libxml2-dev, swig, python-dev,
+ libgcrypt11-dev | libgcrypt20-dev
+Standards-Version: 3.8.3
+Homepage: http://www.freediameter.net
+
+Package: freediameter-common
+Architecture: any
+Depends: ${shlibs:Depends}, ${misc:Depends}
+Description: The freeDiameter libraries.
+ This package contains the freeDiameter framework core libraries, 
+ required by all freeDiameter components.
+ It may also be useful for other projects which need to 
+ perform operations on Diameter messages. 
+ .
+ The freeDiameter framework provides support for the Diameter
+ Base Protocol. Without any extension, the framework can only
+ be used as a Diameter routing agent. You probably want to 
+ install some freeDiameter extension(s) to extend its 
+ features, and also the freediameter-daemon package that
+ will initialize the framework for you.
+ .
+ See 'freeDiameter-dev' package to retrieve the API for the library.
+
+Package: freediameter-dev
+Architecture: any
+Section: contrib/devel
+Depends: freediameter-common (= ${binary:Version}), libsctp-dev, libgnutls-dev, libgcrypt-dev
+Description: This package provides the development files for freeDiameter.
+
+Package: freediameter-daemon
+Architecture: any
+Depends: ${shlibs:Depends}, ${misc:Depends}, freediameter-common (= ${binary:Version})
+Suggests: ssl-cert, freediameter-dictionary-rfc4005, freediameter-dictionary-rfc4072, freediameter-dictionary-rfc4740,
+  freediameter-dictionary-mip6, freediameter-dictionary-legacy
+Description: The freeDiameter daemon. 
+ This daemon is a simple loader for the freeDiameter framework.
+ It is shipped with a small set of extensions, for
+ example to configure the routing behavior. See the 
+ examples in /usr/share/freediameter* for more details.
+
+Package: freediameter-debug-tools
+Architecture: any
+Section: contrib/debug
+Depends: ${misc:Depends}, freediameter-common (= ${binary:Version})
+Suggests: python, libmysqlclient16 | libmysqlclient18
+Description: freeDiameter debug tools.
+ This package provides useful tools to help tracking 
+ problems in freeDiameter installation. For example,
+ the dbg_interactive.fdx extension allows access to the 
+ framework via a python interpreter console.  
+
+Package: freediameter-dictionary-rfc4005
+Architecture: any
+Depends: ${misc:Depends}, freediameter-common (= ${binary:Version})
+Description: RFC4005 (NASREQ) dictionary support.
+ This freeDiameter extension provides the dictionary support
+ for commands and AVP defined in RFC4005 (NASREQ).
+ .
+ In order to use this extension, your main freeDiameter 
+ configuration file must contain a LoadExtension directive. 
+ See freeDiameter documentation for more details. 
+ .
+ This extension does not require a configuration file.
+
+Package: freediameter-dictionary-rfc4006
+Architecture: any
+Depends: ${misc:Depends}, freediameter-common (= ${binary:Version})
+Description: RFC4006 (DCCA) dictionary support (incomplete).
+ This freeDiameter extension provides the dictionary support
+ for commands and AVP defined in RFC4006 (DCCA).
+ .
+ In order to use this extension, your main freeDiameter 
+ configuration file must contain a LoadExtension directive. 
+ See freeDiameter documentation for more details. 
+ .
+ This extension does not require a configuration file.
+ .
+ Currently this extension is not complete: only AVP definitions 
+ are included. See the source file for more details.
+
+Package: freediameter-dictionary-rfc4072
+Architecture: any
+Depends: ${misc:Depends}, freediameter-common (= ${binary:Version}), freediameter-dictionary-rfc4005 (= ${binary:Version})
+Description: RFC4072 (Diameter EAP) dictionary support.
+ This freeDiameter extension provides the dictionary support
+ for commands and AVP defined in RFC4072 (Diameter EAP).
+ .
+ In order to use this extension, your main freeDiameter 
+ configuration file must contain a LoadExtension directive. 
+ See freeDiameter documentation for more details. 
+ .
+ This extension does not require a configuration file.
+
+Package: freediameter-dictionary-rfc4740
+Architecture: any
+Depends: ${misc:Depends}, freediameter-common (= ${binary:Version})
+Description: RFC4740 (Diameter SIP) dictionary support.
+ This freeDiameter extension provides the dictionary support
+ for commands and AVP defined in RFC4740 (Diameter SIP).
+ .
+ In order to use this extension, your main freeDiameter 
+ configuration file must contain a LoadExtension directive. 
+ See freeDiameter documentation for more details. 
+ .
+ This extension does not require a configuration file.
+
+Package: freediameter-dictionary-mip6
+Architecture: any
+Depends: ${misc:Depends}, freediameter-common (= ${binary:Version})
+Description: Diameter Mobile IPv6 application dictionary support.
+ This package contains a set of extensions to provide the support
+ for commands and AVP defined in several RFCs related to
+ Diameter MIPv6. It is split is several extensions:
+ mip6a, mip6i, nas-mipv6, rfc5777.
+ .
+ In order to use these extensions, your main freeDiameter 
+ configuration file must contain LoadExtension directives. 
+ See freeDiameter documentation for more details. 
+ .
+ These extensions do not require a configuration file.
+
+Package: freediameter-dictionary-legacy
+Architecture: any
+Depends: ${misc:Depends}, freediameter-common (= ${binary:Version}), libxml2
+Description: Legacy XML dictionary files support.
+ This freeDiameter extension allows the use of XML dictionary
+ files with the freeDiameter framework. Please note that
+ dictionaries provided as XML files come with less features
+ than native binary format, so the later should be preferred
+ when possible.
+ .
+ In order to use this extension, your main freeDiameter 
+ configuration file must contain a LoadExtension directive. 
+ See freeDiameter documentation for more details. 
+ .
+ This extension requires a configuration file. See 
+ dict_legacy_xml.conf.sample for documentation.
+
+Package: freediameter-radius-gateway
+Architecture: any
+Depends: ${misc:Depends}, freediameter-daemon (= ${binary:Version})
+Suggests: freediameter-dictionary-rfc4072 (= ${binary:Version}), freediameter-dictionary-rfc4740 (= ${binary:Version})
+Description: RADIUS/Diameter extensible gateway.
+ This freeDiameter extension implements a RADIUS to Diameter
+ gateway. It allows a RADIUS client to connect to a Diameter
+ server.
+ .
+ The support for specific Diameter applications and/or RADIUS 
+ extensions is provided in the gateway by the use of plugins.
+ Currently, the following plugins are available:
+  - echodrop.rgwx : drop or echo a RADIUS attribute. 
+                    The attribute is not converted to Diameter.
+		    See echodrop.rgwx.conf.sample for details.
+  - auth.rgwx : Convert Access-Request to Diameter AAR or DER.
+                Requests For Comments: RADIUS: 2865, 3162, 2868,
+		2869, 3579; Diameter: 4005, 4072.
+		Requires freediameter-dictionary-rfc4072.
+  - sip.rgwx  : Convert Access-Request to Diameter SIP messages.
+                Requests For Comments: Diameter: 4740.
+		Requires freediameter-dictionary-rfc4740.
+  - acct.rgwx : Converts Accounting-Request (2866) to Diameter 
+                ACR (3588).
+		Requires freediameter-dictionary-rfc4072.
+ .
+ In order to use this extension, your main freeDiameter 
+ configuration file must contain a LoadExtension directive. 
+ See freeDiameter documentation for more details. 
+ .
+ This extension requires a configuration file.
+ See app_radgw.conf.sample for more details.
+
+Package: freediameter-accounting-server
+Architecture: any
+Depends: ${misc:Depends}, freediameter-daemon (= ${binary:Version}), libpq5
+Suggests: freediameter-dictionary-rfc4072
+Description: freeDiameter simple Accounting server.
+ This freeDiameter extension implements the Diameter Base 
+ Accounting application. It saves the accounting records
+ in a PostgreSQL database backend in a highly configurable
+ maneer.
+ .
+ In order to use this extension, your main freeDiameter 
+ configuration file must contain a LoadExtension directive. 
+ See freeDiameter documentation for more details. 
+ .
+ This extension requires a configuration file.
+ See app_acct.conf.sample for more details.
+ .
+ You may find some useful resources to parse the saved records
+ in the contrib/app_acct_tools folder in source package.
+
+Package: freediameter-eap-server
+Architecture: any
+Depends: ${misc:Depends}, freediameter-daemon (= ${binary:Version}), libmysqlclient16 | libmysqlclient18, freediameter-dictionary-rfc4072 (= ${binary:Version})
+Description: freeDiameter Diameter EAP server implementation.
+ This freeDiameter extension implements a Diameter EAP server. 
+ It supports EAP-MD5 and EAP-TLS methods currently.
+ .
+ In order to use this extension, your main freeDiameter 
+ configuration file must contain a LoadExtension directive. 
+ See freeDiameter documentation for more details. 
+ .
+ This extension requires a configuration file.
+ See app_diameap.conf.sample and 
+ http://diameap.yagami.freediameter.net for more details.
+
+Package: freediameter-sip-server
+Architecture: any
+Depends: ${misc:Depends}, freediameter-daemon (= ${binary:Version}), libmysqlclient16 | libmysqlclient18, freediameter-dictionary-rfc4740 (= ${binary:Version})
+Description: freeDiameter Diameter SIP server implementation.
+ This freeDiameter extension implements a prototype 
+ Diameter SIP server.
+ See http://www.freediameter.net/trac/wiki/app_sip.fdx for
+ status information.
+ .
+ In order to use this extension, your main freeDiameter 
+ configuration file must contain a LoadExtension directive. 
+ See freeDiameter documentation for more details. 
+ .
+ This extension requires a configuration file.
+ See app_sip.conf.sample for more details.
+
diff --git a/contrib/debian/copyright b/contrib/debian/copyright
new file mode 100644
index 0000000..114bfa6
--- /dev/null
+++ b/contrib/debian/copyright
@@ -0,0 +1,35 @@
+Format-Specification: http://dep.debian.net/deps/dep5/
+Name: freeDiameter
+Maintainer: Sebastien Decugis <sdecugis@freediameter.net>
+Source: http://www.freediameter.net
+
+Files: *
+Copyright: 2008-2011, WIDE Project and NICT.
+License: BSD
+ Redistribution and use of this software in source and binary forms, with or without modification, are
+ permitted provided that the following conditions are met:
+ .
+ * Redistributions of source code must retain the above
+   copyright notice, this list of conditions and the
+   following disclaimer.
+ . 
+ * Redistributions in binary form must reproduce the above
+   copyright notice, this list of conditions and the
+   following disclaimer in the documentation and/or other
+   materials provided with the distribution.
+ .
+ * Neither the name of the WIDE Project or NICT nor the
+   names of its contributors may be used to endorse or
+   promote products derived from this software without
+   specific prior written permission of WIDE Project and
+   NICT.
+ .
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
+ WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+ TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
diff --git a/contrib/debian/dirs b/contrib/debian/dirs
new file mode 100644
index 0000000..e9e5399
--- /dev/null
+++ b/contrib/debian/dirs
@@ -0,0 +1 @@
+etc/freeDiameter/
diff --git a/contrib/debian/docs b/contrib/debian/docs
new file mode 100644
index 0000000..5238a99
--- /dev/null
+++ b/contrib/debian/docs
@@ -0,0 +1,3 @@
+INSTALL*
+LICENSE
+README
diff --git a/contrib/debian/freediameter-accounting-server.examples b/contrib/debian/freediameter-accounting-server.examples
new file mode 100644
index 0000000..adce646
--- /dev/null
+++ b/contrib/debian/freediameter-accounting-server.examples
@@ -0,0 +1 @@
+doc/app_acct.conf.sample
diff --git a/contrib/debian/freediameter-accounting-server.install b/contrib/debian/freediameter-accounting-server.install
new file mode 100644
index 0000000..6d3b1d9
--- /dev/null
+++ b/contrib/debian/freediameter-accounting-server.install
@@ -0,0 +1 @@
+usr/lib/freeDiameter/app_acct.fdx
diff --git a/contrib/debian/freediameter-common.examples b/contrib/debian/freediameter-common.examples
new file mode 100644
index 0000000..8abb336
--- /dev/null
+++ b/contrib/debian/freediameter-common.examples
@@ -0,0 +1,5 @@
+doc/freediameter.conf.sample
+doc/acl_wl.conf.sample
+doc/rt_default.conf.sample
+doc/rt_ereg.conf.sample
+doc/single_host
diff --git a/contrib/debian/freediameter-common.install b/contrib/debian/freediameter-common.install
new file mode 100644
index 0000000..b8861ed
--- /dev/null
+++ b/contrib/debian/freediameter-common.install
@@ -0,0 +1,6 @@
+usr/lib/libfdproto.so*
+usr/lib/libfdcore.so*
+usr/lib/freeDiameter/acl_wl.fdx
+usr/lib/freeDiameter/rt_default.fdx
+usr/lib/freeDiameter/rt_ereg.fdx
+usr/lib/freeDiameter/dbg_monitor.fdx
diff --git a/contrib/debian/freediameter-daemon.default b/contrib/debian/freediameter-daemon.default
new file mode 100644
index 0000000..ed8b792
--- /dev/null
+++ b/contrib/debian/freediameter-daemon.default
@@ -0,0 +1,7 @@
+# Defaults for freediameter initscript
+# sourced by /etc/init.d/freediameter
+# installed at /etc/default/freediameter by the maintainer scripts
+
+# Additional options that are passed to the Daemon.
+# See "freeDiameterd --help" for supported flags.
+DAEMON_OPTS=""
diff --git a/contrib/debian/freediameter-daemon.init b/contrib/debian/freediameter-daemon.init
new file mode 100644
index 0000000..7b2a31a
--- /dev/null
+++ b/contrib/debian/freediameter-daemon.init
@@ -0,0 +1,160 @@
+#! /bin/sh
+
+### BEGIN INIT INFO
+# Provides:          freediameter
+# Default-Start:     2 3 4 5
+# Default-Stop:      0 1 6
+# Required-Start:    $remote_fs $syslog
+# Required-Stop:     $remote_fs $syslog
+# Short-Description: Start freeDiameter daemon at boot time
+# Description:       Start the freeDiameter daemon at boot time.
+#	freeDiameter is an extensible implementation of the Diameter protocol,
+#	designed for Authentication, Authorization and Accounting. Diameter is
+#	an evolution of the RADIUS protocol.
+### END INIT INFO#
+
+DAEMON=/usr/bin/freeDiameterd
+CONF=/etc/freeDiameter/freeDiameter.conf
+NAME=freediameter
+DESC="freeDiameter daemon"
+
+test -x $DAEMON || exit 0
+
+LOGDIR=/var/log/freediameter
+PIDFILE=/var/run/$NAME.pid
+DODTIME=30                  # Time to wait for the server to die, in seconds
+                            # The value is high because we wait for STA answers
+			    # before disconnecting the peers.
+
+# Include freediameter defaults if available
+if [ -f /etc/default/freediameter ] ; then
+    . /etc/default/freediameter
+fi
+
+test x"" != x$DAEMON_OPTS || test -f $CONF || exit 0
+
+set -e
+
+running_pid()
+{
+    # Check if a given process pid's cmdline matches a given name
+    pid=$1
+    name=$2
+    [ -z "$pid" ] && return 1
+    [ ! -d /proc/$pid ] &&  return 1
+    cmd=`cat /proc/$pid/cmdline | tr "\000" "\n"|head -n 1 |cut -d : -f 1`
+    # Is this the expected child?
+    [ "$cmd" != "$name" ] &&  return 1
+    return 0
+}
+
+running()
+{
+# Check if the process is running looking at /proc
+# (works for all users)
+
+    # No pidfile, probably no daemon present
+    [ ! -f "$PIDFILE" ] && return 1
+    # Obtain the pid and check it against the binary name
+    pid=`cat $PIDFILE`
+    running_pid $pid $DAEMON || return 1
+    return 0
+}
+
+force_stop() {
+# Forcefully kill the process
+    [ ! -f "$PIDFILE" ] && return
+    if running ; then
+        kill -15 $pid
+        # Is it really dead?
+        [ -n "$DODTIME" ] && sleep "$DODTIME"s
+        if running ; then
+            kill -9 $pid
+            [ -n "$DODTIME" ] && sleep "$DODTIME"s
+            if running ; then
+                echo "Cannot kill $LABEL (pid=$pid)!"
+                exit 1
+            fi
+        fi
+    fi
+    rm -f $PIDFILE
+    return 0
+}
+
+case "$1" in
+  start)
+        echo -n "Starting $DESC: "
+        start-stop-daemon --start --quiet --pidfile $PIDFILE \
+            --exec $DAEMON -- $DAEMON_OPTS
+        if running ; then
+            echo "$NAME."
+        else
+            echo " ERROR."
+        fi
+        ;;
+  stop)
+        echo -n "Stopping $DESC: "
+        start-stop-daemon --stop --quiet --pidfile $PIDFILE \
+            --exec $DAEMON
+        echo "$NAME."
+        ;;
+  force-stop)
+        echo -n "Forcefully stopping $DESC: "
+        force_stop
+        if ! running ; then
+            echo "$NAME."
+        else
+            echo " ERROR."
+        fi
+        ;;
+  #reload)
+        #
+        # If the daemon can reload its config files on the fly
+        # for example by sending it SIGHUP, do it here.
+        #
+        # If the daemon responds to changes in its config file
+        # directly anyway, make this a do-nothing entry.
+        #
+        # echo "Reloading $DESC configuration files."
+        # start-stop-daemon --stop --signal 1 --quiet --pidfile \
+        #       /var/run/$NAME.pid --exec $DAEMON
+  #;;
+  force-reload)
+        #
+        # If the "reload" option is implemented, move the "force-reload"
+        # option to the "reload" entry above. If not, "force-reload" is
+        # just the same as "restart" except that it does nothing if the
+        # daemon isn't already running.
+        # check wether $DAEMON is running. If so, restart
+        start-stop-daemon --stop --test --quiet --pidfile \
+            /var/run/$NAME.pid --exec $DAEMON \
+            && $0 restart \
+            || exit 0
+        ;;
+  restart)
+    echo -n "Restarting $DESC: "
+        start-stop-daemon --stop --quiet --pidfile \
+            /var/run/$NAME.pid --exec $DAEMON
+        [ -n "$DODTIME" ] && sleep $DODTIME
+        start-stop-daemon --start --quiet --pidfile \
+            /var/run/$NAME.pid --exec $DAEMON -- $DAEMON_OPTS
+        echo "$NAME."
+        ;;
+  status)
+    echo -n "$LABEL is "
+    if running ;  then
+        echo "running"
+    else
+        echo " not running."
+        exit 1
+    fi
+    ;;
+  *)
+    N=/etc/init.d/$NAME
+    # echo "Usage: $N {start|stop|restart|reload|force-reload}" >&2
+    echo "Usage: $N {start|stop|restart|force-reload|status|force-stop}" >&2
+    exit 1
+    ;;
+esac
+
+exit 0
diff --git a/contrib/debian/freediameter-daemon.install b/contrib/debian/freediameter-daemon.install
new file mode 100644
index 0000000..cf167a3
--- /dev/null
+++ b/contrib/debian/freediameter-daemon.install
@@ -0,0 +1 @@
+usr/bin/freeDiameterd*
diff --git a/contrib/debian/freediameter-debug-tools.examples b/contrib/debian/freediameter-debug-tools.examples
new file mode 100644
index 0000000..9750d1e
--- /dev/null
+++ b/contrib/debian/freediameter-debug-tools.examples
@@ -0,0 +1,3 @@
+doc/test_app.conf.sample
+doc/test_netemul.conf.sample
+doc/dbg_interactive.py.sample
diff --git a/contrib/debian/freediameter-debug-tools.install b/contrib/debian/freediameter-debug-tools.install
new file mode 100644
index 0000000..32c7f56
--- /dev/null
+++ b/contrib/debian/freediameter-debug-tools.install
@@ -0,0 +1,5 @@
+usr/lib/freeDiameter/dbg_rt.fdx
+usr/lib/freeDiameter/test_app.fdx
+usr/lib/freeDiameter/test_sip.fdx
+usr/lib/freeDiameter/test_netemul.fdx
+usr/lib/freeDiameter/dbg_interactive.fdx
diff --git a/contrib/debian/freediameter-dev.install b/contrib/debian/freediameter-dev.install
new file mode 100644
index 0000000..e055d40
--- /dev/null
+++ b/contrib/debian/freediameter-dev.install
@@ -0,0 +1 @@
+usr/include/freeDiameter/*
diff --git a/contrib/debian/freediameter-dictionary-legacy.examples b/contrib/debian/freediameter-dictionary-legacy.examples
new file mode 100644
index 0000000..9aede23
--- /dev/null
+++ b/contrib/debian/freediameter-dictionary-legacy.examples
@@ -0,0 +1,2 @@
+doc/dict_legacy_xml.conf.sample
+contrib/dict_legacy/dictionary.dtd
diff --git a/contrib/debian/freediameter-dictionary-legacy.install b/contrib/debian/freediameter-dictionary-legacy.install
new file mode 100644
index 0000000..acddf9b
--- /dev/null
+++ b/contrib/debian/freediameter-dictionary-legacy.install
@@ -0,0 +1 @@
+usr/lib/freeDiameter/dict_legacy_xml.fdx
diff --git a/contrib/debian/freediameter-dictionary-mip6.install b/contrib/debian/freediameter-dictionary-mip6.install
new file mode 100644
index 0000000..b337c3e
--- /dev/null
+++ b/contrib/debian/freediameter-dictionary-mip6.install
@@ -0,0 +1,4 @@
+usr/lib/freeDiameter/dict_nas_mipv6.fdx
+usr/lib/freeDiameter/dict_mip6i.fdx
+usr/lib/freeDiameter/dict_mip6a.fdx
+usr/lib/freeDiameter/dict_rfc5777.fdx
diff --git a/contrib/debian/freediameter-dictionary-rfc4005.install b/contrib/debian/freediameter-dictionary-rfc4005.install
new file mode 100644
index 0000000..1c82430
--- /dev/null
+++ b/contrib/debian/freediameter-dictionary-rfc4005.install
@@ -0,0 +1 @@
+usr/lib/freeDiameter/dict_nasreq.fdx
diff --git a/contrib/debian/freediameter-dictionary-rfc4006.install b/contrib/debian/freediameter-dictionary-rfc4006.install
new file mode 100644
index 0000000..0284a39
--- /dev/null
+++ b/contrib/debian/freediameter-dictionary-rfc4006.install
@@ -0,0 +1 @@
+usr/lib/freeDiameter/dict_dcca.fdx
diff --git a/contrib/debian/freediameter-dictionary-rfc4072.install b/contrib/debian/freediameter-dictionary-rfc4072.install
new file mode 100644
index 0000000..39c44ad
--- /dev/null
+++ b/contrib/debian/freediameter-dictionary-rfc4072.install
@@ -0,0 +1 @@
+usr/lib/freeDiameter/dict_eap.fdx
diff --git a/contrib/debian/freediameter-dictionary-rfc4740.install b/contrib/debian/freediameter-dictionary-rfc4740.install
new file mode 100644
index 0000000..08dbfe2
--- /dev/null
+++ b/contrib/debian/freediameter-dictionary-rfc4740.install
@@ -0,0 +1 @@
+usr/lib/freeDiameter/dict_sip.fdx
diff --git a/contrib/debian/freediameter-eap-server.examples b/contrib/debian/freediameter-eap-server.examples
new file mode 100644
index 0000000..7a9ed7a
--- /dev/null
+++ b/contrib/debian/freediameter-eap-server.examples
@@ -0,0 +1,2 @@
+doc/app_diameap.conf.sample
+doc/eap_tls_plugin.diameap.conf.sample
diff --git a/contrib/debian/freediameter-eap-server.install b/contrib/debian/freediameter-eap-server.install
new file mode 100644
index 0000000..bafb174
--- /dev/null
+++ b/contrib/debian/freediameter-eap-server.install
@@ -0,0 +1,2 @@
+usr/lib/freeDiameter/app_diameap.fdx
+usr/lib/freeDiameter/*.emp
diff --git a/contrib/debian/freediameter-radius-gateway.examples b/contrib/debian/freediameter-radius-gateway.examples
new file mode 100644
index 0000000..0326df0
--- /dev/null
+++ b/contrib/debian/freediameter-radius-gateway.examples
@@ -0,0 +1,2 @@
+doc/app_radgw.conf.sample
+doc/echodrop.rgwx.conf.sample
diff --git a/contrib/debian/freediameter-radius-gateway.install b/contrib/debian/freediameter-radius-gateway.install
new file mode 100644
index 0000000..23ee8dc
--- /dev/null
+++ b/contrib/debian/freediameter-radius-gateway.install
@@ -0,0 +1,2 @@
+usr/lib/freeDiameter/app_radgw.fdx
+usr/lib/freeDiameter/*.rgwx
diff --git a/contrib/debian/freediameter-sip-server.examples b/contrib/debian/freediameter-sip-server.examples
new file mode 100644
index 0000000..f49290b
--- /dev/null
+++ b/contrib/debian/freediameter-sip-server.examples
@@ -0,0 +1,4 @@
+doc/app_sip.conf.sample
+doc/app_sip.sql
+doc/app_sip_SL.sql
+doc/test_sip.conf.sample
diff --git a/contrib/debian/freediameter-sip-server.install b/contrib/debian/freediameter-sip-server.install
new file mode 100644
index 0000000..4b8c612
--- /dev/null
+++ b/contrib/debian/freediameter-sip-server.install
@@ -0,0 +1,3 @@
+usr/lib/freeDiameter/app_sip.fdx
+usr/share/doc/freeDiameter-sip-server/*
+usr/bin/freediameter-sip-*
diff --git a/contrib/debian/rules b/contrib/debian/rules
new file mode 100755
index 0000000..808f7ea
--- /dev/null
+++ b/contrib/debian/rules
@@ -0,0 +1,31 @@
+#!/usr/bin/make -f
+# -*- makefile -*-
+# Sample debian/rules that uses debhelper.
+#
+# This file was originally written by Joey Hess and Craig Small.
+# As a special exception, when this file is copied by dh-make into a
+# dh-make output file, you may use that output file without restriction.
+# This special exception was added by Craig Small in version 0.37 of dh-make.
+#
+# Modified to make a template file for a multi-binary package with separated
+# build-arch and build-indep targets  by Bill Allombert 2001
+
+# Uncomment this to turn on verbose mode.
+#export DH_VERBOSE=1
+
+# This has to be exported to make some magic below work.
+export DH_OPTIONS
+
+# Comment this out if you want to include the tests when the package is built
+skip_the_tests=-DBUILD_TESTING:BOOL=OFF
+
+%:
+	dh  $@
+
+override_dh_auto_configure:
+	dh_auto_configure -- $(skip_the_tests) \
+		-DCMAKE_BUILD_TYPE:STRING=DebianPackage \
+		-DDEFAULT_CONF_PATH:PATH=/etc/freeDiameter \
+		-DALL_EXTENSIONS:BOOL=ON
+		
+
diff --git a/contrib/debian/update_changelog.txt b/contrib/debian/update_changelog.txt
new file mode 100644
index 0000000..ac6efbd
--- /dev/null
+++ b/contrib/debian/update_changelog.txt
@@ -0,0 +1,3 @@
+new release: dch -v 1.0.3 -D UNRELEASED --release-heuristic log
+Simple addition: dch "changelog entry text"
+
diff --git a/contrib/dict_dcca/README b/contrib/dict_dcca/README
new file mode 100644
index 0000000..7da3cc8
--- /dev/null
+++ b/contrib/dict_dcca/README
@@ -0,0 +1,5 @@
+Files provided courtesy of Konstantin Chekushin under the same license as freeDiameter.
+
+Comment:
+"They are not full, I've filled only that I wanted to use in our app_dcca module. "
+
diff --git a/contrib/dict_dcca/dict_dcca_3gpp.c b/contrib/dict_dcca/dict_dcca_3gpp.c
new file mode 100644
index 0000000..af78426
--- /dev/null
+++ b/contrib/dict_dcca/dict_dcca_3gpp.c
@@ -0,0 +1,841 @@
+/* 
+ * Dictionary definitions of objects specified in DCCA (Nokia, 3GPP).
+ */
+#include <freeDiameter/extension.h>
+
+
+/* The content of this file follows the same structure as dict_base_proto.c */
+
+#define CHECK_dict_new( _type, _data, _parent, _ref )	\
+	CHECK_FCT(  fd_dict_new( fd_g_config->cnf_dict, (_type), (_data), (_parent), (_ref))  );
+
+#define CHECK_dict_search( _type, _criteria, _what, _result )	\
+	CHECK_FCT(  fd_dict_search( fd_g_config->cnf_dict, (_type), (_criteria), (_what), (_result), ENOENT) );
+
+struct local_rules_definition {
+	char 			*avp_name;
+	enum rule_position	position;
+	int 			min;
+	int			max;
+};
+
+#define RULE_ORDER( _position ) ((((_position) == RULE_FIXED_HEAD) || ((_position) == RULE_FIXED_TAIL)) ? 1 : 0 )
+
+#define PARSE_loc_rules( _rulearray, _parent) {								\
+	int __ar;											\
+	for (__ar=0; __ar < sizeof(_rulearray) / sizeof((_rulearray)[0]); __ar++) {			\
+		struct dict_rule_data __data = { NULL, 							\
+			(_rulearray)[__ar].position,							\
+			0, 										\
+			(_rulearray)[__ar].min,								\
+			(_rulearray)[__ar].max};							\
+		__data.rule_order = RULE_ORDER(__data.rule_position);					\
+		CHECK_FCT(  fd_dict_search( 								\
+			fd_g_config->cnf_dict,								\
+			DICT_AVP, 									\
+			AVP_BY_NAME, 									\
+			(_rulearray)[__ar].avp_name, 							\
+			&__data.rule_avp, 0 ) );							\
+		if ( !__data.rule_avp ) {								\
+			TRACE_DEBUG(INFO, "AVP Not found: '%s'", (_rulearray)[__ar].avp_name );		\
+			return ENOENT;									\
+		}											\
+		CHECK_FCT_DO( fd_dict_new( fd_g_config->cnf_dict, DICT_RULE, &__data, _parent, NULL),	\
+			{							        		\
+				TRACE_DEBUG(INFO, "Error on rule with AVP '%s'",      			\
+					 (_rulearray)[__ar].avp_name );		      			\
+				return EINVAL;					      			\
+			} );							      			\
+	}									      			\
+}
+
+#define enumval_def_u32( _val_, _str_ ) \
+		{ _str_, 		{ .u32 = _val_ }}
+
+#define enumval_def_os( _len_, _val_, _str_ ) \
+		{ _str_, 		{ .os = { .data = (unsigned char *)_val_, .len = _len_ }}}
+
+
+static int dict_dcca_3gpp_entry(char * conffile)
+{
+	TRACE_ENTRY("%p", conffile);		
+	
+	/* Applications section */
+	{		
+                /* Create the vendors */
+                {
+                        struct dict_vendor_data vendor_data = { 10415, "3GPP" };
+                        CHECK_FCT(fd_dict_new(fd_g_config->cnf_dict, DICT_VENDOR, &vendor_data, NULL, NULL));
+                }                                
+  
+	}
+	
+	
+	/* AVP section */
+        {
+                struct dict_object * Address_type;
+                struct dict_object * UTF8String_type;
+                struct dict_object * DiameterIdentity_type;
+                struct dict_object * DiameterURI_type;
+                struct dict_object * Time_type;
+
+                CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "Address", &Address_type);
+                CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "UTF8String", &UTF8String_type);
+                CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "DiameterIdentity", &DiameterIdentity_type);
+                CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "DiameterURI", &DiameterURI_type);
+                CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "Time", &Time_type);                                
+
+                /* Reporting-Reason */
+                {
+                  /* 
+                     Enumerated. Will be present if quota was 
+                     exhausted for one or more metering types. Only 
+                     one Reporting-Reason AVP can be present in the 
+                     Used-Service-Unit AVP. (Note that the Reporting-
+                     Reason AVP may be present also at the MSCC 
+                     level; see below.)
+                     The following values are supported:
+
+                     QUOTA_EXHAUSTED(3); Quota for the 
+                     associated metering type has been 
+                     exhausted. With this reporting reason there is 
+                     only one metering type in this Used-Service-
+                     Unit AVP.
+
+                     OTHER_QUOTA_TYPE(5); Quota for one or 
+                     more of the other metering types has been 
+                     exhausted. With this reporting reason there 
+                     may be multiple metering types in Used-
+                     Service-Unit AVP.
+
+                     POOL_EXHAUSTED(8); Quota from the 
+                     credit pool has been exhausted. This reporting 
+                     reason is used if the quota for the associated 
+                     metering type was granted from a credit pool 
+                     by using the GSU-Pool-Reference AVP in the 
+                     CCA. With this reporting reason there is only 
+                     one metering type in the Used-Service-Unit 
+                     AVP.
+                  */
+
+                  struct dict_object              *type;
+                  struct dict_type_data           tdata = { AVP_TYPE_INTEGER32,   "Enumerated(Reporting-Reason)" , NULL, NULL, NULL };
+				  struct dict_enumval_data        t_1 = { "QHT",                      { .i32 = 1 }};
+				  struct dict_enumval_data        t_2 = { "FINAL",                      { .i32 = 2 }};
+                  struct dict_enumval_data        t_3 = { "QUOTA_EXHAUSTED",                      { .i32 = 3 }};
+				  struct dict_enumval_data        t_4 = { "VALIDITY_TIME",                      { .i32 = 4 }};
+                  struct dict_enumval_data        t_5 = { "OTHER_QUOTA_TYPE",        { .i32 = 5 }};
+				  struct dict_enumval_data        t_6 = { "RATING_CONDITION_CHANGE",        { .i32 = 6 }};
+				  struct dict_enumval_data        t_7 = { "FORCED_REAUTHORIZATION",        { .i32 = 7 }};
+                  struct dict_enumval_data        t_8 = { "POOL_EXHAUSTED",                  { .i32 = 8 }};
+
+                  struct dict_avp_data    data = { 
+                    872,                                    /* Code */
+                    10415,                                      /* Vendor */
+                    "Reporting-Reason",                    /* Name */
+                    AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,   /* Fixed flags */
+                    AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,                     /* Fixed flag values */
+                    AVP_TYPE_INTEGER32                      /* base type of data */
+                  };
+                  /* Create the Enumerated type, and then the AVP */
+                  CHECK_dict_new( DICT_TYPE, &tdata , NULL, &type);
+                  CHECK_dict_new( DICT_ENUMVAL, &t_3 , type, NULL);
+                  CHECK_dict_new( DICT_ENUMVAL, &t_5 , type, NULL);
+                  CHECK_dict_new( DICT_ENUMVAL, &t_8 , type, NULL);
+                  CHECK_dict_new( DICT_AVP, &data , type, NULL);
+                }               
+
+                /* Trigger */
+                {
+                  /*
+                    Grouped. The presence of the Trigger AVP in the 
+                    CCR identifies the event(s) triggering the CCR.
+                   */
+
+                  struct dict_avp_data data = {
+                    1264,                                    /* Code */
+                    10415,                                      /* Vendor */
+                    "Trigger",                  /* Name */
+                    AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,   /* Fixed flags */
+                    AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,                     /* Fixed flag values */
+                    AVP_TYPE_GROUPED                        /* base type of data */
+                  };
+                  CHECK_dict_new( DICT_AVP, &data , NULL, NULL);
+                }
+
+                /* Trigger-Type */
+                {
+                  /* 
+                     Enumerated. One or more of these AVPs may be 
+                     present. Indicates the event that triggered the 
+                     MSCC. Supported values are:
+
+                     CHANGE_IN_SGSN_IP_ADDRESS (1), a  change in the SGSN address.
+
+                     CHANGEINQOS_ANY (2), a change in the QoS profile
+
+                     CHANGEINRAT (4), a change in radio access technology
+
+                   */
+
+                  struct dict_object              *type;
+                  struct dict_type_data           tdata = { AVP_TYPE_INTEGER32,   "Enumerated(Trigger-Type)" , NULL, NULL, NULL };
+                  struct dict_enumval_data        t_1 = { "CHANGE_IN_SGSN_IP_ADDRESS",                      { .i32 = 1 }};
+                  struct dict_enumval_data        t_2 = { "CHANGEINQOS_ANY",        { .i32 = 2 }};
+                  struct dict_enumval_data        t_4 = { "CHANGEINRAT",                  { .i32 = 4 }};
+
+                  struct dict_avp_data    data = { 
+                    870,                                    /* Code */
+                    10415,                                      /* Vendor */
+                    "Trigger-Type",                    /* Name */
+                    AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,   /* Fixed flags */
+                    AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,                     /* Fixed flag values */
+                    AVP_TYPE_INTEGER32                      /* base type of data */
+                  };
+                  /* Create the Enumerated type, and then the AVP */
+                  CHECK_dict_new( DICT_TYPE, &tdata , NULL, &type);
+                  CHECK_dict_new( DICT_ENUMVAL, &t_1 , type, NULL);
+                  CHECK_dict_new( DICT_ENUMVAL, &t_2 , type, NULL);
+                  CHECK_dict_new( DICT_ENUMVAL, &t_4 , type, NULL);
+                  CHECK_dict_new( DICT_AVP, &data , type, NULL);
+                }
+                
+                /* Service-Information */
+                {
+                  /* 
+                     Grouped. The Service-Information purpose is to 
+                     allow the transmission of additional 3GPP service 
+                     specific information elements (3GPP 32.299 
+                     Rel7).
+                  */
+
+                  struct dict_avp_data data = {
+                    873,                                    /* Code */
+                    10415,                                      /* Vendor */
+                    "Service-Information",                  /* Name */
+                    AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,   /* Fixed flags */
+                    AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,                     /* Fixed flag values */
+                    AVP_TYPE_GROUPED                        /* base type of data */
+                  };
+                  CHECK_dict_new( DICT_AVP, &data , NULL, NULL);
+                }
+
+                /* PS-Information */
+                {
+                  /* 
+                     Grouped. Its purpose is to allow the transmission 
+                     of additional PS service specific information 
+                     elements (3GPP 32.299 Rel7).
+                  */
+
+                  struct dict_avp_data data = {
+                    874,                                    /* Code */
+                    10415,                                      /* Vendor */
+                    "PS-Information",                  /* Name */
+                    AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,   /* Fixed flags */
+                    AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,                     /* Fixed flag values */
+                    AVP_TYPE_GROUPED                        /* base type of data */
+                  };
+                  CHECK_dict_new( DICT_AVP, &data , NULL, NULL);
+                }
+
+                /* PDP-Address */
+                {
+                  /*
+                    Address. Present only in the initial CCR. Contains 
+                    the user equipment IP address. This AVP is 
+                    defined in 3GPP 32.299 Rel7. 
+                  */
+
+                  struct dict_avp_data data = { 
+                    1227,                                    /* Code */
+                    10415,                                      /* Vendor */
+                    "PDP-Address",                      /* Name */
+                    AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,   /* Fixed flags */
+                    AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,                     /* Fixed flag values */
+                    AVP_TYPE_OCTETSTRING                    /* base type of data */
+                  };
+                  CHECK_dict_new( DICT_AVP, &data , Address_type, NULL);
+                }
+
+                /* 3GPP-IMSI */
+                {
+                  /*
+		    IMSI encoded in UTF-8 per 3GPP TS 23.003. No
+		    padding. Maximum length of data: 15.
+                  */
+                  struct dict_avp_data data = { 
+                    1,                                    /* Code */
+                    10415,                                      /* Vendor */
+                    "3GPP-IMSI",                            /* Name */
+                    AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,   /* Fixed flags */
+                    AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,                     /* Fixed flag values */
+                    AVP_TYPE_OCTETSTRING                      /* base type of data */
+                  };
+                  CHECK_dict_new( DICT_AVP, &data , UTF8String_type, NULL);
+                }
+
+                /* 3GPP-Charging-Id */
+                {
+                  /*
+                    Unsigned32. (3GPP TS 29.061 Rel7) . The 
+                    charging identifier for the PDP context. The Flexi 
+                    ISN generates the 3GPP charging ID for both 
+                    virtual and normal PDP contexts with one excep-
+                    tion. If the Flexi ISN acts as a NAS server and the 
+                    charging ID selection is set to NAS Client, the 
+                    charging ID will be the NAand not the 3GPP charging ID of Flexi ISN. 
+                    Present in the initial CCR only.S client
+                  */
+                  struct dict_avp_data data = { 
+                    2,                                    /* Code */
+                    10415,                                      /* Vendor */
+                    "3GPP-Charging-Id",                      /* Name */
+                    AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,   /* Fixed flags */
+                    AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,                     /* Fixed flag values */
+                    AVP_TYPE_UNSIGNED32                     /* base type of data */
+                  };
+                  CHECK_dict_new( DICT_AVP, &data , NULL, NULL);
+                }
+
+                /* 3GPP-PDP-Type */
+                {
+                  /*
+                    Enumerated. (3GPP TS 29.061 Rel7 ). Type of 
+                    PDP context, for example, IP or PPP. Present in 
+                    the initial CCR only.
+		    0 = IPv4
+		    1 = PPP
+		    2 = IPv6
+		    3 = IPv4v6
+                  */
+                  struct dict_avp_data    data = { 
+                    3,                                    /* Code */
+                    10415,                                      /* Vendor */
+                    "3GPP-PDP-Type",                    /* Name */
+                    AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,   /* Fixed flags */
+                    AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,                     /* Fixed flag values */
+                    AVP_TYPE_UNSIGNED32                      /* base type of data */
+                  };
+                  CHECK_dict_new( DICT_AVP, &data , NULL, NULL);
+                }
+
+                /* 3GPP-CG-Address */
+                {
+                  /*
+                    OctetString. (3GPP TS 29.061 Rel4). The address 
+                    of the charging gateway that has been marked as 
+                    the default charging gateway for the PDP context. 
+                    The address is expressed as a four-byte integer. 
+                    Present in the initial CCR only.
+                  */
+                  struct dict_avp_data data = { 
+                    4,                                    /* Code */
+                    10415,                                      /* Vendor */
+                    "3GPP-CG-Address",                      /* Name */
+                    AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,   /* Fixed flags */
+                    AVP_FLAG_VENDOR,                     /* Fixed flag values */
+                    AVP_TYPE_OCTETSTRING                     /* base type of data */
+                  };
+                  CHECK_dict_new( DICT_AVP, &data , Address_type, NULL);
+                }
+
+                /* 3GPP-GPRS-Negotiated-QoS-Profile */
+                {
+                  /* 
+                     UTF8String. (3GPP TS 29.061 Rel7 ). The QoS 
+                     profile applied by the Flexi ISN. In update and ter-
+                     mination requests, this AVP is present only when 
+                     the CCR has been triggered by a PDP context 
+                     update affecting the negotiated QoS
+		     Each octet is described by two UTF-8-encoded
+                     characters denoting the hexadecimal
+                     representation.
+                  */
+                  struct dict_avp_data data = { 
+                    5,                                    /* Code */
+                    10415,                                      /* Vendor */
+                    "3GPP-GPRS-Negotiated-QoS-Profile",                    /* Name */
+                    AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,   /* Fixed flags */
+                    AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,                     /* Fixed flag values */
+                    AVP_TYPE_OCTETSTRING                      /* base type of data */
+                  };
+                  CHECK_dict_new( DICT_AVP, &data , UTF8String_type, NULL);
+                }
+
+                /* 3GPP-SGSN-Address */
+                {
+                  /*
+                    OctetString. (3GPP TS 29.061 Rel4). The address 
+                    of the charging gateway that has been marked as 
+                    the default charging gateway for the PDP context. 
+                    The address is expressed as a four-byte integer. 
+                    Present in the initial CCR only.
+                  */
+                  struct dict_avp_data data = { 
+                    6,                                    /* Code */
+                    10415,                                      /* Vendor */
+                    "3GPP-SGSN-Address",                      /* Name */
+                    AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,   /* Fixed flags */
+                    AVP_FLAG_VENDOR,                     /* Fixed flag values */
+                    AVP_TYPE_OCTETSTRING                     /* base type of data */
+                  };
+                  CHECK_dict_new( DICT_AVP, &data , Address_type, NULL);
+                }               
+
+                /* 3GPP-GGSN-Address */
+                {
+                  /*
+                    OctetString. (3GPP TS 29.061 Rel4). Usually the 
+                    IP address of Flexi ISN. The only exception is 
+                    when the Flexi ISN acts as a NAS server and the 
+                    charging ID selection is set to NAS Client; then the 
+                    GGSN IP address will be the NAIP address. Present in the initial CCR only.S client
+                  */
+                  struct dict_avp_data data = { 
+                    7,                                    /* Code */
+                    10415,                                      /* Vendor */
+                    "3GPP-GGSN-Address",                      /* Name */
+                    AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,   /* Fixed flags */
+                    AVP_FLAG_VENDOR,                     /* Fixed flag values */
+                    AVP_TYPE_OCTETSTRING                     /* base type of data */
+                  };
+                  CHECK_dict_new( DICT_AVP, &data , Address_type, NULL);
+                }
+
+                /* 3GPP-IMSI-MCC-MNC */
+                {
+                  /*
+                    UTF8String. MCC and MNC extracted from the 
+                    user's IMSI (first 5 or 6 digits, as applicable from 
+                    the presented IMSI). The MCC-MNCs are 
+                    extracted from the tables configured in FlexiISN 
+                    configuration under the General and Roaming 
+                    configurations.
+                  */
+                  struct dict_avp_data data = { 
+                    8,                                    /* Code */
+                    10415,                                      /* Vendor */
+                    "3GPP-IMSI-MCC-MNC",                    /* Name */
+                    AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,   /* Fixed flags */
+                    AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,                     /* Fixed flag values */
+                    AVP_TYPE_OCTETSTRING                      /* base type of data */
+                  };
+                  CHECK_dict_new( DICT_AVP, &data , UTF8String_type, NULL);
+                }
+
+                /* 3GPP-GGSN-MCC-MNC */
+                {
+                  /* 
+                     UTF8String. (3GPP TS 29.061 Rel7 ). Contains 
+                     the mobile country and network code of the PLMN 
+                     that the Flexi ISN belongs to. Present in the initial 
+                     CCR only. The first entry in the list of local PLMNs 
+                     in the Flexi ISN configuration determines the value 
+                     of this AVP.
+                  */
+                  struct dict_avp_data data = { 
+                    9,                                    /* Code */
+                    10415,                                      /* Vendor */
+                    "3GPP-GGSN-MCC-MNC",                    /* Name */
+                    AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,   /* Fixed flags */
+                    AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,                     /* Fixed flag values */
+                    AVP_TYPE_OCTETSTRING                      /* base type of data */
+                  };
+                  CHECK_dict_new( DICT_AVP, &data , UTF8String_type, NULL);
+                }
+
+                /* 3GPP-NSAPI */
+                {
+                  /* 
+                     UTF8String. (3GPP TS 29.061 Rel7 ). Indicates 
+                     the NSAPI of the PDP context. Contains one octet 
+                     consisting of a single digit. Present in the initial 
+                     CCR only.
+                  */
+                  struct dict_avp_data data = { 
+                    10,                                    /* Code */
+                    10415,                                      /* Vendor */
+                    "3GPP-NSAPI",                    /* Name */
+                    AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,   /* Fixed flags */
+                    AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,                     /* Fixed flag values */
+                    AVP_TYPE_OCTETSTRING                      /* base type of data */
+                  };
+                  CHECK_dict_new( DICT_AVP, &data , UTF8String_type, NULL);
+                }
+
+                /* 3GPP-Session-Stop-Indicator */
+                {
+                  /*
+                    OctetString. (3GPP TS 29.061 Rel4). The 
+                    presence of this AVP indicates that the last 
+                    context of the PDP session has been deleted. May 
+                    be present in the termination CCR only. Contains 
+                    one octet that has a value of 0xff.
+                  */
+                  struct dict_avp_data data = { 
+                    11,                                    /* Code */
+                    10415,                                      /* Vendor */
+                    "3GPP-Session-Stop-Indicator",                      /* Name */
+                    AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,   /* Fixed flags */
+                    AVP_FLAG_VENDOR,                     /* Fixed flag values */
+                    AVP_TYPE_OCTETSTRING                     /* base type of data */
+                  };
+                  CHECK_dict_new( DICT_AVP, &data , NULL, NULL);
+                }
+
+                /* 3GPP-Selection-Mode */
+                {
+                  /*
+                    UTF8String. (3GPP TS 29.061 Rel7 ). Consists of 
+                    one octet containing the selection mode as 
+                    received from SGSN in the Create PDP Context 
+                    Request. Present in the initial CCR only.
+                  */
+                  struct dict_avp_data data = { 
+                    12,                                    /* Code */
+                    10415,                                      /* Vendor */
+                    "3GPP-Selection-Mode",                    /* Name */
+                    AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,   /* Fixed flags */
+                    AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,                     /* Fixed flag values */
+                    AVP_TYPE_OCTETSTRING                      /* base type of data */
+                  };
+                  CHECK_dict_new( DICT_AVP, &data , UTF8String_type, NULL);
+                }
+
+                /* 3GPP-Charging-Characteristics */
+                {
+                  /*
+                    UTF8String. (3GPP TS 29.061 Rel7 ). The 
+                    charging characteristics for the PDP context. 
+                    Present in the initial CCR only. Consists of four 
+                    octets. Each octet contains a single UTF-8 
+                    encoded digit. The content of the charging charac-
+                    teristics is described in 3GPP TS 32.215.
+                  */
+                  struct dict_avp_data data = { 
+                    13,                                    /* Code */
+                    10415,                                      /* Vendor */
+                    "3GPP-Charging-Characteristics",                    /* Name */
+                    AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,   /* Fixed flags */
+                    AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,                     /* Fixed flag values */
+                    AVP_TYPE_OCTETSTRING                      /* base type of data */
+                  };
+                  CHECK_dict_new( DICT_AVP, &data , UTF8String_type, NULL);
+                }
+
+                /* 3GPP-CG-IPv6-Address */
+                {
+                  /*
+                    UTF8String.. (3GPP TS 29.061 Rel? (<=10) ). The 
+		    IPv6 address of the charging gateway.
+                  */
+                  struct dict_avp_data data = { 
+                    14,                                    /* Code */
+                    10415,                                      /* Vendor */
+                    "3GPP-CG-IPv6-Address",                    /* Name */
+                    AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,   /* Fixed flags */
+                    AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,                     /* Fixed flag values */
+                    AVP_TYPE_OCTETSTRING                      /* base type of data */
+                  };
+                  CHECK_dict_new( DICT_AVP, &data , UTF8String_type, NULL);
+                }
+
+                /* 3GPP-SGSN-IPv6-Address */
+                {
+                  /*
+                    UTF8String.. (3GPP TS 29.061 Rel? (<=10) ). The 
+		    IPv6 address of the SGSN.
+                  */
+                  struct dict_avp_data data = { 
+                    15,                                    /* Code */
+                    10415,                                      /* Vendor */
+                    "3GPP-SGSN-IPv6-Address",                    /* Name */
+                    AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,   /* Fixed flags */
+                    AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,                     /* Fixed flag values */
+                    AVP_TYPE_OCTETSTRING                      /* base type of data */
+                  };
+                  CHECK_dict_new( DICT_AVP, &data , UTF8String_type, NULL);
+                }
+
+                /* 3GPP-GGSN-IPv6-Address */
+                {
+                  /*
+                    UTF8String.. (3GPP TS 29.061 Rel? (<=10) ). The 
+		    IPv6 address of the GGSN.
+                  */
+                  struct dict_avp_data data = { 
+                    16,                                    /* Code */
+                    10415,                                      /* Vendor */
+                    "3GPP-GGSN-IPv6-Address",                    /* Name */
+                    AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,   /* Fixed flags */
+                    AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,                     /* Fixed flag values */
+                    AVP_TYPE_OCTETSTRING                      /* base type of data */
+                  };
+                  CHECK_dict_new( DICT_AVP, &data , UTF8String_type, NULL);
+                }
+
+                /* 3GPP-GGSN-IPv6-DNS-Servers */
+                {
+                  /*
+                    UTF8String.. (3GPP TS 29.061 Rel? (<=10) ). List
+		    of IPv6 addresses of DNS servers for an APN in
+		    order of preference (max. 15 servers, 16 bytes
+		    each).
+                  */
+                  struct dict_avp_data data = { 
+                    17,                                    /* Code */
+                    10415,                                      /* Vendor */
+                    "3GPP-GGSN-IPv6-DNS-Servers",                    /* Name */
+                    AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,   /* Fixed flags */
+                    AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,                     /* Fixed flag values */
+                    AVP_TYPE_OCTETSTRING                      /* base type of data */
+                  };
+                  CHECK_dict_new( DICT_AVP, &data , UTF8String_type, NULL);
+                }
+
+                /* 3GPP-SGSN-MCC-MNC */
+                {
+                  /* 
+                     UTF8String. (3GPP TS 29.061 Rel7 ). MCC and 
+                     MNC extracted from the RAI within Create or 
+                     Update PDP Context Request. In update and ter-
+                     mination requests, this AVP is present only when 
+                     the CCR has been triggered by a routing area 
+                     update.
+                  */
+                  struct dict_avp_data data = { 
+                    18,                                    /* Code */
+                    10415,                                      /* Vendor */
+                    "3GPP-SGSN-MCC-MNC",                    /* Name */
+                    AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,   /* Fixed flags */
+                    AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,                     /* Fixed flag values */
+                    AVP_TYPE_OCTETSTRING                      /* base type of data */
+                  };
+                  CHECK_dict_new( DICT_AVP, &data , UTF8String_type, NULL);
+                }
+
+                /* Missing: 3GPP-Teardown-Indicator (19) */
+
+                /* 3GPP-IMEISV */
+                {
+                  /*
+		    IMEI(SV) encoded as sequence of UTF8 characters.
+                  */
+                  struct dict_avp_data data = { 
+                    20,                                    /* Code */
+                    10415,                                      /* Vendor */
+                    "3GPP-IMEISV",                      /* Name */
+                    AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,   /* Fixed flags */
+                    AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,                     /* Fixed flag values */
+                    AVP_TYPE_OCTETSTRING                     /* base type of data */
+                  };
+                  CHECK_dict_new( DICT_AVP, &data , UTF8String_type, NULL);
+                }
+
+                /* 3GPP-RAT-Type */
+                {
+                  /* 
+                     OctetString. (3GPP TS 29.061 Rel7 ) Defines the 
+                     method used to access the network. Consists of a 
+                     single octet. The following values may be sent:
+                     UTRAN (1), GERAN (2), WLAN (3), NAS (254), 
+                     Unspecified (255). 
+                     This AVP is included in the initial CCR and in 
+                     update or termination CCRs if the value changes.
+                  */
+                  struct dict_avp_data data = { 
+                    21,                                    /* Code */
+                    10415,                                      /* Vendor */
+                    "3GPP-RAT-Type",                      /* Name */
+                    AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,   /* Fixed flags */
+                    AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,                     /* Fixed flag values */
+                    AVP_TYPE_OCTETSTRING                     /* base type of data */
+                  };
+                  CHECK_dict_new( DICT_AVP, &data , NULL, NULL);
+                }
+
+                /* 3GPP-User-Location-Info */
+                {
+                  /*
+                    OctetString. (3GPP TS 29.061 Rel7 ) Contains 
+                    information about the user's current geographical 
+                    location as received from the SGSN. Present 
+                    always in initial CCR if the value is known and in 
+                    update and termination CCRs if the value 
+                    changes.
+                  */
+                  struct dict_avp_data data = { 
+                    22,                                    /* Code */
+                    10415,                                      /* Vendor */
+                    "3GPP-User-Location-Info",                      /* Name */
+                    AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,   /* Fixed flags */
+                    AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,                     /* Fixed flag values */
+                    AVP_TYPE_OCTETSTRING                     /* base type of data */
+                  };
+                  CHECK_dict_new( DICT_AVP, &data , NULL, NULL);
+                }
+
+                /* 3GPP-MS-TimeZone */
+                {
+                  /*
+                    OctetString. (3GPP TS 29.061 Rel7 ) 3GPP-MS-
+                    TimeZone is AVP is present always in the initial CCR if the 
+                    value is known and in the update and termination 
+                    CCRs if the value changes. This IE is encoded 
+                    according to 3GPP TS 29.061 Rel7
+                  */
+                  struct dict_avp_data data = { 
+                    23,                                    /* Code */
+                    10415,                                      /* Vendor */
+                    "3GPP-MS-TimeZone",                      /* Name */
+                    AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,   /* Fixed flags */
+                    AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,                     /* Fixed flag values */
+                    AVP_TYPE_OCTETSTRING                     /* base type of data */
+                  };
+                  CHECK_dict_new( DICT_AVP, &data , NULL, NULL);
+                }
+
+		/* Missing: 3GPP-CAMEL-Charging-Info (24) */
+		/* Missing: 3GPP-Packet-Filter (25) */
+		/* Missing: 3GPP-Negotiated-DSCP (26) */
+		/* Missing: 3GPP-Allocate-IP-Type (27) */
+
+                /* PDP-Context-Type */
+                {
+                  /* 
+                     Enumerated. Indicates the type of a PDP context 
+                     and is only included in CCR initial.
+
+                     values are 0 for primary and 1 for secondary 
+                     (3GPP 32.299 Rel7)
+                  */
+                  struct dict_object              *type;
+                  struct dict_type_data           tdata = { AVP_TYPE_INTEGER32,   "Enumerated(PDP-Context-Type)" , NULL, NULL, NULL };
+                  struct dict_enumval_data        t_0 = { "PRIMARY",                      { .i32 = 0 }};
+                  struct dict_enumval_data        t_1 = { "SECONDARY",        { .i32 = 1 }};
+
+                  struct dict_avp_data    data = { 
+                    1247,                                    /* Code */
+                    10415,                                      /* Vendor */
+                    "PDP-Context-Type",                    /* Name */
+                    AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,   /* Fixed flags */
+                    AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,                     /* Fixed flag values */
+                    AVP_TYPE_INTEGER32                      /* base type of data */
+                  };
+                  /* Create the Enumerated type, and then the AVP */
+                  CHECK_dict_new( DICT_TYPE, &tdata , NULL, &type);
+                  CHECK_dict_new( DICT_ENUMVAL, &t_0 , type, NULL);
+                  CHECK_dict_new( DICT_ENUMVAL, &t_1 , type, NULL);
+                  CHECK_dict_new( DICT_AVP, &data , type, NULL);
+                }
+
+                /* IMS-Information */
+                {
+                  /*
+                    Grouped. Its purpose is to allow the transmission 
+                    of additional IMS service specific information ele-
+                    ments. (3GPP 32.299 Rel7)
+                  */
+                  struct dict_avp_data data = {
+                    876,                                    /* Code */
+                    10415,                                      /* Vendor */
+                    "IMS-Information",                  /* Name */
+                    AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,   /* Fixed flags */
+                    AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,                     /* Fixed flag values */
+                    AVP_TYPE_GROUPED                        /* base type of data */
+                  };
+                  CHECK_dict_new( DICT_AVP, &data , NULL, NULL);
+                }
+
+                /* IMS-Charging-Identifier */
+                {
+                  /*
+                    UTF8String. Contains the IMS charging identifier 
+                    as given to the Flexi ISN by the IMS. This AVP is 
+                    defined in 3GPP TS 32.225. This AVP is present 
+                    in IMS sessions only. Present in the initial CCR 
+                    only.
+                  */
+                  struct dict_avp_data data = { 
+                    841,                                    /* Code */
+                    10415,                                      /* Vendor */
+                    "IMS-Charging-Identifier",                    /* Name */
+                    AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,   /* Fixed flags */
+                    AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,                     /* Fixed flag values */
+                    AVP_TYPE_OCTETSTRING                      /* base type of data */
+                  };
+                  CHECK_dict_new( DICT_AVP, &data , UTF8String_type, NULL);
+                }
+                
+
+                
+
+                /* Max-Requested-Bandwidth-UL */
+                {
+                  /*
+                    Unsigned32. The Max-Requested-Bandwidth-
+                    UL/DL AVP indicates the maximum allowed bit 
+                    rate (in bits per second) for the uplink direction. 
+                    (Re-used from 3GPP 29.214)
+                  */
+                  struct dict_avp_data data = { 
+                    515,                                    /* Code */
+                    10415,                                      /* Vendor */
+                    "Max-Requested-Bandwidth-UL",                      /* Name */
+                    AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,   /* Fixed flags */
+                    AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,                     /* Fixed flag values */
+                    AVP_TYPE_UNSIGNED32                     /* base type of data */
+                  };
+                  CHECK_dict_new( DICT_AVP, &data , NULL, NULL);
+                }
+
+                /* Max-Requested-Bandwidth-DL */
+                {
+                  /*
+                    Unsigned32. The Max-Requested-Bandwidth-
+                    UL/DL AVP indicates the maximum allowed bit 
+                    rate (in bits per second) for the uplink direction.
+                  */
+                  struct dict_avp_data data = { 
+                    516,                                    /* Code */
+                    10415,                                      /* Vendor */
+                    "Max-Requested-Bandwidth-DL",                      /* Name */
+                    AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,   /* Fixed flags */
+                    AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,                     /* Fixed flag values */
+                    AVP_TYPE_UNSIGNED32                     /* base type of data */
+                  };
+                  CHECK_dict_new( DICT_AVP, &data , NULL, NULL);
+                }
+
+                /* QoS-Information */
+                {
+                  /*
+                    Grouped. This is the QoS that the DCCA 
+                    server requests from Flexi ISN to be applied for 
+                    this PDP context. This AVP and all AVPs con-
+                    tained within are described in 3GPP TS 29.212 
+                    Release 7. The ARP AVP is introduced with 
+                    Release 8. The relevant types are defined on 
+                    table 5.3.1 of TS 29.212.
+                  */
+
+                  struct dict_avp_data data = {
+                    1016,                                    /* Code */
+                    10415,                                      /* Vendor */
+                    "QoS-Information",                  /* Name */
+                    AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,   /* Fixed flags */
+                    AVP_FLAG_VENDOR,                     /* Fixed flag values */
+                    AVP_TYPE_GROUPED                        /* base type of data */
+                  };
+                  CHECK_dict_new( DICT_AVP, &data , NULL, NULL);
+                }                
+        }
+
+
+	
+	TRACE_DEBUG(INFO, "Extension 'Dictionary definitions for DCCA 3GPP' initialized");
+	return 0;
+}
+
+EXTENSION_ENTRY("dict_dcca_3gpp", dict_dcca_3gpp_entry, "dict_dcca");
diff --git a/contrib/dict_dcca/dict_dcca_nokia.c b/contrib/dict_dcca/dict_dcca_nokia.c
new file mode 100644
index 0000000..5ff7420
--- /dev/null
+++ b/contrib/dict_dcca/dict_dcca_nokia.c
@@ -0,0 +1,281 @@
+/* 
+ * Dictionary definitions of objects specified in DCCA (Nokia, 3GPP).
+ */
+#include <freeDiameter/extension.h>
+
+
+/* The content of this file follows the same structure as dict_base_proto.c */
+
+#define CHECK_dict_new( _type, _data, _parent, _ref )	\
+	CHECK_FCT(  fd_dict_new( fd_g_config->cnf_dict, (_type), (_data), (_parent), (_ref))  );
+
+#define CHECK_dict_search( _type, _criteria, _what, _result )	\
+	CHECK_FCT(  fd_dict_search( fd_g_config->cnf_dict, (_type), (_criteria), (_what), (_result), ENOENT) );
+
+struct local_rules_definition {
+	char 			*avp_name;
+	enum rule_position	position;
+	int 			min;
+	int			max;
+};
+
+#define RULE_ORDER( _position ) ((((_position) == RULE_FIXED_HEAD) || ((_position) == RULE_FIXED_TAIL)) ? 1 : 0 )
+
+#define PARSE_loc_rules( _rulearray, _parent) {								\
+	int __ar;											\
+	for (__ar=0; __ar < sizeof(_rulearray) / sizeof((_rulearray)[0]); __ar++) {			\
+		struct dict_rule_data __data = { NULL, 							\
+			(_rulearray)[__ar].position,							\
+			0, 										\
+			(_rulearray)[__ar].min,								\
+			(_rulearray)[__ar].max};							\
+		__data.rule_order = RULE_ORDER(__data.rule_position);					\
+		CHECK_FCT(  fd_dict_search( 								\
+			fd_g_config->cnf_dict,								\
+			DICT_AVP, 									\
+			AVP_BY_NAME, 									\
+			(_rulearray)[__ar].avp_name, 							\
+			&__data.rule_avp, 0 ) );							\
+		if ( !__data.rule_avp ) {								\
+			TRACE_DEBUG(INFO, "AVP Not found: '%s'", (_rulearray)[__ar].avp_name );		\
+			return ENOENT;									\
+		}											\
+		CHECK_FCT_DO( fd_dict_new( fd_g_config->cnf_dict, DICT_RULE, &__data, _parent, NULL),	\
+			{							        		\
+				TRACE_DEBUG(INFO, "Error on rule with AVP '%s'",      			\
+					 (_rulearray)[__ar].avp_name );		      			\
+				return EINVAL;					      			\
+			} );							      			\
+	}									      			\
+}
+
+#define enumval_def_u32( _val_, _str_ ) \
+		{ _str_, 		{ .u32 = _val_ }}
+
+#define enumval_def_os( _len_, _val_, _str_ ) \
+		{ _str_, 		{ .os = { .data = (unsigned char *)_val_, .len = _len_ }}}
+
+
+static int dict_dcca_nokia_entry(char * conffile)
+{
+	TRACE_ENTRY("%p", conffile);		
+	
+	/* Applications section */               
+	{		
+                /* Create the vendors */                                
+                {
+                        struct dict_vendor_data vendor_data = { 94, "Nokia" };
+                        CHECK_FCT(fd_dict_new(fd_g_config->cnf_dict, DICT_VENDOR, &vendor_data, NULL, NULL));
+                }
+  
+	}
+	
+	
+	/* AVP section */
+        {
+                struct dict_object * Address_type;
+                struct dict_object * UTF8String_type;
+                struct dict_object * DiameterIdentity_type;
+                struct dict_object * DiameterURI_type;
+                struct dict_object * Time_type;
+
+                CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "Address", &Address_type);
+                CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "UTF8String", &UTF8String_type);
+                CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "DiameterIdentity", &DiameterIdentity_type);
+                CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "DiameterURI", &DiameterURI_type);
+                CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "Time", &Time_type);                                
+
+                /* NSN-Token-Value */
+                {
+                  /* 
+                     OctetString. A token that was received, for 
+                     example, from the subscription portal [14]. The 
+                     maximum length of the token is 64 octets.
+                     When this AVP is included in the MSCC, the USU 
+                     and Reporting-Reason AVPs will not be included 
+                     (because the token is not a trigger to report quota 
+                     usage). Additionally, the Rating-Group and 
+                     Service-Id AVPs will have the values received 
+                     from the subscription portal.
+                   */
+                  struct dict_avp_data data = { 
+                    5113,                                    /* Code */
+                    94,                                      /* Vendor */
+                    "NSN-Token-Value",                      /* Name */
+                    AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,   /* Fixed flags */
+                    AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,                     /* Fixed flag values */
+                    AVP_TYPE_OCTETSTRING                     /* base type of data */
+                  };
+                  CHECK_dict_new( DICT_AVP, &data , NULL, NULL);
+                }
+                
+                /* Quota-Consumption-Time */
+                {
+                  /*
+                    Unsigned32. Contains the time quota envelope 
+                    expiration time in seconds. This is the time 
+                    elapsed from the previous service request, to 
+                    the moment the Flexi ISN considers that the 
+                    time envelope finishes. The value of this AVP 
+                    will be in effect for the remainder of the session 
+                    or until a new value is received. If this AVP is 
+                    not present, the default value configured for the 
+                    rating group will be used. The OCS may 
+                    disable the time quota envelope expiration by 
+                    setting the value of this AVP to 0. The value of 
+                    QCT sent from the OCS for a certain MSCC 
+                    instance is stored in the Flexi ISN and it is used 
+                    if the OCS does not sent a new value in the 
+                    CCAs that follow
+                  */
+                  struct dict_avp_data data = { 
+                    5109,                                    /* Code */
+                    94,                                      /* Vendor */
+                    "Quota-Consumption-Time",                      /* Name */
+                    AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,   /* Fixed flags */
+                    AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,                     /* Fixed flag values */
+                    AVP_TYPE_UNSIGNED32                     /* base type of data */
+                  };
+                  CHECK_dict_new( DICT_AVP, &data , NULL, NULL);
+                }
+
+                /* Quota-Holding-Time */
+                {
+                  /* 
+                     Unsigned32. Indicates how long the Flexi ISN 
+                     will keep the granted quota after a service 
+                     request has been received. The unit is in 
+                     seconds. When this time elapses, the Flexi ISN 
+                     ends the MSCC instance and reports the used 
+                     quota without requesting more. The value of 
+                     this AVP will be in effect for the remainder of 
+                     the session or until a new value is received. If 
+                     this AVP is not present, the default value con-
+                     figured for the rating group will be used. The 
+                     OCS may disable the Quota Holding Timer by 
+                     setting the value of this AVP to 0. The value of 
+                     the QHT sent from the OCS for a certain 
+                     MSCC instance is stored in the Flexi ISN, and 
+                     it is used if the OCS does not sent a new value 
+                     in the CCAs that follow.
+                  */
+                  struct dict_avp_data data = { 
+                    5110,                                    /* Code */
+                    94,                                      /* Vendor */
+                    "Quota-Holding-Time",                      /* Name */
+                    AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,   /* Fixed flags */
+                    AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,                     /* Fixed flag values */
+                    AVP_TYPE_UNSIGNED32                     /* base type of data */
+                  };
+                  CHECK_dict_new( DICT_AVP, &data , NULL, NULL);
+                }
+
+                /* Default-Quota */
+                {
+                  /*
+                    Grouped. Indicates the absolute number of 
+                    units that are available for consumption during 
+                    each upcoming OCS interrogation (e.g. after a 
+                    CCR has been sent but before the CCA is 
+                    received). If this AVP is not present, the Flexi 
+                    ISN will use the configured or earlier received 
+                    default quota. If this AVP is present but does 
+                    not include the default quota for a certain unit 
+                    type, that unit type is considered to have no 
+                    default quota. 
+                    The usage of default quota can be disabled in 
+                    certain situations by modifying the Flexi ISN 
+                    settings
+                  */
+                  struct dict_avp_data data = {
+                    5111,                                    /* Code */
+                    94,                                      /* Vendor */
+                    "Default-Quota",                  /* Name */
+                    AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,   /* Fixed flags */
+                    AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,                     /* Fixed flag values */
+                    AVP_TYPE_GROUPED                        /* base type of data */
+                  };
+                  CHECK_dict_new( DICT_AVP, &data , NULL, NULL);
+                }                
+
+                /* Session-Start-Indicator */
+                {
+                  /*
+                    OctetString. (3GPP TS 29.061 Rel4). The address 
+                    of the charging gateway that has been marked as 
+                    the default charging gateway for the PDP context. 
+                    The address is expressed as a four-byte integer. 
+                    Present in the initial CCR only.
+                  */
+                  struct dict_avp_data data = { 
+                    5105,                                    /* Code */
+                    94,                                      /* Vendor */
+                    "Session-Start-Indicator",                      /* Name */
+                    AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,   /* Fixed flags */
+                    AVP_FLAG_VENDOR,                     /* Fixed flag values */
+                    AVP_TYPE_OCTETSTRING                     /* base type of data */
+                  };
+                  CHECK_dict_new( DICT_AVP, &data , NULL, NULL);
+                }                
+
+                /* Rulebase-id */
+                {
+                  /*
+                  */
+                  struct dict_avp_data data = { 
+                    5106,                                    /* Code */
+                    94,                                      /* Vendor */
+                    "Rulebase-id",                    /* Name */
+                    AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,   /* Fixed flags */
+                    AVP_FLAG_VENDOR,                     /* Fixed flag values */
+                    AVP_TYPE_OCTETSTRING                      /* base type of data */
+                  };
+                  CHECK_dict_new( DICT_AVP, &data , UTF8String_type, NULL);
+                }                
+
+                /* Time-Of-First-Usage */
+                {
+                  /*
+                    Time. Contains a time-stamp identifying the date 
+                    and time of the first increment of the used units 
+                    counter since the previous report. If no used units 
+                    were gathered during the previous reporting inter-
+                    val, this AVP will not be present.
+                  */
+                  struct dict_avp_data data = { 
+                    5103,                                     /* Code */
+                    94,                                      /* Vendor */
+                    "Time-Of-First-Usage",                      /* Name */
+                    AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,   /* Fixed flags */
+                    AVP_FLAG_VENDOR,                     /* Fixed flag values */
+                    AVP_TYPE_OCTETSTRING                    /* base type of data */
+                  };
+                  CHECK_dict_new( DICT_AVP, &data , Time_type, NULL);
+                }
+
+                /* Time-Of-Last-Usage */
+                {
+                  /*
+                    Time. Contains a time-stamp identifying the date 
+                    and time of the first increment of the used units 
+                    counter since the previous report. If no used units 
+                    were gathered during the previous reporting inter-
+                    val, this AVP will not be present.
+                  */
+                  struct dict_avp_data data = { 
+                    5104,                                     /* Code */
+                    94,                                      /* Vendor */
+                    "Time-Of-Last-Usage",                      /* Name */
+                    AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,   /* Fixed flags */
+                    AVP_FLAG_VENDOR,                     /* Fixed flag values */
+                    AVP_TYPE_OCTETSTRING                    /* base type of data */
+                  };
+                  CHECK_dict_new( DICT_AVP, &data , Time_type, NULL);
+                }
+        }
+	
+	TRACE_DEBUG(INFO, "Extension 'Dictionary definitions for DCCA Nokia' initialized");
+	return 0;
+}
+
+EXTENSION_ENTRY("dict_dcca_nokia", dict_dcca_nokia_entry, "dict_dcca");
diff --git a/contrib/dict_gx/README b/contrib/dict_gx/README
new file mode 100644
index 0000000..ce5b548
--- /dev/null
+++ b/contrib/dict_gx/README
@@ -0,0 +1,3 @@
+File sent to the mailing-list by German Barros <gbarros@ipcomsa.com>.
+To be used with the dict_legacy_xml extension.
+
diff --git a/contrib/dict_gx/dict_gx.xml b/contrib/dict_gx/dict_gx.xml
new file mode 100644
index 0000000..c985fe5
--- /dev/null
+++ b/contrib/dict_gx/dict_gx.xml
@@ -0,0 +1,709 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE dictionary SYSTEM "dictionary.dtd">
+
+<!--******************* Diccionario Gx === German Barros ******************************************************************* -->
+
+<dictionary>
+
+
+
+	<!-- ******************************************************** -->
+	<!-- ********************* Vendors ************************** -->
+	<!-- ******************************************************** -->
+
+	<vendor id="10415" name="3GPP" />
+
+	<!-- ******************************************************** -->
+	<!-- ***************** Gx Application ********************* -->
+	<!-- ******************************************************** -->
+
+	<application id="16777238" name="Gx">
+
+
+		<!-- ====================================================================== -->
+		<!-- ========================== COMMAND CODES =========================== -->
+		<!-- ====================================================================== -->
+
+		<!-- *** Command-Codes *** -->
+
+		<!-- [3GPP TS 29.212 V7.7.0] , clause 5.6.2 and 5.6.3 -->
+		<command name="CC" code="272" vendor-id="10415">
+
+		</command>
+
+		<!-- [3GPP TS 29.212 V7.7.0] , clause 5.6.4 and 5.6.5 -->
+		<command name="RA" code="258" vendor-id="10415" />
+
+
+		<!-- ====================================================================== -->
+		<!-- ========================= Gx Specific AVPs ======================== -->
+		<!-- ====================================================================== -->
+
+
+		<!-- Ref = [3GPP - 29.214] 5.3.2 -->
+		<avp name="Access-Network-Charging-Address" code="501" mandatory="must"
+			may-encrypt="yes" vendor-id="10415">
+			<type type-name="Address" />
+		</avp>
+
+
+		<!-- [3GPP TS 29.212 V7.7.0] , clause 5.3.1 -->
+		<avp name="Bearer-Usage" vendor-id="10415" code="1000" mandatory="must"
+			may-encrypt="yes">
+			<type type-name="Enumerated" />
+			<enum name="GENERAL" code="0" />
+			<enum name="IMS_SIGNALLING" code="1" />
+		</avp>
+
+			<!-- [3GPP TS 29.212 V7.7.0] , clause 5.3.23 -->
+		<avp name="Bearer-Control-Mode" vendor-id="10415" code="1023"
+			mandatory="must" may-encrypt="yes">
+
+			<type type-name="Enumerated" />
+			<enum name="UE_ONLY" code="0" />
+			<enum name="RESERVED" code="1" />
+			<enum name="UE_NW" code="2" />
+
+		</avp>
+		
+			<!-- [3GPP TS 29.212 V7.7.0] , clause 5.3.8 -->
+		<avp name="Metering-Method" vendor-id="10415" code="1007"
+			mandatory="must" may-encrypt="yes" protected="may" type="Enumerated">
+			<type type-name="Enumerated" />
+			<enum name="DURATION" code="0" />
+			<enum name="VOLUME" code="1" />
+			<enum name="DURATION_VOLUME" code="2" />
+		</avp>
+		<!-- [3GPP TS 29.229 V7.7.0] , clause 6.3.20 -->
+		<avp name="Primary-Event-Charging-Function-Name" vendor-id="10415"
+			code="619" mandatory="must" may-encrypt="yes">
+			<type type-name="DiameterURI" />
+		</avp>
+
+		<!-- [3GPP TS 29.229 V7.7.0] , clause 6.3.21 -->
+		<avp name="Secondary-Event-Charging-Function-Name" vendor-id="10415"
+			code="620" mandatory="must" may-encrypt="yes">
+			<type type-name="DiameterURI" />
+		</avp>
+
+		<!-- [3GPP TS 29.229 V7.7.0] , clause 6.3.22 -->
+		<avp name="Primary-Charging-Collection-Function-Name" vendor-id="10415"
+			code="621" mandatory="must" may-encrypt="yes">
+			<type type-name="DiameterURI" />
+		</avp>
+
+		<!-- [3GPP TS 29.229 V7.7.0] , clause 6.3.23 -->
+		<avp name="Secondary-Charging-Collection-Function-Name" vendor-id="10415"
+			code="622" mandatory="must" may-encrypt="yes">
+			<type type-name="DiameterURI" />
+		</avp>
+
+		<!-- [3GPP TS 29.214 v7.3.0] , clause 5.3.4 -->
+		<avp name="Access-Network-Charging-Identifier-Value" vendor-id="10415"
+			code="503" mandatory="must" may-encrypt="yes">
+			<type type-name="OctetString" />
+		</avp>
+
+
+		<!-- [3GPP TS 29.061 V7.9.0] , clause 16.4.7 -->
+		<avp name="3GPP-RAT-Type" vendor-id="10415" code="21" mandatory="mustnot"
+			may-encrypt="yes">
+			<type type-name="OctetString" />
+		</avp>
+
+
+			<!-- Ref = RFC 4006 chap 8.48 -->
+		<avp name="Subscription-Id-Data" code="444" mandatory="must"
+			may-encrypt="yes">
+			<type type-name="UTF8String" />
+		</avp>
+		<!-- Ref = RFC 4006 chap 8.47 -->
+		<avp name="Subscription-Id-Type" code="450" mandatory="must"
+			protected="may" may-encrypt="yes">
+			<type type-name="Enumerated" />
+			<enum name="END_USER_E164" code="0" />
+			<enum name="END_USER_IMSI" code="1" />
+			<enum name="END_USER_SIP_URI" code="2" />
+			<enum name="END_USER_NAI" code="3" />
+			<enum name="END_USER_PRIVATE" code="4" />
+		</avp>
+
+		<!-- [RFC 4006] , clause 8.2 -->
+		<avp name="CC-Request-Number" code="415" mandatory="must"
+			may-encrypt="yes">
+			<type type-name="Unsigned32" />
+		</avp>
+
+		<!-- [RFC 4006] , clause 8.3 -->
+		<avp name="CC-Request-Type" code="416" mandatory="must"
+			may-encrypt="yes">
+			<type type-name="Enumerated" />
+			<enum name="INITIAL_REQUEST" code="1" />
+			<enum name="UPDATE_REQUEST" code="2" />
+			<enum name="TERMINATION_REQUEST" code="3" />
+			<enum name="EVENT_REQUEST" code="4" />
+		</avp>
+
+		<!-- [RFC 4006] , clause 8.38 -->
+		<avp name="Redirect-Address-Type" code="433" mandatory="must"
+			may-encrypt="yes">
+			<type type-name="Enumerated" />
+			<enum name="IPV4_ADDRESS" code="0" />
+			<enum name="IPV6_ADDRESS" code="1" />
+			<enum name="URL" code="2" />
+			<enum name="SIP_URI" code="3" />
+		</avp>
+<!-- [RFC 4006] , clause 8.39 -->
+		<avp name="Redirect-Server-Address" code="435" mandatory="must"
+			may-encrypt="yes">
+			<type type-name="UTF8String" />
+		</avp>
+		
+			<!-- [3GPP TS 29.212 V7.7.0] , clause 5.3.19 -->
+		<avp name="PCC-Rule-Status" vendor-id="10415" code="1019"
+			mandatory="must" may-encrypt="yes">
+			<type type-name="Enumerated" />
+			<enum name="ACTIVE" code="0" />
+			<enum name="INACTIVE" code="1" />
+			<enum name="TEMPORARILY INACTIVE" code="2" />
+		</avp>
+
+		<!-- [RFC 4005] , clause 6.11.1 -->
+		<avp name="Framed-IP-Address" code="8" mandatory="must"
+			may-encrypt="yes">
+			<type type-name="OctetString" />
+		</avp>
+
+		<!-- [RFC 4005] , clause 6.11.6 -->
+		<avp name="Framed-IPv6-Prefix" code="97" mandatory="must"
+			may-encrypt="yes">
+			<type type-name="OctetString" />
+		</avp>
+
+		<!-- [RFC 4005] , clause 4.5 -->
+		<avp name="Called-Station-Id" code="30" mandatory="must"
+			may-encrypt="yes">
+			<type type-name="UTF8String" />
+		</avp>
+
+		<!-- [RFC 4005] , clause 6.7 -->
+		<avp name="Filter-Id" code="11" mandatory="must" may-encrypt="yes">
+			<type type-name="UTF8String" />
+		</avp>
+
+		<!-- [3GPP TS 29.212 V7.7.0] , clause 5.3.21 -->
+		<avp name="Bearer-Operation" vendor-id="10415" code="1021"
+			mandatory="must" may-encrypt="yes">
+			<type type-name="Enumerated" />
+			<enum name="TERMINATION" code="0" />
+			<enum name="ESTABLISHMENT" code="1" />
+			<enum name="MODIFICATION" code="2" />
+		</avp>
+		
+		<!-- [3GPP TS 29.212 V7.7.0] , clause 5.3.24 -->
+		<avp name="Network-Request-Support" vendor-id="10415" code="1024"
+			mandatory="must" may-encrypt="yes">
+			<type type-name="Enumerated"/>
+      
+				<enum name="NETWORK_REQUEST_NOT_SUPPORTED" code="0" />
+				<enum name="NETWORK_REQUEST_SUPPORTED" code="1" />
+		</avp>
+
+				<!-- [3GPP TS 29.212 V7.7.0] , clause 5.3.5 -->
+		<avp name="Charging-Rule-Base-Name" vendor-id="10415" code="1004"
+			mandatory="must" may-encrypt="yes">
+			<type type-name="UTF8String" />
+		</avp>
+		<!-- [3GPP TS 29.212 V7.7.0] , clause 5.3.15 -->
+		<avp name="ToS-Traffic-Class" vendor-id="10415" code="1014"
+			mandatory="must" may-encrypt="yes">
+			<type type-name="OctetString" />
+		</avp>
+
+		<!-- [3GPP TS 29.212 V7.7.0] , clause 5.3.27 -->
+		<avp name="IP-CAN-Type" vendor-id="10415" code="1027" mandatory="must"
+			may-encrypt="yes">
+			<type type-name="Enumerated" />
+			<enum name="3GPP" code="0" />
+			<enum name="DOCSIS" code="1" />
+			<enum name="xDSL" code="2" />
+			<enum name="WiMAX" code="3" />
+			<enum name="3GPP2" code="4" />
+		</avp>
+
+		<!-- [3GPP TS 29.212 V7.7.0] , clause 5.3.28 -->
+		<avp name="QoS-Negotiation" vendor-id="10415" code="1029"
+			mandatory="must" may-encrypt="yes">
+			<type type-name="Enumerated" />
+			<enum name="NO_QOS_NEGOTIATION" code="0" />
+			<enum name="QOS_NEGOTIATION_SUPPORTED" code="1" />
+		</avp>
+
+		<!-- [3GPP TS 29.212 V7.7.0] , clause 5.3.29 -->
+		<avp name="QoS-Upgrade" vendor-id="10415" code="1030" mandatory="must"
+			may-encrypt="yes">
+			<type type-name="Enumerated" />
+			<enum name="QOS_UPGRADE_NOT_SUPPORTED" code="0" />
+			<enum name="QOS_UPGRADE_SUPPORTED" code="1" />
+		</avp>
+
+		<!-- [3GPP TS 29.212 V7.7.0] , clause 5.3.30 -->
+		<avp name="Rule-Failure-Code" vendor-id="10415" code="1031"
+			mandatory="must" may-encrypt="yes">
+			<type type-name="Enumerated" />
+			<enum name="UNKNOWN_RULE_NAME" code="1" />
+			<enum name="RATING_GROUP_ERROR" code="2" />
+			<enum name="SERVICE_IDENTIFIER_ERROR" code="3" />
+			<enum name="GW/PCEF_MALFUNCTION" code="4" />
+			<enum name="RESOURCES_LIMITATION" code="5" />
+			<enum name="MAX_NR_BEARERS_REACHED" code="6" />
+			<enum name="UNKNOWN_BEARER_ID" code="7" />
+			<enum name="MISSING_BEARER_ID" code="8" />
+			<enum name="MISSING_FLOW_DESCRIPTION" code="9" />
+		</avp>
+
+		<!-- [3GPP TS 29.212 V7.7.0] , clause 5.3.34 -->
+		<avp name="Session-Release-Cause" vendor-id="10415" code="1035"
+			mandatory="must" may-encrypt="yes">
+			<type type-name="Enumerated" />
+			<enum name="UNSPECIFIED_REASONS" code="0" />
+			<enum name="UE_SUBSCRIPTION_REASON" code="1" />
+			<enum name="INSUFFICIENT_SERVER_RESOURCES" code="2" />
+		</avp>
+
+
+
+		<!-- [3GPP TS 29.061 V7.9.0] , clause 16.4.7. -->
+		<avp name="3GPP-SGSN-MCC-MNC" vendor-id="10415" code="18"
+			mandatory="mustnot" may-encrypt="yes">
+			<type type-name="UTF8String" />
+		</avp>
+
+		<!-- [3GPP TS 29.061 V7.9.0] , clause 16.4.7 -->
+		<avp name="3GPP-User-Location-Info" vendor-id="10415" code="22"
+			mandatory="mustnot" may-encrypt="yes">
+			<type type-name="OctetString" />
+		</avp>
+
+
+		<!-- [3GPP TS 29.212 V7.7.0] , clause 5.3.31 -->
+		<avp name="Revalidation-Time" vendor-id="10415" code="1032"
+			mandatory="must" may-encrypt="yes">
+			<type type-name="Time" />
+		</avp>
+
+		<!-- [3GPP TS 29.212 V7.7.0] , clause 5.3.32 -->
+		<avp name="Rule-Activation-Time" code="1033" mandatory="must"
+			may-encrypt="yes">
+			<type type-name="Time" />
+		</avp>
+
+
+		<!-- [3GPP TS 29.212 V7.7.0] , clause 5.3.33 -->
+		<avp name="Rule-Deactivation-Time" vendor-id="10415" code="1034"
+			mandatory="must" may-encrypt="yes">
+			<type type-name="Time" />
+		</avp>
+
+		<!-- [3GPP TS 29.061 V7.7.0] , clause 16.4.7.1 -->
+		<avp name="3GPP-SGSN-Address" vendor-id="10415" code="6" mandatory="mustnot"
+			may-encrypt="yes">
+			<type type-name="OctetString" />
+		</avp>
+
+		<!-- [3GPP TS 29.061 V7.7.0] , clause 16.4.7.1 -->
+		<avp name="3GPP-SGSN-IPv6-Address" vendor-id="10415" code="15"
+			mandatory="mustnot" may-encrypt="yes">
+			<type type-name="OctetString" />
+		</avp>
+
+		<!-- [3GPP TS 29.061 V7.7.0] , clause 17.7.12 -->
+		<avp name="RAI" vendor-id="10415" code="909" mandatory="must"
+			may-encrypt="yes">
+			<type type-name="UTF8String" />
+		</avp>
+
+		<!-- [3GPP TS 29.061 V7.7.0] , clause 16.4.7 -->
+		<avp name="3GPP-MS-TimeZone" vendor-id="10415" code="23" mandatory="mustnot"
+			may-encrypt="yes">
+			<type type-name="OctetString" />
+		</avp>
+		
+		<!-- [3GPP TS 29.212 V7.7.0] , clause 5.3.20 -->
+		<avp name="Bearer-Identifier" vendor-id="10415" code="1020"
+			mandatory="must" may-encrypt="yes">
+			<type type-name="OctetString" />
+		</avp>
+
+		<!-- [3GPP TS 29.212 V7.7.0] , clause 5.3.6 -->
+		<avp name="Charging-Rule-Name" vendor-id="10415" code="1005"
+			mandatory="must" may-encrypt="yes">
+			<type type-name="OctetString" />
+		</avp>
+
+
+		<!-- [RFC 4006] , clause 8.28 -->
+		<avp name="Service-Identifier" code="439" mandatory="must"
+			may-encrypt="yes">
+			<type type-name="Unsigned32" />
+		</avp>
+		
+		<!-- [RFC 4006] , clause 8.29 -->
+		<avp name="Rating-Group" code="432" mandatory="must" may-encrypt="yes">
+			<type type-name="Unsigned32" />
+		</avp>
+		<!-- [3GPP TS 29.214 V7.3.0] , clause 5.3.11 -->
+		<avp name="Flow-Status" vendor-id="10415" code="511" mandatory="must"
+			may-encrypt="yes">
+			<type type-name="Enumerated" />
+			<enum name="ENABLED-UPLINK" code="0" />
+			<enum name="ENABLED-DOWNLINK" code="1" />
+			<enum name="ENABLED" code="2" />
+			<enum name="DISABLED" code="3" />
+			<enum name="REMOVED" code="4" />
+		</avp>
+				<!-- [3GPP TS 29.212 V7.7.0] , clause 5.3.17 -->
+		<avp name="QoS-Class-Identifier" vendor-id="10415" code="1028"
+			mandatory="must" may-encrypt="yes">
+			<type type-name="Enumerated" />
+			<enum name="FINAL_SERVICE_INFORMATION" code="0" />
+			<enum name="PRELIMINARY_SERVICE_INFORMATION" code="1" />
+		</avp>
+			<!-- Ref = [3GPP - 29.214] 5.3.15 -->
+		<avp name="Max-Requested-Bandwidth-UL" code="516" vendor-id="10415"
+			mandatory="must" may-encrypt="yes">
+			<type type-name="Unsigned32" />
+		</avp>
+		<!-- [3GPP TS 29.212 V7.7.0] , clause 5.3.25 -->
+		<avp name="Guaranteed-Bitrate-DL" vendor-id="10415" code="1025"
+			mandatory="must" may-encrypt="yes">
+			<type type-name="Unsigned32" />
+		</avp>
+
+		<!-- [3GPP TS 29.212 V7.7.0] , clause 5.3.26 -->
+		<avp name="Guaranteed-Bitrate-UL" vendor-id="10415" code="1026"
+			mandatory="must" may-encrypt="yes">
+			<type type-name="Unsigned32" />
+		</avp>
+		<!-- [3GPP TS 29.212 V7.7.0] , clause 5.3.20 -->
+		<avp name="Bearer-Identifier" vendor-id="10415" code="1020"
+			mandatory="must" may-encrypt="yes">
+			<type type-name="OctetString" />
+		</avp>
+		<avp name="Max-Requested-Bandwidth-UL" code="516" mandatory="must" vendor-id="10415" may-encrypt="yes">
+			<type type-name="Unsigned32"/>
+		</avp>
+		   <avp name="Max-Requested-Bandwidth-DL" code="515" mandatory="must" vendor-id="10415" may-encrypt="yes">
+			<type type-name="Unsigned32"/>
+		</avp>
+		<!-- [3GPP TS 29.212 V7.7.0] , clause 5.3.16 -->
+		<avp name="QoS-Information" vendor-id="10415" code="1016"
+			mandatory="must" may-encrypt="yes">
+			<grouped>
+				<required>
+					<avprule name="QoS-Class-Identifier" minimum="1" maximum="1" />
+					<avprule name="Max-Requested-Bandwidth-UL" minimum="1"
+						maximum="1" />
+					<avprule name="Max-Requested-Bandwidth-DL" minimum="1"
+						maximum="1" />
+					<avprule name="Guaranteed-Bitrate-UL" minimum="1" maximum="1" />
+					<avprule name="Guaranteed-Bitrate-DL" minimum="1" maximum="1" />
+					<avprule name="Bearer-Identifier" minimum="1" maximum="1" />
+				</required>
+			</grouped>
+		</avp>
+		<!-- [3GPP TS 29.214 V7.3.0] , clause 5.3.8 -->
+		<avp name="Flow-Description" vendor-id="10415" code="507"
+			mandatory="must" may-encrypt="yes">
+			<type type-name="IPFilterRule" />
+		</avp>
+		<!-- [3GPP TS 29.212 V7.7.0] , clause 5.3.12 -->
+		<avp name="Reporting-Level" vendor-id="10415" code="1011"
+			mandatory="must" may-encrypt="yes">
+			<type type-name="Enumerated" />
+			<enum name="SERVICE_IDENTIFIER_LEVEL" code="0" />
+			<enum name="RATING_GROUP_LEVEL" code="1" />
+		</avp>
+		<!-- [3GPP TS 29.212 V7.7.0] , clause 5.3.9 -->
+		<avp name="Offline" vendor-id="10415" code="1008" mandatory="must"
+			may-encrypt="yes">
+			<type type-name="Enumerated" />
+			<enum name="DISABLE_OFFLINE" code="0" />
+			<enum name="ENABLE_OFFLINE" code="1" />
+		</avp>
+
+		<!-- [3GPP TS 29.212 V7.7.0] , clause 5.3.10 -->
+		<avp name="Online" vendor-id="10415" code="1009" mandatory="must"
+			may-encrypt="yes">
+			<type type-name="Enumerated" />
+			<enum name="DISABLE_ONLINE" code="0" />
+			<enum name="ENABLE_ONLINE" code="1" />
+		</avp>
+
+		<!-- [3GPP TS 29.212 V7.7.0] , clause 5.3.11 -->
+		<avp name="Precedence" vendor-id="10415" code="1010" mandatory="must"
+			may-encrypt="yes">
+			<type type-name="Unsigned32" />
+		</avp>
+		
+		<!-- [3GPP TS 29.214 V7.3.0] , clause 5.3.6 -->
+		<avp name="AF-Charging-Identifier" vendor-id="10415" code="505"
+			mandatory="must" may-encrypt="yes">
+			<type type-name="OctetString" />
+		</avp>
+
+		<!-- Ref = [3GPP - 29.214] 5.3.14 -->
+		<avp name="Max-Requested-Bandwidth-DL" code="515" vendor-id="10415"
+			mandatory="must" may-encrypt="yes">
+			<type type-name="Unsigned32" />
+		</avp>
+		<!-- [3GPP TS 29.214 V7.3.0] , clause 5.3.17 -->
+		<avp name="Media-Component-Number" vendor-id="10415" code="518"
+			mandatory="must" may-encrypt="yes">
+			<type type-name="Unsigned32" />
+		</avp>
+
+		<!-- [3GPP TS 29.214 V7.3.0] , clause 5.3.9 -->
+		<avp name="Flow-Number" vendor-id="10415" code="509" mandatory="must"
+			may-encrypt="yes">
+			<type type-name="Unsigned32" />
+		</avp>
+<!-- [3GPP TS 29.214 V7.3.0] , clause 5.3.10 -->
+		<avp name="Flows" vendor-id="10415" code="510" mandatory="must"
+			may-encrypt="yes">
+			<grouped>
+				<required>
+					<avprule name="Media-Component-Number" minimum="1" maximum="1" />
+				</required>
+				<optional>
+					<avprule name="Flow-Number" maximum="1" />
+				</optional>
+			</grouped>
+		</avp>
+		<!-- [3GPP TS 29.212 V7.7.0] , clause 5.3.4 -->
+		<avp name="Charging-Rule-Definition" vendor-id="10415" code="1003"
+			mandatory="must" may-encrypt="yes">
+			<grouped>
+				<required>
+					<avprule name="Charging-Rule-Name" minimum="1" maximum="1" />
+					<avprule name="Service-Identifier" maximum="1" />
+					<avprule name="Rating-Group" maximum="1" />
+				</required>
+				<optional>
+					<avprule name="Flow-Description" maximum="1" />
+				</optional>
+				<required>
+					<avprule name="Flow-Status" maximum="1" />
+					<avprule name="QoS-Information" maximum="1" />
+					<avprule name="Reporting-Level" maximum="1" />
+					<avprule name="Online" maximum="1" />
+					<avprule name="Offline" maximum="1" />
+					<avprule name="Metering-Method" maximum="1" />
+					<avprule name="Precedence" maximum="1" />
+					<avprule name="AF-Charging-Identifier" maximum="1" />
+				</required>
+				<optional>
+					<avprule name="Flows" maximum="1" />
+				</optional>
+			</grouped>
+		</avp>
+		
+		<!-- [3GPP TS 29.212 V7.7.0] , clause 5.3.2 -->
+		<avp name="Charging-Rule-Install" vendor-id="10415" code="1001"
+			mandatory="must" may-encrypt="yes">
+			<grouped>
+				<optional>
+					<avprule name="Charging-Rule-Definition" maximum="1" />
+					<avprule name="Charging-Rule-Name" maximum="1" />
+					<avprule name="Charging-Rule-Base-Name" maximum="1" />
+				</optional>
+				<required>
+					<avprule name="Bearer-Identifier" minumin="1" maximum="1" />
+				</required>
+				<optional>
+					<avprule name="Rule-Activation-Time" maximum="1" />
+					<avprule name="Rule-Deactivation-Time" maximum="1" />
+				</optional>
+			</grouped>
+		</avp>
+
+		<!-- [3GPP TS 29.212 V7.7.0] , clause 5.3.3 -->
+		<avp name="Charging-Rule-Remove" vendor-id="10415" code="1002"
+			mandatory="must" may-encrypt="yes">
+			<grouped>
+				<optional>
+					<avprule name="Charging-Rule-Name" maximum="1" />
+					<avprule name="Charging-Rule-Base-Name" maximum="1" />
+				</optional>
+			</grouped>
+		</avp>
+
+		
+
+
+
+		
+
+		<!-- [3GPP TS 29.212 V7.7.0] , clause 5.3.7 -->
+		<avp name="Event-Trigger" vendor-id="10415" code="1006" mandatory="must"
+			may-encrypt="yes">
+			<type type-name="Enumerated" />
+			<enum name="SGSN_CHANGE" code="0" />
+			<enum name="QOS_CHANGE" code="1" />
+			<enum name="RAT_CHANGE" code="2" />
+			<enum name="TFT_CHANGE" code="3" />
+			<enum name="PLMN_CHANGE" code="4" />
+			<enum name="LOSS_OF_BEARER" code="5" />
+			<enum name="RECOVERY_OF_BEARER" code="6" />
+			<enum name="IP-CAN_CHANGE" code="7" />
+			<enum name="PCEF_MALFUNCTION" code="8" />
+			<enum name="RESOURCES_LIMITATION" code="9" />
+			<enum name="MAX_NR_BEARERS_REACHED" code="10" />
+			<enum name="QOS_CHANGE_EXCEEDING_AUTHORIZATION" code="11" />
+			<enum name="RAI_CHANGE" code="12" />
+			<enum name="USER_LOCATION_CHANGE" code="13" />
+			<enum name="NO_EVENT_TRIGGERS" code="14" />
+			<enum name="OUT_OF_CREDIT" code="15" />
+			<enum name="REALLOCATION_OF_CREDIT" code="16" />
+			<enum name="REVALIDATION_TIMEOUT" code="17" />
+		</avp>
+
+	
+
+		
+
+		
+
+		<!-- [3GPP TS 29.212 V7.7.0] , clause 5.3.13 -->
+		<avp name="TFT-Filter" vendor-id="10415" code="1012" mandatory="must"
+			may-encrypt="yes">
+			<type type-name="IPFilterRule" />
+		</avp>
+
+
+		<!-- [3GPP TS 29.212 V7.7.0] , clause 5.3.14 -->
+		<avp name="TFT-Packet-Filter-Information" vendor-id="10415" code="1013"
+			mandatory="must" may-encrypt="yes">
+			<grouped>
+				<required>
+					<avprule name="Precedence" minimum="1" maximum="1" />
+					<avprule name="TFT-Filter" minimum="1" maximum="1" />
+					<avprule name="ToS-Traffic-Class" minimum="1" maximum="1" />
+				</required>
+			</grouped>
+		</avp>
+		
+<!-- [RFC 4006] , clause 8.35 -->
+		<avp name="Final-Unit-Action" code="449" mandatory="must"
+			may-encrypt="yes">
+			<type type-name="Enumerated" />
+			<enum name="TERMINATE" code="0" />
+			<enum name="REDIRECT" code="1" />
+			<enum name="RESTRICT_ACCESS" code="2" />
+		</avp>
+		
+		<!-- [RFC 4006] , clause 8.36 -->
+		<avp name="Restriction-Filter-Rule" code="438" mandatory="must"
+			may-encrypt="yes">
+			<type type-name="IPFilterRule" />
+		</avp>
+		<!-- [RFC 4006] , clause 8.37 -->
+		<avp name="Redirect-Server" code="434" mandatory="must"
+			may-encrypt="yes">
+			<grouped>
+				<required>
+					<avprule name="Redirect-Address-Type" minimum="1" maximum="1" />
+					<avprule name="Redirect-Server-Address" minimum="1"
+						maximum="1" />
+				</required>
+			</grouped>
+		</avp>
+		<!-- [RFC 4006] , clause 8.34 -->
+		<avp name="Final-Unit-Indication" code="430" mandatory="must"
+			may-encrypt="yes">
+			<grouped>
+				<required>
+					<avprule name="Final-Unit-Action" minimum="1" maximum="1" />
+					<avprule name="Restriction-Filter-Rule" minimum="1"
+						maximum="1" />
+					<avprule name="Filter-Id" minimum="1" maximum="1" />
+					<avprule name="Redirect-Server" minimum="1" maximum="1" />
+				</required>
+			</grouped>
+		</avp>
+		
+		<!-- [3GPP TS 29.212 V7.7.0] , clause 5.3.18 -->
+		<avp name="Charging-Rule-Report" vendor-id="10415" code="1018"
+			mandatory="must" may-encrypt="yes">
+			<grouped>
+				<optional>
+					<avprule name="Charging-Rule-Name" maximum="1" />
+					<avprule name="Charging-Rule-Base-Name" maximum="1" />
+				</optional>
+				<required>
+					<avprule name="PCC-Rule-Status" minimum="1" maximum="1" />
+				</required>
+				<optional>
+					<avprule name="Rule-Failure-Code" maximum="1" />
+					<avprule name="Final-Unit-Indication" maximum="1" />
+				</optional>
+			</grouped>
+		</avp>
+
+	
+
+		<!-- [3GPP TS 29.212 V7.7.0] , clause 5.3.22 -->
+		<avp name="Access-Network-Charging-Identifier-Gx" vendor-id="10415"
+			code="1022" mandatory="must" may-encrypt="yes">
+			<grouped>
+				<required>
+					<avprule name="Access-Network-Charging-Identifier-Value"
+						minimum="1" maximum="1" />
+				</required>
+				<optional>
+					<avprule name="Charging-Rule-Base-Name" maximum="1" />
+					<avprule name="Charging-Rule-Name" maximum="1" />
+				</optional>
+			</grouped>
+		</avp>
+
+	
+
+		<!-- [3GPP TS 29.229 V7.7.0] , clause 6.3.19 -->
+		<avp name="Charging-Information" vendor-id="10415" code="618"
+			mandatory="must" may-encrypt="yes">
+			<grouped>
+				<required>
+					<avprule name="Primary-Event-Charging-Function-Name"
+						minimum="1" maximum="1" />
+					<avprule name="Secondary-Event-Charging-Function-Name"
+						minimum="1" maximum="1" />
+					<avprule name="Primary-Charging-Collection-Function-Name"
+						minimum="1" maximum="1" />
+					<avprule name="Secondary-Charging-Collection-Function-Name"
+						minimum="1" maximum="1" />
+				</required>
+			</grouped>
+		</avp>
+
+		
+		
+
+
+		<!-- Ref = RFC 4006 chap 8.46 -->
+		<avp name="Subscription-Id" code="443" mandatory="must"
+			may-encrypt="yes">
+			<grouped>
+				<required>
+					<avprule name="Subscription-Id-Type" />
+					<avprule name="Subscription-Id-Data" />
+				</required>
+			</grouped>
+		</avp>
+	
+		
+
+
+	</application>
+</dictionary>
+
diff --git a/contrib/dict_legacy/README b/contrib/dict_legacy/README
new file mode 100644
index 0000000..86b2418
--- /dev/null
+++ b/contrib/dict_legacy/README
@@ -0,0 +1,14 @@
+The dictionary.dtd file originates from draft-frascone-xml-dictionary-00.
+A few modifications may have been performed (see file history in Mercurial)
+However, no DTD validation is performed by the parser, but the extension
+expects a known format therefore the flexibility is limited.
+
+
+Additional XML dictionary files can be found:
+  - Circum project (circum.sf.net)
+  	under share/*.xml
+
+  - OpenDiameter project (diameter.sf.net)
+  	under libdiameter/config/dictionary.xml (will probably require some stripping)
+ 
+
diff --git a/contrib/dict_legacy/dictionary.dtd b/contrib/dict_legacy/dictionary.dtd
new file mode 100644
index 0000000..a2fced9
--- /dev/null
+++ b/contrib/dict_legacy/dictionary.dtd
@@ -0,0 +1,69 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!ELEMENT dictionary (vendor*, base*, application*)>
+
+<!ELEMENT vendor EMPTY>
+<!ATTLIST vendor
+        id CDATA #REQUIRED
+        name CDATA #REQUIRED
+>
+
+<!ELEMENT base (command*, typedefn*, avp*)>
+<!ATTLIST base
+        uri CDATA #IMPLIED
+>
+
+<!ELEMENT application (command*, typedefn*, avp*)>
+<!ATTLIST application
+        id CDATA #REQUIRED
+        name CDATA #IMPLIED
+        uri CDATA #IMPLIED
+>
+<!ELEMENT command (requestrules*, answerrules*)>
+<!ATTLIST command
+        name CDATA #REQUIRED
+        code CDATA #REQUIRED
+        vendor-id CDATA #IMPLIED
+        pbit (0 | 1) "1"
+>
+
+<!ELEMENT typedefn EMPTY>
+<!ATTLIST typedefn
+        type-name ID #REQUIRED
+        type-parent IDREF #IMPLIED
+        description CDATA #IMPLIED
+>
+<!ELEMENT avp ((type | grouped), (enum*))>
+<!ATTLIST avp
+        name ID #REQUIRED
+        description CDATA #IMPLIED
+        code CDATA #REQUIRED
+        mandatory CDATA #IMPLIED
+        vendor-id CDATA #IMPLIED
+>
+<!ELEMENT type EMPTY>
+<!ATTLIST type
+        type-name IDREF #REQUIRED
+>
+<!ELEMENT grouped (fixed*, required*, optional*)>
+<!ELEMENT enum EMPTY>
+<!ATTLIST enum
+        name CDATA #REQUIRED
+        code CDATA #REQUIRED
+>
+
+<!ELEMENT requestrules (fixed*, required*, optional*)>
+<!ELEMENT answerrules (fixed*, required*, optional*)>
+
+<!ELEMENT fixed    (avprule*)>
+<!ELEMENT required (avprule*)>
+<!ELEMENT optional (avprule*)>
+
+<!ELEMENT avprule EMPTY>
+<!ATTLIST avprule
+        name IDREF #REQUIRED
+        position (first | last | unspecified)  "unspecified"
+        maximum CDATA #IMPLIED
+        minimum CDATA #IMPLIED
+>
+
+
diff --git a/contrib/nightly_tests/README b/contrib/nightly_tests/README
new file mode 100644
index 0000000..67d97e9
--- /dev/null
+++ b/contrib/nightly_tests/README
@@ -0,0 +1,86 @@
+This folder contains information and scripts to run a new test configuration for nightly builds 
+and reporting the results to freeDiameter dashboard at:
+  http://www.freediameter.net/CDash/index.php?project=freeDiameter
+
+The information gathered here mostly comes from the following pages:
+ http://www.itk.org/Wiki/CMake_Testing_With_CTest
+ http://www.itk.org/Wiki/CMake_Scripting_Of_CTest
+ http://www.itk.org/Wiki/CTest:Buildserver
+
+=============
+
+INSTRUCTIONS to setup a new build slave for the freeDiameter buildserver:
+-- note: the build slave should have cmake version 2.8 at least so that ctest will update the source tree properly.
+
+1) Install all dependencies for freeDiameter as follow: 
+  a) Debian / Ubuntu: See the "prereqs.ubuntu" file
+	$ sudo aptitude install `wget http://www.freediameter.net/hg/freeDiameter/raw-file/tip/contrib/nightly_tests/prereqs.ubuntu -O - | grep -v -e "^#"`
+	
+  b) FreeBSD: See the "prereqs.freebsd" file
+      - install base system and ports
+      - install freediameter dependencies as follow:
+      # pkg_add -r -v wget
+      # pkg_add -r -v `wget http://www.freediameter.net/hg/freeDiameter/raw-file/tip/contrib/nightly_tests/prereqs.freebsd -O - | grep -v -e "^#"`
+      
+  c) OpenSUSE:
+	$ sudo zypper install `wget http://www.freediameter.net/hg/freeDiameter/raw-file/tip/contrib/nightly_tests/prereqs.opensuse -O - | grep -v -e "^#"`
+  
+  d) Fedora:
+	$ sudo yum install wget
+	$ sudo yum install `wget http://www.freediameter.net/hg/freeDiameter/raw-file/tip/contrib/nightly_tests/prereqs.fedora -O - | grep -v -e "^#"`
+	
+     You may also have issues with SELinux later, an easy workaround is to disable it (until better solution)
+        # setenforce Permissive
+        
+
+2) Create the "test" database for app_acct test (we assume the tests are run as user "test" here)
+      - check INSTALL.FreeBSD file for specific PostgreSQL pre-install instructions.
+      - These are the instructions for Debian/Ubuntu/OpenSUSE,  adjust as needed:
+	# su - postgres
+	# createuser --interactive test
+	 Shall the new role be a superuser? (y/n) n
+	 Shall the new role be allowed to create databases? (y/n) y
+	 Shall the new role be allowed to create more new roles? (y/n) n
+	# logout
+	$ whoami
+	 test
+	$ createdb test
+	$ psql test
+	 psql (8.4.4)
+	 Type "help" for help.
+
+	 test=> 
+	 CREATE TABLE incoming_test (
+	 recorded_on timestamp with time zone NOT NULL,
+	 "Accounting-Record-Type" integer,
+	 "Session-Id" bytea,
+	 "Accounting-Record-Number" integer,
+	 "Route-Record1" bytea,
+	 "Route-Record2" bytea,
+	 "Route-Record3" bytea,
+	 "Route-Record4" bytea );
+	 \q
+	 
+
+3) Create a directory ~/fDtests
+	$ cd
+	$ mkdir fDtests
+	$ cd fDtests
+
+4) Retrieve the runtests.sh script and save in this directory
+	$ wget http://www.freediameter.net/hg/freeDiameter/raw-file/tip/contrib/nightly_tests/runtests.sh
+	$ chmod +x runtests.sh
+
+5) Create a file local.cmake defining the name of the build slave in this directory also.
+	$ echo "SET(CTEST_SITE \""`hostname`"\")" > local.cmake
+	
+   For FreeBSD, in addition do:
+   	$ echo "set(CTEST_BUILD_OPTIONS \"\${CTEST_BUILD_OPTIONS} -DFLEX_EXECUTABLE:FILEPATH=/usr/local/bin/flex\")" >> local.cmake
+	
+6) Run the runtests.sh script once to check it works properly (freeBSD might require: ln -s /usr/local/bin/bash /bin/bash)
+
+7) Set up a crontab to run the script
+	$ wget http://www.freediameter.net/hg/freeDiameter/raw-file/tip/contrib/nightly_tests/cronjob.sh
+	$ chmod +x cronjob.sh
+	$ crontab -l
+0 0 * * * /home/test/fDtests/cronjob.sh > /home/test/fDtests/cronjob.log 2>&1
diff --git a/contrib/nightly_tests/alldefault.conf b/contrib/nightly_tests/alldefault.conf
new file mode 100644
index 0000000..0376918
--- /dev/null
+++ b/contrib/nightly_tests/alldefault.conf
@@ -0,0 +1,2 @@
+
+set(CTEST_BUILD_NAME "Default")
diff --git a/contrib/nightly_tests/allext.conf b/contrib/nightly_tests/allext.conf
new file mode 100644
index 0000000..ba94a09
--- /dev/null
+++ b/contrib/nightly_tests/allext.conf
@@ -0,0 +1,9 @@
+
+# This configuration compiles all the extensions. It also performs a coverage test.
+# For this to pass, you need to setup the pg database for app_acct test.
+
+set(CTEST_BUILD_NAME "All extensions (default)")
+
+set(CTEST_BUILD_OPTIONS "${CTEST_BUILD_OPTIONS} -DALL_EXTENSIONS:BOOL=ON")
+set(CTEST_BUILD_OPTIONS "${CTEST_BUILD_OPTIONS} -DTEST_APP_ACCT:BOOL=ON -DTEST_APP_ACCT_CONNINFO:STRING=user=test\\ dbname=test")
+
diff --git a/contrib/nightly_tests/allextdbg.conf b/contrib/nightly_tests/allextdbg.conf
new file mode 100644
index 0000000..60e9df6
--- /dev/null
+++ b/contrib/nightly_tests/allextdbg.conf
@@ -0,0 +1,11 @@
+
+# This configuration compiles all the extensions. It also performs a coverage test.
+# For this to pass, you need to setup the pg database for app_acct test.
+
+set(WITH_COVERAGE TRUE)
+set(CTEST_BUILD_NAME "All extensions (Debug)")
+
+set(CTEST_BUILD_OPTIONS "${CTEST_BUILD_OPTIONS} -DALL_EXTENSIONS:BOOL=ON")
+set(CTEST_BUILD_OPTIONS "${CTEST_BUILD_OPTIONS} -DCMAKE_BUILD_TYPE:STRING=Debug")
+set(CTEST_BUILD_OPTIONS "${CTEST_BUILD_OPTIONS} -DTEST_APP_ACCT:BOOL=ON -DTEST_APP_ACCT_CONNINFO:STRING=user=test\\ dbname=test")
+
diff --git a/contrib/nightly_tests/allextdeb.conf b/contrib/nightly_tests/allextdeb.conf
new file mode 100644
index 0000000..876baaf
--- /dev/null
+++ b/contrib/nightly_tests/allextdeb.conf
@@ -0,0 +1,10 @@
+
+# This configuration compiles all the extensions. It also performs a coverage test.
+# For this to pass, you need to setup the pg database for app_acct test.
+
+set(CTEST_BUILD_NAME "All extensions (DebianPackage)")
+
+set(CTEST_BUILD_OPTIONS "${CTEST_BUILD_OPTIONS} -DALL_EXTENSIONS:BOOL=ON")
+set(CTEST_BUILD_OPTIONS "${CTEST_BUILD_OPTIONS} -DCMAKE_BUILD_TYPE:STRING=DebianPackage")
+set(CTEST_BUILD_OPTIONS "${CTEST_BUILD_OPTIONS} -DTEST_APP_ACCT:BOOL=ON -DTEST_APP_ACCT_CONNINFO:STRING=user=test\\ dbname=test")
+
diff --git a/contrib/nightly_tests/allextmax.conf b/contrib/nightly_tests/allextmax.conf
new file mode 100644
index 0000000..a67468e
--- /dev/null
+++ b/contrib/nightly_tests/allextmax.conf
@@ -0,0 +1,10 @@
+
+# This configuration compiles all the extensions. It also performs a coverage test.
+# For this to pass, you need to setup the pg database for app_acct test.
+
+set(CTEST_BUILD_NAME "All extensions (MaxPerformance)")
+
+set(CTEST_BUILD_OPTIONS "${CTEST_BUILD_OPTIONS} -DALL_EXTENSIONS:BOOL=ON")
+set(CTEST_BUILD_OPTIONS "${CTEST_BUILD_OPTIONS} -DCMAKE_BUILD_TYPE:STRING=MaxPerformance")
+set(CTEST_BUILD_OPTIONS "${CTEST_BUILD_OPTIONS} -DTEST_APP_ACCT:BOOL=ON -DTEST_APP_ACCT_CONNINFO:STRING=user=test\\ dbname=test")
+
diff --git a/contrib/nightly_tests/allextprof.conf b/contrib/nightly_tests/allextprof.conf
new file mode 100644
index 0000000..9d6d66c
--- /dev/null
+++ b/contrib/nightly_tests/allextprof.conf
@@ -0,0 +1,11 @@
+
+# This configuration compiles all the extensions. It also performs a coverage test.
+# For this to pass, you need to setup the pg database for app_acct test.
+
+set(WITH_COVERAGE TRUE)
+set(CTEST_BUILD_NAME "All extensions (Profiling)")
+
+set(CTEST_BUILD_OPTIONS "${CTEST_BUILD_OPTIONS} -DALL_EXTENSIONS:BOOL=ON")
+set(CTEST_BUILD_OPTIONS "${CTEST_BUILD_OPTIONS} -DCMAKE_BUILD_TYPE:STRING=Profiling")
+set(CTEST_BUILD_OPTIONS "${CTEST_BUILD_OPTIONS} -DTEST_APP_ACCT:BOOL=ON -DTEST_APP_ACCT_CONNINFO:STRING=user=test\\ dbname=test")
+
diff --git a/contrib/nightly_tests/allextrel.conf b/contrib/nightly_tests/allextrel.conf
new file mode 100644
index 0000000..60457cb
--- /dev/null
+++ b/contrib/nightly_tests/allextrel.conf
@@ -0,0 +1,10 @@
+
+# This configuration compiles all the extensions. It also performs a coverage test.
+# For this to pass, you need to setup the pg database for app_acct test.
+
+set(CTEST_BUILD_NAME "All extensions (Release)")
+
+set(CTEST_BUILD_OPTIONS "${CTEST_BUILD_OPTIONS} -DALL_EXTENSIONS:BOOL=ON")
+set(CTEST_BUILD_OPTIONS "${CTEST_BUILD_OPTIONS} -DCMAKE_BUILD_TYPE:STRING=Release")
+set(CTEST_BUILD_OPTIONS "${CTEST_BUILD_OPTIONS} -DTEST_APP_ACCT:BOOL=ON -DTEST_APP_ACCT_CONNINFO:STRING=user=test\\ dbname=test")
+
diff --git a/contrib/nightly_tests/allextval.conf b/contrib/nightly_tests/allextval.conf
new file mode 100644
index 0000000..48e32aa
--- /dev/null
+++ b/contrib/nightly_tests/allextval.conf
@@ -0,0 +1,11 @@
+
+# This configuration compiles all the extensions. It also performs a coverage test.
+# For this to pass, you need to setup the pg database for app_acct test.
+
+set(WITH_COVERAGE TRUE)
+set(CTEST_BUILD_NAME "All extensions (DebugValgrind)")
+
+set(CTEST_BUILD_OPTIONS "${CTEST_BUILD_OPTIONS} -DALL_EXTENSIONS:BOOL=ON")
+set(CTEST_BUILD_OPTIONS "${CTEST_BUILD_OPTIONS} -DCMAKE_BUILD_TYPE:STRING=DebugValgrind")
+set(CTEST_BUILD_OPTIONS "${CTEST_BUILD_OPTIONS} -DTEST_APP_ACCT:BOOL=ON -DTEST_APP_ACCT_CONNINFO:STRING=user=test\\ dbname=test")
+
diff --git a/contrib/nightly_tests/cronjob.sh b/contrib/nightly_tests/cronjob.sh
new file mode 100644
index 0000000..de1809f
--- /dev/null
+++ b/contrib/nightly_tests/cronjob.sh
@@ -0,0 +1,9 @@
+#!/bin/bash 
+
+# This script will simply retrieve the latest "runtest" script and run it.
+pushd ~/fDtests
+mv -f runtests.sh runtests.sh.prev
+wget "http://www.freediameter.net/hg/freeDiameter/raw-file/tip/contrib/nightly_tests/runtests.sh"
+chmod +x runtests.sh
+popd
+~/fDtests/runtests.sh
diff --git a/contrib/nightly_tests/idnaignore.conf b/contrib/nightly_tests/idnaignore.conf
new file mode 100644
index 0000000..5c344ac
--- /dev/null
+++ b/contrib/nightly_tests/idnaignore.conf
@@ -0,0 +1,4 @@
+
+set(CTEST_BUILD_OPTIONS "${CTEST_BUILD_OPTIONS} -DDIAMID_IDNA_IGNORE:BOOL=ON")
+
+set(CTEST_BUILD_NAME "IDNA Ignore")
diff --git a/contrib/nightly_tests/idnareject.conf b/contrib/nightly_tests/idnareject.conf
new file mode 100644
index 0000000..dbcbe69
--- /dev/null
+++ b/contrib/nightly_tests/idnareject.conf
@@ -0,0 +1,4 @@
+
+set(CTEST_BUILD_OPTIONS "${CTEST_BUILD_OPTIONS} -DDIAMID_IDNA_REJECT:BOOL=ON")
+
+set(CTEST_BUILD_NAME "IDNA Reject")
diff --git a/contrib/nightly_tests/nosctp.conf b/contrib/nightly_tests/nosctp.conf
new file mode 100644
index 0000000..f37aa3e
--- /dev/null
+++ b/contrib/nightly_tests/nosctp.conf
@@ -0,0 +1,5 @@
+
+# Remove SCTP support at compilation
+set(CTEST_BUILD_OPTIONS "${CTEST_BUILD_OPTIONS} -DDISABLE_SCTP:BOOL=ON")
+
+set(CTEST_BUILD_NAME "No SCTP")
diff --git a/contrib/nightly_tests/prereqs.fedora b/contrib/nightly_tests/prereqs.fedora
new file mode 100644
index 0000000..9be4305
--- /dev/null
+++ b/contrib/nightly_tests/prereqs.fedora
@@ -0,0 +1,15 @@
+# Fedora packages names of dependencies for nightly tests (using "yum install <packages>"):
+cmake make gcc gcc-c++ flex bison gnutls-devel libgcrypt-devel mercurial
+lksctp-tools-devel kernel-modules-extra
+postgresql-server postgresql-devel
+mysql-server mysql-devel
+libxml2 libxml2-devel libidn-devel
+swig python-devel
+
+# For postgresql server to start automatically, you may have to issue:
+#   service postgresql initdb
+#   chkconfig --level 345 postgresql on
+
+# To allow SCTP sockets to be bound in SELinux, I don't know the command,
+# so let's disable SELinux for the moment:
+#   setenforce Permissive
diff --git a/contrib/nightly_tests/prereqs.freebsd b/contrib/nightly_tests/prereqs.freebsd
new file mode 100644
index 0000000..86a239e
--- /dev/null
+++ b/contrib/nightly_tests/prereqs.freebsd
@@ -0,0 +1,5 @@
+# 1: install base system and ports
+# 2: install wget with command: pkg_add -r -v wget
+# Finally, install the other packages from this file
+# pkg_add -r -F -v `wget http://www.freediameter.net/hg/freeDiameter/raw-file/tip/contrib/nightly_tests/prereqs.freebsd -O - | grep -v -e "^#"`
+bash cmake mercurial flex bison libgcrypt gnutls postgresql84-client postgresql84-server mysql50-client libxml2 swig
diff --git a/contrib/nightly_tests/prereqs.opensuse b/contrib/nightly_tests/prereqs.opensuse
new file mode 100644
index 0000000..2ece2dc
--- /dev/null
+++ b/contrib/nightly_tests/prereqs.opensuse
@@ -0,0 +1,9 @@
+# OpenSUSE packages names of dependencies for nightly tests (using "zypper install <packages>"):
+# zypper install `wget http://www.freediameter.net/hg/freeDiameter/raw-file/tip/contrib/nightly_tests/prereqs.opensuse -O - | grep -v -e "^#"`
+cmake mercurial make gcc gcc-c++ flex bison lksctp-tools-devel libgnutls-devel libgcrypt-devel
+postgresql-server postgresql-devel libmysqlclient-devel libxml2-devel swig python-devel
+
+# Afterwards, you may need to issue the following command so that postgresql starts at boot: 
+#  insserv postgresql
+# or for open Suse 12.x:
+#  systemctl enable postgresql.service
diff --git a/contrib/nightly_tests/prereqs.ubuntu b/contrib/nightly_tests/prereqs.ubuntu
new file mode 100644
index 0000000..02ea907
--- /dev/null
+++ b/contrib/nightly_tests/prereqs.ubuntu
@@ -0,0 +1,3 @@
+# Packages (Ubuntu names)
+cmake mercurial make gcc g++ flex bison binutils libsctp-dev libgnutls-dev valgrind wget libpq-dev postgresql libmysqlclient-dev libxml2-dev libxml2 swig python-dev 
+
diff --git a/contrib/nightly_tests/runtests.sh b/contrib/nightly_tests/runtests.sh
new file mode 100644
index 0000000..e339b9b
--- /dev/null
+++ b/contrib/nightly_tests/runtests.sh
@@ -0,0 +1,133 @@
+#!/bin/bash -x
+
+# This script will retrieve the list of tests to run from the freediameter website,
+# and execute them one by one.
+
+ROOTDIR=$HOME/fDtests
+if [ ! -d $ROOTDIR ]; then
+   echo "The working directory $ROOTDIR does not exist. Please create it or edit the script."
+   exit 1;
+fi
+
+WORKDIR=$ROOTDIR/data
+
+# The script requires a local.cmake file to exist and define the following:
+# CTEST_SITE=
+#     the name of the build slave.
+# Example: SET(CTEST_SITE "Ubuntu-Lucid-64b")
+if [ ! -e $ROOTDIR/local.cmake ]; then
+   echo "Missing $ROOTDIR/local.cmake file, generating one (edit as needed, and run the script again)";
+   echo "SET(CTEST_SITE \""`hostname --fqdn`"\")" > $ROOTDIR/local.cmake
+   exit 1;
+fi
+
+# Now, cleanup any previous built data, but keep the sources (to get the diffs)
+if [ ! -d $WORKDIR ]; then 
+   mkdir $WORKDIR
+else
+   rm -rf $WORKDIR/*/build
+fi
+
+echo "Starting Nightly tests, time: "`date`
+
+# Retrieve the default parameters.
+wget "http://www.freediameter.net/hg/freeDiameter/raw-file/tip/CTestConfig.cmake" -O $WORKDIR/1_default.cmake
+if [ ! -e $WORKDIR/1_default.cmake ]; then
+   echo "Error retrieving CTestConfig.cmake file";
+   exit 1;
+fi
+
+# Retrieve the list of build names
+wget "http://www.freediameter.net/hg/freeDiameter/raw-file/tip/contrib/nightly_tests/tests.list" -O $WORKDIR/2_tests.list
+if [ ! -e $WORKDIR/2_tests.list ]; then
+   echo "Error retrieving tests.list file";
+   exit 1;
+fi
+
+# Now, for each test in the list
+for t in $(cat $WORKDIR/2_tests.list | grep -v -e "^#"); do
+   # Create the work environment if needed
+   if [ ! -d $WORKDIR/$t ]; then 
+       mkdir $WORKDIR/$t
+   fi
+   
+   #### Create the script
+   
+   # Project name, nightly time
+   cp $WORKDIR/1_default.cmake $WORKDIR/$t/CTestScript.cmake
+   
+   # Create path names, default build configuration, ...
+   cat >> $WORKDIR/$t/CTestScript.cmake << EOF
+      ##########################
+      SET(CTEST_SOURCE_DIRECTORY "$WORKDIR/$t/source")
+      SET(CTEST_BINARY_DIRECTORY "$WORKDIR/$t/build")
+
+      set(CTEST_CMAKE_GENERATOR "Unix Makefiles")
+      
+      set(CTEST_BUILD_CONFIGURATION "Profiling")
+      set(WITH_MEMCHECK FALSE)
+      set(WITH_COVERAGE FALSE)
+      
+      set(CTEST_BUILD_OPTIONS "")
+      set(CTEST_BUILD_NAME "Unnamed")
+
+      ##########################
+EOF
+   
+   wget "http://www.freediameter.net/hg/freeDiameter/raw-file/tip/contrib/nightly_tests/$t.conf" -O $WORKDIR/$t/params.conf
+   if [ ! -e $WORKDIR/$t/params.conf ]; then
+      echo "Error retrieving $t.conf file";
+      continue;
+   fi
+   
+   # The retrieved parameters will overwrite the defaults
+   cat $WORKDIR/$t/params.conf >> $WORKDIR/$t/CTestScript.cmake
+   
+   # Overwrite with all the local data (site name, ...)
+   echo "######## Local site data: "  >> $WORKDIR/$t/CTestScript.cmake
+   cat $ROOTDIR/local.cmake >> $WORKDIR/$t/CTestScript.cmake
+   
+   # Now, the remaining of the script
+   cat >> $WORKDIR/$t/CTestScript.cmake << EOF
+       #######################################################################
+
+       # ctest_empty_binary_directory(\${CTEST_BINARY_DIRECTORY})
+
+       find_program(CTEST_HG_COMMAND NAMES hg)
+       find_program(CTEST_COVERAGE_COMMAND NAMES gcov)
+       find_program(CTEST_MEMORYCHECK_COMMAND NAMES valgrind)
+
+       # set(CTEST_MEMORYCHECK_SUPPRESSIONS_FILE \${CTEST_SOURCE_DIRECTORY}/tests/valgrind.supp)
+
+       if(NOT EXISTS "\${CTEST_SOURCE_DIRECTORY}")
+	 set(CTEST_CHECKOUT_COMMAND "\${CTEST_HG_COMMAND} clone http://www.freediameter.net/hg/freeDiameter \${CTEST_SOURCE_DIRECTORY}")
+       endif()
+
+       set(CTEST_UPDATE_COMMAND "\${CTEST_HG_COMMAND}")
+
+       set(CTEST_CONFIGURE_COMMAND "\${CMAKE_COMMAND} -DCMAKE_BUILD_TYPE:STRING=\${CTEST_BUILD_CONFIGURATION}")
+       set(CTEST_CONFIGURE_COMMAND "\${CTEST_CONFIGURE_COMMAND} -DBUILD_TESTING:BOOL=ON -DOPT_TEST_ARGUMENTS:STRING=-d \${CTEST_BUILD_OPTIONS}")
+       set(CTEST_CONFIGURE_COMMAND "\${CTEST_CONFIGURE_COMMAND} \\"-G\${CTEST_CMAKE_GENERATOR}\\"")
+       set(CTEST_CONFIGURE_COMMAND "\${CTEST_CONFIGURE_COMMAND} \\"\${CTEST_SOURCE_DIRECTORY}\\"")
+
+       ctest_start("Nightly")
+       ctest_update()
+       ctest_configure()
+       ctest_build()
+       ctest_test()
+       if (WITH_COVERAGE AND CTEST_COVERAGE_COMMAND)
+	 ctest_coverage()
+       endif (WITH_COVERAGE AND CTEST_COVERAGE_COMMAND)
+       if (WITH_MEMCHECK AND CTEST_MEMORYCHECK_COMMAND)
+	 ctest_memcheck()
+       endif (WITH_MEMCHECK AND CTEST_MEMORYCHECK_COMMAND)
+       ctest_submit()
+EOF
+
+   # OK, now run this test, it will submit its results.
+   ctest -S $WORKDIR/$t/CTestScript.cmake -V
+done
+
+echo "Completed Nightly tests, time: "`date`
+
+
diff --git a/contrib/nightly_tests/tests.list b/contrib/nightly_tests/tests.list
new file mode 100644
index 0000000..afd2124
--- /dev/null
+++ b/contrib/nightly_tests/tests.list
@@ -0,0 +1,12 @@
+allext
+allextdbg
+allextval
+allextret
+allextprof
+allextmax
+allextdeb
+alldefault
+nosctp
+idnaignore
+idnareject
+#noext
diff --git a/contrib/test_Gx/CMakeLists.txt b/contrib/test_Gx/CMakeLists.txt
new file mode 100644
index 0000000..c9b0283
--- /dev/null
+++ b/contrib/test_Gx/CMakeLists.txt
@@ -0,0 +1,13 @@
+# The dict_nasreq extension
+PROJECT("Gx Interface for freediameter" C)
+
+# Compile as a module
+FD_ADD_EXTENSION(app_gx main_gx.c)
+
+
+####
+## INSTALL section ##
+
+INSTALL(TARGETS app_gx 
+       LIBRARY DESTINATION ${INSTALL_EXTENSIONS_SUFFIX}
+       COMPONENT freeDiameter-rx-interface)
diff --git a/contrib/test_Gx/main_gx.c b/contrib/test_Gx/main_gx.c
new file mode 100644
index 0000000..7811661
--- /dev/null
+++ b/contrib/test_Gx/main_gx.c
@@ -0,0 +1,819 @@
+/****************
+ Contributed by: Krishnan Srinivasan <hsirk_6@yahoo.com>
+ License: to be specified.
+ TODO:
+ 
+ ****************/
+
+
+#include <freeDiameter/extension.h>
+#include <signal.h>
+#include <time.h>
+#define AUTH_APP_ID				    16777238
+#define VENDOR_ID_3GPP  			    10415
+/* The content of this file follows the same structure as dict_base_proto.c */
+
+#if 0
+#define CHECK_dict_new( _type, _data, _parent, _ref )  \
+       CHECK_FCT(  fd_dict_new( fd_g_config->cnf_dict, (_type), (_data), (_parent), (_ref))  );
+#endif
+
+void dump_sess_eyec(struct session *sess, const char *);
+
+static int ccr_cb( struct msg ** msg, struct avp * avp, struct session * sess, void * opaque, enum disp_action * act);
+static int reauth_cb( struct msg ** msg, struct avp * avp, struct session * sess, void * opaque, enum disp_action * act);
+static int cca_cb( struct msg ** msg, struct avp * avp, struct session * sess, void * opaque, enum disp_action * act);
+static struct disp_hdl * ccr_cb_hdl = NULL; /* handler for ccr req cb */
+static struct disp_hdl * cca_cb_hdl = NULL; /* handler for cca req cb */
+static struct disp_hdl * reauth_cb_hdl = NULL; /* handler for cca req cb */
+
+struct dict_object *ccr_cmd = NULL;
+struct dict_object *cca_cmd = NULL;
+struct dict_object *dataobj_re_auth_request_type = NULL;
+struct dict_object * origin_host = NULL;
+struct dict_object * origin_realm = NULL;
+struct dict_object * dest_host = NULL;
+struct dict_object * dest_realm = NULL;
+struct dict_object *reauth_cmd = NULL;
+struct dict_object * auth_app_id    = NULL; 
+struct dict_object * service_cxt_id = NULL ; 
+struct dict_object * cc_req_type    = NULL; 
+struct dict_object * cc_req_num    = NULL; 
+struct dict_object * bearer_usage    = NULL; 
+struct dict_object * pflt_oper    = NULL; 
+struct dict_object * pflt_info    = NULL; 
+struct dict_object * pflt_id	= NULL; 
+struct dict_object * gx_inf;
+struct dict_object * term_cause = NULL;
+
+struct session *g_sess = NULL;
+struct session_handler *g_hdlr = NULL;
+
+enum gx_state {
+    STATE_INIT = 0,
+    STATE_INTERMEDIATE ,
+    STATE_FINAL
+};
+struct gx_sm_t {
+    enum gx_state state;
+    pthread_t tid;
+    struct fifo *events;
+    pthread_mutex_t p_sm_mtx;
+    int req_num;
+    struct session *sess;  
+} g_gx_sm;
+
+int snd_ccr_msg(struct gx_sm_t **gx_sm  , struct dict_object *cmd_r ) ;
+
+void sig_hdlr(void);
+
+void *gx_sm_th(void *sm);
+#define press_key_continue() { printf("%s %d\n", __FUNCTION__, __LINE__);}
+static int app_gx_entry(char * conffile)
+{
+//     TRACE_ENTRY("%p", conffile);	       
+       {
+	       application_id_t dcca_id = AUTH_APP_ID;
+	       application_id_t ccr_id = 272;
+	       application_id_t cca_id = 272;
+	       application_id_t reauth_id = 258;
+	       CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_APPLICATION, APPLICATION_BY_ID, &dcca_id, &gx_inf, ENOENT));
+       CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_COMMAND, CMD_BY_CODE_R, &ccr_id, &ccr_cmd, ENOENT));
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_COMMAND, CMD_BY_CODE_A, &cca_id, &cca_cmd, ENOENT));
+  //   CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_COMMAND, CMD_BY_CODE_R, &reauth_id, &reauth_cmd, ENOENT));
+
+       }
+
+       /* Applications section */
+#if 0
+     {
+	// Gx interface
+	       {
+	struct dict_application_data data = { AUTH_APP_ID, "3GPP-Gx Application" };
+	 CHECK_dict_new( DICT_APPLICATION, &data, NULL, &gx_inf);
+
+	       }				
+  
+	}
+#endif
+
+
+	// Do registeration and init stuff
+      {
+	struct disp_when data;
+       
+       TRACE_DEBUG(FULL, "Initializing dispatch callbacks for Gx interface");
+	   
+       memset(&data, 0, sizeof(data));
+       data.app = gx_inf;
+	   data.command = ccr_cmd;
+       /* Now specific handler for CCR-CMD */
+	   CHECK_FCT( fd_disp_register( ccr_cb, DISP_HOW_CC, &data, NULL, &ccr_cb_hdl ) );
+
+ 
+       memset(&data, 0, sizeof(data));
+       data.app = gx_inf;
+	   data.command = cca_cmd;
+
+	   CHECK_FCT( fd_disp_register( cca_cb, DISP_HOW_CC, &data, NULL, &cca_cb_hdl ) );
+       
+#ifdef REAUTH
+	CHECK_FCT(fd_dict_search(fd_g_config->cnf_dict, DICT_COMMAND, CMD_BY_NAME,
+				       "Re-Auth-Request", &reauth_cmd, ENOENT));
+	memset(&data, 0, sizeof(data));
+       data.app = gx_inf;
+	   data.command = reauth_cmd;
+	printf("register REAUTH\n");
+	   CHECK_FCT( fd_disp_register( reauth_cb, DISP_HOW_CC, &data, NULL, &reauth_cb_hdl ) );
+#endif
+
+
+     }
+
+	
+       CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, 
+			       DICT_AVP, AVP_BY_NAME, 
+			       "Origin-Host", 
+				&origin_host, 
+				ENOENT) );
+
+       CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, 
+			       DICT_AVP, 
+			       AVP_BY_NAME, 
+			       "Origin-Realm", 
+			       &origin_realm, 
+			       ENOENT) );
+
+       CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, 
+			       DICT_AVP, 
+			       AVP_BY_NAME, 
+			       "Destination-Host", 
+				&dest_host, 
+				ENOENT) );
+
+       CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, 
+			       DICT_AVP, 
+			       AVP_BY_NAME, 
+			       "Destination-Realm", 
+			       &dest_realm, 
+			       ENOENT) );
+
+
+       CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, 
+			       DICT_AVP, 
+			       AVP_BY_NAME, 
+			       "Auth-Application-Id", 
+			       &auth_app_id, 
+				ENOENT) );
+
+
+       CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, 
+			       DICT_AVP, 
+			       AVP_BY_NAME, 
+			       "Service-Context-Id", 
+			       &service_cxt_id, 
+				ENOENT) );
+
+    CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, 
+			       DICT_AVP, 
+			       AVP_BY_NAME, 
+			       "CC-Request-Type", 
+			       &cc_req_type, 
+				ENOENT) );
+
+    CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, 
+			       DICT_AVP, 
+			       AVP_BY_NAME, 
+			       "Termination-Cause", 
+			       &term_cause, 
+				ENOENT) );
+
+    CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, 
+			       DICT_AVP, 
+			       AVP_BY_NAME, 
+			       "CC-Request-Number", 
+			       &cc_req_num, 
+				ENOENT) );
+    {
+	struct dict_avp_request req = { VENDOR_ID_3GPP, 0, "Bearer-Usage"}; 
+
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, 
+				   DICT_AVP, 
+				   AVP_BY_NAME_AND_VENDOR, 
+				   &req, 
+				   &bearer_usage, 
+				    ENOENT) );
+    }
+    {
+	struct dict_avp_request req = { VENDOR_ID_3GPP, 0, "Packet-Filter-Operation"}; 
+
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, 
+				   DICT_AVP, 
+				   AVP_BY_NAME_AND_VENDOR, 
+				   &req, 
+				   &pflt_oper, 
+				    ENOENT) );
+    }
+    {
+	struct dict_avp_request req = { VENDOR_ID_3GPP, 0, "Packet-Filter-Information"}; 
+
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, 
+				   DICT_AVP, 
+				   AVP_BY_NAME_AND_VENDOR, 
+				   &req, 
+				   &pflt_info, 
+				    ENOENT) );
+    }
+    {
+	struct dict_avp_request req = { VENDOR_ID_3GPP, 0, "Packet-Filter-Identifier"}; 
+
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, 
+				   DICT_AVP, 
+				   AVP_BY_NAME_AND_VENDOR, 
+				   &req, 
+				   &pflt_id, 
+				    ENOENT) );
+    }
+
+    CHECK_FCT(fd_sess_handler_create( &g_hdlr, free, NULL));
+    CHECK_FCT( fd_fifo_new(&g_gx_sm.events));  
+    CHECK_FCT( fd_disp_app_support( gx_inf, NULL, 1 , 0));
+
+    CHECK_FCT( fd_event_trig_regcb(SIGUSR1, "app_gx", sig_hdlr ) );
+
+
+       TRACE_DEBUG(INFO, "Extension 'Gx' initialized");
+       return 0;
+}
+
+void * gx_sm_th(void *sm)
+{
+   struct gx_sm_t *gx_sm = (struct gx_sm_t *) sm;
+    struct timespec tout;
+    int evt_code;
+
+	    CHECK_SYS_DO( clock_gettime( CLOCK_REALTIME, &tout), goto out);
+	    tout.tv_sec =+ 60 ;
+   
+    while(1) {
+ 
+	fd_event_timedget(gx_sm->events, &tout , ETIMEDOUT, &evt_code, NULL, NULL );
+	 CHECK_SYS_DO( clock_gettime( CLOCK_REALTIME, &tout), goto out);
+	printf("in tout sec %d\n", tout.tv_sec); 
+	if(evt_code == ETIMEDOUT) {
+	    
+	    snd_ccr_msg(&gx_sm, ccr_cmd);
+	    gx_sm->req_num++ ;
+	    gx_sm->state = STATE_INTERMEDIATE;
+	    CHECK_SYS_DO( clock_gettime( CLOCK_REALTIME, &tout), goto out);
+	    tout.tv_sec += 30 ;
+
+	}
+       // printf("press enter\n");
+       // getchar();
+    }
+     
+ out: 
+ return NULL;
+}
+//TBD
+int init_gx_sm(struct gx_sm_t *sm)
+{
+    sm->state = STATE_INIT;
+    sm->tid = 0;//
+    sm->events = NULL;
+    pthread_mutex_t p_sm_mtx;
+    sm->req_num = 0;
+    sm->sess = NULL;
+
+return 0;
+}
+int free_gx_sm(struct gx_sm_t *sm)
+{
+    
+  free(sm);
+}
+struct gx_sm_t *gl_gx_sm = NULL;
+
+void sig_hdlr()
+{
+struct gx_sm_t *gx_sm = gl_gx_sm;
+
+    if( gx_sm) {
+
+	fd_sess_dump( 0 , g_gx_sm.sess);
+
+     } else {
+
+	if(gx_sm= (struct gx_sm_t *)malloc(sizeof(struct gx_sm_t))) {
+	    init_gx_sm(gx_sm);
+	   }
+	   gl_gx_sm = gx_sm;
+	}
+
+      snd_ccr_msg( &gx_sm, ccr_cmd);
+    return;
+}
+
+static void cr_cb_ans(void *data, struct msg  **msg)
+{
+    printf("call back \n");
+   return;
+}
+
+/*				     < Session-Id >
+				   { Origin-Host }
+				   { Origin-Realm }
+				   { Destination-Realm }
+				   { Auth-Application-Id }
+				   { Service-Context-Id }
+				   { CC-Request-Type }
+				   { CC-Request-Number }
+*/
+
+int snd_ccr_msg(struct gx_sm_t **sm , struct dict_object *cmd_r ) 
+{
+       struct msg * req = NULL;
+       struct avp * avp = NULL;
+       union avp_value val;
+       struct ta_mess_info * mi = NULL, *svg;
+       struct session *sess = NULL;
+    struct gx_sm_t *gx_sm = NULL;
+    struct gx_sm_t *ptr = NULL;
+
+       TRACE_DEBUG(FULL, "Creating a new CCR message for sending. %p", gx_sm);
+       
+       /* Create the request from template */
+       CHECK_FCT_DO( fd_msg_new( cmd_r, MSGFL_ALLOC_ETEID, &req ), goto out );
+       
+    gx_sm = *sm;
+       /* Create a new session */
+    if(!gx_sm->sess) {
+
+	   CHECK_FCT_DO( fd_sess_new( &sess, 
+				   fd_g_config->cnf_diamid, 
+				   fd_g_config->cnf_diamid_len, 
+				    "CCR_SESSION", strlen("CCR_SESSION") ), goto out );
+	
+	printf("statemachine: %p %p %p\n", *(&gx_sm), gx_sm , *sm);
+	gx_sm->sess = sess;
+	printf("new session %p \n", sess);
+	//Hold the session till terminate happens
+	       CHECK_FCT( fd_sess_ref_msg(sess) );
+
+      } else {
+
+	sess = gx_sm->sess;
+	printf("use previous session %p \n", sess);
+
+      }
+     
+     fd_sess_dump( 0 , sess);
+    
+       
+//     dump_sess_eyec( sess, __FUNCTION__);
+       /* Now set all AVPs values */
+       
+       /* Session-Id */
+       {
+	       os0_t sid;
+	       size_t sidlen;
+	struct dict_object *sess_id = NULL;
+
+       CHECK_FCT( fd_dict_search(   fd_g_config->cnf_dict
+				   , DICT_AVP, AVP_BY_NAME
+				   , "Session-Id"
+				   , &sess_id, ENOENT) );
+
+	       CHECK_FCT_DO( fd_sess_getsid ( sess, &sid, &sidlen ), goto out );
+	       CHECK_FCT_DO( fd_msg_avp_new ( sess_id, 0, &avp ), goto out );
+	       val.os.data = sid;
+	       val.os.len  = sidlen;
+	       CHECK_FCT_DO( fd_msg_avp_setvalue( avp, &val ), goto out );
+	       CHECK_FCT_DO( fd_msg_avp_add( req, MSG_BRW_FIRST_CHILD, avp ), goto out );
+       }
+
+       /* Set the Destination-Realm AVP */
+       {
+	       CHECK_FCT_DO( fd_msg_avp_new ( dest_realm, 0, &avp ), goto out  );
+	       val.os.data = (unsigned char *)("vm");
+	       val.os.len  = strlen("vm");
+	       CHECK_FCT_DO( fd_msg_avp_setvalue( avp, &val ), goto out  );
+	       CHECK_FCT_DO( fd_msg_avp_add( req, MSG_BRW_LAST_CHILD, avp ), goto out  );
+       }
+       
+
+       /* Set the Destination-Host AVP if needed*/
+    {
+	       CHECK_FCT_DO( fd_msg_avp_new ( dest_host, 0, &avp ), goto out  );
+	       val.os.data = (unsigned char *)("192.168.101.3");
+	       val.os.len  = strlen("192.168.101.3");
+	       CHECK_FCT_DO( fd_msg_avp_setvalue( avp, &val ), goto out  );
+	       CHECK_FCT_DO( fd_msg_avp_add( req, MSG_BRW_LAST_CHILD, avp ), goto out  );
+    }
+       
+
+       /* Set Origin-Host & Origin-Realm */
+       CHECK_FCT_DO( fd_msg_add_origin ( req, 0 ), goto out  );
+
+
+   /*  Set Auth-Application ID */
+    {
+       CHECK_FCT_DO( fd_msg_avp_new ( auth_app_id, 0, &avp ), goto out  );
+	       val.i32 =  AUTH_APP_ID; // Auth-App id is 4 for CCR 
+	       CHECK_FCT_DO( fd_msg_avp_setvalue( avp, &val ), goto out  );
+	       CHECK_FCT_DO( fd_msg_avp_add( req, MSG_BRW_LAST_CHILD, avp ), goto out  );
+    }
+
+    /*     Set Service Context ID     */
+    {
+
+       CHECK_FCT_DO( fd_msg_avp_new ( service_cxt_id, 0, &avp ), goto out  );
+	val.os.data = (unsigned char *)("test@tst");
+	       CHECK_FCT_DO( fd_msg_avp_setvalue( avp, &val ), goto out  );
+	       CHECK_FCT_DO( fd_msg_avp_add( req, MSG_BRW_LAST_CHILD, avp ), goto out  );
+
+    }
+
+    /*     Set Request Type	      */
+    {
+#define CCR_INIT_REQUEST		1
+#define CCR_UPDATE_REQUEST		2
+#define CCR_TERMINATION_REQUEST 	3
+#define CCR_EVENT_REQUEST		4
+//TODO Change this to use  enum object
+       CHECK_FCT_DO( fd_msg_avp_new ( cc_req_type, 0, &avp ), goto out  );
+	if(gx_sm->state == STATE_INIT)
+	    val.i32 = CCR_INIT_REQUEST;
+	else if(gx_sm->state == STATE_FINAL)
+	    val.i32 = CCR_TERMINATION_REQUEST;
+	 else 
+	    val.i32 = CCR_UPDATE_REQUEST;
+
+	       CHECK_FCT_DO( fd_msg_avp_setvalue( avp, &val ), goto out  );
+	       CHECK_FCT_DO( fd_msg_avp_add( req, MSG_BRW_LAST_CHILD, avp ), goto out  );
+
+    }
+
+    /*     Set Request Number	      */
+    {
+       CHECK_FCT_DO( fd_msg_avp_new ( cc_req_num, 0, &avp ), goto out  );
+	val.i32 = gx_sm->req_num;
+	       CHECK_FCT_DO( fd_msg_avp_setvalue( avp, &val ), goto out  );
+	       CHECK_FCT_DO( fd_msg_avp_add( req, MSG_BRW_LAST_CHILD, avp ), goto out  );
+	gx_sm->req_num++; 
+    }
+
+    switch(gx_sm->state) {
+
+     case STATE_INIT:
+
+	{
+	//Set Bearer-Usage
+    //TODO Change this to use  enum object
+       CHECK_FCT_DO( fd_msg_avp_new ( bearer_usage, 0, &avp ), goto out  );
+	val.i32 = 1;//IMS
+	       CHECK_FCT_DO( fd_msg_avp_setvalue( avp, &val ), goto out  );
+	       CHECK_FCT_DO( fd_msg_avp_add( req, MSG_BRW_LAST_CHILD, avp ), goto out  );
+	} 
+       {
+	//Set Packet Filter Operation 
+	//TODO Change this to use  enum object
+       CHECK_FCT_DO( fd_msg_avp_new ( pflt_oper, 0, &avp ), goto out  );
+	val.i32 = 1;//ADDITION
+	       CHECK_FCT_DO( fd_msg_avp_setvalue( avp, &val ), goto out  );
+	       CHECK_FCT_DO( fd_msg_avp_add( req, MSG_BRW_LAST_CHILD, avp ), goto out  );
+	 } 
+	struct avp *flt_info = NULL; 
+	{
+	    //Set Packet Filter Information 
+	   CHECK_FCT_DO( fd_msg_avp_new ( pflt_info, 0, &flt_info ), goto out  );
+
+   
+	       CHECK_FCT_DO( fd_msg_avp_add( req, MSG_BRW_LAST_CHILD, flt_info ), goto out  );
+	} 
+	// Set Packet Filter Identity
+	{
+
+	 CHECK_FCT_DO( fd_msg_avp_new ( pflt_id, 0, &avp ), goto out  );
+	  val.os.data = (unsigned char *)("ID");
+		 val.os.len  = strlen("ID");
+	  CHECK_FCT_DO( fd_msg_avp_setvalue( avp, &val ), goto out  );
+	  if(flt_info) {
+		   CHECK_FCT_DO( fd_msg_avp_add( flt_info, MSG_BRW_LAST_CHILD, avp ), goto out  );
+	   }else {
+		printf("flt_info NULL\n");
+	    }
+
+	 }
+	CHECK_FCT(fd_sess_state_store(g_hdlr, sess, &gx_sm));
+
+	break;
+     case STATE_FINAL:
+	 {
+	//Set Packet Filter Operation 
+	//TODO Change this to use  enum object
+       CHECK_FCT_DO( fd_msg_avp_new ( term_cause, 0, &avp ), goto out  );
+	val.i32 = 1;//Diameter logout
+	       CHECK_FCT_DO( fd_msg_avp_setvalue( avp, &val ), goto out  );
+	       CHECK_FCT_DO( fd_msg_avp_add( req, MSG_BRW_LAST_CHILD, avp ), goto out  );
+	 } 
+	break;
+     default: 
+	printf("State mismatch \n");
+    }
+       fflush(stderr);
+       
+       /* Send the request */
+    printf("CCA %p\n",req);
+// Everthing Done Store the state: reply should retreive it 
+       CHECK_FCT_DO( fd_msg_send( &req, NULL, NULL ), goto out );
+
+out:
+       return;
+}
+
+
+static int reauth_cb( struct msg ** msg, struct avp * avp, struct session * sess, void * opaque, enum disp_action * act)
+{
+       struct msg *ans, *qry;
+       struct avp * a;
+
+       TRACE_ENTRY("%p %p %p %p", msg, avp, sess, act);
+       
+       if (msg == NULL)
+	       return EINVAL;
+       
+       
+       /* Create answer header */
+       qry = *msg;
+       CHECK_FCT( fd_msg_new_answer_from_req ( fd_g_config->cnf_dict, msg, 0 ) );
+       ans = *msg;
+       
+       /* Set the Origin-Host, Origin-Realm, Result-Code AVPs */
+       CHECK_FCT( fd_msg_rescode_set( ans, "DIAMETER_SUCCESS", NULL, NULL, 1 ) );
+       
+       /* Send the answer */
+       CHECK_FCT( fd_msg_send( msg, NULL, NULL ) );
+       
+       
+
+}
+static int dcca_ans_from_req( struct dict_object * obj, struct msg *qry, struct msg **msg)
+{
+       struct avp *avp  = NULL;
+       struct avp_hdr * avpdata;
+    int  rc = -1;
+
+    CHECK_FCT(fd_msg_search_avp( qry, obj, &avp));
+    CHECK_FCT(fd_msg_avp_hdr(avp, &avpdata));
+    avp = NULL;
+
+       CHECK_FCT_DO( fd_msg_avp_new ( obj, 0, &avp ), goto out  );
+       CHECK_FCT_DO( fd_msg_avp_setvalue( avp, avpdata->avp_value ), goto out  );
+       CHECK_FCT_DO( fd_msg_avp_add( *msg, MSG_BRW_LAST_CHILD, avp ), goto out  );
+
+ rc = 0;
+out:
+ return rc;
+
+}
+/* Dummy ccr which :
+   Read the cc-req-type && cc-req-number from the msg and stick it back
+  in the reply
+
+*/
+static int ccr_cb( struct msg ** msg, struct avp * r_avp, struct session * sess, void * opaque, enum disp_action * act)
+{
+       struct msg *ans, *qry;
+       struct avp *avp  = NULL;
+       struct avp_hdr * avp_data;
+    int rc  = - 1; 
+
+       TRACE_ENTRY("%p %p %p %p", msg, r_avp, sess, act);
+       
+       if (msg == NULL)
+	       return EINVAL;
+       
+       
+       /* Create answer header */
+       qry = *msg;
+       CHECK_FCT_DO( fd_msg_new_answer_from_req ( fd_g_config->cnf_dict, msg, 0 ) , goto out);
+       ans = *msg;
+       
+       /* Set the Origin-Host, Origin-Realm, Result-Code AVPs */
+       CHECK_FCT_DO( fd_msg_rescode_set( ans, "DIAMETER_SUCCESS", NULL, NULL, 1 ), goto out );
+
+// Get the auth_app_id and from the reply and set it in the reply 
+    CHECK_FCT_DO(dcca_ans_from_req( auth_app_id, qry, msg), goto out);
+    CHECK_FCT_DO(dcca_ans_from_req( cc_req_type, qry, msg), goto out);
+    CHECK_FCT_DO(dcca_ans_from_req( cc_req_num, qry, msg), goto out);
+
+       /* Send the answer */
+       CHECK_FCT_DO( fd_msg_send( msg, NULL, NULL ), goto out );
+    rc  = 0;
+  out:
+    //Free up the memory
+    return rc ;
+
+}
+int send_reauth_req()
+
+{
+       struct dict_application_data appdata;
+    struct avp *avp = NULL;
+    union avp_value val ;
+    struct msg *qry, *ans = NULL;
+    struct msg *req = NULL;
+    struct msg *tst = NULL;
+       struct dict_object * auth_app_id = NULL, *reauth_req_type = NULL;
+
+//    qry = *msg;
+
+
+    { // Send new reauth request
+
+	   CHECK_FCT_DO( fd_msg_new( reauth_cmd, MSGFL_ALLOC_ETEID, &req ), goto out );
+       CHECK_FCT(  fd_dict_getval(gx_inf, &appdata)  );
+    
+       struct msg_hdr * header = NULL;
+	       CHECK_FCT( fd_msg_hdr ( req, &header ) );
+	       header->msg_appl = appdata.application_id;
+
+    }
+
+       /* Session-Id */
+       {
+	       os0_t sid;
+	       size_t sidlen;
+	struct dict_object *sess_id = NULL;
+       CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Session-Id", &sess_id, ENOENT) );
+
+	       //CHECK_FCT_DO( fd_sess_getsid ( sess, &sid, &sidlen ), goto out );
+	       CHECK_FCT_DO( fd_msg_avp_new ( sess_id, 0, &avp ), goto out );
+	       val.os.data = sid;
+	       val.os.len  = sidlen;
+	       CHECK_FCT_DO( fd_msg_avp_setvalue( avp, &val ), goto out );
+	       CHECK_FCT_DO( fd_msg_avp_add( req, MSG_BRW_FIRST_CHILD, avp ), goto out );
+	       
+       }
+
+       /* Set the Destination-Realm AVP */
+       {
+	       CHECK_FCT_DO( fd_msg_avp_new ( dest_realm, 0, &avp ), goto out  );
+	       val.os.data = (unsigned char *)("vm");
+	       val.os.len  = strlen("vm");
+	       CHECK_FCT_DO( fd_msg_avp_setvalue( avp, &val ), goto out  );
+	       CHECK_FCT_DO( fd_msg_avp_add( req, MSG_BRW_LAST_CHILD, avp ), goto out  );
+       }
+       
+       /* Set the Destination-Host AVP if needed*/
+//     if (ta_conf->dest_host) {
+	       CHECK_FCT_DO( fd_msg_avp_new ( dest_host, 0, &avp ), goto out  );
+	       val.os.data = (unsigned char *)("cli.vm");
+	       val.os.len  = strlen("cli.vm");
+	       CHECK_FCT_DO( fd_msg_avp_setvalue( avp, &val ), goto out  );
+	       CHECK_FCT_DO( fd_msg_avp_add( req, MSG_BRW_LAST_CHILD, avp ), goto out  );
+//     }
+    
+       /* Set Origin-Host & Origin-Realm */
+       CHECK_FCT_DO( fd_msg_add_origin ( req, 0 ), goto out  );
+
+       /* AUTH_Application-ID */
+       CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Auth-Application-Id", &auth_app_id, ENOENT) );
+	       CHECK_FCT_DO( fd_msg_avp_new ( auth_app_id, 0, &avp ), goto out  );
+	       val.i32 = appdata.application_id;
+	       CHECK_FCT_DO( fd_msg_avp_setvalue( avp, &val ), goto out  );
+	       CHECK_FCT_DO( fd_msg_avp_add( req, MSG_BRW_LAST_CHILD, avp ), goto out  );
+
+       /* Re-Auth Request Type */
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Re-Auth-Request-Type", &reauth_req_type, ENOENT) );
+	   CHECK_FCT_DO( fd_msg_avp_new ( reauth_req_type, 0, &avp ), goto out  );
+	val.i32 = 0;
+	CHECK_FCT_DO( fd_msg_avp_setvalue( avp, &val ), goto out  );
+	CHECK_FCT_DO( fd_msg_avp_add( req, MSG_BRW_LAST_CHILD, avp ), goto out  );
+
+
+       CHECK_FCT_DO( fd_msg_send( &req, cr_cb_ans, NULL ), goto out );
+out:
+    return 0 ;
+
+
+}
+/* Search a given AVP model in an AVP (extracted from libfreediameter/message.c ) */
+int fd_avp_search_avp ( struct avp * groupedavp, struct dict_object * what, struct avp ** avp )
+{
+       struct avp * nextavp;
+       struct avp_hdr * nextavphdr;
+       struct dict_avp_data    dictdata;
+       
+       
+       TRACE_ENTRY("%p %p %p", groupedavp, what, avp);
+       
+       CHECK_FCT(  fd_dict_getval(what, &dictdata)  );
+       
+       // Loop only in the group AVP 
+       CHECK_FCT(  fd_msg_browse(groupedavp, MSG_BRW_FIRST_CHILD, (void *)&nextavp, NULL)  );
+       CHECK_FCT( fd_msg_avp_hdr( nextavp, &nextavphdr )  );
+       
+       while (nextavphdr) {
+	       
+	       if ( (nextavphdr->avp_code   == dictdata.avp_code) && (nextavphdr->avp_vendor == dictdata.avp_vendor) ) // always 0 if no Vendor flag
+	       {
+		       break;
+	       }
+	       
+	       // Otherwise move to next AVP in the grouped AVP 
+	       CHECK_FCT( fd_msg_browse(nextavp, MSG_BRW_NEXT, (void *)&nextavp, NULL) );
+	       
+	       if(nextavp!=NULL)
+	       {
+		       CHECK_FCT( fd_msg_avp_hdr( nextavp, &nextavphdr )  );
+	       }
+	       else
+		       nextavphdr=NULL;
+       }
+       if (avp)
+	       *avp = nextavp;
+       
+       if (avp && nextavp) {
+	       struct dictionary * dict;
+	       CHECK_FCT( fd_dict_getdict( what, &dict) );
+	       CHECK_FCT_DO( fd_msg_parse_dict( nextavp, dict, NULL ),  );
+       }
+       
+       if (avp || nextavp)
+	       return 0;
+       else
+	       return ENOENT;
+}
+
+static int cca_cb( struct msg ** msg, 
+		   struct avp * t_avp , 
+		   struct session * sess, 
+		   void * opaque, 
+		   enum disp_action * act)
+{
+    struct avp *avp = NULL, *g_avp = NULL;
+    struct msg *req = *msg;
+    struct dict_object *chrg_rule_name = NULL ;
+    struct dict_object *chrg_rule_grp = NULL ;
+       struct avp_hdr * avpdata = NULL;
+    struct dict_avp_request grule_req =   {VENDOR_ID_3GPP, 0,"Charging-Rule-Install"};
+    struct dict_avp_request rule_req =   {VENDOR_ID_3GPP, 0,"Charging-Rule-Name"};
+    struct timespec sess_timeout;
+    struct gx_sm_t *gx_sm = NULL;
+  //  struct session *sess = NULL;
+    
+    
+       CHECK_FCT(fd_sess_state_retrieve( g_hdlr, sess, &gx_sm));
+    fd_sess_dump( 0, sess);
+    if(gx_sm->state != STATE_FINAL) { 
+
+	       CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict
+				   , DICT_AVP, AVP_BY_NAME_AND_VENDOR
+				   , &grule_req 
+				   , &chrg_rule_grp
+				   , ENOENT));
+    
+	   CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict
+				   , DICT_AVP, AVP_BY_NAME_AND_VENDOR
+				   , &rule_req 
+				   , &chrg_rule_name
+				   , ENOENT));
+
+
+	CHECK_FCT(fd_msg_search_avp ( *msg, chrg_rule_grp, &g_avp ));
+	CHECK_FCT(fd_avp_search_avp(g_avp, chrg_rule_name, &avp));
+
+	if(avp) {
+	       CHECK_FCT(fd_msg_avp_hdr(avp, &avpdata));
+	} else {
+	    printf("NULL AVP \n");
+	}
+	printf("charging-rule-name %s\n", avpdata->avp_value->os.data);
+	gx_sm->state = STATE_FINAL;
+	dump_sess_eyec( sess, __FUNCTION__);
+	printf("next dump\n");
+	CHECK_FCT(fd_sess_state_store( g_hdlr, sess, &gx_sm));
+	fd_msg_free(*msg);
+	*msg = NULL;
+
+   } else {
+	printf("Session terminated\n");
+	free_gx_sm(gx_sm);
+	fd_msg_free(*msg);
+	fd_sess_reclaim(&sess);
+	*msg = NULL;
+    }
+    fd_sess_dump( 0 , sess);
+
+    return 0;
+}
+
+static int gx_entry(char * conffile)
+{
+ return 0;
+}
+EXTENSION_ENTRY( "app_gx", app_gx_entry, "dict_dcca_3gpp");
+//EXTENSION_ENTRY( "app_gx", gx_entry);
diff --git a/contrib/test_Gx/readme.txt b/contrib/test_Gx/readme.txt
new file mode 100644
index 0000000..127d517
--- /dev/null
+++ b/contrib/test_Gx/readme.txt
@@ -0,0 +1,6 @@
+This content was contributed by Krishnan Srinivasan from Allot Communication.
+
+The dictionary entries may need some adjustments to 
+match the content of the dict_dcca_3gpp extension.
+
+Thank you Krishnan!
diff --git a/contrib/tools/README b/contrib/tools/README
new file mode 100644
index 0000000..bbb235d
--- /dev/null
+++ b/contrib/tools/README
@@ -0,0 +1,2 @@
+org_to_fd.pl converts org files like diameter-rfcs.org to C fragments
+that can be included in freeDiameter code.
diff --git a/contrib/tools/diameter-rfcs.org b/contrib/tools/diameter-rfcs.org
new file mode 100644
index 0000000..5d92cae
--- /dev/null
+++ b/contrib/tools/diameter-rfcs.org
@@ -0,0 +1,188 @@
+| Attribute Name                   | Code | Section | Data        | MUST | MAY | SHLD NOT | MUST NOT | Encr |
+| # RFC 3588 - Diameter #          |      |         |             |      |     |          |          |      |
+| Acct-Interim-Interval            |   85 |   9.8.2 | Unsigned32  | M    | P   |          | V        | Y    |
+| Accounting-Realtime-Required     |  483 |   9.8.7 | Enumerated  | M    | P   |          | V        | Y    |
+| Acct-Multi-Session-Id            |   50 |   9.8.5 | UTF8String  | M    | P   |          | V        | Y    |
+| Accounting-Record-Number         |  485 |   9.8.3 | Unsigned32  | M    | P   |          | V        | Y    |
+| Accounting-Record-Type           |  480 |   9.8.1 | Enumerated  | M    | P   |          | V        | Y    |
+| Accounting-Session-Id            |   44 |   9.8.4 | OctetString | M    | P   |          | V        | Y    |
+| Accounting-Sub-Session-Id        |  287 |   9.8.6 | Unsigned64  | M    | P   |          | V        | Y    |
+| Acct-Application-Id              |  259 |     6.9 | Unsigned32  | M    | P   |          | V        | N    |
+| Auth-Application-Id              |  258 |     6.8 | Unsigned32  | M    | P   |          | V        | N    |
+| Auth-Request-Type                |  274 |     8.7 | Enumerated  | M    | P   |          | V        | N    |
+| Authorization-Lifetime           |  291 |     8.9 | Unsigned32  | M    | P   |          | V        | N    |
+| Auth-Grace-Period                |  276 |    8.10 | Unsigned32  | M    | P   |          | V        | N    |
+| Auth-Session-State               |  277 |    8.11 | Enumerated  | M    | P   |          | V        | N    |
+| Re-Auth-Request-Type             |  285 |    8.12 | Enumerated  | M    | P   |          | V        | N    |
+| Class                            |   25 |    8.20 | OctetString | M    | P   |          | V        | Y    |
+| Destination-Host                 |  293 |     6.5 | DiamIdent   | M    | P   |          | V        | N    |
+| Destination-Realm                |  283 |     6.6 | DiamIdent   | M    | P   |          | V        | N    |
+| Disconnect-Cause                 |  273 |   5.4.3 | Enumerated  | M    | P   |          | V        | N    |
+| E2E-Sequence-AVP                 |  300 |    6.15 | Grouped     | M    | P   |          | V        | Y    |
+| Error-Message                    |  281 |     7.3 | UTF8String  |      | P   |          | V,M      | N    |
+| Error-Reporting-Host             |  294 |     7.4 | DiamIdent   |      | P   |          | V,M      | N    |
+| Event-Timestamp                  |   55 |    8.21 | Time        | M    | P   |          | V        | N    |
+| Experimental-Result              |  297 |     7.6 | Grouped     | M    | P   |          | V        | N    |
+| Experimental-Result-Code         |  298 |     7.7 | Unsigned32  | M    | P   |          | V        | N    |
+| Failed-AVP                       |  279 |     7.5 | Grouped     | M    | P   |          | V        | N    |
+| Firmware-Revision                |  267 |   5.3.4 | Unsigned32  |      |     |          | P,V,M    | N    |
+| Host-IP-Address                  |  257 |   5.3.5 | Address     | M    | P   |          | V        | N    |
+| Inband-Security-Id               |  299 |    6.10 | Unsigned32  | M    | P   |          | V        | N    |
+| Multi-Round-Time-Out             |  272 |    8.19 | Unsigned32  | M    | P   |          | V        | Y    |
+| Origin-Host                      |  264 |     6.3 | DiamIdent   | M    | P   |          | V        | N    |
+| Origin-Realm                     |  296 |     6.4 | DiamIdent   | M    | P   |          | V        | N    |
+| Origin-State-Id                  |  278 |    8.16 | Unsigned32  | M    | P   |          | V        | N    |
+| Product-Name                     |  269 |   5.3.7 | UTF8String  |      |     |          | P,V,M    | N    |
+| Proxy-Host                       |  280 |   6.7.3 | DiamIdent   | M    |     |          | P,V      | N    |
+| Proxy-Info                       |  284 |   6.7.2 | Grouped     | M    |     |          | P,V      | N    |
+| Proxy-State                      |   33 |   6.7.4 | OctetString | M    |     |          | P,V      | N    |
+| Redirect-Host                    |  292 |    6.12 | DiamURI     | M    | P   |          | V        | N    |
+| Redirect-Host-Usage              |  261 |    6.13 | Enumerated  | M    | P   |          | V        | N    |
+| Redirect-Max-Cache-Time          |  262 |    6.14 | Unsigned32  | M    | P   |          | V        | N    |
+| Result-Code                      |  268 |     7.1 | Unsigned32  | M    | P   |          | V        | N    |
+| Route-Record                     |  282 |   6.7.1 | DiamIdent   | M    |     |          | P,V      | N    |
+| Session-Id                       |  263 |     8.8 | UTF8String  | M    | P   |          | V        | Y    |
+| Session-Timeout                  |   27 |    8.13 | Unsigned32  | M    | P   |          | V        | N    |
+| Session-Binding                  |  270 |    8.17 | Unsigned32  | M    | P   |          | V        | Y    |
+| Session-Server-Failover          |  271 |    8.18 | Enumerated  | M    | P   |          | V        | Y    |
+| Supported-Vendor-Id              |  265 |   5.3.6 | Unsigned32  | M    | P   |          | V        | N    |
+| Termination-Cause                |  295 |    8.15 | Enumerated  | M    | P   |          | V        | N    |
+| User-Name                        |    1 |    8.14 | UTF8String  | M    | P   |          | V        | Y    |
+| Vendor-Id                        |  266 |   5.3.3 | Unsigned32  | M    | P   |          | V        | N    |
+| Vendor-Specific-Application-Id   |  260 |    6.11 | Grouped     | M    | P   |          | V        | N    |
+| # RFC 4005 - NAS #               |      |         |             |      |     |          |          |      |
+| NAS-Port                         |    5 |     4.2 | Unsigned32  | M    | P   |          | V        | Y    |
+| NAS-Port-Id                      |   87 |     4.3 | UTF8String  | M    | P   |          | V        | Y    |
+| NAS-Port-Type                    |   61 |     4.4 | Enumerated  | M    | P   |          | V        | Y    |
+| Called-Station-Id                |   30 |     4.5 | UTF8String  | M    | P   |          | V        | Y    |
+| Calling-Station-Id               |   31 |     4.6 | UTF8String  | M    | P   |          | V        | Y    |
+| Connect-Info                     |   77 |     4.7 | UTF8String  | M    | P   |          | V        | Y    |
+| Originating-Line-Info            |   94 |     4.8 | OctetString |      | M,P |          | V        | Y    |
+| Reply-Message                    |   18 |     4.9 | UTF8String  | M    | P   |          | V        | Y    |
+| User-Password                    |    2 |     5.1 | OctetString | M    | P   |          | V        | Y    |
+| Password-Retry                   |   75 |     5.2 | Unsigned32  | M    | P   |          | V        | Y    |
+| Prompt                           |   76 |     5.3 | Enumerated  | M    | P   |          | V        | Y    |
+| CHAP-Auth                        |  402 |     5.4 | Grouped     | M    | P   |          | V        | Y    |
+| CHAP-Algorithm                   |  403 |     5.5 | Enumerated  | M    | P   |          | V        | Y    |
+| CHAP-Ident                       |  404 |     5.6 | OctetString | M    | P   |          | V        | Y    |
+| CHAP-Response                    |  405 |     5.7 | OctetString | M    | P   |          | V        | Y    |
+| CHAP-Challenge                   |   60 |     5.8 | OctetString | M    | P   |          | V        | Y    |
+| ARAP-Password                    |   70 |     5.9 | OctetString | M    | P   |          | V        | Y    |
+| ARAP-Challenge-Response          |   84 |    5.10 | OctetString | M    | P   |          | V        | Y    |
+| ARAP-Security                    |   73 |    5.11 | Unsigned32  | M    | P   |          | V        | Y    |
+| ARAP-Security-Data               |   74 |    5.12 | OctetString | M    | P   |          | V        | Y    |
+| Service-Type                     |    6 |     6.1 | Enumerated  | M    | P   |          | V        | Y    |
+| Callback-Number                  |   19 |     6.2 | UTF8String  | M    | P   |          | V        | Y    |
+| Callback-Id                      |   20 |     6.3 | UTF8String  | M    | P   |          | V        | Y    |
+| Idle-Timeout                     |   28 |     6.4 | Unsigned32  | M    | P   |          | V        | Y    |
+| Port-Limit                       |   62 |     6.5 | Unsigned32  | M    | P   |          | V        | Y    |
+| NAS-Filter-Rule                  |  400 |     6.6 | IPFltrRule  | M    | P   |          | V        | Y    |
+| Filter-Id                        |   11 |     6.7 | UTF8String  | M    | P   |          | V        | Y    |
+| Configuration-Token              |   78 |     6.8 | OctetString | M    |     |          | P,V      |      |
+| QoS-Filter-Rule                  |  407 |     6.9 | QoSFltrRule |      |     |          |          |      |
+| Framed-Protocol                  |    7 |  6.10.1 | Enumerated  | M    | P   |          | V        | Y    |
+| Framed-Routing                   |   10 |  6.10.2 | Enumerated  | M    | P   |          | V        | Y    |
+| Framed-MTU                       |   12 |  6.10.3 | Unsigned32  | M    | P   |          | V        | Y    |
+| Framed-Compression               |   13 |  6.10.4 | Enumerated  | M    | P   |          | V        | Y    |
+| Framed-IP-Address                |    8 |  6.11.1 | OctetString | M    | P   |          | V        | Y    |
+| Framed-IP-Netmask                |    9 |  6.11.2 | OctetString | M    | P   |          | V        | Y    |
+| Framed-Route                     |   22 |  6.11.3 | UTF8String  | M    | P   |          | V        | Y    |
+| Framed-Pool                      |   88 |  6.11.4 | OctetString | M    | P   |          | V        | Y    |
+| Framed-Interface-Id              |   96 |  6.11.5 | Unsigned64  | M    | P   |          | V        | Y    |
+| Framed-IPv6-Prefix               |   97 |  6.11.6 | OctetString | M    | P   |          | V        | Y    |
+| Framed-IPv6-Route                |   99 |  6.11.7 | UTF8String  | M    | P   |          | V        | Y    |
+| Framed-IPv6-Pool                 |  100 |  6.11.8 | OctetString | M    | P   |          | V        | Y    |
+| Framed-IPX-Network               |   23 |  6.12.1 | UTF8String  | M    | P   |          | V        | Y    |
+| Framed-Appletalk-Link            |   37 |  6.13.1 | Unsigned32  | M    | P   |          | V        | Y    |
+| Framed-Appletalk-Network         |   38 |  6.13.2 | Unsigned32  | M    | P   |          | V        | Y    |
+| Framed-Appletalk-Zone            |   39 |  6.13.3 | OctetString | M    | P   |          | V        | Y    |
+| ARAP-Features                    |   71 |  6.14.1 | OctetString | M    | P   |          | V        | Y    |
+| ARAP-Zone-Access                 |   72 |  6.14.2 | Enumerated  | M    | P   |          | V        | Y    |
+| Login-IP-Host                    |   14 |  6.15.1 | OctetString | M    | P   |          | V        | Y    |
+| Login-IPv6-Host                  |   98 |  6.15.2 | OctetString | M    | P   |          | V        | Y    |
+| Login-Service                    |   15 |  6.15.3 | Enumerated  | M    | P   |          | V        | Y    |
+| Login-TCP-Port                   |   16 |  6.16.1 | Unsigned32  | M    | P   |          | V        | Y    |
+| Login-LAT-Service                |   34 |  6.17.1 | OctetString | M    | P   |          | V        | Y    |
+| Login-LAT-Node                   |   35 |  6.17.2 | OctetString | M    | P   |          | V        | Y    |
+| Login-LAT-Group                  |   36 |  6.17.3 | OctetString | M    | P   |          | V        | Y    |
+| Login-LAT-Port                   |   63 |  6.17.4 | OctetString | M    | P   |          | V        | Y    |
+| Tunneling                        |  401 |     7.1 | Grouped     | M    | P   |          | V        | N    |
+| Tunnel-Type                      |   64 |     7.2 | Enumerated  | M    | P   |          | V        | Y    |
+| Tunnel-Medium-Type               |   65 |     7.3 | Enumerated  | M    | P   |          | V        | Y    |
+| Tunnel-Client-Endpoint           |   66 |     7.4 | UTF8String  | M    | P   |          | V        | Y    |
+| Tunnel-Server-Endpoint           |   67 |     7.5 | UTF8String  | M    | P   |          | V        | Y    |
+| Tunnel-Password                  |   69 |     7.6 | OctetString | M    | P   |          | V        | Y    |
+| Tunnel-Private-Group-Id          |   81 |     7.7 | OctetString | M    | P   |          | V        | Y    |
+| Tunnel-Assignment-Id             |   82 |     7.8 | OctetString | M    | P   |          | V        | Y    |
+| Tunnel-Preference                |   83 |     7.9 | Unsigned32  | M    | P   |          | V        | Y    |
+| Tunnel-Client-Auth-Id            |   90 |    7.10 | UTF8String  | M    | P   |          | V        | Y    |
+| Tunnel-Server-Auth-Id            |   91 |    7.11 | UTF8String  | M    | P   |          | V        | Y    |
+| Accounting-Input-Octets          |  363 |     8.1 | Unsigned64  | M    | P   |          | V        | Y    |
+| Accounting-Output-Octets         |  364 |     8.2 | Unsigned64  | M    | P   |          | V        | Y    |
+| Accounting-Input-Packets         |  365 |     8.3 | Unsigned64  | M    | P   |          | V        | Y    |
+| Accounting-Output-Packets        |  366 |     8.4 | Unsigned64  | M    | P   |          | V        | Y    |
+| Acct-Session-Time                |   46 |     8.5 | Unsigned32  | M    | P   |          | V        | Y    |
+| Acct-Authentic                   |   45 |     8.6 | Enumerated  | M    | P   |          | V        | Y    |
+| Acounting-Auth-Method            |  406 |     8.7 | Enumerated  | M    | P   |          | V        | Y    |
+| Acct-Delay-Time                  |   41 |     8.8 | Unsigned32  | M    | P   |          | V        | Y    |
+| Acct-Link-Count                  |   51 |     8.9 | Unsigned32  | M    | P   |          | V        | Y    |
+| Acct-Tunnel-Connection           |   68 |    8.10 | OctetString | M    | P   |          | V        | Y    |
+| Acct-Tunnel-Packets-Lost         |   86 |    8.11 | Unsigned32  | M    | P   |          | V        | Y    |
+| NAS-Identifier                   |   32 |   9.3.1 | UTF8String  | M    | P   |          | V        | Y    |
+| NAS-IP-Address                   |    4 |   9.3.2 | OctetString | M    | P   |          | V        | Y    |
+| NAS-IPv6-Address                 |   95 |   9.3.3 | OctetString | M    | P   |          | V        | Y    |
+| State                            |   24 |   9.3.4 | OctetString | M    | P   |          | V        | Y    |
+| Termination-Cause                |  295 |   9.3.5 | Enumerated  | M    | P   |          | V        | Y    |
+| Origin-AAA-Protocol              |  408 |   9.3.6 | Enumerated  | M    | P   |          | V        | Y    |
+| # RFC 4006 - DCCA #              |      |         |             |      |     |          |          |      |
+| CC-Correlation-Id                |  411 |     8.1 | OctetString |      | P,M |          | V        | Y    |
+| CC-Input-Octets                  |  412 |    8.24 | Unsigned64  | M    | P   |          | V        | Y    |
+| CC-Money                         |  413 |    8.22 | Grouped     | M    | P   |          | V        | Y    |
+| CC-Output-Octets                 |  414 |    8.25 | Unsigned64  | M    | P   |          | V        | Y    |
+| CC-Request-Number                |  415 |     8.2 | Unsigned32  | M    | P   |          | V        | Y    |
+| CC-Request-Type                  |  416 |     8.3 | Enumerated  | M    | P   |          | V        | Y    |
+| CC-Service-Specific-Units        |  417 |    8.26 | Unsigned64  | M    | P   |          | V        | Y    |
+| CC-Session-Failover              |  418 |     8.4 | Enumerated  | M    | P   |          | V        | Y    |
+| CC-Sub-Session-Id                |  419 |     8.5 | Unsigned64  | M    | P   |          | V        | Y    |
+| CC-Time                          |  420 |    8.21 | Unsigned32  | M    | P   |          | V        | Y    |
+| CC-Total-Octets                  |  421 |    8.23 | Unsigned64  | M    | P   |          | V        | Y    |
+| CC-Unit-Type                     |  454 |    8.32 | Enumerated  | M    | P   |          | V        | Y    |
+| Check-Balance-Result             |  422 |     8.6 | Enumerated  | M    | P   |          | V        | Y    |
+| Cost-Information                 |  423 |     8.7 | Grouped     | M    | P   |          | V        | Y    |
+| Cost-Unit                        |  424 |    8.12 | UTF8String  | M    | P   |          | V        | Y    |
+| Credit-Control                   |  426 |    8.13 | Enumerated  | M    | P   |          | V        | Y    |
+| Credit-Control-Failure-Handling  |  427 |    8.14 | Enumerated  | M    | P   |          | V        | Y    |
+| Currency-Code                    |  425 |    8.11 | Unsigned32  | M    | P   |          | V        | Y    |
+| Direct-Debiting-Failure-Handling |  428 |    8.15 | Enumerated  | M    | P   |          | V        | Y    |
+| Exponent                         |  429 |     8.9 | Integer32   | M    | P   |          | V        | Y    |
+| Final-Unit-Action                |  449 |    8.35 | Enumerated  | M    | P   |          | V        | Y    |
+| Final-Unit-Indication            |  430 |    8.34 | Grouped     | M    | P   |          | V        | Y    |
+| Granted-Service-Unit             |  431 |    8.17 | Grouped     | M    | P   |          | V        | Y    |
+| G-S-U-Pool-Identifier            |  453 |    8.31 | Unsigned32  | M    | P   |          | V        | Y    |
+| G-S-U-Pool-Reference             |  457 |    8.30 | Grouped     | M    | P   |          | V        | Y    |
+| Multiple-Services-Credit-Control |  456 |    8.16 | Grouped     | M    | P   |          | V        | Y    |
+| Multiple-Services-Indicator      |  455 |    8.40 | Enumerated  | M    | P   |          | V        | Y    |
+| Rating-Group                     |  432 |    8.29 | Unsigned32  | M    | P   |          | V        | Y    |
+| Redirect-Address-Type            |  433 |    8.38 | Enumerated  | M    | P   |          | V        | Y    |
+| Redirect-Server                  |  434 |    8.37 | Grouped     | M    | P   |          | V        | Y    |
+| Redirect-Server-Address          |  435 |    8.39 | UTF8String  | M    | P   |          | V        | Y    |
+| Requested-Action                 |  436 |    8.41 | Enumerated  | M    | P   |          | V        | Y    |
+| Requested-Service-Unit           |  437 |    8.18 | Grouped     | M    | P   |          | V        | Y    |
+| Restriction-Filter-Rule          |  438 |    8.36 | IPFiltrRule | M    | P   |          | V        | Y    |
+| Service-Context-Id               |  461 |    8.42 | UTF8String  | M    | P   |          | V        | Y    |
+| Service-Identifier               |  439 |    8.28 | Unsigned32  | M    | P   |          | V        | Y    |
+| Service-Parameter-Info           |  440 |    8.43 | Grouped     |      | P,M |          | V        | Y    |
+| Service-Parameter-Type           |  441 |    8.44 | Unsigned32  |      | P,M |          | V        | Y    |
+| Service-Parameter-Value          |  442 |    8.45 | OctetString |      | P,M |          | V        | Y    |
+| Subscription-Id                  |  443 |    8.46 | Grouped     | M    | P   |          | V        | Y    |
+| Subscription-Id-Data             |  444 |    8.48 | UTF8String  | M    | P   |          | V        | Y    |
+| Subscription-Id-Type             |  450 |    8.47 | Enumerated  | M    | P   |          | V        | Y    |
+| Tariff-Change-Usage              |  452 |    8.27 | Enumerated  | M    | P   |          | V        | Y    |
+| Tariff-Time-Change               |  451 |    8.20 | Time        | M    | P   |          | V        | Y    |
+| Unit-Value                       |  445 |     8.8 | Grouped     | M    | P   |          | V        | Y    |
+| Used-Service-Unit                |  446 |    8.19 | Grouped     | M    | P   |          | V        | Y    |
+| User-Equipment-Info              |  458 |    8.49 | Grouped     |      | P,M |          | V        | Y    |
+| User-Equipment-Info-Type         |  459 |    8.50 | Enumerated  |      | P,M |          | V        | Y    |
+| User-Equipment-Info-Value        |  460 |    8.51 | OctetString |      | P,M |          | V        | Y    |
+| Value-Digits                     |  447 |    8.10 | Integer64   | M    | P   |          | V        | Y    |
+| Validity-Time                    |  448 |    8.33 | Unsigned32  | M    | P   |          | V        | Y    |
diff --git a/contrib/tools/org_to_fd.pl b/contrib/tools/org_to_fd.pl
new file mode 100755
index 0000000..9cc0631
--- /dev/null
+++ b/contrib/tools/org_to_fd.pl
@@ -0,0 +1,96 @@
+#!/usr/bin/env perl
+use strict;
+use Getopt::Std;
+
+our ($opt_V, $opt_v);
+
+# default to 3GPP
+my ($vendor) = 10415;
+my ($vendor_name) = "3GPP";
+
+sub convert_must_to_flags($) {
+    my ($allmust) = @_;
+    my ($mustfields) = "";
+    $mustfields .= "AVP_FLAG_VENDOR |" if ($allmust =~ m/V/);
+    $mustfields .= "AVP_FLAG_MANDATORY |" if ($allmust =~ m/M/);
+    $mustfields =~ s/ \|$//;
+    return $mustfields;
+}
+
+sub base_type($) {
+    my ($type) = @_;
+
+    return "AVP_TYPE_GROUPED" if ($type =~ m/Grouped/);
+    return "AVP_TYPE_OCTETSTRING" if ($type =~ m/(Address|DiameterIdentity|DiameterURI|OctetString|IPFilterRule|Time|UTF8String)/);
+    return "AVP_TYPE_INTEGER32" if ($type =~ m/Enumerated|Integer32/);
+    return "AVP_TYPE_INTEGER64" if ($type =~ m/Integer64/);
+    return "AVP_TYPE_UNSIGNED32" if ($type =~ m/Unsigned32/);
+    return "AVP_TYPE_UNSIGNED64" if ($type =~ m/Unsigned64/);
+    return "AVP_TYPE_FLOAT32" if ($type =~ m/Float32/);
+    return "AVP_TYPE_FLOAT64" if ($type =~ m/Float64/);
+
+    return "UNKNOWN TYPE: $type";
+}
+
+sub print_insert($$) {
+    my ($type, $name) = @_;
+    my $avp_type;
+
+    if ($type =~ m/(Grouped|OctetString|Integer32|Integer64|Unsigned32|Unsigned64|Float32|Float64)/) {
+        $avp_type = "NULL";
+    } elsif ($type =~ m/Enumerated/) {
+        print "\t\tstruct dict_object		*type;\n";
+        print "\t\tstruct dict_type_data	 tdata = { AVP_TYPE_INTEGER32, \"" . ($vendor_name ? "$vendor_name/" : "") ."Enumerated($name)\", NULL, NULL, NULL };\n";
+        # XXX: add enumerated values
+        print "\t\tCHECK_dict_new(DICT_TYPE, &tdata, NULL, &type);\n";
+        $avp_type = "type";
+    } else {
+        $avp_type = "${type}_type";
+    }
+
+    print "\t\tCHECK_dict_new(DICT_AVP, &data, $avp_type, NULL);\n";
+}
+
+sub usage($) {
+    die("usage: org_to_fd.pl [-V vendor_name -v vendor_code] [file ...]\n");
+    exit(@_);
+}
+
+getopts("V:v:") || usage(1);
+
+if (defined($opt_v)) {
+    $vendor = $opt_v;
+    if (!defined($opt_V)) {
+	usage(1);
+    }
+    $vendor_name = $opt_V;
+}
+
+print "\t/* The following is created automatically. Do not modify. */\n";
+print "\t/* Changes will be lost during the next update. Modify the source org file instead. */\n\n";
+
+while (<>) {
+    my ($dummy, $name, $code, $section, $type, $must, $may, $shouldnot, $mustnot, $encr) = split /\|/;
+
+    next if ($name =~ m/Attribute Name/);
+    if ($name =~ m/ # (.*)/) {
+        print "\t/* $1 */\n";
+        next;
+    }
+        
+
+    $name =~ s/ *//g;
+    $code =~ s/ *//g;
+    $type =~ s/ *//g;
+
+    print "\t/* $name */\n\t{\n\t\tstruct dict_avp_data data = {\n";
+    print "\t\t\t$code,\t/* Code */\n";
+    print "\t\t\t$vendor,\t/* Vendor */\n";
+    print "\t\t\t\"$name\",\t/* Name */\n";
+    print "\t\t\t" . convert_must_to_flags("$must, $mustnot") . ",\t/* Fixed flags */\n";
+    print "\t\t\t" . convert_must_to_flags("$must") . ",\t/* Fixed flag values */\n";
+    print "\t\t\t" . base_type($type) . "\t/* base type of data */\n";
+    print "\t\t};\n";
+    print_insert($type, $name);
+    print "\t};\n\n";
+}
diff --git a/contrib/update_copyright.sh b/contrib/update_copyright.sh
new file mode 100755
index 0000000..64e4465
--- /dev/null
+++ b/contrib/update_copyright.sh
@@ -0,0 +1,33 @@
+#!/bin/bash -x
+
+# This script will search all copyrights dates from source files, and update these if 
+# the file has been modified at a later date.
+
+if [ ! -f include/freeDiameter/libfdcore.h ];
+then echo "This script must be run from the source top directory"
+exit 1;
+fi;
+
+# Create a clean working copy
+TMPDIR=`mktemp -d up_cop.XXXXXXX` || exit 1
+hg clone . $TMPDIR/fD || exit 1
+pushd $TMPDIR/fD
+
+# Now, for each file with a copyright
+for SRC_FILE in `find . -name .hg -prune -or -type f -exec grep -q 'Copyright (c) 20.., WIDE Project and NICT' {} \; -print`;
+do 
+HG_YEAR=`hg log --template '{date|shortdate}' $SRC_FILE | tr - ' ' | awk '{print \$1}'`
+CPY_YEAR=`grep 'Copyright (c) 20.., WIDE Project and NICT' $SRC_FILE | awk '{print substr(\$4, 1, 4) }'`
+if [ $HG_YEAR -gt $CPY_YEAR ];
+then
+echo "Updating copyright $CPY_YEAR -> $HG_YEAR in $SRC_FILE";
+sed -i -e "s/Copyright (c) $CPY_YEAR, WIDE Project and NICT/Copyright (c) $HG_YEAR, WIDE Project and NICT/" $SRC_FILE
+fi;
+done
+
+hg commit -m"Updated copyright information"
+hg push
+popd
+rm -rf $TMPDIR
+hg update
+
diff --git a/contrib/wireshark/HOWTO b/contrib/wireshark/HOWTO
new file mode 100644
index 0000000..d6d9123
--- /dev/null
+++ b/contrib/wireshark/HOWTO
@@ -0,0 +1,68 @@
+	  --------
+	  FOREWORD
+	  --------
+			   
+The patch in this folder allows Wireshark to process packets that contain TLS-protected
+Diameter messages over SCTP multi-stream associations. Each SCTP stream pairs is handled
+as a separate TLS channel (RFC3436), which is consistent with freeDiameter 1.0.x mechanism.
+
+It should be noted however that rfc3588bis (revised Diameter) recommends that DTLS is used
+instead of TLS over SCTP, for the reasons highlighted in the introduction of RFC6083.
+When this new mechanism is implemented in freeDiameter, a different patch will probably
+be required for wireshark.
+
+
+The instructions in this file will change your wireshark binary in a way suitable for
+analysis of Diameter over TLS over SCTP, but may have unexpected side-effects
+on some other protocols analysis (including DTLS).
+
+The instructions refer to Debian-style packaging (apt), you should adapt 
+the process to build a new modified package of wireshark for your distribution.
+
+The provided patch has been successfully tested with:
+ - wireshark-1.2.7 (Ubuntu Lucid)
+ - wireshark-1.2.11 (Ubuntu Maverick)
+It may or may not work on more recent or ancient versions.
+
+
+	------------
+	INSTRUCTIONS
+	------------
+
+The steps are:
+ - get your wireshark source
+ 	apt-get source wireshark
+	cd wireshark-1.2.*
+	
+ - apply the patch
+ 	cat ~/wireshark-1.2.7-diameter-tls.patch | patch -p1
+
+ - increase the version number
+ 	dch -lfD "Added support for Diameter over TLS over SCTP"
+	
+ - Create a new package, this might take a while
+	fakeroot debian/rules binary
+
+ - Install the modified version
+ 	sudo dpkg --install ../wireshark-common_*fD*.deb ../wireshark_*fD*.deb
+
+ - Start the new wireshark:
+ 	wireshark &
+	
+To analyze a capture file, you will need the private keys of both peers involved.
+
+Let's imagine for example:
+  peer A with IP address 192.168.0.10 has private key privA.pem
+  peer B with IP address 192.168.0.11 has private key privB.pem
+  
+In wireshark you must do the following:
+ - go to menu Edit->Preferences
+ - In the left panel, under Protocols, scroll to "SSL" and select it.
+ - In the right panel, fill "RSA keys list" as follow:
+	192.168.0.10,3869,diameter,/absolute/path/to/privA.pem;192.168.0.11,3869,diameter,/absolute/path/to/privB.pem
+ - You may find also useful to select an SSL debug file to get a hint of any problem.
+ 
+Once this configuration is complete, you should be able to see the contents of SCTP packets, 
+including protected Diameter payload.
+
+Check the "sample" subdirectory for a test capture file.
diff --git a/contrib/wireshark/sample/192.168.103.10.priv.pem b/contrib/wireshark/sample/192.168.103.10.priv.pem
new file mode 100644
index 0000000..9da15dd
--- /dev/null
+++ b/contrib/wireshark/sample/192.168.103.10.priv.pem
@@ -0,0 +1,15 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIICXAIBAAKBgQDMcXy2iVqcXkGaY44yNihVNzW/zHptqID49/ZyyyOinxHenvf9
+o/fr613XvUuyquaapL99yiMPuLU3I1UxxacWBSAb496eGd7fY1Udw1RtqKCeb60c
+jpTc3zKySGPHtnzOxeSMDK/R6uqkFirF6Lnu18mKZyAwJtvFYnh0wK3SwwIDAQAB
+AoGAa6kX08hhPxcj1Pm4WBjNBJMeavJzRmwF/xYVYj43ddvuvR1Z2ugOFt7LfGDj
+DCOTbLx1Wvinng/W3kJtCtjbM3w3k5cuFJdJcURXda73IHSaJOHnBAw5RlvFCE79
+12yKqGOBgy80gGHDlqnSIjISCGb/9wLcHYLccakekckPc4ECQQDubt5fWzN4wUwU
+yW+e/SO9Vz4j+FiIC2aZy2OM9XXt6cgh4v0hQ3l0sWVJ6lTvK17aD9LXE5rluAOI
+thnPZElFAkEA24GH8Po/+3K6A5d5Zh1+hwoMLbWrykQDWSOgtmaOtbAvezlolF8O
+W18pVdvyMJg3gUiCA/rHG+r+OBxa4sx4ZwJAH4c1jHJo2fzlbJI+Wk2q3iydIPCD
+9GldhdSpM0h58Z3KQwDa6/0aIF4cwKtl08JuZnNVM+95ugqdHQTHYO8n6QJBAIgO
+m+KEWxBSpnX/d+IRuhGd6rqSdu8ihSjFaqJko2R+1o98oBQHb3C3ZXmwoUf5sb3S
+4bPxx2TIndbNzI/zyVUCQGqN7eyoeTxtPD8P08lUGTUnC2n0imZ1mU5p8Bnv8gw5
+lwt9qxuz0Ujr7uFPPu58bvGsYeoFUV23WRmS0rKLXv0=
+-----END RSA PRIVATE KEY-----
diff --git a/contrib/wireshark/sample/192.168.103.20.priv.pem b/contrib/wireshark/sample/192.168.103.20.priv.pem
new file mode 100644
index 0000000..9f69f7a
--- /dev/null
+++ b/contrib/wireshark/sample/192.168.103.20.priv.pem
@@ -0,0 +1,15 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIICXgIBAAKBgQDef8CrqawfvmCLBwmlPRlWjwB6V4TvVMRhivAYlwwFbUSoU5bm
+2D780IBr3fNL3zP38ySa7r9cXxPgk7mbj3PhcJbI0Ix0AjQdFSB08AOXev4gqU8p
+qgEODFV04tnFhOcDysp77qH/DFuNwxd2xtFUbGKfGhroAssHxJuogOmiWQIDAQAB
+AoGAP6H7wVyCLIXu6HP3zzkdIQM+2L5k92mfzGHG7tFsD7VDWHyngJfB093xjGfq
+p/1KyJPSGTlEoy9R6P12rMWnFv7sYYKmPGfKdRUMxZYIXbplw6+L/gwW3MCiOMDD
+zRzRjknE3a+Mjo3e2XMHh6Z+GJ61megMeGInODP05/h66AECQQDyFhT+D8DVj1hp
+RlaYTFDKCmS9rgMQ+g4YyqMLzuakkKwaJwbCIlMbQortGBvY9I+0uZC4jklcOpnl
+YYcGIUEBAkEA60l5uAVBk6vKWKWX2cksBP/VlJM2B9pkvmlL7tPwJVEfoaAzZx4N
+rPpC9sOsFlX1ShpirAmIqmvY16in4xEJWQJBAOvULSEOcZjZapQrjEIS3gTkOR06
+fgw0vDTUeh8PsEmSEcXsTL4jt/fvS+0KNl6UZ8Xzm5LeMYLiJ3d4GZQUIwECQQCb
+vYLoH/KMQMYrb1DYQ6TzmjRRqC+3ewP8Vc6BQ6BN0yjQ3y2nL+l1eiIhHNwn3LYE
+Wvq9TYI87C4YcfbPAlPhAkEA0bNU/Utgdbv/yT4lUmw+0toqFHkcT5s13RFWzNJU
+KdQ308kwz9rSDmuQ8eYzn5V02TioJKV4r0NZz+WcCyDY3A==
+-----END RSA PRIVATE KEY-----
diff --git a/contrib/wireshark/sample/README b/contrib/wireshark/sample/README
new file mode 100644
index 0000000..c75cfa1
--- /dev/null
+++ b/contrib/wireshark/sample/README
@@ -0,0 +1,56 @@
+This folder contains an example capture file, as well as the two
+private keys required to decode the TLS-protected exchanges.
+
+In order to decrypt properly the packets, you'll need a patched wireshark (see parent directory)
+and the SSL "RSA Private Keys" properties set to (replace with real full path):
+  192.168.103.10,3869,diameter,freeDiameter/contrib/wireshark/sample/192.168.103.10.priv.pem;192.168.103.20,3869,diameter,freeDiameter/contrib/wireshark/sample/192.168.103.20.priv.pem
+
+
+This capture contains everything that was exchanged by the peer since it boot up.
+The captured peer is "relay.a.rt.freediameter.net" with IP address 192.168.103.20.
+
+Here is the detail of what you can see in the capture, if the decyphering 
+works as expected, in chronological order:
+
+-----------------------------------------------------------------------------
+Frames		| Comments
+-----------------------------------------------------------------------------
+1-24		| Peer booting up: DHCP, NTP, ...
+		|
+25-29		| Connection attempt from 192.168.103.10
+		|   first attempt on SCTP (frames 26-27)
+		|   then on TCP (frames 28-29)
+		|
+32-35		| freeDiameter starting: Diameter Identities
+		|   from the peer's configuration file are
+		|   DNS resolved.
+		|
+36-39		| SCTP connection to 192.168.103.10
+		|
+40-45		| Failed attempt to connect to 192.168.103.30
+		|   where freeDiameter was not started.
+		|
+46-49		| (I think this is trigged by Debug output, 
+		|   I have to check)
+		|
+50-73		| TLS handshake on first stream pair (#0).
+		|
+74-90		| Resumed handshakes on streams #1 and #2 in parallel.
+		|   (not sure where to find that it is resumed,
+		|    except that certificates are not re-exchanged)
+		|
+91-92		| CER/CEA exchange.
+93-96		| DWR/DWA exchange.
+		|
+103-118		| SCTP heartbeats are exchanged more frequently than DWR/DWA.
+		|
+119-124		| Concurrent DWR/DWA (it happens sometimes)
+		|
+125-128		| Another failed attempt to 192.168.103.30 (cf. frames 40-45)
+		|
+137-140		| DPR/DPA exchange.
+		|
+141-153		| TLS clean shutdown on all streams in parallel.
+		|
+154-157		| SCTP association is closed.
+-----------------------------------------------------------------------------
diff --git a/contrib/wireshark/sample/capture.cap b/contrib/wireshark/sample/capture.cap
new file mode 100644
index 0000000..a680590
--- /dev/null
+++ b/contrib/wireshark/sample/capture.cap
Binary files differ
diff --git a/contrib/wireshark/wireshark-1.2.7-diameter-tls.patch b/contrib/wireshark/wireshark-1.2.7-diameter-tls.patch
new file mode 100644
index 0000000..02a1824
--- /dev/null
+++ b/contrib/wireshark/wireshark-1.2.7-diameter-tls.patch
@@ -0,0 +1,685 @@
+diff -Nur wireshark-1.2.7/epan/conversation.c wireshark-1.2.7-fD/epan/conversation.c
+--- wireshark-1.2.7/epan/conversation.c	2010-04-01 01:44:39.000000000 +0900
++++ wireshark-1.2.7-fD/epan/conversation.c	2011-02-23 14:26:35.000000000 +0900
+@@ -40,6 +40,11 @@
+ static GHashTable *conversation_hashtable_exact = NULL;
+ 
+ /*
++ * Hash table for conversations without strid.
++ */
++static GHashTable *conversation_hashtable_no_strid = NULL;
++
++/*
+  * Hash table for conversations with one wildcard address.
+  */
+ static GHashTable *conversation_hashtable_no_addr2 = NULL;
+@@ -63,6 +68,7 @@
+ 	port_type ptype;
+ 	guint32	port1;
+ 	guint32	port2;
++	guint32	strid;
+ } conversation_key;
+ #endif
+ /*
+@@ -193,6 +199,7 @@
+ 	hash_val += key->port1;
+ 	ADD_ADDRESS_TO_HASH(hash_val, &key->addr2);
+ 	hash_val += key->port2;
++	hash_val += key->strid;
+ 
+ 	return hash_val;
+ }
+@@ -217,6 +224,78 @@
+ 	 */
+ 	if (v1->port1 == v2->port1 &&
+ 	    v1->port2 == v2->port2 &&
++	    v1->strid == v2->strid &&
++	    ADDRESSES_EQUAL(&v1->addr1, &v2->addr1) &&
++	    ADDRESSES_EQUAL(&v1->addr2, &v2->addr2)) {
++		/*
++		 * Yes.  It's the same conversation, and the two
++		 * address/port pairs are going in the same direction.
++		 */
++		return 1;
++	}
++
++	/*
++	 * Is the first port 2 the same as the second port 1, the first
++	 * port 1 the same as the second port 2, the first address 2
++	 * the same as the second address 1, and the first address 1
++	 * the same as the second address 2?
++	 */
++	if (v1->port2 == v2->port1 &&
++	    v1->port1 == v2->port2 &&
++	    v1->strid == v2->strid &&
++	    ADDRESSES_EQUAL(&v1->addr2, &v2->addr1) &&
++	    ADDRESSES_EQUAL(&v1->addr1, &v2->addr2)) {
++		/*
++		 * Yes.  It's the same conversation, and the two
++		 * address/port pairs are going in opposite directions.
++		 */
++		return 1;
++	}
++
++	/*
++	 * The addresses or the ports don't match.
++	 */
++	return 0;
++}
++
++/*
++ * Compute the hash value for two given address/port pairs if the match
++ * has a wildcard stream id.
++ */
++static guint
++conversation_hash_no_strid(gconstpointer v)
++{
++	const conversation_key *key = (const conversation_key *)v;
++	guint hash_val;
++
++	hash_val = 0;
++	ADD_ADDRESS_TO_HASH(hash_val, &key->addr1);
++	hash_val += key->port1;
++	hash_val += key->port2;
++
++	return hash_val;
++}
++
++/*
++ * Compare two conversation keys, except for the stream id value.
++ */
++static gint
++conversation_match_no_strid(gconstpointer v, gconstpointer w)
++{
++	const conversation_key *v1 = (const conversation_key *)v;
++	const conversation_key *v2 = (const conversation_key *)w;
++
++	if (v1->ptype != v2->ptype)
++		return 0;	/* different types of port */
++
++	/*
++	 * Are the first and second port 1 values the same, the first and
++	 * second port 2 values the same, the first and second address
++	 * 1 values the same, and the first and second address 2 values
++	 * the same?
++	 */
++	if (v1->port1 == v2->port1 &&
++	    v1->port2 == v2->port2 &&
+ 	    ADDRESSES_EQUAL(&v1->addr1, &v2->addr1) &&
+ 	    ADDRESSES_EQUAL(&v1->addr2, &v2->addr2)) {
+ 		/*
+@@ -263,6 +342,7 @@
+ 	ADD_ADDRESS_TO_HASH(hash_val, &key->addr1);
+ 	hash_val += key->port1;
+ 	hash_val += key->port2;
++	hash_val += key->strid;
+ 
+ 	return hash_val;
+ }
+@@ -289,6 +369,7 @@
+ 	 */
+ 	if (v1->port1 == v2->port1 &&
+ 	    v1->port2 == v2->port2 &&
++	    v1->strid == v2->strid &&
+ 	    ADDRESSES_EQUAL(&v1->addr1, &v2->addr1)) {
+ 		/*
+ 		 * Yes.  It's the same conversation, and the two
+@@ -317,6 +398,7 @@
+ 	ADD_ADDRESS_TO_HASH(hash_val, &key->addr1);
+ 	hash_val += key->port1;
+ 	ADD_ADDRESS_TO_HASH(hash_val, &key->addr2);
++	hash_val += key->strid;
+ 
+ 	return hash_val;
+ }
+@@ -342,6 +424,7 @@
+ 	 * address 2 values the same?
+ 	 */
+ 	if (v1->port1 == v2->port1 &&
++	    v1->strid == v2->strid &&
+ 	    ADDRESSES_EQUAL(&v1->addr1, &v2->addr1) &&
+ 	    ADDRESSES_EQUAL(&v1->addr2, &v2->addr2)) {
+ 		/*
+@@ -370,6 +453,7 @@
+ 	hash_val = 0;
+ 	ADD_ADDRESS_TO_HASH(hash_val, &key->addr1);
+ 	hash_val += key->port1;
++	hash_val += key->strid;
+ 
+ 	return hash_val;
+ }
+@@ -394,6 +478,7 @@
+ 	 * and second address 1 values the same?
+ 	 */
+ 	if (v1->port1 == v2->port1 &&
++	    v1->strid == v2->strid &&
+ 	    ADDRESSES_EQUAL(&v1->addr1, &v2->addr1)) {
+ 		/*
+ 		 * Yes.  It's the same conversation, and the two
+@@ -420,6 +505,8 @@
+ 	conversation_keys = NULL;
+ 	if (conversation_hashtable_exact != NULL)
+ 		g_hash_table_destroy(conversation_hashtable_exact);
++	if (conversation_hashtable_no_strid != NULL)
++		g_hash_table_destroy(conversation_hashtable_no_strid);
+ 	if (conversation_hashtable_no_addr2 != NULL)
+ 		g_hash_table_destroy(conversation_hashtable_no_addr2);
+ 	if (conversation_hashtable_no_port2 != NULL)
+@@ -438,6 +525,9 @@
+ 	conversation_hashtable_exact =
+ 	    g_hash_table_new(conversation_hash_exact,
+ 	      conversation_match_exact);
++	conversation_hashtable_no_strid =
++	    g_hash_table_new(conversation_hash_no_strid,
++	      conversation_match_no_strid);
+ 	conversation_hashtable_no_addr2 =
+ 	    g_hash_table_new(conversation_hash_no_addr2,
+ 	      conversation_match_no_addr2);
+@@ -466,6 +556,15 @@
+ conversation_new(guint32 setup_frame, address *addr1, address *addr2, port_type ptype,
+     guint32 port1, guint32 port2, guint options)
+ {
++	return conversation_new_ext(setup_frame, addr1, addr2, ptype,
++    		port1, port2, options & ~(DISTINCT_SCTP_STREAMID), 0);
++
++}
++
++conversation_t *
++conversation_new_ext(guint32 setup_frame, address *addr1, address *addr2, port_type ptype,
++    guint32 port1, guint32 port2, guint options, guint16 strid)
++{
+ /*
+ 	DISSECTOR_ASSERT(!(options | CONVERSATION_TEMPLATE) || ((options | (NO_ADDR2 | NO_PORT2 | NO_PORT2_FORCE))) &&
+ 				"A conversation template may not be constructed without wildcard options");
+@@ -486,7 +585,11 @@
+ 		if (options & (NO_PORT2|NO_PORT2_FORCE)) {
+ 			hashtable = conversation_hashtable_no_port2;
+ 		} else {
+-			hashtable = conversation_hashtable_exact;
++			if (options & DISTINCT_SCTP_STREAMID) {
++				hashtable = conversation_hashtable_exact;
++			} else {
++				hashtable = conversation_hashtable_no_strid;
++			}
+ 		}
+ 	}
+ 
+@@ -495,6 +598,7 @@
+ 	existing_key.ptype = ptype;
+ 	existing_key.port1 = port1;
+ 	existing_key.port2 = port2;
++	existing_key.strid = strid;
+ 
+ 	conversation = g_hash_table_lookup(hashtable, &existing_key);
+ 	tc = conversation; /* Remember if lookup was successful */
+@@ -507,6 +611,7 @@
+ 	new_key->ptype = ptype;
+ 	new_key->port1 = port1;
+ 	new_key->port2 = port2;
++	new_key->strid = strid;
+ 
+ 	if (conversation) {
+ 		for (; conversation->next; conversation = conversation->next)
+@@ -568,8 +673,13 @@
+ 		g_hash_table_insert(conversation_hashtable_no_addr2,
+ 		    conv->key_ptr, conv);
+ 	} else {
+-		g_hash_table_insert(conversation_hashtable_exact,
+-		    conv->key_ptr, conv);
++		if (conv->options & DISTINCT_SCTP_STREAMID) {
++			g_hash_table_insert(conversation_hashtable_exact,
++			    conv->key_ptr, conv);
++		} else {
++			g_hash_table_insert(conversation_hashtable_no_strid,
++			    conv->key_ptr, conv);
++		}
+ 	}
+ }
+ 
+@@ -602,18 +712,23 @@
+ 		g_hash_table_insert(conversation_hashtable_no_port2,
+ 		    conv->key_ptr, conv);
+ 	} else {
+-		g_hash_table_insert(conversation_hashtable_exact,
+-		    conv->key_ptr, conv);
++		if (conv->options & DISTINCT_SCTP_STREAMID) {
++			g_hash_table_insert(conversation_hashtable_exact,
++			    conv->key_ptr, conv);
++		} else {
++			g_hash_table_insert(conversation_hashtable_no_strid,
++			    conv->key_ptr, conv);
++		}
+ 	}
+ }
+ 
+ /*
+  * Search a particular hash table for a conversation with the specified
+- * {addr1, port1, addr2, port2} and set up before frame_num.
++ * {addr1, port1, addr2, port2, strid} and set up before frame_num.
+  */
+ static conversation_t *
+ conversation_lookup_hashtable(GHashTable *hashtable, guint32 frame_num, address *addr1, address *addr2,
+-    port_type ptype, guint32 port1, guint32 port2)
++    port_type ptype, guint32 port1, guint32 port2, guint16 strid)
+ {
+ 	conversation_t* conversation;
+ 	conversation_t* match;
+@@ -628,6 +743,7 @@
+ 	key.ptype = ptype;
+ 	key.port1 = port1;
+ 	key.port2 = port2;
++	key.strid = strid;
+ 
+ 	match = g_hash_table_lookup(hashtable, &key);
+ 
+@@ -685,12 +801,19 @@
+ find_conversation(guint32 frame_num, address *addr_a, address *addr_b, port_type ptype,
+     guint32 port_a, guint32 port_b, guint options)
+ {
++	return find_conversation_ext(frame_num, addr_a, addr_b, ptype,
++    		port_a, port_b, options | IGNORE_SCTP_STREAMID, 0);
++}
++conversation_t *
++find_conversation_ext(guint32 frame_num, address *addr_a, address *addr_b, port_type ptype,
++    guint32 port_a, guint32 port_b, guint options, guint16 strid)
++{
+    conversation_t *conversation;
+ 
+    /*
+-    * First try an exact match, if we have two addresses and ports.
++    * First try an exact match, if we have two addresses and ports and strid.
+     */
+-   if (!(options & (NO_ADDR_B|NO_PORT_B))) {
++   if (!(options & (NO_ADDR_B|NO_PORT_B|IGNORE_SCTP_STREAMID))) {
+       /*
+        * Neither search address B nor search port B are wildcarded,
+        * start out with an exact match.
+@@ -699,7 +822,7 @@
+       conversation =
+          conversation_lookup_hashtable(conversation_hashtable_exact,
+          frame_num, addr_a, addr_b, ptype,
+-         port_a, port_b);
++         port_a, port_b, strid);
+       if ((conversation == NULL) && (addr_a->type == AT_FC)) {
+          /* In Fibre channel, OXID & RXID are never swapped as
+           * TCP/UDP ports are in TCP/IP.
+@@ -707,7 +830,33 @@
+          conversation =
+             conversation_lookup_hashtable(conversation_hashtable_exact,
+             frame_num, addr_b, addr_a, ptype,
+-            port_a, port_b);
++            port_a, port_b, strid);
++      }
++      if (conversation != NULL)
++         return conversation;
++   }
++
++   /*
++    * Then, ignoring strid try an exact match, if we have two addresses and ports.
++    */
++   if (!(options & (NO_ADDR_B|NO_PORT_B|NO_IGNORE_SCTP_STREAMID))) {
++      /*
++       * Neither search address B nor search port B are wildcarded,
++       * start out with an exact match.
++       * Exact matches check both directions.
++       */
++      conversation =
++         conversation_lookup_hashtable(conversation_hashtable_no_strid,
++         frame_num, addr_a, addr_b, ptype,
++         port_a, port_b, strid);
++      if ((conversation == NULL) && (addr_a->type == AT_FC)) {
++         /* In Fibre channel, OXID & RXID are never swapped as
++          * TCP/UDP ports are in TCP/IP.
++          */
++         conversation =
++            conversation_lookup_hashtable(conversation_hashtable_no_strid,
++            frame_num, addr_b, addr_a, ptype,
++            port_a, port_b, strid);
+       }
+       if (conversation != NULL)
+          return conversation;
+@@ -729,7 +878,7 @@
+        */
+       conversation =
+          conversation_lookup_hashtable(conversation_hashtable_no_addr2,
+-         frame_num, addr_a, addr_b, ptype, port_a, port_b);
++         frame_num, addr_a, addr_b, ptype, port_a, port_b, strid);
+       if ((conversation == NULL) && (addr_a->type == AT_FC)) {
+          /* In Fibre channel, OXID & RXID are never swapped as
+           * TCP/UDP ports are in TCP/IP.
+@@ -737,7 +886,7 @@
+          conversation =
+             conversation_lookup_hashtable(conversation_hashtable_no_addr2,
+             frame_num, addr_b, addr_a, ptype,
+-            port_a, port_b);
++            port_a, port_b, strid);
+       }
+       if (conversation != NULL) {
+          /*
+@@ -779,7 +928,7 @@
+       if (!(options & NO_ADDR_B)) {
+          conversation =
+             conversation_lookup_hashtable(conversation_hashtable_no_addr2,
+-            frame_num, addr_b, addr_a, ptype, port_b, port_a);
++            frame_num, addr_b, addr_a, ptype, port_b, port_a, strid);
+          if (conversation != NULL) {
+             /*
+              * If this is for a connection-oriented
+@@ -821,14 +970,14 @@
+        */
+       conversation =
+          conversation_lookup_hashtable(conversation_hashtable_no_port2,
+-         frame_num, addr_a, addr_b, ptype, port_a, port_b);
++         frame_num, addr_a, addr_b, ptype, port_a, port_b, strid);
+       if ((conversation == NULL) && (addr_a->type == AT_FC)) {
+          /* In Fibre channel, OXID & RXID are never swapped as
+           * TCP/UDP ports are in TCP/IP
+           */
+          conversation =
+             conversation_lookup_hashtable(conversation_hashtable_no_port2,
+-            frame_num, addr_b, addr_a, ptype, port_a, port_b);
++            frame_num, addr_b, addr_a, ptype, port_a, port_b, strid);
+       }
+       if (conversation != NULL) {
+          /*
+@@ -870,7 +1019,7 @@
+       if (!(options & NO_PORT_B)) {
+          conversation =
+             conversation_lookup_hashtable(conversation_hashtable_no_port2,
+-            frame_num, addr_b, addr_a, ptype, port_b, port_a);
++            frame_num, addr_b, addr_a, ptype, port_b, port_a, strid);
+          if (conversation != NULL) {
+             /*
+              * If this is for a connection-oriented
+@@ -907,7 +1056,7 @@
+     */
+    conversation =
+       conversation_lookup_hashtable(conversation_hashtable_no_addr2_or_port2,
+-      frame_num, addr_a, addr_b, ptype, port_a, port_b);
++      frame_num, addr_a, addr_b, ptype, port_a, port_b, strid);
+    if (conversation != NULL) {
+       /*
+        * If this is for a connection-oriented protocol:
+@@ -952,11 +1101,11 @@
+    if (addr_a->type == AT_FC)
+       conversation =
+       conversation_lookup_hashtable(conversation_hashtable_no_addr2_or_port2,
+-      frame_num, addr_b, addr_a, ptype, port_a, port_b);
++      frame_num, addr_b, addr_a, ptype, port_a, port_b, strid);
+    else
+       conversation =
+       conversation_lookup_hashtable(conversation_hashtable_no_addr2_or_port2,
+-      frame_num, addr_b, addr_a, ptype, port_b, port_a);
++      frame_num, addr_b, addr_a, ptype, port_b, port_a, strid);
+    if (conversation != NULL) {
+       /*
+        * If this is for a connection-oriented protocol, set the
+diff -Nur wireshark-1.2.7/epan/conversation.h wireshark-1.2.7-fD/epan/conversation.h
+--- wireshark-1.2.7/epan/conversation.h	2010-04-01 01:44:39.000000000 +0900
++++ wireshark-1.2.7-fD/epan/conversation.h	2011-02-23 14:25:44.000000000 +0900
+@@ -39,11 +39,13 @@
+  * TEMPLATE flag will be altered once the first connections (connection
+  * oriented protocols only) to include the newly found information which
+  * matched the wildcard options.
++ * DISTINCT_SCTP_STREAMID will also save the SCTP stream identifier, if any.
+  */
+ #define NO_ADDR2 0x01
+ #define NO_PORT2 0x02
+ #define NO_PORT2_FORCE 0x04
+ #define CONVERSATION_TEMPLATE 0x08
++#define DISTINCT_SCTP_STREAMID 0x10
+ 
+ /*
+  * Flags to pass to "find_conversation()" to indicate that the address B
+@@ -51,6 +53,8 @@
+  */
+ #define NO_ADDR_B 0x01
+ #define NO_PORT_B 0x02
++#define IGNORE_SCTP_STREAMID 0x04
++#define NO_IGNORE_SCTP_STREAMID 0x08
+ 
+ #include "packet.h"		/* for conversation dissector type */
+ 
+@@ -64,6 +68,7 @@
+ 	port_type ptype;
+ 	guint32	port1;
+ 	guint32	port2;
++	guint16	strid;
+ } conversation_key;
+ 
+ typedef struct conversation {
+@@ -85,6 +90,13 @@
+ extern conversation_t *find_conversation(guint32 frame_num, address *addr_a, address *addr_b,
+     port_type ptype, guint32 port_a, guint32 port_b, guint options);
+ 
++/* for SCTP stream */
++extern conversation_t *conversation_new_ext(guint32 setup_frame, address *addr1, address *addr2,
++    port_type ptype, guint32 port1, guint32 port2, guint options, guint16 strid);
++extern conversation_t *find_conversation_ext(guint32 frame_num, address *addr_a, address *addr_b,
++    port_type ptype, guint32 port_a, guint32 port_b, guint options, guint16 strid);
++    
++
+ extern void conversation_add_proto_data(conversation_t *conv, int proto,
+     void *proto_data);
+ extern void *conversation_get_proto_data(conversation_t *conv, int proto);
+diff -Nur wireshark-1.2.7/epan/dissectors/packet-diameter.c wireshark-1.2.7-fD/epan/dissectors/packet-diameter.c
+--- wireshark-1.2.7/epan/dissectors/packet-diameter.c	2010-04-01 01:44:21.000000000 +0900
++++ wireshark-1.2.7-fD/epan/dissectors/packet-diameter.c	2011-02-23 13:33:10.000000000 +0900
+@@ -63,8 +63,10 @@
+ #include "packet-ntp.h"
+ #include "packet-diameter.h"
+ #include "diam_dict.h"
++#include "packet-ssl.h"
+ 
+ #define SCTP_PORT_DIAMETER	3868
++#define SCTP_TLS_PORT_DIAMETER	3869
+ 
+ /* Diameter Header Flags */
+ /*                                      RPETrrrrCCCCCCCCCCCCCCCCCCCCCCCC  */
+@@ -271,10 +273,13 @@
+ 
+ 
+ static guint gbl_diameterSctpPort=SCTP_PORT_DIAMETER;
++static guint gbl_diameterSctpTlsPort=SCTP_TLS_PORT_DIAMETER;
+ 
+ static dissector_handle_t diameter_tcp_handle;
+ static range_t *global_diameter_tcp_port_range;
++static range_t *global_diameter_tcp_tls_port_range;
+ #define DEFAULT_DIAMETER_PORT_RANGE "3868"
++#define DEFAULT_DIAMETER_TLS_PORT_RANGE "3869"
+ 
+ /* desegmentation of Diameter over TCP */
+ static gboolean gbl_diameter_desegment = TRUE;
+@@ -1358,13 +1363,27 @@
+     dissector_add("tcp.port", port, diameter_tcp_handle);
+ }
+ 
++static void
++range_delete_callback_sec(guint32 port)
++{
++    ssl_dissector_delete(port, "diameter", TRUE);
++}
++
++static void
++range_add_callback_sec(guint32 port)
++{
++    ssl_dissector_add(port, "diameter", TRUE);
++}
++
+ void
+ proto_reg_handoff_diameter(void)
+ {
+ 	static gboolean Initialized=FALSE;
+ 	static guint SctpPort;
++	static guint SctpsPort;
+ 	static dissector_handle_t diameter_handle;
+ 	static range_t *diameter_tcp_port_range;
++	static range_t *diameters_tcp_port_range;
+ 
+ 	if (!Initialized) {
+ 		diameter_handle = find_dissector("diameter");
+@@ -1382,20 +1401,27 @@
+ 		/* AVP Code: 463 EAP-Reissued-Payload */
+ 		dissector_add("diameter.base", 463, 
+ 			new_create_dissector_handle(dissect_diameter_eap_payload, proto_diameter));
++			
++		/* set port for future deletes */
++		diameter_tcp_port_range = range_copy(global_diameter_tcp_port_range);
++		range_foreach(diameter_tcp_port_range, range_add_callback);
++		diameters_tcp_port_range = range_copy(global_diameter_tcp_tls_port_range);
++		range_foreach(diameters_tcp_port_range, range_add_callback_sec);
++		
++		dissector_add("sctp.port", gbl_diameterSctpPort, diameter_handle);
++		ssl_dissector_add(gbl_diameterSctpTlsPort, "diameter", TRUE);
+ 
+ 		Initialized=TRUE;
+ 	} else {
+ 		range_foreach(diameter_tcp_port_range, range_delete_callback);
+ 		g_free(diameter_tcp_port_range);
++		range_foreach(diameters_tcp_port_range, range_delete_callback_sec);
++		g_free(diameters_tcp_port_range);
+ 		dissector_delete("sctp.port", SctpPort, diameter_handle);
+ 	}
+ 
+-	/* set port for future deletes */
+-	diameter_tcp_port_range = range_copy(global_diameter_tcp_port_range);
+-	range_foreach(diameter_tcp_port_range, range_add_callback);
+ 
+-	SctpPort=gbl_diameterSctpPort;
+-	dissector_add("sctp.port", gbl_diameterSctpPort, diameter_handle);
++	
+ }
+ 
+ /* registration with the filtering engine */
+@@ -1543,8 +1569,9 @@
+ 	diameter_dissector_table = register_dissector_table("diameter.base", "DIAMETER_3GPP_AVPS", FT_UINT32, BASE_DEC);
+ 	diameter_3gpp_avp_dissector_table = register_dissector_table("diameter.3gpp", "DIAMETER_3GPP_AVPS", FT_UINT32, BASE_DEC);
+ 
+-	/* Set default TCP ports */
++	/* Set default TCP & TLS ports */
+ 	range_convert_str(&global_diameter_tcp_port_range, DEFAULT_DIAMETER_PORT_RANGE, MAX_UDP_PORT);
++	range_convert_str(&global_diameter_tcp_tls_port_range, DEFAULT_DIAMETER_TLS_PORT_RANGE, MAX_UDP_PORT);
+ 
+ 	/* Register configuration options for ports */
+ 	diameter_module = prefs_register_protocol(proto_diameter,
+diff -Nur wireshark-1.2.7/epan/dissectors/packet-sctp.c wireshark-1.2.7-fD/epan/dissectors/packet-sctp.c
+--- wireshark-1.2.7/epan/dissectors/packet-sctp.c	2010-04-01 01:44:28.000000000 +0900
++++ wireshark-1.2.7-fD/epan/dissectors/packet-sctp.c	2011-02-23 13:54:13.000000000 +0900
+@@ -2693,6 +2693,7 @@
+   b_bit = tvb_get_guint8(chunk_tvb, CHUNK_FLAGS_OFFSET) & SCTP_DATA_CHUNK_B_BIT;
+   u_bit = tvb_get_guint8(chunk_tvb, CHUNK_FLAGS_OFFSET) & SCTP_DATA_CHUNK_U_BIT;
+   stream_id = tvb_get_ntohs(chunk_tvb, DATA_CHUNK_STREAM_ID_OFFSET);
++  pinfo->strid = stream_id;
+   stream_seq_num = tvb_get_ntohs(chunk_tvb, DATA_CHUNK_STREAM_SEQ_NUMBER_OFFSET);
+   tsn = tvb_get_ntohl(chunk_tvb, DATA_CHUNK_TSN_OFFSET);
+ 
+diff -Nur wireshark-1.2.7/epan/dissectors/packet-ssl.c wireshark-1.2.7-fD/epan/dissectors/packet-ssl.c
+--- wireshark-1.2.7/epan/dissectors/packet-ssl.c	2010-04-01 01:44:34.000000000 +0900
++++ wireshark-1.2.7-fD/epan/dissectors/packet-ssl.c	2011-02-23 14:56:36.000000000 +0900
+@@ -500,6 +500,7 @@
+     guint* conv_version;
+     Ssl_private_key_t * private_key;
+     guint32 port;
++    guint16 strid;
+ 
+     ti = NULL;
+     ssl_tree   = NULL;
+@@ -507,9 +508,14 @@
+     first_record_in_frame = TRUE;
+     ssl_session = NULL;
+     port = 0;
++    strid = 0;
+ 
+ 
+     ssl_debug_printf("\ndissect_ssl enter frame #%u (%s)\n", pinfo->fd->num, (pinfo->fd->flags.visited)?"already visited":"first time");
++    
++    if (pinfo->ptype == PT_SCTP) {
++    	ssl_debug_printf("\ndissect_ssl SCTP stream %hd\n", pinfo->strid);
++    }
+ 
+     /* Track the version using conversations to reduce the
+      * chance that a packet that simply *looks* like a v2 or
+@@ -523,14 +529,14 @@
+      *       the conv_version, must set the copy in the conversation
+      *       in addition to conv_version
+      */
+-    conversation = find_conversation(pinfo->fd->num, &pinfo->src, &pinfo->dst, pinfo->ptype,
+-                                     pinfo->srcport, pinfo->destport, 0);
++    conversation = find_conversation_ext(pinfo->fd->num, &pinfo->src, &pinfo->dst, pinfo->ptype,
++                                     pinfo->srcport, pinfo->destport, NO_IGNORE_SCTP_STREAMID, pinfo->strid);
+ 
+     if (!conversation)
+     {
+         /* create a new conversation */
+-        conversation = conversation_new(pinfo->fd->num, &pinfo->src, &pinfo->dst, pinfo->ptype,
+-                                        pinfo->srcport, pinfo->destport, 0);
++        conversation = conversation_new_ext(pinfo->fd->num, &pinfo->src, &pinfo->dst, pinfo->ptype,
++                                        pinfo->srcport, pinfo->destport, (pinfo->ptype == PT_SCTP) ? DISTINCT_SCTP_STREAMID : 0, pinfo->strid);
+         ssl_debug_printf("  new conversation = %p created\n", (void *)conversation);
+     }
+     conv_data = conversation_get_proto_data(conversation, proto_ssl);
+@@ -549,7 +555,7 @@
+         conversation_add_proto_data(conversation, proto_ssl, ssl_session);
+ 
+         /* we need to know which side of the conversation is speaking */
+-        if (ssl_packet_from_server(ssl_associations, pinfo->srcport, pinfo->ptype == PT_TCP)) {
++        if (ssl_packet_from_server(ssl_associations, pinfo->srcport, pinfo->ptype != PT_UDP)) {
+             dummy.addr = pinfo->src;
+             dummy.port = port = pinfo->srcport;
+         } else {
+@@ -762,7 +768,7 @@
+      * add decrypted data to this packet info */
+     ssl_debug_printf("decrypt_ssl3_record: app_data len %d ssl, state 0x%02X\n",
+         record_length, ssl->state);
+-    direction = ssl_packet_from_server(ssl_associations, pinfo->srcport, pinfo->ptype == PT_TCP);
++    direction = ssl_packet_from_server(ssl_associations, pinfo->srcport, pinfo->ptype != PT_UDP);
+ 
+     /* retrieve decoder for this packet direction */
+     if (direction != 0) {
+@@ -1504,7 +1510,7 @@
+             col_append_str(pinfo->cinfo, COL_INFO, "Change Cipher Spec");
+         dissect_ssl3_change_cipher_spec(tvb, ssl_record_tree,
+                                         offset, conv_version, content_type);
+-        if (ssl) ssl_change_cipher(ssl, ssl_packet_from_server(ssl_associations, pinfo->srcport, pinfo->ptype == PT_TCP));
++        if (ssl) ssl_change_cipher(ssl, ssl_packet_from_server(ssl_associations, pinfo->srcport, pinfo->ptype != PT_UDP));
+         break;
+     case SSL_ID_ALERT:
+     {
+@@ -1566,8 +1572,8 @@
+         /* we need dissector information when the selected packet is shown.
+          * ssl session pointer is NULL at that time, so we can't access
+          * info cached there*/
+-        association = ssl_association_find(ssl_associations, pinfo->srcport, pinfo->ptype == PT_TCP);
+-        association = association ? association: ssl_association_find(ssl_associations, pinfo->destport, pinfo->ptype == PT_TCP);
++        association = ssl_association_find(ssl_associations, pinfo->srcport, pinfo->ptype != PT_UDP);
++        association = association ? association: ssl_association_find(ssl_associations, pinfo->destport, pinfo->ptype != PT_UDP);
+ 
+         proto_item_set_text(ssl_record_tree,
+            "%s Record Layer: %s Protocol: %s",
+diff -Nur wireshark-1.2.7/epan/dissectors/packet-ssl-utils.c wireshark-1.2.7-fD/epan/dissectors/packet-ssl-utils.c
+--- wireshark-1.2.7/epan/dissectors/packet-ssl-utils.c	2010-04-01 01:44:27.000000000 +0900
++++ wireshark-1.2.7-fD/epan/dissectors/packet-ssl-utils.c	2011-02-23 13:33:10.000000000 +0900
+@@ -2713,9 +2713,10 @@
+     fprintf(stderr, "association_add() could not find handle for protocol:%s\n",protocol);
+   } else {
+     if(port) {
+-      if(tcp)
++      if(tcp) {
+         dissector_add("tcp.port", port, handle);
+-      else
++        dissector_add("sctp.port", port, handle);
++      } else
+         dissector_add("udp.port", port, handle);
+     }
+     g_tree_insert(associations, assoc, assoc);
+diff -Nur wireshark-1.2.7/epan/packet_info.h wireshark-1.2.7-fD/epan/packet_info.h
+--- wireshark-1.2.7/epan/packet_info.h	2010-04-01 01:44:40.000000000 +0900
++++ wireshark-1.2.7-fD/epan/packet_info.h	2011-02-23 13:54:52.000000000 +0900
+@@ -169,6 +169,7 @@
+   tvbuff_t *gssapi_decrypted_tvb;
+   gboolean gssapi_data_encrypted;
+ 
++  guint16 strid; /* Stream Id of the last DATA chunk in the packet */
+   guint32 ppid;  /* SCTP PPI of current DATA chunk */
+   guint32 ppids[MAX_NUMBER_OF_PPIDS]; /* The first NUMBER_OF_PPIDS PPIDS which are present
+                                       * in the SCTP packet
diff --git a/doc/acl_wl.conf.sample b/doc/acl_wl.conf.sample
new file mode 100644
index 0000000..6686f1a
--- /dev/null
+++ b/doc/acl_wl.conf.sample
@@ -0,0 +1,19 @@
+# Configuration file for the peer whitelist extension.
+#
+# This extension is meant to allow connection from remote peers, without actively
+# maintaining this connection ourselves (as it would be the case by declaring the 
+# peer in a ConnectPeer directive).
+# The format of this file is very simple. It contains a list of peer names
+# separated by spaces or newlines. 
+#
+# The peer name must be a fqdn. We allow also a special "*" character as the
+# first label of the fqdn, to allow all fqdn with the same domain name.
+# Example: *.example.net will allow host1.example.net and host2.example.net
+#
+# At the beginning of a line, the following flags are allowed (case sensitive) -- either or both can appear:
+# ALLOW_OLD_TLS : we accept unprotected CER/CEA exchange with Inband-Security-Id = TLS
+# ALLOW_IPSEC   : we accept implicitly protected connection with with peer (Inband-Security-Id = IPSec)
+# It is specified for example as:
+# ALLOW_IPSEC vpn.example.net vpn2.example.net *.vpn.example.net
+# These flag take effect from their position, until the end of the line.
+
diff --git a/doc/app_acct.conf.sample b/doc/app_acct.conf.sample
new file mode 100644
index 0000000..a3fae80
--- /dev/null
+++ b/doc/app_acct.conf.sample
@@ -0,0 +1,82 @@
+#######################
+# This file contains the description of configuration and general information about the
+# "App_Acct" extension.
+
+# This extension provides a simple Diameter Accounting server.
+#  The extension does receive the Accounting-Request message, then
+# saves the contents of the AVP in a database, as configured here.
+#  The data is not processed at all. The intent is that a dedicated
+# application will then pull from this database and process the data (consolidate 
+# sessions, ...)
+
+# In order to enable this extension, the main freeDiameter configuration file
+# must contain the following declaration:
+# LoadExtension = "extensions/app_acct.fdx" : "/path/to/app_acct.conf" ;
+#######################
+
+#################
+## Part I: AVP ##
+#################
+
+# Configure here the AVPs that must be stored in the database.
+# The format is:
+#	  "AVP-dictionary-name" = {
+#		field = "db-field-name";
+#		required;
+#		multi=N;
+#	  };
+# Where:
+#  AVP-dictionary-name:
+# 	The name of the AVP, such as "Session-Id". Only this field is mandatory.
+#  field="...":
+#	The name of the field in the database where is AVP contents will be saved.
+#	The default is that the field is named as the AVP-dictionary-name.
+#  required:
+#	By default, if the AVP is not in the Diameter message, it is not passed in 
+#	the INSERT statement (will get NULL). If Required is specified for the AVP,
+#	an error is returned in the Diameter answer, and the data is discarded.
+#  multi=N:
+#	If an AVP may appear several times in a request, you may specify a number of
+#	occurrences to save in the database. The Nth first occurrences of the AVP 
+#	will be saved in fields "db-field-name1", "db-field-name2", ... "db-field-nameN"
+#
+# In case the default behavior for an AVP is fine, you can use the short syntax:
+#  "AVP-dictionary-name";
+#
+# Note that at the moment, GROUPED AVP are not supported. Also, only the top-level AVPs are
+# searched. This behavior can be changed quite easily if needed.
+
+# You may look at contrib/app_acct_tools/app_acct.conf and database.sql files
+# for an example of setup.
+
+
+#######################
+## Part II: Database ##
+#######################
+
+# You must specify the connection information to the database here.
+# Please note that if the connection is terminated, it will trig the shutdown of the freeDiameter daemon
+# For this reason, you should as much as possible use a local database.
+
+# ConnInfo:
+# The connection string to the database. See http://www.postgresql.org/docs/8.4/static/libpq-connect.html
+# Example: ConnInfo = "host=localhost port=5432 dbname=acct user=acct password=freediameter";
+
+# Table:
+# The name of the table to use. The fields and types in this table must be created accordingly to the Part I configuration in this file.
+# Example: Table = "incoming";
+
+# Timestamp_field:
+# Optionally, you can specify a name of a field that will receive the value 'now' when a new record is inserted.
+# Default: no timestamp is inserted.
+# Example: Timestamp_field = "recorded_on";
+
+# Server_name_field:
+# Optionally, you can specify a field which will receive the Diameter Identity of the local server for each record saved.
+# This is useful especially if you have several Accounting servers and want to check Load-Balancing behavior or so,
+# after aggregating all the data.
+# Default: no server name inserted.
+# Example: Server_name_field = "recorded_serv";
+
+
+
diff --git a/doc/app_diameap.conf.sample b/doc/app_diameap.conf.sample
new file mode 100644
index 0000000..c0a8aa7
--- /dev/null
+++ b/doc/app_diameap.conf.sample
@@ -0,0 +1,44 @@
+##### a sample Configuration file for DiamEAP
+
+# MySQL Database settings
+# Specify connection parameters for DiamEAP MySQL database: 
+# - username and password to connect to the MySQL Server
+# - databaseserver : the MySQL server location. It can be the IP address or the host name where MySQL server is located. 'localhost' can be used as the location if the server is locatd in the same host than DiamEAP.
+# - database_name : the created database for DiamEAP.
+
+# Syntax :
+# DiamEAP_MySQL = "<username>" , "<password>" , "<databaseserver>" , "<database_name>";
+
+
+
+##### Extensible Authentication Protocol (EAP) Methods Plugins #####
+# An EAP method is identified by its EAP method name, EAP TYPE, VENDOR and path to its EAP Method Plugin. 
+# Optionally, path to a configuration file of plugin can also be provided. 
+# Location of plugins and their configuration files can be provided by the absolute pathor the relative path from the location configured in cmake.
+# An EAP Method Plugin can not be loaded twice. Only the first added method will be loaded.
+# Any EAP Method plugin with a same EAP_TYPE value than an already loaded one will be discarded.
+# EAP Methods are added in the same order they are added to the the configuration file.
+ 
+# Syntax : 
+# Load_plugin = "<EAP method name>":EAP_TYPE:VENDOR:"<Path to EAP method >":"<Path to configuration file>";
+#
+# 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.diameap.conf";
+
+Load_plugin = "EAP Identity":1:0:"/extensions/eap_identity.emp":"";
+
+# Enable/disable checking User's Identity. If disabled, default parameters value will be used for authentication and authorization attributes.
+# Default values are defined in database for 'Default User'.
+Check_User_Identity = 1;
+
+# In addition to authentication DiamEAP can be configured to check authorization of authenticated users. If set to 0 authorization is disabled, otherwise enabled.( by default disabled).
+Authorization = 1;
+
+# This parameter specify the maximum number of seconds provided to the access device for responding to an EAP request. (by default set to 30 seconds)
+#Multi_Round_Time_Out=30;
+
+# After receivin a number of invalid EAP packets, DiamEAP reject the authentication by responding with Failure Authentication. 
+# The default value of maximum number of invalid EAP packets is set to 5 packets. 
+# The value of maximum invalid EAP packets can be modified by adding a new value.
+#MAX_Invalid_EAP_Packets=5;
diff --git a/doc/app_radgw.conf.sample b/doc/app_radgw.conf.sample
new file mode 100644
index 0000000..82e1619
--- /dev/null
+++ b/doc/app_radgw.conf.sample
@@ -0,0 +1,105 @@
+# This file contains information for configuring the app_radgw extension.
+# To find how to have freeDiameter load this extension, please refer to the freeDiameter documentation.
+#
+# The app_radgw extension allows a freeDiameter agent to serve as a
+# RADIUS/Diameter gateway. Typically, a RADIUS client (e.g. a NAS) will connect to
+# this agent, and the message will be converted to Diameter and sent to a Diameter server.
+#
+# Note that this extension does not provide a fully functionnal RADIUS/Diameter gateway.
+# You need to load plugins to handle specific RADIUS messages and convert them to 
+# Diameter apps such as NASREQ, EAP, ... See the next section for information.
+
+
+###########
+# PLUGINS #
+###########
+
+# Additional plugins must be loaded to support specific RADIUS messages and attributes.
+
+# Plugins are registered either for every message, or by port (auth or acct), or by port and code.
+# The general format is:
+# RGWX = plugin [: conf_file] [: port] [: code(s)] ;
+#  Where:
+#    plugin is the quoted file name (relative or absolute) of the plugin to load (.rgwx files).
+#    conf_file (optional) is the quoted name of the configuration file.
+#    port (optional), either auth or acct. 
+#       If not specified, extension is called for messages incoming on both ports
+#    code(s): space-separated list of command codes for which this extension must be called.
+#       If not specified, the extension is called for all incoming messages.
+#       The values are interpreted as hexadecimal.
+#
+# The plugins are called in the order they appear in this file.
+# Here are some explained examples:
+#  RGWX = "3579.rgwx";   Load this extension and call it for all messages. No configuration file.
+#  RGWX = "3579.rgwx" : "3579.conf";  Same as previous but with a configuration file specified.
+#  RGWX = "3579.rgwx" : auth; No configuration file, but called only for RADIUS messages received on authentication port.
+#  RGWX = "3579.rgwx" : 4 8 b;  Called for messages with command code 4, 8, or 11 only.
+#  RGWX = "3579.rgwx" : "3579.conf" : auth : 4 8 b;  All parameters combined.
+
+# Once the list of extensions for an incoming message has been called (or if the list is empty), 
+# an error is logged if some RADIUS attributes of the message have not been handled.
+
+RGWX = "extensions/echodrop.rgwx" : "echodrop.rgwx.conf"; # See echodrop.rgwx.conf.sample file
+RGWX = "extensions/auth.rgwx" : auth; 
+RGWX = "extensions/acct.rgwx" : acct;
+# RGWX = "extensions/debug.rgwx"; # Uncomment to see the result of the translation plugins.
+
+# For some extensions (auth, acct), a false configuration file name 
+# can be passed to specify flags, such as "nonai" to ignore NAI-based routing.
+
+##################
+# RADIUS Clients #
+##################
+
+# Each RADIUS client must be declared in the form: 
+#   nas = IP / shared-secret ;
+# IP can be ipv4 or ipv6
+# port can be additionaly restricted with brackets: IP[port] (ex: 192.168.0.1[1812])
+# shared-secret can be a quoted string, or a list of hexadecimal values.
+# examples:
+# nas = 192.168.100.1 / "secret key" ; # the shared secret buffer is 0x736563726574206b6579 (length 10 bytes)
+# nas = fe00::1 / 73 65 63 72 65 74 20 6b 65 79; # same shared secret as previously
+# When a packet is received from an IP not declared here, it is discarded.
+
+# If the RADIUS client is a Proxy that forwards messages from different peers, it must be
+# declared instead as follow:
+#   pxy = IP / shared-secret ;
+# Note that it is not recommended to use this gateway implementation with a proxy currently,
+# since the management of duplicate messages might be insufficient.
+
+# The old notation cli = ... is equivalent to nas = ... and kept for backward compatibility.
+
+
+####################
+#  Authentication  #
+#  Authorization   #
+####################
+
+# Enable the RADIUS/Diameter authentication/authorization gateway?
+# auth_server_enable = 1;
+
+# The port on which the accounting server listens
+# auth_server_port = 1812;
+
+# The IPv4 on which to bind the server, or "disable" if IPv4 must not be used.
+# auth_server_ip4 = 0.0.0.0;
+
+# The IPv6 address to which the server is bound, or "disable"
+# auth_server_ip6 = :: ;
+
+
+################
+#  Accounting  #
+################
+
+# Enable the RADIUS/Diameter accounting gateway?
+# acct_server_enable = 1;
+
+# The port on which the accounting server listens
+# acct_server_port = 1813;
+
+# The IPv4 on which to bind the server, or "disable" if no IPv4 is wanted.
+# acct_server_ip4 = 0.0.0.0;
+
+# The IPv6 address to which the server is bound, or "disable"
+# acct_server_ip6 = :: ;
diff --git a/doc/app_redirect.conf.sample b/doc/app_redirect.conf.sample
new file mode 100644
index 0000000..72044d6
--- /dev/null
+++ b/doc/app_redirect.conf.sample
@@ -0,0 +1,97 @@
+# This file contains the configuration for the app_redirect extension of freeDiameter.
+#
+# This extension provides configurable Redirect messages.
+
+# Lines starting with a # are comments and ignored.
+# Spaces and newlines are not meaningful, except inside quoted areas.
+
+#########################################################################################
+#        See Diameter RFC for a detailed explanation on Redirects semantics             #
+#########################################################################################
+
+## default_redirect_cache_time
+# Specify the default value for Redirect-Max-Cache-Time.
+# This value can be overwritten for each rule as specified below.
+# If this value is not specified, the default is:
+#default_redirect_cache_time = 86400;  ## => 1 day
+
+# The remaining of this file contains a list of RULE elements.
+# Each RULE consists in three parts:
+#  - a CRITERIA that specifies which messages the RULE applies to.
+#  - a REDIRECT_TYPE that specifies what type of redirect is to be sent, and its duration.
+#  - a TARGET_HOSTS list that specifies the host(s) to send the message to.
+#
+# The rules are matched in the order they appear in this file. Once a rule has matched, the
+# remaining rules are not processed.
+#
+# The basic format of a rule is:
+#  REDIRECT_TYPE : CRITERIA to TARGET_HOSTS ;
+
+# These are a few examples. The definition of each term follows.
+#
+# 1) REALM_AND_APPLICATION : app=3 "Destination-Realm"="myrealm.net" to "aaas://acct1.myrealm.net" "aaas://acct2.myrealm.net";
+#  will ask all peers sending a Base Accounting message for realm "myrealm.net" to send
+# this message directly to either 'acct1.myrealm.net' or 'acct2.myrealm.net'.
+#
+# 2) ALL_SESSION 3600 : "Origin-AAA-Protocol"=1 "Destination-Realm"="myrealm.net" to "aaas://raddiam.myrealm.net";
+#  Will ask any peer sending messages translated from RADIUS and targeted to this realm
+# to address all the messages from the same session to 'raddiam.myrealm.net'. The
+# redirect entry should be stored for 1 hour.
+#
+# 3) ALL_HOST : from.realm=[".*\.(fr|de|es)"] to "aaas://relay-EU.myrealm.net";
+#    ALL_HOST : from.realm=[".*\.(cn|jp|vn)"] to "aaas://relay-ASIA.myrealm.net";
+#  Redirect messages to different relays depending on where they come from.
+#
+# 4) ALL_HOST : to "aaas://newserv.myrealm.net";
+#  This server was relocated, tell all peers to go directly to the new one.
+#  This rule should appear last because it matches all messages, so further rules will never be used.
+
+
+# 
+# REDIRECT_TYPE
+#
+
+# The redirect_type is one of the following (see Redirect-Host-Usage AVP definition in RFC for semantics):
+# DONT_CACHE
+# ALL_SESSION
+# ALL_REALM
+# REALM_AND_APPLICATION
+# ALL_APPLICATION
+# ALL_HOST
+# ALL_USER
+
+# In addition, an integer can follow. If specified, it overwrites the default_redirect_cache_time
+# value for this rule. The value is always specified in seconds.
+
+# 
+# CRITERIA
+#
+
+# Each RULE can contain 0 or more criteria.
+# If no criteria is specified, all messages are assumed to match (wildcard).
+# If more than one criteria is specified, an "AND" relationship is assumed.
+# If you need to specify "OR", just create separate rules.
+#
+# In the following definitions, "STR/REG" stands for:
+#   - a quoted string "some.peer" that will match exactly this string (case-insensitive), or
+#   - a bracket-quoted string ["some regex"] that will be interpreted as a POSIX extended regular expression (case-sensitive), and attempt to match the string.
+#
+# A criteria is one of the following:
+#    from.id="STR/REG"		-> matches messages received from peer with this Diameter Identity.
+#    from.realm="STR/REG"	-> matches messages received from peer with this Realm.
+#    app=U32_VALUE		-> matches messages with this Diameter Application-Id value in its header.
+#    "AVP-name"=U32_VALUE	-> matches messages that contain an avp "AVP-name" (replace with the realm name) with this value.
+#    "AVP-name"="STR/REG"	-> matches messages that contain an avp "AVP-name" (replace with the realm name) with this .
+
+# 
+# TARGET_HOSTS
+#
+
+# This is a simple list of DiameterURI that must be sent back.
+# See the RFC for valid format of Diameter URI:
+#  "aaa://" FQDN [ port ] [ transport ] [ protocol ]
+# "aaas://" FQDN [ port ] [ transport ] [ protocol ]
+
+######################################################################################
+
+
diff --git a/doc/app_sip.conf.sample b/doc/app_sip.conf.sample
new file mode 100644
index 0000000..3bb47fe
--- /dev/null
+++ b/doc/app_sip.conf.sample
@@ -0,0 +1,28 @@
+
+# MODE Diameter-SIP server (DSSERVER) or Subscriber Locator (SL)
+#You must have at least in your network a Diameter SIP server and a Subscriber Locator (on different nodes)
+mode = DSSERVER;
+
+
+# Administrator commands port (port should be provided with "-p" in remote line)
+ppr_port=90;
+rtr_port=91;
+
+
+#******************#
+#*****DATABASE*****#
+#******************#
+# DATASOURCE: MYSQL
+datasource = MYSQL;
+
+#MYSQL connection details
+mysql_login = "login";
+mysql_password = "password";
+mysql_database = "db";
+mysql_server = "server.fr";
+
+#If value=0, default port for mysql will be set
+mysql_port = 0;
+
+#Prefix for tables (default is "ds")
+mysql_prefix = "ds";
diff --git a/doc/app_sip.sql b/doc/app_sip.sql
new file mode 100644
index 0000000..bfd5279
--- /dev/null
+++ b/doc/app_sip.sql
@@ -0,0 +1,117 @@
+--Can be used in phpMyAdmin
+
+SET SQL_MODE="NO_AUTO_VALUE_ON_ZERO";
+
+--
+-- DIAMETER SERVER DATABASE
+--
+
+-- --------------------------------------------------------
+
+--
+-- Table structure for table `ds_data_types`
+--
+
+CREATE TABLE IF NOT EXISTS `ds_data_types` (
+  `id_data_type` int(11) NOT NULL AUTO_INCREMENT,
+  `label_type` varchar(255) NOT NULL,
+  PRIMARY KEY (`id_data_type`)
+) ENGINE=MyISAM  DEFAULT CHARSET=latin1 AUTO_INCREMENT=2 ;
+
+-- --------------------------------------------------------
+
+--
+-- Table structure for table `ds_networks`
+--
+
+CREATE TABLE IF NOT EXISTS `ds_networks` (
+  `id_network` int(11) NOT NULL AUTO_INCREMENT,
+  `label_network` varchar(255) NOT NULL,
+  PRIMARY KEY (`id_network`)
+) ENGINE=MyISAM  DEFAULT CHARSET=latin1 AUTO_INCREMENT=3 ;
+
+-- --------------------------------------------------------
+
+--
+-- Table structure for table `ds_sip_aor`
+--
+
+CREATE TABLE IF NOT EXISTS `ds_sip_aor` (
+  `id_sip_aor` int(11) NOT NULL AUTO_INCREMENT,
+  `id_user` int(11) NOT NULL,
+  `sip_aor` varchar(255) NOT NULL,
+  `sip_server_uri` varchar(255) DEFAULT NULL,
+  `registered` tinyint(1) NOT NULL DEFAULT '0',
+  PRIMARY KEY (`id_sip_aor`,`id_user`)
+) ENGINE=InnoDB  DEFAULT CHARSET=latin1 AUTO_INCREMENT=4 ;
+
+-- --------------------------------------------------------
+
+--
+-- Table structure for table `ds_sip_services`
+--
+
+CREATE TABLE IF NOT EXISTS `ds_sip_services` (
+  `id_service` int(11) NOT NULL AUTO_INCREMENT,
+  `label_service` varchar(255) NOT NULL,
+  PRIMARY KEY (`id_service`)
+) ENGINE=MyISAM  DEFAULT CHARSET=latin1 AUTO_INCREMENT=2 ;
+
+-- --------------------------------------------------------
+
+--
+-- Table structure for table `ds_users`
+--
+
+CREATE TABLE IF NOT EXISTS `ds_users` (
+  `id_user` int(11) NOT NULL AUTO_INCREMENT,
+  `username` varchar(50) NOT NULL,
+  `password` varchar(50) NOT NULL,
+  `SIP_Server_URI` varchar(255) DEFAULT NULL,
+  `temp_SIP_Server_URI` varchar(255) DEFAULT NULL,
+  `authentication_pending` tinyint(1) NOT NULL DEFAULT '0',
+  `registrated` tinyint(1) NOT NULL DEFAULT '0',
+  PRIMARY KEY (`id_user`)
+) ENGINE=InnoDB  DEFAULT CHARSET=latin1 AUTO_INCREMENT=2 ;
+
+-- --------------------------------------------------------
+
+--
+-- Table structure for table `ds_user_data`
+--
+
+CREATE TABLE IF NOT EXISTS `ds_user_data` (
+  `id_user_data` int(11) NOT NULL AUTO_INCREMENT,
+  `id_sip_aor` int(11) NOT NULL,
+  `id_data_type` int(11) NOT NULL,
+  `data` longblob NOT NULL,
+  PRIMARY KEY (`id_user_data`,`id_sip_aor`,`id_data_type`)
+) ENGINE=MyISAM  DEFAULT CHARSET=latin1 AUTO_INCREMENT=3 ;
+
+-- --------------------------------------------------------
+
+--
+-- Table structure for table `ds_user_networks`
+--
+
+CREATE TABLE IF NOT EXISTS `ds_user_networks` (
+  `id_user_network` int(11) NOT NULL AUTO_INCREMENT,
+  `id_user` int(11) NOT NULL,
+  `id_network` int(11) NOT NULL,
+  PRIMARY KEY (`id_user_network`,`id_user`)
+) ENGINE=MyISAM  DEFAULT CHARSET=latin1 AUTO_INCREMENT=3 ;
+
+-- --------------------------------------------------------
+
+--
+-- Table structure for table `ds_user_services`
+--
+
+CREATE TABLE IF NOT EXISTS `ds_user_services` (
+  `id_user_service` int(11) NOT NULL AUTO_INCREMENT,
+  `id_user` int(11) NOT NULL,
+  `id_service` int(11) NOT NULL,
+  `compulsory` tinyint(1) NOT NULL DEFAULT '0',
+  PRIMARY KEY (`id_user_service`,`id_user`)
+) ENGINE=MyISAM  DEFAULT CHARSET=latin1 AUTO_INCREMENT=6 ;
+
diff --git a/doc/app_sip_SL.sql b/doc/app_sip_SL.sql
new file mode 100644
index 0000000..7435ba3
--- /dev/null
+++ b/doc/app_sip_SL.sql
@@ -0,0 +1,21 @@
+
+
+SET SQL_MODE="NO_AUTO_VALUE_ON_ZERO";
+
+--
+-- SUBSCRIBER LOCATOR DATABASE
+--
+
+-- --------------------------------------------------------
+
+--
+-- Table structure for table `ds_sip_aor_map`
+--
+
+CREATE TABLE IF NOT EXISTS `ds_sip_aor_map` (
+  `id_map` int(11) NOT NULL AUTO_INCREMENT,
+  `sip_aor` varchar(255) NOT NULL,
+  `diameter_uri` varchar(255) NOT NULL,
+  PRIMARY KEY (`id_map`)
+) ENGINE=MyISAM  DEFAULT CHARSET=latin1 AUTO_INCREMENT=2 ;
+
diff --git a/doc/dbg_interactive.py.sample b/doc/dbg_interactive.py.sample
new file mode 100644
index 0000000..8f1ffe8
--- /dev/null
+++ b/doc/dbg_interactive.py.sample
@@ -0,0 +1,783 @@
+# Example file for the dbg_interactive.fdx extension.
+#
+# This extension provides an interactive python interpreter console that allows
+# interacting with freeDiameter framework.
+#
+# The adaptation layer between Python and C is provided by SWIG (http://swig.org). 
+# You may refer to SWIG documentation for more information on how the wrapper is generated and used.
+# The name of the module wrapping freeDiameter framework is: _fDpy
+#
+# Similar to all freeDiameter extensions, an optional filename can be specified in the
+# main freeDiameter.conf configuration file for the dbg_interactive.fdx extension.
+# If such file is provided, it will be passed to the python interpreter as a python script
+# to execute. Otherwise, the interpreter will be interactive.
+#
+# SWIG deals with structures as follow:
+# Given the structure:
+# struct foo { int a; }
+# The following functions are available to python (their C equivalent processing is given in [ ]):
+# s = new_foo()	   [ s = calloc(1, sizeof(struct foo)) ]
+# foo_a_set(s, 2)  [ s->a = 2 ]
+# foo_a_get(s)     [ returns s->a value ]
+# delete_foo(s)    [ free(s)  ]
+#
+# In addition, thanks to the proxy (aka shadow) class, we can also do the more user-friendly:
+# s = foo()
+# s.a = 2
+# s.a
+# del s
+#
+
+# The remaining of this file gives some examples of how to use the python interpreter.
+# Note that at the moment not 100% of the framework is usable. 
+# You may have to extend some classes or write some typemaps in the source code 
+# of the extension to do what you want.
+
+
+############# Compilation-time constants (from freeDiameter-host.h) ############
+
+# Display current version
+print "%s %d.%d.%d" % (FD_PROJECT_NAME, FD_PROJECT_VERSION_MAJOR, FD_PROJECT_VERSION_MINOR, FD_PROJECT_VERSION_REV)
+
+
+############# Debug ############
+
+# Change the global debug level of the framework (cvar contains all global variables)
+cvar.fd_g_debug_lvl = 1
+
+
+# Turn on debug for a specific function (if framework compiled with DEBUG support)
+cvar.fd_debug_one_function = "gc_th_fct"
+
+
+# Print messages to freeDiameter's debug facility
+# Note: the python version does not support printf-like argument list. The formating should be done in python.
+#       See SWIG documentation about varargs functions for more information.
+fd_log(FD_LOG_NOTICE, "3 + 4 = %d" % (7))
+
+
+# Display some framework state information
+conf = fd_conf_dump();
+print conf;
+
+fd_peer_dump_list(0)
+fd_servers_dump(0)
+fd_ext_dump(0)
+
+
+############# Global variables ############
+
+# Display the local Diameter Identity:
+print "Local Diameter Identity:", cvar.fd_g_config.cnf_diamid
+
+# Display realm, using the low-level functions (skip proxy classe definitions):
+print "Realm:", _fDpy.fd_config_cnf_diamrlm_get(_fDpy.cvar.fd_g_config)
+
+
+
+############# Lists ############
+
+# Note: we use different names from the C API here, for usability.
+l1 = fd_list()   # Will be our sentinel
+l2 = fd_list()
+l3 = fd_list()
+l1.isempty()
+l1.insert_next(l2)   # l1 -> l2
+l1.isempty()
+l1.insert_prev(l3)   # l1 -> l2 -> l3 (circular list)
+l1.dump()
+l3.detach()          # l1 -> l2
+l4=fd_list()
+l5=fd_list()
+l3.insert_next(l4)   #   l3 -> l4
+l3.insert_next(l5)   #   l3 -> l5 -> l4
+l1.concat(l3)        # l1 -> l2 -> l5 -> l4
+
+elements = l1.enum_as()  # default: enumerates as fd_list. Warning: this a copy, changing the python list has no effect on the underlying fd_list.
+for li in elements:
+  li.dump()
+
+del elements
+del l2
+del l3
+del l4
+del l5
+l1.isempty() # The destructor has an implicit fd_list_unlink call
+del l1
+
+
+############# Hash ############
+
+hex(fd_os_hash("hello world"))	# It accepts binary data
+
+
+############# Dictionary ############
+
+##### Create a dedicated dictionary for our tests
+d = dictionary()
+d.dump()
+
+# New vendor
+v = dict_vendor_data()
+v.vendor_id = 123
+v.vendor_name = "My test vendor"
+my_vendor = d.new_obj(DICT_VENDOR, v)
+del v
+d.dump()
+d.vendors_list()
+
+# Compact invocation also possible:
+v2 = dict_vendor_data(124, "My test vendor 2")
+del v2
+
+# New application
+a = dict_application_data()
+a.application_id = 99
+a.application_name = "My test appl"
+my_appl = d.new_obj(DICT_APPLICATION, a, my_vendor)
+del a
+
+a2 = dict_application_data(99, "My test appl 2")
+del a2
+
+# New type (callbacks are not supported yet...)
+t = dict_type_data()
+t.type_base = AVP_TYPE_INTEGER32
+t.type_name = "My integer AVP"
+my_type_int = d.new_obj(DICT_TYPE, t, my_appl)
+t.type_base = AVP_TYPE_OCTETSTRING
+t.type_name = "My binary buffer AVP"
+my_type_os = d.new_obj(DICT_TYPE, t, my_appl)
+del t
+
+t2 = dict_type_data(AVP_TYPE_UNSIGNED32, "u32 type")
+del t2
+
+# Constants
+c = dict_enumval_data()
+c.enum_name = "AVP_VALUE_TROIS"
+c.enum_value.i32 = 3
+d.new_obj(DICT_ENUMVAL, c, my_type_int)
+
+c.enum_name = "A_BUFFER_CONSTANT"
+c.enum_value.os = "This is a very long AVP value that we prefer to represent as a constant"
+c.enum_value.os.dump()
+d.new_obj(DICT_ENUMVAL, c, my_type_os)
+del c
+
+c2 = dict_enumval_data("enum 23", 23)  # The constructor only accepts unsigned32, for other values, set them afterwards
+c3 = dict_enumval_data("enum other")
+c3.os = "other value"
+del c2
+del c3
+
+# AVP
+a = dict_avp_data()
+a.avp_code = 234
+a.avp_name = "my integer avp"
+a.avp_flag_mask = AVP_FLAG_MANDATORY
+a.avp_basetype = AVP_TYPE_INTEGER32
+my_avp_int = d.new_obj(DICT_AVP, a, my_type_int)
+
+a.avp_vendor = 123
+a.avp_name = "my OS avp"
+a.avp_flag_mask = AVP_FLAG_MANDATORY + AVP_FLAG_VENDOR
+a.avp_flag_val = AVP_FLAG_VENDOR
+a.avp_basetype = AVP_TYPE_OCTETSTRING
+my_avp_os = d.new_obj(DICT_AVP, a, my_type_os)
+del a
+
+a2 = dict_avp_data(235, "no vendor, not mandatory", AVP_TYPE_OCTETSTRING)
+a3 = dict_avp_data(236, "vendor 12, not mandatory", AVP_TYPE_OCTETSTRING, 12)
+a4 = dict_avp_data(237, "vendor 12, mandatory", AVP_TYPE_OCTETSTRING, 12, 1)
+a5 = dict_avp_data(238, "no vendor, mandatory", AVP_TYPE_OCTETSTRING, 0, 1)
+del a2
+del a3
+del a4
+del a5
+
+
+# Command
+c = dict_cmd_data()
+c.cmd_code = 345
+c.cmd_name = "My-Python-Request"
+c.cmd_flag_mask = CMD_FLAG_REQUEST + CMD_FLAG_PROXIABLE
+c.cmd_flag_val = CMD_FLAG_REQUEST + CMD_FLAG_PROXIABLE
+my_req = d.new_obj(DICT_COMMAND, c, my_appl)
+c.cmd_name = "My-Python-Answer"
+c.cmd_flag_val = CMD_FLAG_PROXIABLE
+my_ans = d.new_obj(DICT_COMMAND, c, my_appl)
+del c
+
+c2 = dict_cmd_data(346, "Second-Request", 1) # Default created with PROXIABLE flag.
+c3 = dict_cmd_data(346, "Second-Answer",  0) 
+del c2
+del c3
+
+# Rule
+r = dict_rule_data()
+r.rule_avp = my_avp_int
+r.rule_position = RULE_REQUIRED
+r.rule_min = -1
+r.rule_max = -1
+d.new_obj(DICT_RULE, r, my_req)
+d.new_obj(DICT_RULE, r, my_ans)
+r.rule_avp = my_avp_os
+d.new_obj(DICT_RULE, r, my_req)
+d.new_obj(DICT_RULE, r, my_ans)
+del r
+
+r2 = dict_rule_data(my_avp_int, RULE_REQUIRED) # min & max are optional parameters, default to -1
+r3 = dict_rule_data(my_avp_int, RULE_REQUIRED, 2, 3) # min is 2, max is 3
+r4 = dict_rule_data(my_avp_int, RULE_FIXED_HEAD) # The r4.rule_order = 1 by default, change afterwards if needed.
+del r2
+del r3
+del r4
+
+d.dump()
+del d
+
+####### Now play with the "real" dictionary
+
+gdict = cvar.fd_g_config.cnf_dict
+
+appl = gdict.search ( DICT_APPLICATION, APPLICATION_BY_ID, 3 )
+appl.dump()
+avp = gdict.search ( DICT_AVP, AVP_BY_NAME, "Origin-Host")
+avp.dump()
+errcmd = gdict.error_cmd()
+
+v = avp.getval()
+print v.avp_code
+del v
+
+t = avp.gettype()
+print t
+del t
+
+dict = avp.getdict()
+del dict
+
+
+############# Sessions ############
+
+# handler
+def my_cleanup(state,sid):
+    print "Cleaning up python state for session:", sid
+    print "Received state:", state
+    del state
+
+hdl = session_handler(my_cleanup)
+hdl.dump()
+del hdl
+
+# Session
+hdl = session_handler(my_cleanup)
+s1 = session()
+s1.getsid()
+s2 = session("this.is.a.full.session.id")
+r,s3,isnew = fd_sess_fromsid("this.is.a.full.session.id")  # use this call if "isnew" is really needed...
+s4 = session("host.id", "optional.part")
+s4.settimeout(30) # the python wrapper takes a number of seconds as parameter for simplicity
+s4.dump()
+
+# states
+mystate = [ 34, "blah", [ 32, 12 ] ]
+s1.store(hdl, mystate)
+del mystate
+gotstate = s1.retrieve(hdl)
+print gotstate
+del gotstate
+
+
+############# Routing ############
+
+rd = rt_data()
+
+rd.add("p1.testbed.aaa", "testbed.aaa")
+rd.add("p2.testbed.aaa", "testbed.aaa")
+rd.add("p3.testbed.aaa", "testbed.aaa")
+rd.add("p4.testbed.aaa", "testbed.aaa")
+
+rd.remove("p2.testbed.aaa")
+
+rd.error("p3.testbed.aaa", "relay.testbed.aaa", 3002)
+
+list = rd.extract(-1)
+for c in list.enum_as("struct rtd_candidate *"):
+  print "%s (%s): %s" % (c.diamid, c.realm, c.score)
+
+del rd
+
+
+# A rt_fwd callback has the following prototype:
+def my_rtfwd_cb(msg):
+    print "Forwarding the following message:"
+    msg.dump()
+    return [ 0, msg ]  # return None instead of msg to stop forwarding.
+
+fwdhdl = fd_rt_fwd_hdl( my_rtfwd_cb, RT_FWD_REQ )
+
+
+# A rt_out cb has the following prototype:
+def my_rtout_cb(msg, list):
+    print "Sending out the following message:"
+    msg.dump()
+    print "The possible candidates are:"
+    for c in list.enum_as("struct rtd_candidate *"):
+       print "%s (%s): %s" % (c.diamid, c.realm, c.score)
+    return 0   # returns an error code (standard errno values)
+
+outhdl = fd_rt_out_hdl( my_rtout_cb )  # a priority can be specified as 2nd parameter, default is 0.
+
+
+
+
+
+############# Messages, AVPs ############
+
+## AVP
+
+# Create empty
+blank_avp = avp()
+del blank_avp
+
+# Create from dictionary definitions
+oh = avp(cvar.fd_g_config.cnf_dict.search ( DICT_AVP, AVP_BY_NAME, "Origin-Host"))	                # Octet String
+vi = avp(cvar.fd_g_config.cnf_dict.search ( DICT_AVP, AVP_BY_NAME, "Vendor-Id"))                        # U32
+vsai = avp(cvar.fd_g_config.cnf_dict.search ( DICT_AVP, AVP_BY_NAME, "Vendor-Specific-Application-Id")) # Grouped
+
+# Set values
+val = avp_value()
+val.u32 = 123
+vi.setval(None)  # this cleans a previous value (usually not needed)
+vi.setval(val)
+val.os = "my.origin.host"
+oh.setval(val)
+vsai.add_child(vi) # call as add_child(vi, 1) to add the new AVP at the beginning, default is at the end
+
+# It is possible to initialize the AVP with a blank value as follow:
+blank_with_value = avp(None, AVPFL_SET_BLANK_VALUE)
+# it enables this without doing the setval call:
+blank_with_value.header().avp_value.u32 = 12
+
+
+## Messages
+
+# Create empt (as for avps, pass None or a dictionary object as 1st param, and flags as optional 2nd param)y
+a_msg = msg()
+a_msg.dump()
+del a_msg
+
+# It is also possible to pass MSGFL_* flags in second parameter (ALLOC_ETEID is default)
+msg_no_eid = msg(None, 0)
+msg_no_eid.dump()
+del msg_no_eid
+
+# Create from dictionary
+dwr_dict = cvar.fd_g_config.cnf_dict.search ( DICT_COMMAND, CMD_BY_NAME, "Device-Watchdog-Request" )
+dwr = msg(dwr_dict)
+dwr.dump()
+
+# Create msg from a binary buffer (then you should call parse_dict and parse_rules methods)
+dwr2 = msg("\x01\x00\x00\x14\x80\x00\x01\x18\x00\x00\x00\x00\x00\x00\x00\x00\x1b\xf0\x00\x01")
+
+# Create answer from request (optional parameters: dictionary to use, and flags):
+dwr3 = msg(cvar.fd_g_config.cnf_dict.search ( DICT_COMMAND, CMD_BY_NAME, "Device-Watchdog-Request" ))
+dwa3 = dwr3.create_answer()
+dwr3cpy = dwa3.get_query()
+
+
+## Other functions with AVPs & messages
+
+# Add the AVPs in the message
+dwr.add_child(oh)
+oh.add_next(vsai)   # equivalent to add_child on the parent
+
+# Create a network byte buffer from the message
+dwr.bufferize()
+
+# Get first child AVP (fast)
+avp = dwr.first_child()
+
+# then:
+avp = avp.get_next() # when last AVP, returns None
+
+
+# Get all 1st level children (slower) -- warning, changes to the python list will not be reflected on the underlying message. read-only use.
+dwr.children()
+# example use:
+for a in dwr.children():
+  a.dump(0)  # 0 means: dump only this object, do not walk the tree
+
+
+# Search the first AVP of a given type
+oh_dict = cvar.fd_g_config.cnf_dict.search( DICT_AVP, AVP_BY_NAME, "Origin-Host")
+oh = dwr.search( oh_dict )
+
+# After adding AVPs, the length in the message header is outdated, refresh as follow:
+dwr.update_length()
+
+# Get dictionary model for a message or avp
+dwr.model()
+oh.model().dump()
+
+# Retrieve the header of messages & avp:
+dwr_hdr = dwr.header()
+dwr_hdr.msg_version
+dwr_hdr.msg_hbhid
+
+oh_hdr = oh.header()
+hex(oh_hdr.avp_flags)
+oh_hdr.avp_vendor
+oh_hdr.avp_value.os.as_str() 
+
+
+# Get or set the routing data
+rd = rt_data()
+dwr.set_rtd(rd)
+rd = dwr.get_rtd()
+
+# Test if message is routable
+dwr.is_routable()
+
+# Which peer the message was received from (when received from network)
+dwr.source()
+
+# The session corresponding to this message (returns None when no Session-Id AVP is included)
+dwr.get_session()
+
+
+# Parse a buffer
+buf = "\x01\x00\x00@\x80\x00\x01\x18\x00\x00\x00\x00\x00\x00\x00\x00N\x10\x00\x00\x00\x00\x01\x08@\x00\x00\x16my.origin.host\x00\x00\x00\x00\x01\x04@\x00\x00\x14\x00\x00\x01\n@\x00\x00\x0c\x00\x00\x00{"
+mydwr = msg(buf)
+# Resolve objects in the dictionary. Return value is None or a struct pei_error in case of problem.
+mydwr.parse_dict()  # if not using the fD global dict, pass it as parameter
+err = mydwr.parse_rules()
+err.pei_errcode
+
+
+# Grouped AVPs are browsed with same methods as messages:
+gavp = dwr.children()[1]
+gavp.first_child().dump()
+gavp.children()
+
+
+# Send a message:
+mydwr = msg(buf)
+mydwr.send()
+
+# Optionally, a callback can be registered when a request is sent, with an optional object.
+# This callback takes the answer message as parameter and should return None or a message. (cf. fd_msg_send)
+def send_callback(msg, obj):
+    print "Received answer:"
+    msg.dump()
+    print "Associated data:"
+    obj
+    return None
+
+mydwr = msg(buf)
+mydwr.send(send_callback, some_object)
+
+# Again optionally, a time limit can be specified in this case as follow:
+mydwr.send(send_callback, some_object, 10)
+# In that case, if no answer / error is received after 10 seconds (the value specified), 
+# the callback is called with the request as parameter.
+# Testing for timeout case is done by using msg.is_request()
+def send_callback(msg, obj):
+    if (msg.is_request()):
+        print "Request timed out without answer:"
+    else:
+        print "Received answer:"
+    msg.dump()
+    print "Associated data:"
+    obj
+    return None
+
+
+# Set a result code in an answer message.
+mydwr = msg(buf)
+dwa = mydwr.create_answer()
+dwa.rescode_set()   # This adds the DIAMETER_SUCCESS result code
+dwa.rescode_set("DIAMETER_LIMITED_SUCCESS" )   # This adds a different result code
+dwa.rescode_set("DIAMETER_LIMITED_SUCCESS", "Something went not so well" )   # This adds a different result code + specified Error-Message
+dwa.rescode_set("DIAMETER_INVALID_AVP", None, faulty_avp )   # This adds a Failed-AVP
+dwa.rescode_set("DIAMETER_SUCCESS", None, None, 1 )   # This adds origin information (see fd_msg_rescode_set's type_id for more info)
+
+# Set the origin to local host
+mydwr.add_origin()  # adds Origin-Host & Origin-Realm
+mydwr.add_origin(1) # adds Origin-State-Id in addition.
+
+
+############# DISPATCH (aka. server application) ############
+
+# As for sessions, only one dispatch handler can be registered in this extension at the moment.
+# The callback for the handler has the following syntax:
+def dispatch_cb_model(inmsg, inavp, insession):
+   print "Callback trigged on message: "
+   inmsg.dump()
+   # inavp is None or the AVP that trigged the callback, depending on how it was registered.
+   if inavp:
+     print "From the following AVP:"
+     inavp.dump()
+   else:
+     print "No AVP"
+   # Session is provided only if a Session-Id is in the message
+   if insession:
+     print "The session is: ", insession.getsid()
+   else:
+     print "No session"
+   # Now, for the return value.
+   # This callback must return 3 elements:
+   # - an integer which is interpreted as an error code (errno.h)
+   # - a message or None, depending on the next item
+   # - an enum disp_action value, with the same meaning as in C (see libfreeDiameter.h)
+   del inmsg
+   return [ 0, None, DISP_ACT_CONT ]
+
+
+### Example use: rebuild the server-side of test_app.fdx in python
+
+# The following block defines the dictionary objects from the test_app.fdx application that we use on the remote peer
+gdict = cvar.fd_g_config.cnf_dict
+d_si = gdict.search ( DICT_AVP, AVP_BY_NAME, "Session-Id" )
+d_oh  = gdict.search ( DICT_AVP, AVP_BY_NAME, "Origin-Host" )
+d_or  = gdict.search ( DICT_AVP, AVP_BY_NAME, "Origin-Realm" )
+d_dh  = gdict.search ( DICT_AVP, AVP_BY_NAME, "Destination-Host" )
+d_dr  = gdict.search ( DICT_AVP, AVP_BY_NAME, "Destination-Realm" )
+d_rc  = gdict.search ( DICT_AVP, AVP_BY_NAME, "Result-Code" )
+d_vnd = gdict.new_obj(DICT_VENDOR, 	dict_vendor_data(999999, 	"app_test_py vendor") )
+d_app = gdict.new_obj(DICT_APPLICATION, dict_application_data(0xffffff, "app_test_py appli"), d_vnd)
+d_req = gdict.new_obj(DICT_COMMAND, 	dict_cmd_data(0xfffffe, "Test_py-Request", 1), d_app)
+d_ans = gdict.new_obj(DICT_COMMAND, 	dict_cmd_data(0xfffffe, "Test_py-Answer",  0), d_app)
+d_avp = gdict.new_obj(DICT_AVP, 	dict_avp_data(0xffffff, "app_test_py avp", AVP_TYPE_INTEGER32, 999999 ))
+gdict.new_obj(DICT_RULE, dict_rule_data(d_si, RULE_FIXED_HEAD, 1, 1), d_req)
+gdict.new_obj(DICT_RULE, dict_rule_data(d_si, RULE_FIXED_HEAD, 1, 1), d_ans)
+gdict.new_obj(DICT_RULE, dict_rule_data(d_avp, RULE_REQUIRED, 1, 1), d_req)
+gdict.new_obj(DICT_RULE, dict_rule_data(d_avp, RULE_REQUIRED, 1, 1), d_ans)
+gdict.new_obj(DICT_RULE, dict_rule_data(d_oh, RULE_REQUIRED, 1, 1), d_req)
+gdict.new_obj(DICT_RULE, dict_rule_data(d_oh, RULE_REQUIRED, 1, 1), d_ans)
+gdict.new_obj(DICT_RULE, dict_rule_data(d_or, RULE_REQUIRED, 1, 1), d_req)
+gdict.new_obj(DICT_RULE, dict_rule_data(d_or, RULE_REQUIRED, 1, 1), d_ans)
+gdict.new_obj(DICT_RULE, dict_rule_data(d_dr, RULE_REQUIRED, 1, 1), d_req)
+gdict.new_obj(DICT_RULE, dict_rule_data(d_dh, RULE_OPTIONAL, 0, 1), d_req)
+gdict.new_obj(DICT_RULE, dict_rule_data(d_rc, RULE_REQUIRED, 1, 1), d_ans)
+
+# Now, create the Test_app server callback:
+def test_app_cb(inmsg, inavp, insession):
+   tval = inmsg.search(d_avp).header().avp_value.u32
+   print "Py ECHO Test message from '%s' with test value %x, replying..." % (inmsg.search(d_oh).header().avp_value.os.as_str(), tval)
+   answ = inmsg.create_answer()
+   answ.rescode_set()
+   answ.add_origin()
+   ta = avp(d_avp, AVPFL_SET_BLANK_VALUE)
+   ta.header().avp_value.u32 = tval
+   answ.add_child(ta)
+   return [ 0, answ, DISP_ACT_SEND ]
+
+# Register the callback for dispatch thread:
+hdl = disp_hdl(test_app_cb, DISP_HOW_CC, disp_when(d_app, d_req))  # disp_when() takes 0 to 4 arguments as follow: (app=NULL, cmd=NULL, avp=NULL, val=NULL)
+
+# Don't forget to register the application in the daemon for CER/CEA capabilities.
+fd_disp_app_support ( d_app, d_vnd, 1, 0 )
+
+
+###  For the fun, the client part of the test_app:
+
+def receive_answer(ans, testval):
+   try:
+     tval = ans.search(d_avp).header().avp_value.u32
+   except:
+     print "Error in receive_answer: no Test-AVP included"
+     tval = 0
+   try:
+     print "Py RECV %x (expected: %x) Status: %d From: '%s'" % (tval, testval, ans.search(d_rc).header().avp_value.u32, ans.search(d_oh).header().avp_value.os.as_str())
+   except:
+     print "Error in receive_answer: Result-Code or Origin-Host are missing"
+   del ans
+   return None
+
+import random
+
+def send_query(destrealm="localdomain"):
+   qry = msg(d_req)
+   sess = session()
+   tv = random.randint(1, 1<<32)
+   # Session-Id
+   a = avp(d_si, AVPFL_SET_BLANK_VALUE)
+   a.header().avp_value.os = sess.getsid()
+   qry.add_child(a)
+   # Destination-Realm
+   a = avp(d_dr, AVPFL_SET_BLANK_VALUE)
+   a.header().avp_value.os = destrealm
+   qry.add_child(a)
+   # Origin-Host, Origin-Realm
+   qry.add_origin()
+   # Test-AVP
+   a = avp(d_avp, AVPFL_SET_BLANK_VALUE)
+   a.header().avp_value.u32 = tv
+   qry.add_child(a)
+   print "Py SEND %x to '%s'" % (tv, destrealm)
+   qry.send(receive_answer, tv)
+
+send_query()
+
+
+############# FIFO queues ############
+
+myqueue = fifo()
+
+# enqueue any object
+myqueue.post(3)
+myqueue.post("blah")
+myqueue.post( [ 3, 2 ] )
+
+# Simple get (blocks when the queue is empty)
+myqueue.get()
+
+# Try get: returns the next object, or None if the queue is empty
+myqueue.tryget()
+
+# timed get: like get, but returns None after x seconds
+myqueue.timedget(3)
+
+# Show the number of items in the queue
+myqueue.length()
+
+
+## Variants:
+# All the previous calls are suitable to queue Python objects.
+# In order to interact with objects queued / poped by C counterpart,
+# a second parameter must be passed to specify the object type,
+# as follow:
+ev = fd_event()
+ev.code = FDEV_DUMP_EXT
+cvar.fd_g_config.cnf_main_ev.post(ev, "struct fd_event *")
+
+# Similarly, for *get, we can specify the structure that was queued:
+myqueue.get("struct fd_event *")
+myqueue.tryget("struct fd_event *")
+myqueue.timedget(3, "struct fd_event *")
+
+del myqueue
+
+
+############# HOOKS ############
+
+def my_hook_cb(type, msg, peer, other, oldpmd):
+    print "callback type ", type, " called: ", msg, other, oldpmd
+    return "this is the new pmd"
+
+# Create a wrapped fd_hook_data_hdl:
+datahdl = fd_hook_data_hdl()
+
+# Register the hook callback:
+hdl = fd_hook_hdl(1 << HOOK_MESSAGE_SENT, my_hook_cb, datahdl)
+
+
+
+
+############# PEERS ############
+
+# Get the list of peers defined in the system 
+# (we are supposed to readlock fd_g_peers_rw before accessing this list)
+cvar.fd_g_peers_rw.rdlock()
+peers = cvar.fd_g_peers.enum_as("struct peer_hdr *")
+cvar.fd_g_peers_rw.unlock()
+for p in peers:
+   print "Peer:", p.info.pi_diamid
+
+
+# Create a new peer
+np = peer_info()
+np.pi_diamid = "nas.localdomain"
+np.config.pic_flags.pro4 = PI_P4_TCP
+
+
+# Add this peer into the framework.
+np.add()
+
+# It is possible to specify a callback for when the connection completes or fails with this peer.
+# The prototype is as follow:
+def add_cb(peer):
+    if peer:
+        if peer.runtime.pir_state == STATE_OPEN:
+	   print "Connection to peer '%s' completed" % (peer.pi_diamid)
+	   # can find more information in peer.runtime.*
+	else:
+	   print "Connection to peer '%s' failed (state:%d)" % (peer.pi_diamid, peer.runtime.pir_state)
+    else:
+        print "The peer has been destroyed before it completed the connection."
+
+# Then add the peer like this:
+np.add(add_cb)
+
+
+# Search a peer by its diameter id (returns a peer_hdr object if found) -- similar to fd_peer_getbyid
+p = peer_search("nas.domain.aaa")
+
+
+## Validation callback (see fd_peer_validate_register documentation)
+
+# cb2 prototype:
+def my_validate_cb2(pinfo):
+    print "Cb2 callback trigged for peer %s" % (pinfo.pi_diamid)
+    # Usually, this would be used only to check some TLS properties, 
+    # which is not really possible yet through the python interpreter...
+    return 0   # return an error code if the peer is not validated
+
+# cb prototype:
+def my_validate_cb(pinfo):
+    print "Validate callback trigged for peer %s" % (pinfo.pi_diamid)
+    # If the peer is not allowed to connect:
+    #return -1
+    # If the peer is authorized:
+    #return 1
+    # In addition, if IPsec is allowed,
+    #pinfo.config.pic_flags.sec = PI_SEC_NONE
+    # If no decision has been made:
+    #return 0
+    # If the peer is temporarily authorized but a second callback must be called after TLS negociation:
+    return my_validate_cb2
+
+# Register the callback, it will be called on new incoming connections.
+peer_validate_register(my_validate_cb)
+
+
+
+############# ENDPOINTS ############
+
+ep = fd_endpoint("129.168.168.192")
+
+# with port:
+ep = fd_endpoint("129.168.168.192", 3868)
+
+# With different flags:
+ep = fd_endpoint("129.168.168.192", 3868, EP_FL_PRIMARY)
+
+# Add IP information for the peer
+np = peer_info()
+ep.add_merge(np.pi_endpoints)
+fd_ep_dump(0, np.pi_endpoints)
+
+
+
+############# POSIX functions wrappers ############
+
+# The interface also provides wrappers around base POSIX 
+# synchronization functions:
+
+m = pthread_mutex_t()
+m.lock()
+m.unlock()
+
+c = pthread_cond_t()
+c.signal()
+c.broadcast()
+c.wait(m)
+c.timedwait(m, 5)  # it takes a relative time
+
+r = pthread_rwlock_t()
+r.rdlock()
+r.unlock()
+r.wrlock()
diff --git a/doc/dict_legacy_xml.conf.sample b/doc/dict_legacy_xml.conf.sample
new file mode 100644
index 0000000..feae257
--- /dev/null
+++ b/doc/dict_legacy_xml.conf.sample
@@ -0,0 +1,15 @@
+# This file documents the configuration format for the dict_legacy_xml.fdx freeDiameter extension.
+# In order to load this extension, please refer to main freeDiameter.conf manual.
+
+# This extension allows the use of Diameter dictionary files in XML format,
+# as roughly specified in draft-frascone-xml-dictionary-00.
+# (the actual format is the one from OpenDiameter latest version)
+# Note that this format, although more widely used, is less efficient than the
+# internal freeDiameter format. It is recommended when possible to use the later.
+
+# You may refer to the contrib/dict_legacy/README file for information on where to find such resources.
+
+# This file simply consists in a list of XML dictionary files that must be parsed.
+# Example:
+#  "/etc/freeDiameter/dictionary.xml";
+
diff --git a/doc/eap_tls_plugin.diameap.conf.sample b/doc/eap_tls_plugin.diameap.conf.sample
new file mode 100644
index 0000000..81698be
--- /dev/null
+++ b/doc/eap_tls_plugin.diameap.conf.sample
@@ -0,0 +1,13 @@
+#### a sample configuration file for EAP-TLS
+
+#Certificate and Private key files
+#Cred = "<Path to certificate>" : "<Path to private Key>";
+
+#CA file
+#CA = "<Path to CA file>";
+
+#CRL file
+#CRL = "<Path to CRL file>";
+
+#Enable/disable checking certificate's CN
+check_cert_cn_username = 1;
diff --git a/doc/echodrop.rgwx.conf.sample b/doc/echodrop.rgwx.conf.sample
new file mode 100644
index 0000000..8d68145
--- /dev/null
+++ b/doc/echodrop.rgwx.conf.sample
@@ -0,0 +1,33 @@
+# Sample configuration file for the echodrop.rgwx plugin of RADIUS/Diameter translation agent.
+#
+# This plugin allows to easily specify the following handling of RADIUS attributes
+# received in a RADIUS request:
+#  - ECHO: the attribute will be copied verbatim in the RADIUS answer.
+#  - DROP: the attribute is discarded.
+#
+# In both cases, the attribute is NOT translated in Diameter message.
+#
+# The format of this file is:
+# <action> CODE <code> [ VENDOR <vid> [ TLV <type> | EXT <ext-type> ] ];
+# Where:
+#    <action>: is either DROP or ECHO.
+#    <code>  : is a (decimal) integer between 0 and 255, and designates the type of the attribute.
+#
+#  The remaining of the line is optional, and should only be used 
+#  with lines containing "CODE 26" (Vendor-Specific Attribute)
+#    <vid> : a Vendor value (32 bit), see RFC2865 section 5.26 for detail.
+#
+#  <type>    : The attribute is interpreted as TLV (rfc3865, section 5.26) 
+#		and we match only this "vendor type" value (8 bits).
+#
+#  <ext-type>: NOTE: THIS OPTION IS NOT SUPPORTED PROPERLY YET!!!!
+#	       The attribute is interpreted as extended attribute (draft-ietf-radext-extended-attributes-08)
+#               and we match only this "Ext-Type" value (16 bits).
+#              This option should only be used with "CODE 26 VENDOR 0".
+#		
+# Note that the Proxy-State (code 33) attribute is handled directly as an ECHO parameter by the gateway core.
+
+# Examples:
+# DROP code 18 ; # Reply-Message attribute, should not be included in requests
+# DROP code 26 vendor 9 ; # Drop any Cisco-specific attribute
+# ECHO code 26 vendor 0 ext 256 ; # Echo any extended attribute with the type 256.
diff --git a/doc/freediameter.conf.sample b/doc/freediameter.conf.sample
new file mode 100644
index 0000000..4b2ba9e
--- /dev/null
+++ b/doc/freediameter.conf.sample
@@ -0,0 +1,252 @@
+# This is a sample configuration file for freeDiameter daemon.
+
+# Most of the options can be omitted, as they default to reasonable values.
+# Only TLS-related options must be configured properly in usual setups.
+
+# It is possible to use "include" keyword to import additional files
+# e.g.: include "/etc/freeDiameter.d/*.conf"
+# This is exactly equivalent as copy & paste the content of the included file(s) 
+# where the "include" keyword is found.
+
+
+##############################################################
+##  Peer identity and realm 
+
+# The Diameter Identity of this daemon.
+# This must be a valid FQDN that resolves to the local host.
+# Default: hostname's FQDN
+#Identity = "aaa.koganei.freediameter.net";
+
+# The Diameter Realm of this daemon.
+# Default: the domain part of Identity (after the first dot).
+#Realm = "koganei.freediameter.net";
+
+##############################################################
+##  Transport protocol configuration
+
+# The port this peer is listening on for incoming connections (TCP and SCTP).
+# Default: 3868. Use 0 to disable.
+#Port = 3868;
+
+# The port this peer is listening on for incoming TLS-protected connections (TCP and SCTP).
+# See TLS_old_method for more information about TLS flavours.
+# Note: we use TLS/SCTP instead of DTLS/SCTP at the moment. This will change in future version of freeDiameter.
+# Default: 5868. Use 0 to disable.
+#SecPort = 5868;
+
+# Use RFC3588 method for TLS protection, where TLS is negociated after CER/CEA exchange is completed 
+# on the unsecure connection. The alternative is RFC6733 mechanism, where TLS protects also the 
+# CER/CEA exchange on a dedicated secure port.
+# This parameter only affects outgoing connections. 
+# The setting can be also defined per-peer (see Peers configuration section).
+# Default: use RFC6733 method with separate port for TLS.
+#TLS_old_method;
+
+# Disable use of TCP protocol (only listen and connect over SCTP)
+# Default : TCP enabled
+#No_TCP;
+
+# Disable use of SCTP protocol (only listen and connect over TCP)
+# Default : SCTP enabled
+#No_SCTP;
+# This option is ignored if freeDiameter is compiled with DISABLE_SCTP option.
+
+# Prefer TCP instead of SCTP for establishing new connections.
+# This setting may be overwritten per peer in peer configuration blocs.
+# Default : SCTP is attempted first.
+#Prefer_TCP;
+
+# Default number of streams per SCTP associations.
+# This setting may be overwritten per peer basis.
+# Default : 30 streams
+#SCTP_streams = 30;
+
+##############################################################
+##  Endpoint configuration
+
+# Disable use of IP addresses (only IPv6)
+# Default : IP enabled
+#No_IP;
+
+# Disable use of IPv6 addresses (only IP)
+# Default : IPv6 enabled
+#No_IPv6;
+
+# Specify local addresses the server must bind to
+# Default : listen on all addresses available.
+#ListenOn = "202.249.37.5";
+#ListenOn = "2001:200:903:2::202:1";
+#ListenOn = "fe80::21c:5ff:fe98:7d62%eth0";
+
+
+##############################################################
+##  Server configuration
+
+# How many Diameter peers are allowed to be connecting at the same time ?
+# This parameter limits the number of incoming connections from the time
+# the connection is accepted until the first CER is received.
+# Default: 5 unidentified clients in paralel.
+#ThreadsPerServer = 5;
+
+##############################################################
+##  TLS Configuration
+
+# TLS is managed by the GNUTLS library in the freeDiameter daemon.
+# You may find more information about parameters and special behaviors
+# in the relevant documentation.
+# http://www.gnu.org/software/gnutls/manual/
+
+# Credentials of the local peer
+# The X509 certificate and private key file to use for the local peer.
+# The files must contain PKCS-1 encoded RSA key, in PEM format.
+# (These parameters are passed to gnutls_certificate_set_x509_key_file function)
+# Default : NO DEFAULT
+#TLS_Cred = "<x509 certif file.PEM>" , "<x509 private key file.PEM>";
+TLS_Cred = "/etc/ssl/certs/freeDiameter.pem", "/etc/ssl/private/freeDiameter.key";
+
+# Certificate authority / trust anchors
+# The file containing the list of trusted Certificate Authorities (PEM list)
+# (This parameter is passed to gnutls_certificate_set_x509_trust_file function)
+# The directive can appear several times to specify several files.
+# Default : GNUTLS default behavior
+#TLS_CA = "<file.PEM>";
+
+# Certificate Revocation List file
+# The information about revoked certificates.
+# The file contains a list of trusted CRLs in PEM format. They should have been verified before. 
+# (This parameter is passed to gnutls_certificate_set_x509_crl_file function)
+# Note: openssl CRL format might have interoperability issue with GNUTLS format.
+# Default : GNUTLS default behavior
+#TLS_CRL = "<file.PEM>";
+
+# GNU TLS Priority string
+# This string allows to configure the behavior of GNUTLS key exchanges 
+# algorithms. See gnutls_priority_init function documentation for information.
+# You should also refer to the Diameter required TLS support here:
+#   http://tools.ietf.org/html/rfc6733#section-13.1
+# Default : "NORMAL"
+# Example: TLS_Prio = "NONE:+VERS-TLS1.1:+AES-128-CBC:+RSA:+SHA1:+COMP-NULL";
+#TLS_Prio = "NORMAL";
+
+# Diffie-Hellman parameters size
+# Set the number of bits for generated DH parameters
+# Valid value should be 768, 1024, 2048, 3072 or 4096.
+# (This parameter is passed to gnutls_dh_params_generate2 function, 
+# it usually should match RSA key size)
+# Default : 1024
+#TLS_DH_Bits = 1024;
+
+# Alternatively, you can specify a file to load the PKCS#3 encoded
+# DH parameters directly from. This accelerates the daemon start 
+# but is slightly less secure. If this file is provided, the
+# TLS_DH_Bits parameters has no effect.
+# Default : no default.
+#TLS_DH_File = "<file.PEM>";
+
+
+##############################################################
+##  Timers configuration
+
+# The Tc timer of this peer.
+# It is the delay before a new attempt is made to reconnect a disconnected peer.
+# The value is expressed in seconds. The recommended value is 30 seconds.
+# Default: 30
+#TcTimer = 30;
+
+# The Tw timer of this peer.
+# It is the delay before a watchdog message is sent, as described in RFC 3539.
+# The value is expressed in seconds. The default value is 30 seconds. Value must
+# be greater or equal to 6 seconds. See details in the RFC.
+# Default: 30
+#TwTimer = 30;
+
+##############################################################
+##  Applications configuration
+
+# Disable the relaying of Diameter messages?
+# For messages not handled locally, the default behavior is to forward the
+# message to another peer if any is available, according to the routing 
+# algorithms. In addition the "0xffffff" application is advertised in CER/CEA 
+# exchanges.
+# Default: Relaying is enabled.
+#NoRelay;
+
+# Number of server threads that can handle incoming messages at the same time.
+# Default: 4
+#AppServThreads = 4;
+
+# Other applications are configured by loaded extensions.
+
+##############################################################
+##  Extensions configuration
+
+#  The freeDiameter framework merely provides support for
+# Diameter Base Protocol. The specific application behaviors,
+# as well as advanced functions, are provided
+# by loadable extensions (plug-ins).
+#  These extensions may in addition receive the name of a 
+# configuration file, the format of which is extension-specific.
+#
+# Format:
+#LoadExtension = "/path/to/extension" [ : "/optional/configuration/file" ] ;
+#
+# Examples:
+#LoadExtension = "extensions/sample.fdx";
+#LoadExtension = "extensions/sample.fdx":"conf/sample.conf";
+
+# Extensions are named as follow:
+# dict_* for extensions that add content to the dictionary definitions.
+# dbg_*  for extensions useful only to retrieve more information on the framework execution.
+# acl_*  : Access control list, to control which peers are allowed to connect.
+# rt_*   : routing extensions that impact how messages are forwarded to other peers.
+# app_*  : applications, these extensions usually register callbacks to handle specific messages.
+# test_* : dummy extensions that are useful only in testing environments.
+
+
+# The dbg_msg_dump.fdx extension allows you to tweak the way freeDiameter displays some
+# information about some events. This extension does not actually use a configuration file
+# but receives directly a parameter in the string passed to the extension. Here are some examples:
+## LoadExtension = "dbg_msg_dumps.fdx" : "0x1111"; # Removes all default hooks, very quiet even in case of errors.
+## LoadExtension = "dbg_msg_dumps.fdx" : "0x2222"; # Display all events with few details.
+## LoadExtension = "dbg_msg_dumps.fdx" : "0x0080"; # Dump complete information about sent and received messages.
+# The four digits respectively control: connections, routing decisions, sent/received messages, errors.
+# The values for each digit are:
+#  0 - default - keep the default behavior
+#  1 - quiet   - remove any specific log
+#  2 - compact - display only a summary of the information
+#  4 - full    - display the complete information on a single long line
+#  8 - tree    - display the complete information in an easier to read format spanning several lines.
+
+
+##############################################################
+##  Peers configuration
+
+#  The local server listens for incoming connections. By default,
+# all unknown connecting peers are rejected. Extensions can override this behavior (e.g., acl_wl).
+# 
+#  In addition to incoming connections, the local peer can
+# be configured to establish and maintain connections to some 
+# Diameter nodes and allow connections from these nodes.
+#  This is achieved with the ConnectPeer directive described below.
+#
+# Note that the configured Diameter Identity MUST match
+# the information received inside CEA, or the connection will be aborted.
+#
+# Format:
+#ConnectPeer = "diameterid" [ { parameter1; parameter2; ...} ] ;
+# Parameters that can be specified in the peer's parameter list:
+#  No_TCP; No_SCTP; No_IP; No_IPv6; Prefer_TCP; TLS_old_method;
+#  No_TLS;       # assume transparent security instead of TLS. DTLS is not supported yet (will change in future versions).
+#  Port = 5868;  # The port to connect to
+#  TcTimer = 30;
+#  TwTimer = 30;
+#  ConnectTo = "202.249.37.5";
+#  ConnectTo = "2001:200:903:2::202:1";
+#  TLS_Prio = "NORMAL";
+#  Realm = "realm.net"; # Reject the peer if it does not advertise this realm.
+# Examples:
+#ConnectPeer = "aaa.wide.ad.jp";
+#ConnectPeer = "old.diameter.serv" { TcTimer = 60; TLS_old_method; No_SCTP; Port=3868; } ;
+
+
+##############################################################
diff --git a/doc/rt_busypeers.conf.sample b/doc/rt_busypeers.conf.sample
new file mode 100644
index 0000000..a25f160
--- /dev/null
+++ b/doc/rt_busypeers.conf.sample
@@ -0,0 +1,47 @@
+# This file contains information for configuring the rt_busypeers extension.
+# To find how to have freeDiameter load this extension, please refer to the freeDiameter documentation.
+#
+# The rt_busypeers extension has two purposes. 
+# - when the local peer receives an error DIAMETER_TOO_BUSY from a peer, 
+#   this extension catchs this error and attempts to retransmit the query to another peer if it makes sense, i.e.:
+#      * the peer issuing the error is not the peer referenced in the Destination-Host AVP of the message,
+#      * we have a direct link with the peer that issued the error (see parameter RetryDistantPeers below)
+#
+# - When a request is forwarded by the local peer, start a timer and if the corresponding answer/error has
+#   not been received within RelayTimeout seconds, either send to another peer or return a DIAMETER_TOO_BUSY
+#   error, depending on the RetryMaxPeers parameter.
+#
+# This extension is mainly useful for Diameter agents, for Diameter clients it is recommended to 
+# implement this logic directly in the client application. 
+
+
+# Parameter: SkipTooBusyErrors
+# If defined, this parameter disables the handling of Diameter Errors message with a Result-Code set to DIAMETER_TOO_BUSY in this extension.
+# When this parameter is defined, the parameter RetryDistantPeer has no effect.
+# Default: parameter is not defined.
+#SkipTooBusyErrors;
+
+
+# Parameter: RetryDistantPeers
+# By default, the extension only retries to send messages if the peer that issued the DIAMETER_TOO_BUSY error is directly connected to
+# the local peer (not through a Diameter agent). This avoids the situation where the message is sent to a different relay that will deliver
+# to the same busy peer afterwards. If the parameter is defined, then the extension will also retry sending messages for errors generated in
+# distant peers. This should increase the chance that the message is delivered, but also can increase the load of the network unnecessarily.
+# Default: parameter is not defined.
+#RetryDistantPeers;
+
+
+# Parameter: RetryMaxPeers
+# This parameter specifies the limit on the number of times a request can be re-sent to a different peer, before the local relay gives up and 
+# forwards the error to upstream.
+# Default: 0, meaning all possible candidates are attempted before give up.
+#RetryMaxPeers=0;
+
+
+# Parameter: RelayTimeout
+# If the value of this parameter is not 0, it specifies the number of milliseconds (1/1000 s) that the local relay waits for an answer to a 
+# forwarded request before considering the remote peer is busy and taking corrective action (similar as if that relay had returned TOO_BUSY status).
+# Note: this parameter does not apply for requests issued locally. In that case, the extension issuing the request should directly specify the timeout.
+# Default: 0, meaning that there is no timeout parameter.
+#RelayTimeout=0;
+
diff --git a/doc/rt_default.conf.sample b/doc/rt_default.conf.sample
new file mode 100644
index 0000000..c211100
--- /dev/null
+++ b/doc/rt_default.conf.sample
@@ -0,0 +1,91 @@
+# This file contains the configuration for the rt_default extension of freeDiameter.
+#
+# This extension provides configurable routing properties for freeDiameter.
+
+# Lines starting with a # are comments and ignored.
+
+##############################################################################
+# The freeDiameter daemon will not allow forwarding a message to a peer that:
+# - already forwarded the message (appear as Route-Record inside the message)
+# - connection is not in STATE_OPEN state.
+# We call here "eligible peer" a peer that is not screened out by one of these criteria.
+#
+# Even if a peer is specified as route for a message here, the daemon may
+# choose to send a message to another peer, or return a UNABLE_TO_DELIVER error, if that peer is not eligible 
+# at the time where the message is to be forwarded.
+#
+# Note also that defining a peer here will not result in the daemon trying to establish
+# a connection to this peer. For this purpose, the peer must be defined in the main
+# configuration (ConnectPeer), or connection established through other means (e.g. dynamic peer
+# discovery extension).
+#
+# The default forwarding behavior of freeDiameter is:
+# - if the message contains a Destination-Host AVP, and the designated peer is an eligible candidate, send to this peer.
+# - if a peer does not support the message application or Relay application, give it a penalty for this message 
+#    (it means that unless overwritten by an extension, the message will not be sent to that peer)
+# - if one of the eligible peer advertised a realm matching the message's Destination-Realm, send to this peer.
+#
+# The mechanism is as follow:
+# - the daemon builds a list of eligible peers, then attributes a score to these peers (see enum fd_rt_out_score in freeDiameter.h)
+# - any number of extensions can register a callback and modify the score
+# - after all callbacks have been called, the message is sent to the peer with the higher score. If an error is received, it is retried to the next peer in the list, and so on,
+#   until the list is empty. In such situation, an error UNABLE_TO_DELIVER is generated.
+#
+# This extension allows to modify the score of some peers based on some criteria of the message.
+#
+# Finally, please note that the freeDiameter daemon does not support REDIRECT indications natively. 
+# You have to load the rt_redir extension to add this support.
+##############################################################################
+
+# This file contains a list of RULE elements.
+# Each RULE is made of three components:
+#  - a CRITERIA, which specifies which messages the RULE apply to.
+#  - a TARGET string, that specifies which peer(s) in the eligible list the rule is applied to
+#  - and a SCORE, that is added to the matching peer's current score.
+#
+# In the following definitions, "STR/REG" stands for:
+#   - a quoted string "some.peer" that will match exactly this string (case-insensitive), or
+#   - a bracket-quoted string ["some regex"] that will be interpreted as a POSIX extended regular expression (case-sensitive), and attempt to match the string.
+#
+# The RULE is specified as:
+#    CRITERIA : TARGET += SCORE ;
+#
+# The CRITERIA can be:
+#    *   		-> matches any message.
+#    oh="STR/REG"	-> selects the message if the string or regular expression matches the message's Origin-Host AVP content
+#    or="STR/REG"   	-> idem with Origin-Realm
+#    dh="STR/REG"   	-> idem with Destination-Host
+#    dr="STR/REG"   	-> idem with Destination-Realm
+#    un="STR/REG"   	-> idem with User-Name
+#    si="STR/REG"   	-> idem with Session-Id
+#
+# The TARGET is also of a similar form:
+#    "STR/REG"		-> Will apply the score to this peer if its Diameter-Id is matched by the string or regular expression.
+#    rlm="STR/REG"	-> Idem with the peer's advertized Diameter-Realm.
+#
+# The SCORE is either numeric (positive or negative), or one of the following constants (see values in libfdcore.h):
+#    NO_DELIVERY
+#    DEFAULT
+#    DEFAULT_REALM
+#    REALM
+#    REDIR_HOST     
+#    REDIR_APP      
+#    REDIR_REALM    
+#    REDIR_REALM_APP
+#    REDIR_USER     
+#    REDIR_SESSION  
+#    FINALDEST
+#
+#
+# Here are some examples:
+#  1) Rule to add a default next-hop peer to all messages:
+#    * : "proxy.testbed.aaa" += DEFAULT ;
+#
+#  2) Rule to route messages for a given realm (realmA) through another realm (realmB):
+#    dr="realmA" : rlm="realmB" += DEFAULT_REALM ;
+#
+#  3) Avoid sending messages with decorated NAI to the proxy A:
+#    un=[".+!.+@.+"] : "proxy.A" += NO_DELIVERY ;
+
+
+
diff --git a/doc/rt_ereg.conf.sample b/doc/rt_ereg.conf.sample
new file mode 100644
index 0000000..fd9d4d9
--- /dev/null
+++ b/doc/rt_ereg.conf.sample
@@ -0,0 +1,21 @@
+# This file contains information for configuring the rt_ereg extension.
+# To find how to have freeDiameter load this extension, please refer to the freeDiameter documentation.
+#
+# The rt_ereg extension allows creation of routing rules based on AVP value matching regular expressions.
+
+# First, one must indicate which AVP should be used for matching. 
+# At the moment, only AVP with OCTETSTRING types are valid.
+#  AVP = "User-Name";
+# This parameter is mandatory. There is no default value.
+
+# Then a list of rules follow. A rule has this format:
+#  "pattern" : "server" += score ;
+# Where:
+#  pattern is the quoted-string regex to match, 
+#  server is the next hop in the routing list that will receive the
+#  score, which can be positive or negative.
+# Example:
+#  "[[:digit:]]*" : "serverA.example.net" += -3 ;
+#    means that if the AVP value is only numeric, the ServerA will have its score decreased by 3 points.
+#    (reminder: the server with the peer with the highest score gets the message)
+# Note that all rules are tested for each message that contain the AVP, not only the first match.
diff --git a/doc/single_host/01.pem b/doc/single_host/01.pem
new file mode 100644
index 0000000..7e351a8
--- /dev/null
+++ b/doc/single_host/01.pem
@@ -0,0 +1,60 @@
+Certificate:
+    Data:
+        Version: 3 (0x2)
+        Serial Number: 1 (0x1)
+    Signature Algorithm: sha1WithRSAEncryption
+        Issuer: CN=ca.localdomain, C=FR, ST=BdR, L=Aix, O=fD, OU=Tests
+        Validity
+            Not Before: Jun  1 19:37:14 2017 GMT
+            Not After : Jun  1 19:37:14 2018 GMT
+        Subject: C=FR, ST=BdR, O=fD, OU=Tests, CN=peer1.localdomain
+        Subject Public Key Info:
+            Public Key Algorithm: rsaEncryption
+                Public-Key: (1024 bit)
+                Modulus:
+                    00:c0:e4:f3:ac:bb:49:bf:43:d3:3e:b6:66:60:0a:
+                    94:ff:e3:a9:07:cf:59:28:8d:f2:9e:bd:96:a9:7d:
+                    10:e4:9f:f5:fb:17:ec:d9:16:d2:0f:8d:82:3e:18:
+                    a9:38:97:f9:e4:ac:e3:72:f9:c3:df:8a:d2:e9:88:
+                    67:c1:70:14:94:02:3b:ba:8c:b8:3e:9d:d1:bf:f3:
+                    e6:a1:91:c2:ee:87:80:3d:b8:99:33:82:2d:bd:1b:
+                    27:9c:f5:b6:64:b4:55:b7:96:31:c0:81:8b:46:c1:
+                    c0:c7:7a:43:39:02:1a:8f:6a:e3:0a:d7:f7:79:07:
+                    ab:35:c5:43:64:23:d0:62:05
+                Exponent: 65537 (0x10001)
+        X509v3 extensions:
+            X509v3 Basic Constraints: 
+                CA:FALSE
+            Netscape Comment: 
+                OpenSSL Generated Certificate
+            X509v3 Subject Key Identifier: 
+                35:F8:4A:C9:A9:56:EA:99:5D:58:41:E7:90:78:83:23:02:95:0A:3C
+            X509v3 Authority Key Identifier: 
+                keyid:3A:B5:BD:DF:AB:8D:71:77:F7:1E:FF:2C:EB:B2:D3:2F:52:D6:20:CE
+
+    Signature Algorithm: sha1WithRSAEncryption
+         2b:e2:c6:33:8a:fc:b3:d6:55:d6:16:d4:f7:2d:d8:49:78:6a:
+         f4:12:ec:26:82:2d:15:73:78:b7:4e:34:39:c7:0f:25:3c:73:
+         a3:13:b8:c1:5c:b6:a4:76:78:71:66:0f:6a:f4:53:b9:80:f7:
+         41:dd:5f:0d:7d:7b:d3:b6:d6:8e:fb:81:6f:57:24:d7:ac:5a:
+         52:66:ca:48:a9:37:db:7e:07:b2:ee:8c:81:a6:e6:9c:b3:40:
+         f2:f0:2d:57:d5:20:37:20:5c:23:9c:5e:58:c9:0c:c7:88:02:
+         e7:a1:15:9a:08:cf:fd:c0:7a:97:a2:3a:a1:82:19:41:86:4f:
+         af:3e
+-----BEGIN CERTIFICATE-----
+MIICpDCCAg2gAwIBAgIBATANBgkqhkiG9w0BAQUFADBfMRcwFQYDVQQDDA5jYS5s
+b2NhbGRvbWFpbjELMAkGA1UEBhMCRlIxDDAKBgNVBAgMA0JkUjEMMAoGA1UEBwwD
+QWl4MQswCQYDVQQKDAJmRDEOMAwGA1UECwwFVGVzdHMwHhcNMTcwNjAxMTkzNzE0
+WhcNMTgwNjAxMTkzNzE0WjBUMQswCQYDVQQGEwJGUjEMMAoGA1UECAwDQmRSMQsw
+CQYDVQQKDAJmRDEOMAwGA1UECwwFVGVzdHMxGjAYBgNVBAMMEXBlZXIxLmxvY2Fs
+ZG9tYWluMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDA5POsu0m/Q9M+tmZg
+CpT/46kHz1kojfKevZapfRDkn/X7F+zZFtIPjYI+GKk4l/nkrONy+cPfitLpiGfB
+cBSUAju6jLg+ndG/8+ahkcLuh4A9uJkzgi29Gyec9bZktFW3ljHAgYtGwcDHekM5
+AhqPauMK1/d5B6s1xUNkI9BiBQIDAQABo3sweTAJBgNVHRMEAjAAMCwGCWCGSAGG
++EIBDQQfFh1PcGVuU1NMIEdlbmVyYXRlZCBDZXJ0aWZpY2F0ZTAdBgNVHQ4EFgQU
+NfhKyalW6pldWEHnkHiDIwKVCjwwHwYDVR0jBBgwFoAUOrW936uNcXf3Hv8s67LT
+L1LWIM4wDQYJKoZIhvcNAQEFBQADgYEAK+LGM4r8s9ZV1hbU9y3YSXhq9BLsJoIt
+FXN4t040OccPJTxzoxO4wVy2pHZ4cWYPavRTuYD3Qd1fDX1707bWjvuBb1ck16xa
+UmbKSKk3234Hsu6MgabmnLNA8vAtV9UgNyBcI5xeWMkMx4gC56EVmgjP/cB6l6I6
+oYIZQYZPrz4=
+-----END CERTIFICATE-----
diff --git a/doc/single_host/02.pem b/doc/single_host/02.pem
new file mode 100644
index 0000000..6b5eecb
--- /dev/null
+++ b/doc/single_host/02.pem
@@ -0,0 +1,60 @@
+Certificate:
+    Data:
+        Version: 3 (0x2)
+        Serial Number: 2 (0x2)
+    Signature Algorithm: sha1WithRSAEncryption
+        Issuer: CN=ca.localdomain, C=FR, ST=BdR, L=Aix, O=fD, OU=Tests
+        Validity
+            Not Before: Jun  1 19:37:14 2017 GMT
+            Not After : Jun  1 19:37:14 2018 GMT
+        Subject: C=FR, ST=BdR, O=fD, OU=Tests, CN=peer2.localdomain
+        Subject Public Key Info:
+            Public Key Algorithm: rsaEncryption
+                Public-Key: (1024 bit)
+                Modulus:
+                    00:cf:fa:8a:d1:fc:ee:c2:1c:5d:54:dd:14:53:f1:
+                    7c:d2:a7:39:3f:e5:c1:37:c8:08:84:62:75:78:25:
+                    89:fb:88:20:5d:95:df:92:28:43:d0:3b:9b:6a:d0:
+                    d5:5b:b9:bc:0d:38:4a:c8:dd:2e:82:40:80:d0:0c:
+                    25:e8:8c:52:03:8e:eb:6d:ed:79:3e:50:f9:4d:ae:
+                    2c:63:52:01:2c:1d:c0:89:90:69:cf:93:0a:0f:32:
+                    a8:50:c0:2e:2e:fa:e4:cd:23:19:ab:58:19:1c:f2:
+                    f2:49:c1:42:d6:1d:5a:19:92:18:fc:c9:c2:a9:3e:
+                    1d:7b:32:b0:76:e0:89:94:ef
+                Exponent: 65537 (0x10001)
+        X509v3 extensions:
+            X509v3 Basic Constraints: 
+                CA:FALSE
+            Netscape Comment: 
+                OpenSSL Generated Certificate
+            X509v3 Subject Key Identifier: 
+                8E:94:E0:CE:3E:8D:D6:FD:51:C7:92:CD:9C:2A:D6:5B:1E:67:9F:27
+            X509v3 Authority Key Identifier: 
+                keyid:3A:B5:BD:DF:AB:8D:71:77:F7:1E:FF:2C:EB:B2:D3:2F:52:D6:20:CE
+
+    Signature Algorithm: sha1WithRSAEncryption
+         30:6b:d4:ae:25:ee:8a:d8:0a:6a:4d:50:cb:bc:08:5d:1c:3d:
+         ba:5b:a9:97:63:9a:33:47:36:bc:88:71:b9:7e:3b:e4:3b:15:
+         57:b5:53:5d:aa:e6:56:a9:cc:41:dd:bb:18:fe:21:04:b9:91:
+         17:56:15:01:fc:a3:e0:72:b4:02:74:1e:89:6f:4c:13:3a:ad:
+         12:8b:88:a7:09:38:3c:06:9f:22:62:b8:10:2c:fb:18:45:1c:
+         aa:61:b7:f6:93:86:9d:f4:51:92:b5:ee:c5:81:66:43:f2:ae:
+         ae:55:b9:5b:a2:68:fb:dd:78:2c:1b:12:d9:cf:fb:2d:dc:f7:
+         0f:39
+-----BEGIN CERTIFICATE-----
+MIICpDCCAg2gAwIBAgIBAjANBgkqhkiG9w0BAQUFADBfMRcwFQYDVQQDDA5jYS5s
+b2NhbGRvbWFpbjELMAkGA1UEBhMCRlIxDDAKBgNVBAgMA0JkUjEMMAoGA1UEBwwD
+QWl4MQswCQYDVQQKDAJmRDEOMAwGA1UECwwFVGVzdHMwHhcNMTcwNjAxMTkzNzE0
+WhcNMTgwNjAxMTkzNzE0WjBUMQswCQYDVQQGEwJGUjEMMAoGA1UECAwDQmRSMQsw
+CQYDVQQKDAJmRDEOMAwGA1UECwwFVGVzdHMxGjAYBgNVBAMMEXBlZXIyLmxvY2Fs
+ZG9tYWluMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDP+orR/O7CHF1U3RRT
+8XzSpzk/5cE3yAiEYnV4JYn7iCBdld+SKEPQO5tq0NVbubwNOErI3S6CQIDQDCXo
+jFIDjutt7Xk+UPlNrixjUgEsHcCJkGnPkwoPMqhQwC4u+uTNIxmrWBkc8vJJwULW
+HVoZkhj8ycKpPh17MrB24ImU7wIDAQABo3sweTAJBgNVHRMEAjAAMCwGCWCGSAGG
++EIBDQQfFh1PcGVuU1NMIEdlbmVyYXRlZCBDZXJ0aWZpY2F0ZTAdBgNVHQ4EFgQU
+jpTgzj6N1v1Rx5LNnCrWWx5nnycwHwYDVR0jBBgwFoAUOrW936uNcXf3Hv8s67LT
+L1LWIM4wDQYJKoZIhvcNAQEFBQADgYEAMGvUriXuitgKak1Qy7wIXRw9ulupl2Oa
+M0c2vIhxuX475DsVV7VTXarmVqnMQd27GP4hBLmRF1YVAfyj4HK0AnQeiW9MEzqt
+EouIpwk4PAafImK4ECz7GEUcqmG39pOGnfRRkrXuxYFmQ/KurlW5W6Jo+914LBsS
+2c/7Ldz3Dzk=
+-----END CERTIFICATE-----
diff --git a/doc/single_host/cacert.pem b/doc/single_host/cacert.pem
new file mode 100644
index 0000000..6242099
--- /dev/null
+++ b/doc/single_host/cacert.pem
@@ -0,0 +1,16 @@
+-----BEGIN CERTIFICATE-----
+MIICjDCCAfWgAwIBAgIJAKv7x3ez2Qf9MA0GCSqGSIb3DQEBBQUAMF8xFzAVBgNV
+BAMMDmNhLmxvY2FsZG9tYWluMQswCQYDVQQGEwJGUjEMMAoGA1UECAwDQmRSMQww
+CgYDVQQHDANBaXgxCzAJBgNVBAoMAmZEMQ4wDAYDVQQLDAVUZXN0czAeFw0xNzA2
+MDExOTM3MTNaFw0yNzA1MzAxOTM3MTNaMF8xFzAVBgNVBAMMDmNhLmxvY2FsZG9t
+YWluMQswCQYDVQQGEwJGUjEMMAoGA1UECAwDQmRSMQwwCgYDVQQHDANBaXgxCzAJ
+BgNVBAoMAmZEMQ4wDAYDVQQLDAVUZXN0czCBnzANBgkqhkiG9w0BAQEFAAOBjQAw
+gYkCgYEAqLJpO76yXu8Ksi9y0k9UMQqOq+ZXt0kukQVEdD8oVWaMBjfjiAvMkESI
+DKt4IXvFnQeLJ5HzImH+6b20oXxEBIgYEvp86S8l2tUakhaJ52ONhNMVzDK0Ho0w
+ekC6NkRoZ2glSwR+1G//5UIPIXAbIWv+EFxcOm4sFtDuT55JAdcCAwEAAaNQME4w
+HQYDVR0OBBYEFDq1vd+rjXF39x7/LOuy0y9S1iDOMB8GA1UdIwQYMBaAFDq1vd+r
+jXF39x7/LOuy0y9S1iDOMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADgYEA
+Kykgpd3xB7koXaMRRSAcUq/ZnBVPEtktOxJ9VFv3eFlG+Trd5/VJqP+FOYOecA62
+au4PnZyCvy0Vx2Y0yWL8dxFw62NZc+zRfn2GJbD60a9fUufNNdWZ/NJveq9ZUcwe
+dltU57OFaxMGiVR1gnl0HqSezvwcQvSGfnbv1jLJHlQ=
+-----END CERTIFICATE-----
diff --git a/doc/single_host/cakey.pem b/doc/single_host/cakey.pem
new file mode 100644
index 0000000..910fcbd
--- /dev/null
+++ b/doc/single_host/cakey.pem
@@ -0,0 +1,16 @@
+-----BEGIN PRIVATE KEY-----
+MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAKiyaTu+sl7vCrIv
+ctJPVDEKjqvmV7dJLpEFRHQ/KFVmjAY344gLzJBEiAyreCF7xZ0HiyeR8yJh/um9
+tKF8RASIGBL6fOkvJdrVGpIWiedjjYTTFcwytB6NMHpAujZEaGdoJUsEftRv/+VC
+DyFwGyFr/hBcXDpuLBbQ7k+eSQHXAgMBAAECgYEAgYb7ZfQ14M6J1+a2suRWMJF6
+mmJyVzjJmHAC737O6UOjn+KpwXvNxbfY/mFqC8uNH9T685cMqAm2QKJ4XsWbMuAJ
+HmPWwB4ZMxgkyFyPWl99IaCuYRjjdNVIajWJB6n/7kNzA/uSvEH387L1L8aWZfv6
+rIAhSuV+uNZR7YHbNwECQQDaQ3Kp+Ordq6fsTgo1v+e/TvY/HpZId10bzRqF5wYr
+oS22WOphKfZoYgI9wZwL/Ot0NPle0Z63vN4JUAFm0vWJAkEAxd0ZiH3zJFW53LY5
+kLwLSZvqfReuBePMTlG2gvf+lzvUAoopibzv1Qvo0nD/RFdJ+uAVJQf88zDMFh0b
+FCvEXwJBANhO+/aD4JArrNI+TVQTimNIqDbJ43qSAU6qKF0IJk9a/2i2GiKNaczt
+RPdbR4GB+P9D+NgFutyxawOjrJ/w9rECQG/UvGax0Se7MBZ4A+cy8SpEbm8PYDNC
+AipN8trpMcLmdLiOwFVyLRd76LZwWUaWE2ExH6JTdns5HFBvWOu4pP8CQHaFceh6
+5JAmWSsrqo39/2DFTOBGyLk+ZmH3xI9VOv7IU/ugWpr1l2KFHwQL7fBSD3+Qc6AL
+Zk97EPIbTdLU8r4=
+-----END PRIVATE KEY-----
diff --git a/doc/single_host/demoCA/index.txt b/doc/single_host/demoCA/index.txt
new file mode 100644
index 0000000..90b3918
--- /dev/null
+++ b/doc/single_host/demoCA/index.txt
@@ -0,0 +1,2 @@
+V	180601193714Z		01	unknown	/C=FR/ST=BdR/O=fD/OU=Tests/CN=peer1.localdomain
+V	180601193714Z		02	unknown	/C=FR/ST=BdR/O=fD/OU=Tests/CN=peer2.localdomain
diff --git a/doc/single_host/demoCA/index.txt.attr b/doc/single_host/demoCA/index.txt.attr
new file mode 100644
index 0000000..8f7e63a
--- /dev/null
+++ b/doc/single_host/demoCA/index.txt.attr
@@ -0,0 +1 @@
+unique_subject = yes
diff --git a/doc/single_host/demoCA/index.txt.attr.old b/doc/single_host/demoCA/index.txt.attr.old
new file mode 100644
index 0000000..8f7e63a
--- /dev/null
+++ b/doc/single_host/demoCA/index.txt.attr.old
@@ -0,0 +1 @@
+unique_subject = yes
diff --git a/doc/single_host/demoCA/index.txt.old b/doc/single_host/demoCA/index.txt.old
new file mode 100644
index 0000000..5219195
--- /dev/null
+++ b/doc/single_host/demoCA/index.txt.old
@@ -0,0 +1 @@
+V	180601193714Z		01	unknown	/C=FR/ST=BdR/O=fD/OU=Tests/CN=peer1.localdomain
diff --git a/doc/single_host/demoCA/serial b/doc/single_host/demoCA/serial
new file mode 100644
index 0000000..75016ea
--- /dev/null
+++ b/doc/single_host/demoCA/serial
@@ -0,0 +1 @@
+03
diff --git a/doc/single_host/freeDiameter-1.conf b/doc/single_host/freeDiameter-1.conf
new file mode 100644
index 0000000..ed344f9
--- /dev/null
+++ b/doc/single_host/freeDiameter-1.conf
@@ -0,0 +1,16 @@
+
+# -------- Test configuration ---------
+
+Identity = "peer1.localdomain";
+Realm = "localdomain";
+# Port = 3868;
+# SecPort = 3869;
+
+TLS_Cred = "peer1.cert.pem",
+	   "peer1.key.pem";
+TLS_CA = "cacert.pem";
+
+LoadExtension = "extensions/test_app.fdx" : "test_app1.conf";
+
+ConnectPeer = "peer2.localdomain" { ConnectTo = "127.0.0.1"; No_TLS; port = 30868; };
+
diff --git a/doc/single_host/freeDiameter-2.conf b/doc/single_host/freeDiameter-2.conf
new file mode 100644
index 0000000..f41e988
--- /dev/null
+++ b/doc/single_host/freeDiameter-2.conf
@@ -0,0 +1,15 @@
+# -------- Test configuration ---------
+
+Identity = "peer2.localdomain";
+Realm = "localdomain";
+Port = 30868;
+SecPort = 30869;
+
+TLS_Cred = "peer2.cert.pem",
+	   "peer2.key.pem";
+TLS_CA = "cacert.pem";
+
+LoadExtension = "extensions/test_app.fdx" : "test_app2.conf";
+
+ConnectPeer = "peer1.localdomain" { ConnectTo = "127.0.0.1"; No_TLS; };
+
diff --git a/doc/single_host/make_certs.sh b/doc/single_host/make_certs.sh
new file mode 100644
index 0000000..cf4248b
--- /dev/null
+++ b/doc/single_host/make_certs.sh
@@ -0,0 +1,20 @@
+rm -rf demoCA
+mkdir demoCA
+echo 01 > demoCA/serial
+touch demoCA/index.txt
+
+
+
+# CA self certificate
+openssl req  -new -batch -x509 -days 3650 -nodes -newkey rsa:1024 -out cacert.pem -keyout cakey.pem -subj /CN=ca.localdomain/C=FR/ST=BdR/L=Aix/O=fD/OU=Tests
+
+#peer1
+openssl genrsa -out peer1.key.pem 1024
+openssl req -new -batch -out peer1.csr.pem -key peer1.key.pem -subj /CN=peer1.localdomain/C=FR/ST=BdR/L=Aix/O=fD/OU=Tests
+openssl ca -cert cacert.pem -keyfile cakey.pem -in peer1.csr.pem -out peer1.cert.pem -outdir . -batch
+
+#peer2
+openssl genrsa -out peer2.key.pem 1024
+openssl req -new -batch -out peer2.csr.pem -key peer2.key.pem -subj /CN=peer2.localdomain/C=FR/ST=BdR/L=Aix/O=fD/OU=Tests
+openssl ca -cert cacert.pem -keyfile cakey.pem -in peer2.csr.pem -out peer2.cert.pem -outdir . -batch
+
diff --git a/doc/single_host/peer1.cert.pem b/doc/single_host/peer1.cert.pem
new file mode 100644
index 0000000..7e351a8
--- /dev/null
+++ b/doc/single_host/peer1.cert.pem
@@ -0,0 +1,60 @@
+Certificate:
+    Data:
+        Version: 3 (0x2)
+        Serial Number: 1 (0x1)
+    Signature Algorithm: sha1WithRSAEncryption
+        Issuer: CN=ca.localdomain, C=FR, ST=BdR, L=Aix, O=fD, OU=Tests
+        Validity
+            Not Before: Jun  1 19:37:14 2017 GMT
+            Not After : Jun  1 19:37:14 2018 GMT
+        Subject: C=FR, ST=BdR, O=fD, OU=Tests, CN=peer1.localdomain
+        Subject Public Key Info:
+            Public Key Algorithm: rsaEncryption
+                Public-Key: (1024 bit)
+                Modulus:
+                    00:c0:e4:f3:ac:bb:49:bf:43:d3:3e:b6:66:60:0a:
+                    94:ff:e3:a9:07:cf:59:28:8d:f2:9e:bd:96:a9:7d:
+                    10:e4:9f:f5:fb:17:ec:d9:16:d2:0f:8d:82:3e:18:
+                    a9:38:97:f9:e4:ac:e3:72:f9:c3:df:8a:d2:e9:88:
+                    67:c1:70:14:94:02:3b:ba:8c:b8:3e:9d:d1:bf:f3:
+                    e6:a1:91:c2:ee:87:80:3d:b8:99:33:82:2d:bd:1b:
+                    27:9c:f5:b6:64:b4:55:b7:96:31:c0:81:8b:46:c1:
+                    c0:c7:7a:43:39:02:1a:8f:6a:e3:0a:d7:f7:79:07:
+                    ab:35:c5:43:64:23:d0:62:05
+                Exponent: 65537 (0x10001)
+        X509v3 extensions:
+            X509v3 Basic Constraints: 
+                CA:FALSE
+            Netscape Comment: 
+                OpenSSL Generated Certificate
+            X509v3 Subject Key Identifier: 
+                35:F8:4A:C9:A9:56:EA:99:5D:58:41:E7:90:78:83:23:02:95:0A:3C
+            X509v3 Authority Key Identifier: 
+                keyid:3A:B5:BD:DF:AB:8D:71:77:F7:1E:FF:2C:EB:B2:D3:2F:52:D6:20:CE
+
+    Signature Algorithm: sha1WithRSAEncryption
+         2b:e2:c6:33:8a:fc:b3:d6:55:d6:16:d4:f7:2d:d8:49:78:6a:
+         f4:12:ec:26:82:2d:15:73:78:b7:4e:34:39:c7:0f:25:3c:73:
+         a3:13:b8:c1:5c:b6:a4:76:78:71:66:0f:6a:f4:53:b9:80:f7:
+         41:dd:5f:0d:7d:7b:d3:b6:d6:8e:fb:81:6f:57:24:d7:ac:5a:
+         52:66:ca:48:a9:37:db:7e:07:b2:ee:8c:81:a6:e6:9c:b3:40:
+         f2:f0:2d:57:d5:20:37:20:5c:23:9c:5e:58:c9:0c:c7:88:02:
+         e7:a1:15:9a:08:cf:fd:c0:7a:97:a2:3a:a1:82:19:41:86:4f:
+         af:3e
+-----BEGIN CERTIFICATE-----
+MIICpDCCAg2gAwIBAgIBATANBgkqhkiG9w0BAQUFADBfMRcwFQYDVQQDDA5jYS5s
+b2NhbGRvbWFpbjELMAkGA1UEBhMCRlIxDDAKBgNVBAgMA0JkUjEMMAoGA1UEBwwD
+QWl4MQswCQYDVQQKDAJmRDEOMAwGA1UECwwFVGVzdHMwHhcNMTcwNjAxMTkzNzE0
+WhcNMTgwNjAxMTkzNzE0WjBUMQswCQYDVQQGEwJGUjEMMAoGA1UECAwDQmRSMQsw
+CQYDVQQKDAJmRDEOMAwGA1UECwwFVGVzdHMxGjAYBgNVBAMMEXBlZXIxLmxvY2Fs
+ZG9tYWluMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDA5POsu0m/Q9M+tmZg
+CpT/46kHz1kojfKevZapfRDkn/X7F+zZFtIPjYI+GKk4l/nkrONy+cPfitLpiGfB
+cBSUAju6jLg+ndG/8+ahkcLuh4A9uJkzgi29Gyec9bZktFW3ljHAgYtGwcDHekM5
+AhqPauMK1/d5B6s1xUNkI9BiBQIDAQABo3sweTAJBgNVHRMEAjAAMCwGCWCGSAGG
++EIBDQQfFh1PcGVuU1NMIEdlbmVyYXRlZCBDZXJ0aWZpY2F0ZTAdBgNVHQ4EFgQU
+NfhKyalW6pldWEHnkHiDIwKVCjwwHwYDVR0jBBgwFoAUOrW936uNcXf3Hv8s67LT
+L1LWIM4wDQYJKoZIhvcNAQEFBQADgYEAK+LGM4r8s9ZV1hbU9y3YSXhq9BLsJoIt
+FXN4t040OccPJTxzoxO4wVy2pHZ4cWYPavRTuYD3Qd1fDX1707bWjvuBb1ck16xa
+UmbKSKk3234Hsu6MgabmnLNA8vAtV9UgNyBcI5xeWMkMx4gC56EVmgjP/cB6l6I6
+oYIZQYZPrz4=
+-----END CERTIFICATE-----
diff --git a/doc/single_host/peer1.csr.pem b/doc/single_host/peer1.csr.pem
new file mode 100644
index 0000000..fe7533a
--- /dev/null
+++ b/doc/single_host/peer1.csr.pem
@@ -0,0 +1,11 @@
+-----BEGIN CERTIFICATE REQUEST-----
+MIIBojCCAQsCAQAwYjEaMBgGA1UEAwwRcGVlcjEubG9jYWxkb21haW4xCzAJBgNV
+BAYTAkZSMQwwCgYDVQQIDANCZFIxDDAKBgNVBAcMA0FpeDELMAkGA1UECgwCZkQx
+DjAMBgNVBAsMBVRlc3RzMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDA5POs
+u0m/Q9M+tmZgCpT/46kHz1kojfKevZapfRDkn/X7F+zZFtIPjYI+GKk4l/nkrONy
++cPfitLpiGfBcBSUAju6jLg+ndG/8+ahkcLuh4A9uJkzgi29Gyec9bZktFW3ljHA
+gYtGwcDHekM5AhqPauMK1/d5B6s1xUNkI9BiBQIDAQABoAAwDQYJKoZIhvcNAQEF
+BQADgYEAYhJh9ah6HRLkr5ycEaLtGUOs9vD7GYiUSV9ilIic9/WCGh+KiL59Wq30
+E13ZrLHf6oqjJDOqHmSRDbG9ws5gilYdGdf+Au/mAutmvOwrTVnAOtYzAqJPKTin
+/JbbedfSOFUuc+Ii+qRCpvXdfriBZGRGfVBQYjwywrQz/IJQ+oE=
+-----END CERTIFICATE REQUEST-----
diff --git a/doc/single_host/peer1.key.pem b/doc/single_host/peer1.key.pem
new file mode 100644
index 0000000..fbca847
--- /dev/null
+++ b/doc/single_host/peer1.key.pem
@@ -0,0 +1,15 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIICXAIBAAKBgQDA5POsu0m/Q9M+tmZgCpT/46kHz1kojfKevZapfRDkn/X7F+zZ
+FtIPjYI+GKk4l/nkrONy+cPfitLpiGfBcBSUAju6jLg+ndG/8+ahkcLuh4A9uJkz
+gi29Gyec9bZktFW3ljHAgYtGwcDHekM5AhqPauMK1/d5B6s1xUNkI9BiBQIDAQAB
+AoGBALL/w2A3LGhg+FbpzHazWzFagjDNKV+I2eyU4orFlDeUeR9ZRGDv3F6yYnpd
+SCtMXIjoJuk6/ZkjqjUsb5wB9hUGzOn8pZ6lcdYxYYQpxcJ7gFntDFQF6EnBXR/R
+WpbpXLHigJtqey1Ii6DBOAiyLtDojVV/s2yYeo2p0fHkmtoBAkEA3/H+/RrglCYy
+ce3RIPAODDzNK1esBI1CUiRZ49CIa438rbB+Q2VtYk1YpYBGT7qOaXiFXi1OrlVF
+3KBky4RaeQJBANyBKLI8EL1tVs4uMzJZDiPUjrxgCNysmqs2+3uG/vQJr7s8GS30
+t7/K0KM4xR/sSEyE/5hUUTpBxf+Jn9BloO0CQFyxF2+/zjDD1qFdY/AULFxYVjuY
+YDTKGydQsHwg9jY+YNWrdbeDpdDIXuaxv2iEuSlinyEp86Uo2m/FW7L5J1ECQA/Y
+A/mSkU1bHuKftTQH7Bks+7iTWe+pQ0/MGpPMpmMYkxTsA48mx1EznHwt5xQdITDG
+WaszW8bI1RZAaEhMFR0CQAtvf49GsqNZwvEZYNgUZDxx74a2jydE+tY7m66cxcZI
+bDabRPhSogrneElATPtOVRHs6e5ISFbY9h6L15sDQzU=
+-----END RSA PRIVATE KEY-----
diff --git a/doc/single_host/peer2.cert.pem b/doc/single_host/peer2.cert.pem
new file mode 100644
index 0000000..6b5eecb
--- /dev/null
+++ b/doc/single_host/peer2.cert.pem
@@ -0,0 +1,60 @@
+Certificate:
+    Data:
+        Version: 3 (0x2)
+        Serial Number: 2 (0x2)
+    Signature Algorithm: sha1WithRSAEncryption
+        Issuer: CN=ca.localdomain, C=FR, ST=BdR, L=Aix, O=fD, OU=Tests
+        Validity
+            Not Before: Jun  1 19:37:14 2017 GMT
+            Not After : Jun  1 19:37:14 2018 GMT
+        Subject: C=FR, ST=BdR, O=fD, OU=Tests, CN=peer2.localdomain
+        Subject Public Key Info:
+            Public Key Algorithm: rsaEncryption
+                Public-Key: (1024 bit)
+                Modulus:
+                    00:cf:fa:8a:d1:fc:ee:c2:1c:5d:54:dd:14:53:f1:
+                    7c:d2:a7:39:3f:e5:c1:37:c8:08:84:62:75:78:25:
+                    89:fb:88:20:5d:95:df:92:28:43:d0:3b:9b:6a:d0:
+                    d5:5b:b9:bc:0d:38:4a:c8:dd:2e:82:40:80:d0:0c:
+                    25:e8:8c:52:03:8e:eb:6d:ed:79:3e:50:f9:4d:ae:
+                    2c:63:52:01:2c:1d:c0:89:90:69:cf:93:0a:0f:32:
+                    a8:50:c0:2e:2e:fa:e4:cd:23:19:ab:58:19:1c:f2:
+                    f2:49:c1:42:d6:1d:5a:19:92:18:fc:c9:c2:a9:3e:
+                    1d:7b:32:b0:76:e0:89:94:ef
+                Exponent: 65537 (0x10001)
+        X509v3 extensions:
+            X509v3 Basic Constraints: 
+                CA:FALSE
+            Netscape Comment: 
+                OpenSSL Generated Certificate
+            X509v3 Subject Key Identifier: 
+                8E:94:E0:CE:3E:8D:D6:FD:51:C7:92:CD:9C:2A:D6:5B:1E:67:9F:27
+            X509v3 Authority Key Identifier: 
+                keyid:3A:B5:BD:DF:AB:8D:71:77:F7:1E:FF:2C:EB:B2:D3:2F:52:D6:20:CE
+
+    Signature Algorithm: sha1WithRSAEncryption
+         30:6b:d4:ae:25:ee:8a:d8:0a:6a:4d:50:cb:bc:08:5d:1c:3d:
+         ba:5b:a9:97:63:9a:33:47:36:bc:88:71:b9:7e:3b:e4:3b:15:
+         57:b5:53:5d:aa:e6:56:a9:cc:41:dd:bb:18:fe:21:04:b9:91:
+         17:56:15:01:fc:a3:e0:72:b4:02:74:1e:89:6f:4c:13:3a:ad:
+         12:8b:88:a7:09:38:3c:06:9f:22:62:b8:10:2c:fb:18:45:1c:
+         aa:61:b7:f6:93:86:9d:f4:51:92:b5:ee:c5:81:66:43:f2:ae:
+         ae:55:b9:5b:a2:68:fb:dd:78:2c:1b:12:d9:cf:fb:2d:dc:f7:
+         0f:39
+-----BEGIN CERTIFICATE-----
+MIICpDCCAg2gAwIBAgIBAjANBgkqhkiG9w0BAQUFADBfMRcwFQYDVQQDDA5jYS5s
+b2NhbGRvbWFpbjELMAkGA1UEBhMCRlIxDDAKBgNVBAgMA0JkUjEMMAoGA1UEBwwD
+QWl4MQswCQYDVQQKDAJmRDEOMAwGA1UECwwFVGVzdHMwHhcNMTcwNjAxMTkzNzE0
+WhcNMTgwNjAxMTkzNzE0WjBUMQswCQYDVQQGEwJGUjEMMAoGA1UECAwDQmRSMQsw
+CQYDVQQKDAJmRDEOMAwGA1UECwwFVGVzdHMxGjAYBgNVBAMMEXBlZXIyLmxvY2Fs
+ZG9tYWluMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDP+orR/O7CHF1U3RRT
+8XzSpzk/5cE3yAiEYnV4JYn7iCBdld+SKEPQO5tq0NVbubwNOErI3S6CQIDQDCXo
+jFIDjutt7Xk+UPlNrixjUgEsHcCJkGnPkwoPMqhQwC4u+uTNIxmrWBkc8vJJwULW
+HVoZkhj8ycKpPh17MrB24ImU7wIDAQABo3sweTAJBgNVHRMEAjAAMCwGCWCGSAGG
++EIBDQQfFh1PcGVuU1NMIEdlbmVyYXRlZCBDZXJ0aWZpY2F0ZTAdBgNVHQ4EFgQU
+jpTgzj6N1v1Rx5LNnCrWWx5nnycwHwYDVR0jBBgwFoAUOrW936uNcXf3Hv8s67LT
+L1LWIM4wDQYJKoZIhvcNAQEFBQADgYEAMGvUriXuitgKak1Qy7wIXRw9ulupl2Oa
+M0c2vIhxuX475DsVV7VTXarmVqnMQd27GP4hBLmRF1YVAfyj4HK0AnQeiW9MEzqt
+EouIpwk4PAafImK4ECz7GEUcqmG39pOGnfRRkrXuxYFmQ/KurlW5W6Jo+914LBsS
+2c/7Ldz3Dzk=
+-----END CERTIFICATE-----
diff --git a/doc/single_host/peer2.csr.pem b/doc/single_host/peer2.csr.pem
new file mode 100644
index 0000000..2c5174b
--- /dev/null
+++ b/doc/single_host/peer2.csr.pem
@@ -0,0 +1,11 @@
+-----BEGIN CERTIFICATE REQUEST-----
+MIIBojCCAQsCAQAwYjEaMBgGA1UEAwwRcGVlcjIubG9jYWxkb21haW4xCzAJBgNV
+BAYTAkZSMQwwCgYDVQQIDANCZFIxDDAKBgNVBAcMA0FpeDELMAkGA1UECgwCZkQx
+DjAMBgNVBAsMBVRlc3RzMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDP+orR
+/O7CHF1U3RRT8XzSpzk/5cE3yAiEYnV4JYn7iCBdld+SKEPQO5tq0NVbubwNOErI
+3S6CQIDQDCXojFIDjutt7Xk+UPlNrixjUgEsHcCJkGnPkwoPMqhQwC4u+uTNIxmr
+WBkc8vJJwULWHVoZkhj8ycKpPh17MrB24ImU7wIDAQABoAAwDQYJKoZIhvcNAQEF
+BQADgYEAQz+5ALMObFPv9PAVnjbh2MQ2PqtJeaFxi0rFKCkA4sfWfYvB5zK5Px9i
+J94Z7rRrRocNaTz+ok6JsUn7N1aEjaU3yJq1cRI7G2pqro7z1CMFvMKQlBNVquh4
+sxrM1mHUnKQv5Bx8xpqup2oALk0UovcPGrs6uS9FG9cJHaIRYWQ=
+-----END CERTIFICATE REQUEST-----
diff --git a/doc/single_host/peer2.key.pem b/doc/single_host/peer2.key.pem
new file mode 100644
index 0000000..ae617a8
--- /dev/null
+++ b/doc/single_host/peer2.key.pem
@@ -0,0 +1,15 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIICXAIBAAKBgQDP+orR/O7CHF1U3RRT8XzSpzk/5cE3yAiEYnV4JYn7iCBdld+S
+KEPQO5tq0NVbubwNOErI3S6CQIDQDCXojFIDjutt7Xk+UPlNrixjUgEsHcCJkGnP
+kwoPMqhQwC4u+uTNIxmrWBkc8vJJwULWHVoZkhj8ycKpPh17MrB24ImU7wIDAQAB
+AoGATYipl/8jQ1ovsSN6IJE2Z5HP1fJhRdpc0n2iLVhRSGRHLJxi7Kn2HfsaxYd1
+Au0LHiKOPrO2UviZDPZ6a2dkayMhWZRNeVdOMUFqDGG/b2YfxuVna3JKz2bjxqUb
+i25FW+iBO18c/5FBf1uYkh4zwpYGGbznwXPlxHBBHjTaKoECQQDnhX3E0bVnp2Kq
+dmJTEDstfcWchPutxwmUkKSG4mE3+OglyE/UyGmT0ifasZT5UlVIsRvRx84ftuyP
+GrUAiHFbAkEA5ffTxFORPmggKdEEumqkbq1A9u3fMaTpRF3xiZO4MxIDBWUZdKRf
+D/vp77R8FQxI9lQZRGmFfuQJ9y8BLwwK/QJAV+r6ap5UK+uFbUQNbIuSXWEQhLJ/
+PGuD+NXAlLQsxOuRhJ9/qUb9yLOajNK4xsD8P+F5tf0RCjwVsvYqW+x0VwJBAJHB
+jCVJWiuVz5zxb++/m8zSXvSjO+25OmgsquSqDfvAlM2ckI/PhrkYz+MwH90vVida
+klE8GHKeknpq/nMVTPkCQE+YmXVufxyW+5F8p04LdOGUjrXT6uQv3h24QKSVYtov
+pFJ9vUVppJsITHRC9V3XnFN6S1tei8zh8u04yZhRqYw=
+-----END RSA PRIVATE KEY-----
diff --git a/doc/single_host/test_app1.conf b/doc/single_host/test_app1.conf
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/doc/single_host/test_app1.conf
diff --git a/doc/single_host/test_app2.conf b/doc/single_host/test_app2.conf
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/doc/single_host/test_app2.conf
diff --git a/doc/test_app.conf.sample b/doc/test_app.conf.sample
new file mode 100644
index 0000000..4262e21
--- /dev/null
+++ b/doc/test_app.conf.sample
@@ -0,0 +1,74 @@
+#######################
+# This file contains the description of configuration and general information about the
+# "test_app" extension.
+
+# This extension provides a simple way to send a predefined message over the Diameter Network.
+# It may be used to test the Routing or other base mechanisms from the Diameter network.
+
+# In order to enable this extension, the main freeDiameter configuration file
+# must contain the following declaration:
+# LoadExtension = "extensions/app_test.fdx" : "/path/to/app_test.conf" ;
+# Note that the conffile may be omitted, in which case default parameters will be assumed.
+#######################
+
+
+#######################
+# Configuration of the test message
+
+# This application is defined as a Vendor-Specific application. 
+# Since freeDiameter does not have a IANA-assigned Vendor ID, we let a configurable value here:
+# vendor-id = 999999;
+
+# The application id. Same remark as previously.
+# appli-id = 999999;
+
+# The command code for Test-Request and Test-Answer. The range 0xfffffe-ffffff (dec: 16777215) is reserved for experimental use.
+# cmd-id = 16777214;
+
+# The AVP id for the test.
+# avp-id = 345678;
+
+# Another AVP id for long payload test. default to value 0, meaning this is not used.
+# long-avp-id = 0;
+
+# Define the payload length of the long-avp. Default 5000 bytes.
+# long-avp-len = 5000;
+
+
+#######################
+# Configuration of the extension behavior
+
+# The mode for the extension.
+# - server: Answer incoming requests. The signal is ignored.
+# - client: Send a request when the signal is received, and measure the time to receiving answer.
+# - both: acts as client and server
+# mode = both;
+
+# The behavior can be changed by specifying additional "benchmark;" keyword.
+# When this keyword appears, it changes the behavior as follow:
+#  - server is silent on message reception, only the activity summary is displayed every 30 seconds
+#  - client attempts to send as many messages as possible during 10 seconds and counts them.
+# The benchmark keyword can be followed optionally by two integers:
+#   duration is the time for the measurement, in seconds (default 10).
+#   concurrency is the number of messages that can be on the wire before waiting for an answer (default 100).
+# benchmark [duration concurrency];
+
+
+#######################
+# Client-specific configuration
+
+# The Destination-Realm for the message
+# (default is sending to same realm as local peer).
+# dest-realm = "foreign.net";
+
+# The Destination-Host for the message.
+# (default is not providing this AVP).
+# dest-host = "server.foreign.net";
+
+# The User-Name for the message (may be useful for some routing tests).
+# (default is not providing this AVP).
+# user-name = "user@server.foreign.net";
+
+# The signal that triggers sending the test message
+# Note: Symbolic names are not recognized, you must use integers
+# signal = 10;
diff --git a/doc/test_netemul.conf.sample b/doc/test_netemul.conf.sample
new file mode 100644
index 0000000..f9c4d12
--- /dev/null
+++ b/doc/test_netemul.conf.sample
@@ -0,0 +1,59 @@
+# This file contains information for configuring the test_netemul extension.
+# To find how to have freeDiameter load this extension, please refer to the freeDiameter documentation.
+#
+# The test_netemul extension implements a Diameter proxy that behaves like simple forwarding agent,
+# with the exception that it can introduce delay in the forwarding of the messages and generate duplicates
+# of messages, as can be expected from a real Diameter network. It can also generate routing errors when 
+# connected to more than 2 peers.
+
+
+# LATENCY:
+# Two parameters are used to control the delay introduced in the messages.
+#  - latency_average:
+#   This is the average delay introduced in the packets. 
+#   Set to 0 to not add any latency (beyond the normal processing time).
+#   The value is expressed as an integer followed by a unit which can 
+#   be 's' (seconds) or 'ms' (milliseconds). Example:
+#     latency_average = 700 ms;
+#
+#  - latency_deviation:
+#   This parameter controls the variance in the latency. It is expressed
+#   as a value between 0 % and 100 %. When set to 0 %, all messages will be delayed
+#   by exactly latency_average. Otherwise, it represents the width of the interval 
+#   "around" the average where "most" of the latency will be chosen (the distribution
+#   has a Gaussian shape). Example:
+#      latency_deviation = 25 %;
+#
+# The default values give an added latency "mostly" between 0.4 and 0.6 seconds:
+#  latency_average  = 500 ms;
+#  latency_deviation = 20 % ;
+
+
+# REORDERING:
+# There is no special control over the reordering of messages. It may simply happen
+# as a result of the latency. If you want to get a lot of reordering, set the 
+# latency_variance to a high value.
+
+
+# DUPLICATES:
+# Duplicate messages are expected in the Diameter protocol by design, as a consequence
+# of the failover mechanism that provides the protocol's reliability.
+#  - dupl_proba:
+#   This value gives the probability of producing a duplicate of a forwarded message. 
+#   The value is comprized between 0 (no duplicates) and 1 (duplicate all messages).
+#   Duplicates are created for requests, but may result in duplicate answers 
+#   received by your Diameter client(s), depending on your server(s)'s behavior.
+#   In the case of freeDiameter client, the duplicate answer is automatically filtered out
+#   because the hop-by-hop id has already been used.
+#   Note that each duplicate copy is an independent message,
+#   which receives a different latency, and might be routed to a different server if you
+#   use for example load-balancing.
+#   The parameter can take several forms:
+#    dupl_proba = 0 ;
+#      Disables the generation of duplicate messages completely.
+#    dupl_proba = 1 / 10000 ;
+#    dupl_proba = 0.0001 ;
+#      Around 1 messages over ten thousands will be duplicated.
+#
+# Default value:
+#  dupl_proba = 1 / 100 ;
diff --git a/doc/test_sip.conf.sample b/doc/test_sip.conf.sample
new file mode 100644
index 0000000..365272a
--- /dev/null
+++ b/doc/test_sip.conf.sample
@@ -0,0 +1,8 @@
+#User configuration
+username = "awestfahl"
+password = "test"
+sip_aor = "sip:awestfahl@tera.ics.keio.ac.jp"
+
+#Destination information
+destination_realm = "freediameter.net"
+destination_sip = "sip:awestfahl@freediameter.net"
diff --git a/extensions/CMakeLists.txt b/extensions/CMakeLists.txt
new file mode 100644
index 0000000..96a8334
--- /dev/null
+++ b/extensions/CMakeLists.txt
@@ -0,0 +1,162 @@
+PROJECT("freeDiameter extensions" C)
+
+# We want all resulting objects in the same folder
+SET(LIBRARY_OUTPUT_PATH ${CMAKE_CURRENT_BINARY_DIR})
+
+# Use the macro FD_ADD_EXTENSION(name files...) to create an extension
+# It is equivalent to add_library with the appropriate parameters
+# and naming conventions (.fdx : FreeDiameter eXtension)
+MACRO(FD_ADD_EXTENSION EXTNAME)
+  ADD_LIBRARY(${EXTNAME} MODULE ${ARGN})
+  SET_TARGET_PROPERTIES(${EXTNAME} PROPERTIES PREFIX "" )
+  SET_TARGET_PROPERTIES(${EXTNAME} PROPERTIES SUFFIX ".fdx" )
+ENDMACRO(FD_ADD_EXTENSION)
+
+# Use the macro FD_EXTENSION_SUBDIR(extmacroname subdir descr default) to 
+# add a new extension subdirectory.
+MACRO(FD_EXTENSION_SUBDIR EXTSUBDIR EXTDESCR EXTDEFAULT)
+   STRING(TOUPPER ${EXTSUBDIR} EXTMACRONAME)
+   IF (NOT ALL_EXTENSIONS)
+     OPTION(BUILD_${EXTMACRONAME} "Build ${EXTSUBDIR}.fdx? (${EXTDESCR})" ${EXTDEFAULT})
+   ENDIF (NOT ALL_EXTENSIONS)
+   IF (BUILD_${EXTMACRONAME} OR ALL_EXTENSIONS)
+      SUBDIRS(${EXTSUBDIR})
+   ENDIF (BUILD_${EXTMACRONAME} OR ALL_EXTENSIONS)
+ENDMACRO(FD_EXTENSION_SUBDIR)
+
+OPTION(ALL_EXTENSIONS "Build ALL available extensions? (disable to select individual components)" OFF)
+
+# The extensions include the headers of freeDiameter that contains gnutls objects
+INCLUDE_DIRECTORIES(${LFDCORE_INCLUDES})
+
+
+###########################
+# Extensions section
+
+####
+# Diameter applications dictionaries
+
+FD_EXTENSION_SUBDIR(dict_nasreq "NASREQ (RFC4005) Dictionary definitions"       ON)
+FD_EXTENSION_SUBDIR(dict_eap    "Diameter EAP (RFC4072) Dictionary definitions" ON)
+
+FD_EXTENSION_SUBDIR(dict_dcca   "Diameter CC (RFC4006) Dictionary definitions [incomplete]" ON)
+FD_EXTENSION_SUBDIR(dict_dcca_3gpp   "Diameter CC 3GPP Dictionary definitions [incomplete]" ON)
+FD_EXTENSION_SUBDIR(dict_dcca_starent   "Diameter CC Starent Dictionary definitions" ON)
+
+FD_EXTENSION_SUBDIR(dict_sip    "Diameter SIP (RFC4740) Dictionary definitions" ON)
+
+FD_EXTENSION_SUBDIR(dict_mip6a     "Diameter Mobile IPv6 Auth Dictionary definitions"         ON)
+FD_EXTENSION_SUBDIR(dict_mip6i     "Diameter Mobile IPv6 IKE Dictionary definitions"          ON)
+FD_EXTENSION_SUBDIR(dict_nas_mipv6 "Diameter NAS-to-HAAA Interaction Dictionary definitions"  ON)
+
+FD_EXTENSION_SUBDIR(dict_legacy_xml "Load Diameter dictionary definitions from XML files."    OFF)
+
+
+####
+# Diameter applications
+
+FD_EXTENSION_SUBDIR(app_acct    "Simple accounting application that stores accounting records in flat database" OFF)
+FD_EXTENSION_SUBDIR(app_diameap "Diameter EAP Application server (RFC 4072)" 					OFF)
+FD_EXTENSION_SUBDIR(app_radgw   "RADIUS/Diameter gateway translation - RADIUS client to Diameter server" 	OFF)
+FD_EXTENSION_SUBDIR(app_sip     "Diameter SIP Authentication and Authorization server (RFC 4740)" 		OFF)
+
+FD_EXTENSION_SUBDIR(app_redirect "Diameter Redirect server: send configurable Redirect indications to other peers" OFF)
+
+
+####
+# Routing extensions
+
+FD_EXTENSION_SUBDIR(rt_busypeers "Handling of Diameter TOO_BUSY messages and relay timeouts"	ON)
+FD_EXTENSION_SUBDIR(rt_default   "Configurable routing rules for freeDiameter" 		     	ON)
+FD_EXTENSION_SUBDIR(rt_ereg      "Configurable routing based on regexp matching of AVP values" OFF)
+FD_EXTENSION_SUBDIR(rt_ignore_dh "Stow Destination-Host in Proxy-Info, restore to Origin-Host for answers"	ON)
+FD_EXTENSION_SUBDIR(rt_load_balance "Balance load over multiple equal hosts, based on outstanding requests"	ON)
+FD_EXTENSION_SUBDIR(rt_randomize "Randomly choose one of the highest scored hosts and increase its score by one"	ON)
+FD_EXTENSION_SUBDIR(rt_redirect  "Handling of Diameter Redirect messages" 			ON)
+
+
+####
+# Peers security extensions
+
+FD_EXTENSION_SUBDIR(acl_wl "White-list based authorization of incoming connections" ON)
+
+
+####
+# Debug & test extensions
+
+FD_EXTENSION_SUBDIR(dbg_monitor "Outputs periodical status information"              ON)
+FD_EXTENSION_SUBDIR(dbg_msg_timings "Show some timing information for messages"      ON)
+FD_EXTENSION_SUBDIR(dbg_msg_dumps "Show human-readable content of the received & sent messages"      ON)
+FD_EXTENSION_SUBDIR(dbg_rt      "Routing extension for debugging the routing module" ON)
+FD_EXTENSION_SUBDIR(test_app    "Testing application to send dummy message to another peer, like a Diameter 'ping'" OFF)
+FD_EXTENSION_SUBDIR(test_sip    "Testing application to simulate Diameter-SIP client (RFC4740)" OFF)
+FD_EXTENSION_SUBDIR(dbg_interactive "Python-interpreter based module"                OFF)
+FD_EXTENSION_SUBDIR(test_netemul "Simple Diameter network emulator proxy extension (latency, PDV, duplicates)" OFF)
+
+
+
+# The following extension have very little use except for specific tests, so we disable them except in Debug configurations.
+IF (CMAKE_BUILD_TYPE MATCHES "Debug")
+	FD_EXTENSION_SUBDIR(_sample     "Simple extension to demonstrate extension mechanism, for developpers" OFF)
+	FD_EXTENSION_SUBDIR(test_acct   "Receive Accounting-Requests and display the data, but no storage" OFF)
+	FD_EXTENSION_SUBDIR(test_rt_any "Routing extension randomly sending message to any peer available, for testing purpose" OFF)
+ENDIF (CMAKE_BUILD_TYPE MATCHES "Debug")
+
+
+FD_EXTENSION_SUBDIR(dict_3gpp2_avps "dict_3gpp2_avps extension library" ON)
+FD_EXTENSION_SUBDIR(dict_CreditControl "dict_CreditControl extension library" ON)
+FD_EXTENSION_SUBDIR(dict_CxDx "dict_CxDx extension library" ON)
+FD_EXTENSION_SUBDIR(dict_Gx "dict_Gx extension library" ON)
+FD_EXTENSION_SUBDIR(dict_NAS "dict_NAS extension library" ON)
+FD_EXTENSION_SUBDIR(dict_Rf "dict_Rf extension library" ON)
+FD_EXTENSION_SUBDIR(dict_Ro "dict_Ro extension library" ON)
+FD_EXTENSION_SUBDIR(dict_Rx "dict_Rx extension library" ON)
+FD_EXTENSION_SUBDIR(dict_S6as6d "dict_S6as6d extension library" ON)
+FD_EXTENSION_SUBDIR(dict_S6mS6n "dict_S6mS6n extension library" ON)
+FD_EXTENSION_SUBDIR(dict_S6t "dict_S6t extension library" ON)
+FD_EXTENSION_SUBDIR(dict_SGd "dict_SGd extension library" ON)
+FD_EXTENSION_SUBDIR(dict_SLh "dict_SLh extension library" ON)
+FD_EXTENSION_SUBDIR(dict_Sd "dict_Sd extension library" ON)
+FD_EXTENSION_SUBDIR(dict_Sh "dict_Sh extension library" ON)
+FD_EXTENSION_SUBDIR(dict_T4 "dict_T4 extension library" ON)
+FD_EXTENSION_SUBDIR(dict_T6aT6bT7 "dict_T6aT6bT7 extension library" ON)
+FD_EXTENSION_SUBDIR(dict_Tsp "dict_Tsp extension library" ON)
+#FD_EXTENSION_SUBDIR(dict_base_rfc6733 "dict_base_rfc6733 extension library" ON)
+FD_EXTENSION_SUBDIR(dict_draftload_avps "dict_draftload_avps extension library" ON)
+FD_EXTENSION_SUBDIR(dict_etsi283034_avps "dict_etsi283034_avps extension library" ON)
+FD_EXTENSION_SUBDIR(dict_rfc4004_avps "dict_rfc4004_avps extension library" ON)
+FD_EXTENSION_SUBDIR(dict_rfc4006bis_avps "dict_rfc4006bis_avps extension library" ON)
+FD_EXTENSION_SUBDIR(dict_rfc4072_avps "dict_rfc4072_avps extension library" ON)
+FD_EXTENSION_SUBDIR(dict_rfc4590_avps "dict_rfc4590_avps extension library" ON)
+FD_EXTENSION_SUBDIR(dict_rfc5447_avps "dict_rfc5447_avps extension library" ON)
+FD_EXTENSION_SUBDIR(dict_rfc5580_avps "dict_rfc5580_avps extension library" ON)
+FD_EXTENSION_SUBDIR(dict_rfc5777_avps "dict_rfc5777_avps extension library" ON)
+FD_EXTENSION_SUBDIR(dict_rfc5778_avps "dict_rfc5778_avps extension library" ON)
+FD_EXTENSION_SUBDIR(dict_rfc6734_avps "dict_rfc6734_avps extension library" ON)
+FD_EXTENSION_SUBDIR(dict_rfc6942_avps "dict_rfc6942_avps extension library" ON)
+FD_EXTENSION_SUBDIR(dict_rfc7155_avps "dict_rfc7155_avps extension library" ON)
+FD_EXTENSION_SUBDIR(dict_rfc7683_avps "dict_rfc7683_avps extension library" ON)
+FD_EXTENSION_SUBDIR(dict_rfc7944_avps "dict_rfc7944_avps extension library" ON)
+FD_EXTENSION_SUBDIR(dict_ts29061_avps "dict_ts29061_avps extension library" ON)
+FD_EXTENSION_SUBDIR(dict_ts29128_avps "dict_ts29128_avps extension library" ON)
+FD_EXTENSION_SUBDIR(dict_ts29154_avps "dict_ts29154_avps extension library" ON)
+FD_EXTENSION_SUBDIR(dict_ts29173_avps "dict_ts29173_avps extension library" ON)
+FD_EXTENSION_SUBDIR(dict_ts29212_avps "dict_ts29212_avps extension library" ON)
+FD_EXTENSION_SUBDIR(dict_ts29214_avps "dict_ts29214_avps extension library" ON)
+FD_EXTENSION_SUBDIR(dict_ts29215_avps "dict_ts29215_avps extension library" ON)
+FD_EXTENSION_SUBDIR(dict_ts29217_avps "dict_ts29217_avps extension library" ON)
+FD_EXTENSION_SUBDIR(dict_ts29229_avps "dict_ts29229_avps extension library" ON)
+FD_EXTENSION_SUBDIR(dict_ts29272_avps "dict_ts29272_avps extension library" ON)
+FD_EXTENSION_SUBDIR(dict_ts29273_avps "dict_ts29273_avps extension library" ON)
+FD_EXTENSION_SUBDIR(dict_ts29329_avps "dict_ts29329_avps extension library" ON)
+FD_EXTENSION_SUBDIR(dict_ts29336_avps "dict_ts29336_avps extension library" ON)
+FD_EXTENSION_SUBDIR(dict_ts29337_avps "dict_ts29337_avps extension library" ON)
+FD_EXTENSION_SUBDIR(dict_ts29338_avps "dict_ts29338_avps extension library" ON)
+FD_EXTENSION_SUBDIR(dict_ts29343_avps "dict_ts29343_avps extension library" ON)
+FD_EXTENSION_SUBDIR(dict_ts29344_avps "dict_ts29344_avps extension library" ON)
+FD_EXTENSION_SUBDIR(dict_ts29345_avps "dict_ts29345_avps extension library" ON)
+FD_EXTENSION_SUBDIR(dict_ts29368_avps "dict_ts29368_avps extension library" ON)
+FD_EXTENSION_SUBDIR(dict_ts29468_avps "dict_ts29468_avps extension library" ON)
+FD_EXTENSION_SUBDIR(dict_ts32299_avps "dict_ts32299_avps extension library" ON)
+FD_EXTENSION_SUBDIR(dict_S6c "dict_S6c extension library" ON)
+FD_EXTENSION_SUBDIR(dict_S9 "dict_S9 extension library" ON)
diff --git a/extensions/_sample/CMakeLists.txt b/extensions/_sample/CMakeLists.txt
new file mode 100644
index 0000000..aad630a
--- /dev/null
+++ b/extensions/_sample/CMakeLists.txt
@@ -0,0 +1,14 @@
+# The sample extension
+PROJECT("Sample extension")
+
+# Compile as a module
+FD_ADD_EXTENSION(dbg_sample sample.c hello.cpp fini.c)
+
+
+####
+## INSTALL section ##
+
+# Uncomment the following lines to have the extension installed
+# INSTALL(TARGETS dbg_sample
+# 	LIBRARY DESTINATION ${INSTALL_EXTENSIONS_SUFFIX}
+# 	COMPONENT freeDiameter-debug-tools)
diff --git a/extensions/_sample/fini.c b/extensions/_sample/fini.c
new file mode 100644
index 0000000..df7513c
--- /dev/null
+++ b/extensions/_sample/fini.c
@@ -0,0 +1,45 @@
+/*********************************************************************************************************
+* Software License Agreement (BSD License)                                                               *
+* Author: Sebastien Decugis <sdecugis@freediameter.net>							 *
+*													 *
+* Copyright (c) 2011, WIDE Project and NICT								 *
+* All rights reserved.											 *
+* 													 *
+* Redistribution and use of this software in source and binary forms, with or without modification, are  *
+* permitted provided that the following conditions are met:						 *
+* 													 *
+* * Redistributions of source code must retain the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer.										 *
+*    													 *
+* * Redistributions in binary form must reproduce the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer in the documentation and/or other						 *
+*   materials provided with the distribution.								 *
+* 													 *
+* * Neither the name of the WIDE Project or NICT nor the 						 *
+*   names of its contributors may be used to endorse or 						 *
+*   promote products derived from this software without 						 *
+*   specific prior written permission of WIDE Project and 						 *
+*   NICT.												 *
+* 													 *
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED *
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
+* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR *
+* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 	 *
+* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 	 *
+* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR *
+* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF   *
+* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.								 *
+*********************************************************************************************************/
+
+#include <freeDiameter/extension.h>
+
+/* The function MUST be called this */
+void fd_ext_fini(void)
+{
+	/* This code is executed when the daemon is exiting; cleanup management should be placed here */
+	TRACE_DEBUG(INFO, "Extension is terminated... Bye!");
+	return ;
+}
+
diff --git a/extensions/_sample/hello.cpp b/extensions/_sample/hello.cpp
new file mode 100644
index 0000000..05b340c
--- /dev/null
+++ b/extensions/_sample/hello.cpp
@@ -0,0 +1,48 @@
+/*********************************************************************************************************
+* Software License Agreement (BSD License)                                                               *
+* Author: Sebastien Decugis <sdecugis@freediameter.net>							 *
+*													 *
+* Copyright (c) 2013, WIDE Project and NICT								 *
+* All rights reserved.											 *
+* 													 *
+* Redistribution and use of this software in source and binary forms, with or without modification, are  *
+* permitted provided that the following conditions are met:						 *
+* 													 *
+* * Redistributions of source code must retain the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer.										 *
+*    													 *
+* * Redistributions in binary form must reproduce the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer in the documentation and/or other						 *
+*   materials provided with the distribution.								 *
+* 													 *
+* * Neither the name of the WIDE Project or NICT nor the 						 *
+*   names of its contributors may be used to endorse or 						 *
+*   promote products derived from this software without 						 *
+*   specific prior written permission of WIDE Project and 						 *
+*   NICT.												 *
+* 													 *
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED *
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
+* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR *
+* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 	 *
+* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 	 *
+* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR *
+* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF   *
+* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.								 *
+*********************************************************************************************************/
+
+/* Sample file demonstrating how to write some C++ code */
+
+#include <iostream>
+
+#include <freeDiameter/extension.h>
+
+extern "C" void mycppfunc(); /* will be called from C code */
+
+
+void mycppfunc() {
+	std::cout << "Hello World!" << std::endl;
+	/* done */
+}
diff --git a/extensions/_sample/sample.c b/extensions/_sample/sample.c
new file mode 100644
index 0000000..9072684
--- /dev/null
+++ b/extensions/_sample/sample.c
@@ -0,0 +1,97 @@
+/*********************************************************************************************************
+* Software License Agreement (BSD License)                                                               *
+* Author: Sebastien Decugis <sdecugis@freediameter.net>							 *
+*													 *
+* Copyright (c) 2013, WIDE Project and NICT								 *
+* All rights reserved.											 *
+* 													 *
+* Redistribution and use of this software in source and binary forms, with or without modification, are  *
+* permitted provided that the following conditions are met:						 *
+* 													 *
+* * Redistributions of source code must retain the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer.										 *
+*    													 *
+* * Redistributions in binary form must reproduce the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer in the documentation and/or other						 *
+*   materials provided with the distribution.								 *
+* 													 *
+* * Neither the name of the WIDE Project or NICT nor the 						 *
+*   names of its contributors may be used to endorse or 						 *
+*   promote products derived from this software without 						 *
+*   specific prior written permission of WIDE Project and 						 *
+*   NICT.												 *
+* 													 *
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED *
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
+* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR *
+* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 	 *
+* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 	 *
+* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR *
+* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF   *
+* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.								 *
+*********************************************************************************************************/
+
+/* Sample extension to test extensions mechanism in freeDiameter */
+#include <freeDiameter/extension.h>
+
+/* from sample.cpp */
+void mycppfunc();
+
+static int sample_main(char * conffile);
+
+/* Define the entry point. A convenience macro is provided */
+EXTENSION_ENTRY("sample", sample_main);
+
+/* The extension-specific initialization code */
+static int sample_main(char * conffile)
+{
+	/* The debug macro from main tree can be used the same way */
+	TRACE_ENTRY("%p", conffile);
+	
+	/* This is how we access daemon's global vars */
+	fprintf(stdout, "I am extension " __FILE__ " running on host %s.", fd_g_config->cnf_diamid);
+	
+	/* The configuration file name is received in the conffile var. It's up to extension to parse it */
+	if (conffile) {
+		fprintf(stdout, "I should parse my configuration file there: %s\n", conffile);
+	} else {
+		fprintf(stdout, "I received no configuration file to parse\n");
+	}
+	
+	/* Functions from the libfreediameter can also be used as demonstrated here: */
+	TRACE_DEBUG(INFO, "Let's create that 'Example-AVP'...");
+	{
+		struct dict_object * origin_host_avp = NULL;
+		struct dict_object * session_id_avp = NULL;
+		struct dict_object * example_avp_avp = NULL;
+		struct dict_rule_data rule_data = { NULL, RULE_REQUIRED, 0, -1, 1 };
+		struct dict_avp_data example_avp_data = { 999999, 0, "Example-AVP", AVP_FLAG_VENDOR , 0, AVP_TYPE_GROUPED };
+
+		CHECK_FCT( fd_dict_search ( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Origin-Host", &origin_host_avp, ENOENT));
+		CHECK_FCT( fd_dict_search ( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Session-Id", &session_id_avp, ENOENT));
+		
+		CHECK_FCT( fd_dict_new ( fd_g_config->cnf_dict, DICT_AVP, &example_avp_data , NULL, &example_avp_avp ));
+		
+		rule_data.rule_avp = origin_host_avp;
+		rule_data.rule_min = 1;
+		rule_data.rule_max = 1;
+		CHECK_FCT( fd_dict_new ( fd_g_config->cnf_dict, DICT_RULE, &rule_data, example_avp_avp, NULL ));
+		
+		rule_data.rule_avp = session_id_avp;
+		rule_data.rule_min = 1;
+		rule_data.rule_max = -1;
+		CHECK_FCT( fd_dict_new ( fd_g_config->cnf_dict, DICT_RULE, &rule_data, example_avp_avp, NULL ));
+		
+	}
+	TRACE_DEBUG(INFO, "'Example-AVP' created without error");
+	
+	/* Call the c++ function */
+	mycppfunc();
+	
+	/* The initialization function returns an error code with the standard POSIX meaning (ENOMEM, and so on) */
+	return 0;
+}
+
+/* See file fini.c for an example of destructor */
diff --git a/extensions/acl_wl/CMakeLists.txt b/extensions/acl_wl/CMakeLists.txt
new file mode 100644
index 0000000..bd51150
--- /dev/null
+++ b/extensions/acl_wl/CMakeLists.txt
@@ -0,0 +1,29 @@
+# The acl_wl extension
+PROJECT("Access Control / White List" C)
+
+# Parser files
+BISON_FILE(aw_conf.y)
+FLEX_FILE(aw_conf.l)
+SET_SOURCE_FILES_PROPERTIES(lex.aw_conf.c aw_conf.tab.c PROPERTIES COMPILE_FLAGS "-I ${CMAKE_CURRENT_SOURCE_DIR}")
+
+# List of source files
+SET( ACL_WL_SRC
+	acl_wl.h
+	acl_wl.c
+	aw_tree.c
+	lex.aw_conf.c
+	aw_conf.tab.c
+	aw_conf.tab.h
+)
+
+# Compile as a module
+FD_ADD_EXTENSION(acl_wl ${ACL_WL_SRC})
+
+
+####
+## INSTALL section ##
+
+# We install with the daemon component because it is a base feature.
+INSTALL(TARGETS acl_wl
+	LIBRARY DESTINATION ${INSTALL_EXTENSIONS_SUFFIX}
+	COMPONENT freeDiameter-daemon)
diff --git a/extensions/acl_wl/acl_wl.c b/extensions/acl_wl/acl_wl.c
new file mode 100644
index 0000000..c28ddd9
--- /dev/null
+++ b/extensions/acl_wl/acl_wl.c
@@ -0,0 +1,117 @@
+/*********************************************************************************************************
+* Software License Agreement (BSD License)                                                               *
+* Author: Sebastien Decugis <sdecugis@freediameter.net>							 *
+*													 *
+* Copyright (c) 2011, WIDE Project and NICT								 *
+* All rights reserved.											 *
+* 													 *
+* Redistribution and use of this software in source and binary forms, with or without modification, are  *
+* permitted provided that the following conditions are met:						 *
+* 													 *
+* * Redistributions of source code must retain the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer.										 *
+*    													 *
+* * Redistributions in binary form must reproduce the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer in the documentation and/or other						 *
+*   materials provided with the distribution.								 *
+* 													 *
+* * Neither the name of the WIDE Project or NICT nor the 						 *
+*   names of its contributors may be used to endorse or 						 *
+*   promote products derived from this software without 						 *
+*   specific prior written permission of WIDE Project and 						 *
+*   NICT.												 *
+* 													 *
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED *
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
+* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR *
+* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 	 *
+* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 	 *
+* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR *
+* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF   *
+* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.								 *
+*********************************************************************************************************/
+
+/* 
+ * Whitelist extension for freeDiameter.
+ */
+
+#include "acl_wl.h"
+
+/* The validator function */
+static int aw_validate(struct peer_info * info, int * auth, int (**cb2)(struct peer_info *))
+{
+	int res;
+	
+	TRACE_ENTRY("%p %p %p", info, auth, cb2);
+	
+	CHECK_PARAMS(info && auth && cb2);
+	
+	/* We don't use the second callback */
+	*cb2 = NULL;
+	
+	/* Default to unknown result */
+	*auth = 0;
+	
+	/* Now search the peer in our tree */
+	CHECK_FCT( aw_tree_lookup(info->pi_diamid, &res) );
+	if (res < 0) {
+		/* The peer is not whitelisted */
+		return 0;
+	}
+	
+	/* We found the peer in the tree, now check the status */
+	
+	/* First, if TLS is already in place, just accept */
+	if (info->runtime.pir_cert_list) {
+		*auth = 1;
+		return 0;
+	}
+	
+	/* Now, if we did not specify any flag, reject */
+	if (res == 0) {
+		TRACE_DEBUG(INFO, "Peer '%s' rejected, only TLS-protected connection is whitelisted.", info->pi_diamid);
+		/* We don't actually set *auth = -1, leave space for a further extension to validate the peer */
+		return 0;
+	}
+	
+	/* Otherwise, just set the configured flags for the peer, and authorize it */
+	*auth = 1;
+	
+	/* Save information about the security mechanism to use after CER/CEA exchange */
+	if ((res & PI_SEC_NONE) && (res & PI_SEC_TLS_OLD))
+		res = PI_SEC_NONE; /* If we authorized it, we must have an IPsec tunnel setup, no need for TLS in this case */
+	
+	info->config.pic_flags.sec = res;
+	return 0;
+}
+
+/* entry point */
+static int aw_entry(char * conffile)
+{
+	TRACE_ENTRY("%p", conffile);
+	CHECK_PARAMS(conffile);
+	
+	/* Parse configuration file */
+	CHECK_FCT( aw_conf_handle(conffile) );
+	
+	TRACE_DEBUG(INFO, "Extension ACL_wl initialized with configuration: '%s'", conffile);
+	if (TRACE_BOOL(ANNOYING)) {
+		aw_tree_dump();
+	}
+	
+	/* Register the validator function */
+	CHECK_FCT( fd_peer_validate_register ( aw_validate ) );
+
+	return 0;
+}
+
+/* Unload */
+void fd_ext_fini(void)
+{
+	/* Destroy the tree */
+	aw_tree_destroy();
+}
+
+EXTENSION_ENTRY("acl_wl", aw_entry);
diff --git a/extensions/acl_wl/acl_wl.h b/extensions/acl_wl/acl_wl.h
new file mode 100644
index 0000000..8606c2a
--- /dev/null
+++ b/extensions/acl_wl/acl_wl.h
@@ -0,0 +1,60 @@
+/*********************************************************************************************************
+* Software License Agreement (BSD License)                                                               *
+* Author: Sebastien Decugis <sdecugis@freediameter.net>							 *
+*													 *
+* Copyright (c) 2011, WIDE Project and NICT								 *
+* All rights reserved.											 *
+* 													 *
+* Redistribution and use of this software in source and binary forms, with or without modification, are  *
+* permitted provided that the following conditions are met:						 *
+* 													 *
+* * Redistributions of source code must retain the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer.										 *
+*    													 *
+* * Redistributions in binary form must reproduce the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer in the documentation and/or other						 *
+*   materials provided with the distribution.								 *
+* 													 *
+* * Neither the name of the WIDE Project or NICT nor the 						 *
+*   names of its contributors may be used to endorse or 						 *
+*   promote products derived from this software without 						 *
+*   specific prior written permission of WIDE Project and 						 *
+*   NICT.												 *
+* 													 *
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED *
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
+* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR *
+* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 	 *
+* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 	 *
+* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR *
+* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF   *
+* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.								 *
+*********************************************************************************************************/
+
+/* Header file for the acl_wl extension. 
+ *
+ *  This extension provides a simple mechanism to allow connections from remote peers
+ * without actively maintaining a connection to these peers.
+ *
+ *  See the acl_wl.conf.sample file for the format of the configuration file.
+ */
+ 
+#include <freeDiameter/extension.h>
+
+/* Parse the configuration file */
+int aw_conf_handle(char * conffile);
+
+/* Add to the tree (name is \0 terminated) */
+int aw_tree_add(char * name, int flags);
+
+/* Search in the tree. On return, *result =  -1: not found; >=0: found with PI_SEC_* flags */
+int aw_tree_lookup(char * name, int * result);
+
+/* Cleanup the tree */
+void aw_tree_destroy(void);
+
+/* For debug */
+void aw_tree_dump(void);
+
diff --git a/extensions/acl_wl/aw_conf.l b/extensions/acl_wl/aw_conf.l
new file mode 100644
index 0000000..d6b55c8
--- /dev/null
+++ b/extensions/acl_wl/aw_conf.l
@@ -0,0 +1,103 @@
+/*********************************************************************************************************
+* Software License Agreement (BSD License)                                                               *
+* Author: Sebastien Decugis <sdecugis@freediameter.net>							 *
+*													 *
+* Copyright (c) 2013, WIDE Project and NICT								 *
+* All rights reserved.											 *
+* 													 *
+* Redistribution and use of this software in source and binary forms, with or without modification, are  *
+* permitted provided that the following conditions are met:						 *
+* 													 *
+* * Redistributions of source code must retain the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer.										 *
+*    													 *
+* * Redistributions in binary form must reproduce the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer in the documentation and/or other						 *
+*   materials provided with the distribution.								 *
+* 													 *
+* * Neither the name of the WIDE Project or NICT nor the 						 *
+*   names of its contributors may be used to endorse or 						 *
+*   promote products derived from this software without 						 *
+*   specific prior written permission of WIDE Project and 						 *
+*   NICT.												 *
+* 													 *
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED *
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
+* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR *
+* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 	 *
+* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 	 *
+* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR *
+* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF   *
+* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.								 *
+*********************************************************************************************************/
+
+/* Lex extension's configuration parser.
+ *
+ * The configuration file contains a default priority, and a list of peers with optional overwite priority.
+ * -- see the app_test.conf.sample file for more detail.
+ */
+
+%{
+#include "acl_wl.h"
+/* Include yacc tokens definitions */
+#include "aw_conf.tab.h"
+
+/* Update the column information */
+#define YY_USER_ACTION { 						\
+	yylloc->first_column = yylloc->last_column + 1; 		\
+	yylloc->last_column = yylloc->first_column + yyleng - 1;	\
+}
+
+/* Avoid warning with newer flex */
+#define YY_NO_INPUT
+
+static int curflag = 0;
+
+%}
+
+%option bison-bridge bison-locations
+%option noyywrap
+%option nounput
+
+%%
+
+	/* Update the line count, reset flag value */
+\n			{
+				yylloc->first_line++; 
+				yylloc->last_line++; 
+				yylloc->last_column=0; 
+				curflag = 0;
+			}
+	 
+	/* Eat all spaces but not new lines */
+([[:space:]]{-}[\n])+	;
+	/* Eat all comments */
+#.*$			;
+
+	/* Match the two allowed flags directly in LEX */
+ALLOW_IPSEC		{
+				curflag |= PI_SEC_NONE;
+			}
+
+ALLOW_OLD_TLS		{
+				curflag |= PI_SEC_TLS_OLD;
+			}
+
+	/* Any other string is considered a fqdn or partial fqdn with a star. The star can only be the first label. */
+(\*|[[:alnum:]][[:alnum:]-]*)(\.[[:alnum:]][[:alnum:]-]*)+	{
+				/* We matched a valid label, let's directly save it into the tree. The function will issue the appropriate warnings. */
+				CHECK_FCT_DO( aw_tree_add(yytext, curflag), return LEX_ERROR);
+				yylval->string = yytext;
+				return FQDN;
+			}
+
+	/* No match */
+<*>[[:alnum:]]+		|	/* This rule is only useful to print a complete token in error messages */
+<*>.			{
+				TRACE_ERROR("Unrecognized text on line %d col %d: '%s'.", yylloc->first_line, yylloc->first_column, yytext);
+			 	return LEX_ERROR; 
+			}
+
+%%
diff --git a/extensions/acl_wl/aw_conf.y b/extensions/acl_wl/aw_conf.y
new file mode 100644
index 0000000..4ace8e5
--- /dev/null
+++ b/extensions/acl_wl/aw_conf.y
@@ -0,0 +1,141 @@
+/*********************************************************************************************************
+* Software License Agreement (BSD License)                                                               *
+* Author: Sebastien Decugis <sdecugis@freediameter.net>							 *
+*													 *
+* Copyright (c) 2013, WIDE Project and NICT								 *
+* All rights reserved.											 *
+* 													 *
+* Redistribution and use of this software in source and binary forms, with or without modification, are  *
+* permitted provided that the following conditions are met:						 *
+* 													 *
+* * Redistributions of source code must retain the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer.										 *
+*    													 *
+* * Redistributions in binary form must reproduce the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer in the documentation and/or other						 *
+*   materials provided with the distribution.								 *
+* 													 *
+* * Neither the name of the WIDE Project or NICT nor the 						 *
+*   names of its contributors may be used to endorse or 						 *
+*   promote products derived from this software without 						 *
+*   specific prior written permission of WIDE Project and 						 *
+*   NICT.												 *
+* 													 *
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED *
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
+* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR *
+* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 	 *
+* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 	 *
+* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR *
+* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF   *
+* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.								 *
+*********************************************************************************************************/
+
+/* Yacc extension's configuration parser.
+ * See doc/acl_wl.conf.sample for configuration file format
+ */
+
+/* For development only : */
+%debug 
+%error-verbose
+
+/* The parser receives the configuration file filename as parameter */
+%parse-param {char * conffile}
+
+/* Keep track of location */
+%locations 
+%pure-parser
+
+%{
+#include "acl_wl.h"
+#include "aw_conf.tab.h"	/* bison is not smart enough to define the YYLTYPE before including this code, so... */
+
+#include <string.h>
+#include <errno.h>
+
+/* Forward declaration */
+int yyparse(char * conffile);
+
+static int fqdn_added = 0;
+
+/* Parse the configuration file */
+int aw_conf_handle(char * conffile)
+{
+	extern FILE * aw_confin;
+	int ret;
+	
+	TRACE_ENTRY("%p", conffile);
+	
+	TRACE_DEBUG (FULL, "Parsing configuration file: %s...", conffile);
+	
+	aw_confin = fopen(conffile, "r");
+	if (aw_confin == NULL) {
+		ret = errno;
+		fd_log_debug("Unable to open extension configuration file %s for reading: %s", conffile, strerror(ret));
+		TRACE_DEBUG (INFO, "Error occurred, message logged -- configuration file.");
+		return ret;
+	}
+
+	ret = yyparse(conffile);
+
+	fclose(aw_confin);
+
+	if (ret != 0) {
+		TRACE_DEBUG (INFO, "Unable to parse the configuration file.");
+		return EINVAL;
+	} else {
+		TRACE_DEBUG(FULL, "Read %d FQDN entries successfully.", fqdn_added);
+	}
+	
+	return 0;
+}
+
+/* The Lex parser prototype */
+int aw_conflex(YYSTYPE *lvalp, YYLTYPE *llocp);
+
+/* Function to report the errors */
+void yyerror (YYLTYPE *ploc, char * conffile, char const *s)
+{
+	TRACE_DEBUG(INFO, "Error in configuration parsing");
+	
+	if (ploc->first_line != ploc->last_line)
+		fd_log_debug("%s:%d.%d-%d.%d : %s", conffile, ploc->first_line, ploc->first_column, ploc->last_line, ploc->last_column, s);
+	else if (ploc->first_column != ploc->last_column)
+		fd_log_debug("%s:%d.%d-%d : %s", conffile, ploc->first_line, ploc->first_column, ploc->last_column, s);
+	else
+		fd_log_debug("%s:%d.%d : %s", conffile, ploc->first_line, ploc->first_column, s);
+}
+
+%}
+
+/* Values returned by lex for token */
+%union {
+	char 		 *string;
+}
+
+/* In case of error in the lexical analysis */
+%token 		LEX_ERROR
+
+/* Key words */
+%token <string>	FQDN
+
+
+/* -------------------------------------- */
+%%
+
+	/* The grammar definition */
+conffile:		/* empty grammar is OK */
+			| conffile FQDN
+			{
+				fqdn_added++;
+				TRACE_DEBUG(FULL, "Added FQDN: %s", $2);
+			}
+			| conffile LEX_ERROR
+			{
+				yyerror(&yylloc, conffile, "An error occurred while parsing the configuration file");
+				return EINVAL;
+			}
+			;
+
diff --git a/extensions/acl_wl/aw_tree.c b/extensions/acl_wl/aw_tree.c
new file mode 100644
index 0000000..9b9cbd8
--- /dev/null
+++ b/extensions/acl_wl/aw_tree.c
@@ -0,0 +1,413 @@
+/*********************************************************************************************************
+* Software License Agreement (BSD License)                                                               *
+* Author: Sebastien Decugis <sdecugis@freediameter.net>							 *
+*													 *
+* Copyright (c) 2013, WIDE Project and NICT								 *
+* All rights reserved.											 *
+* 													 *
+* Redistribution and use of this software in source and binary forms, with or without modification, are  *
+* permitted provided that the following conditions are met:						 *
+* 													 *
+* * Redistributions of source code must retain the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer.										 *
+*    													 *
+* * Redistributions in binary form must reproduce the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer in the documentation and/or other						 *
+*   materials provided with the distribution.								 *
+* 													 *
+* * Neither the name of the WIDE Project or NICT nor the 						 *
+*   names of its contributors may be used to endorse or 						 *
+*   promote products derived from this software without 						 *
+*   specific prior written permission of WIDE Project and 						 *
+*   NICT.												 *
+* 													 *
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED *
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
+* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR *
+* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 	 *
+* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 	 *
+* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR *
+* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF   *
+* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.								 *
+*********************************************************************************************************/
+
+#include "acl_wl.h"
+
+/* The configuration simply contains the allowed fqdn and/or domains (*.example.net)
+ * It is represented similarly to the DNS tree:
+ *              (root)--___
+ *              /    \     \
+ *            tld1  tld2   (tld3...)
+ *             /      |
+ *          label1   label2
+ *                    /   \
+ *                 lbl21 lbl22
+ *                  /       \
+ *               lbl211      *
+ *
+ * This tree would whitelist:
+ *   - label1.tld1
+ *   - lbl211.lbl21.label2.tld2
+ *   - *.lbl22.label2.tld2
+ *
+ * The functions to add and search the tree are in aw_tree.c.
+ *
+ */
+ 
+/* Maximum depth of the tree. We set a static size to avoid dynamic allocations. We report an error if this is not sufficient. */
+#define AW_TREE_MAXDEPTH 10
+
+/* An element of the tree */
+struct tree_item {
+	struct fd_list	chain;		/* Link to elements at the same level. Ordered alphabetically. */
+	struct fd_list	children;	/* Sentinel for the subtree. */
+	char *		str;	/* the \0 terminated label, or NULL if it is a generic container ("*") */
+	int		flags;	/* PI_SEC_* flags */
+	int		leaf;	/* true if this item can be a leaf of the tree */
+};
+
+/* The root of the tree */
+static struct fd_list tree_root = FD_LIST_INITIALIZER(tree_root);
+
+/* Note: we don't need to lock, since we add only when parsing the conf, and then read only */
+
+
+/* The parsed name */
+struct split_name {
+	struct {
+		char * str;	/* start of this label */
+		size_t len;	/* length of this label. It does not include the final "." or "\0" */
+	}   label[AW_TREE_MAXDEPTH];
+	int last_lbl;	/* idx of last label defined */
+};
+
+/* The following function explodes a name into a split_name structure */
+static int parse_name(char * name, struct split_name * result)
+{
+	int i, l, prev_offset;
+	
+	TRACE_ENTRY("%p %p", name, result);
+	
+	/* First, initialize the result array */
+	memset(result, 0, sizeof(struct split_name));
+	result->label[0].str = name;
+	l = 0; prev_offset = 0;
+	
+	for (i=0; name[i] != '\0'; i++) {
+		if (name[i]=='.') {
+			l++;
+			CHECK_PARAMS( l < AW_TREE_MAXDEPTH );
+			
+			/* The previous label is complete, write its size */
+			result->label[l - 1].len = i - prev_offset;
+			prev_offset = i + 1;
+			
+			/* Write the start of the new label */
+			result->label[l].str = name + i + 1;
+		}
+	}
+	
+	/* Finally, write the size of the last label */
+	result->label[l].len = i - prev_offset;
+	
+	result->last_lbl = l;
+	
+#if 0
+	fd_log_debug("Parsed name %s as:", name);
+	for (i=0; i<=l; i++)
+		fd_log_debug("  str[%d] len: %d, v:%.*s", i, result->label[i].len, result->label[i].len, result->label[i].str);
+#endif /* 0 */
+	return 0;
+}
+
+/* Create a new tree_item structure */
+static struct tree_item * new_ti(char * str, size_t len, int flags, int leaf)
+{
+	struct tree_item * ti;
+	char * s = NULL;
+	
+	TRACE_ENTRY("%p %zd %x", str, len, flags);
+	
+	if (str) {
+		CHECK_MALLOC_DO(s = malloc(len + 1), return NULL);
+		memcpy(s, str, len);
+		s[len] = '\0';
+	}
+	
+	CHECK_MALLOC_DO( ti = malloc(sizeof(struct tree_item)), {free(s); return NULL; } );
+	memset(ti, 0, sizeof(struct tree_item));
+	
+	fd_list_init(&ti->chain, ti);
+	fd_list_init(&ti->children, ti);
+	ti->str = s;
+	ti->flags = flags;
+	ti->leaf = leaf;
+	
+	return ti;
+}
+
+/* Recursively delete a subtree */
+static void delete_tree(struct fd_list * senti)
+{
+	while (!FD_IS_LIST_EMPTY(senti)) {
+		struct tree_item * ti = (struct tree_item *)(senti->next);
+		
+		/* Delete recursively its children first */
+		delete_tree(&ti->children);
+		
+		/* Now, unlink from the sentinel list */
+		fd_list_unlink(&ti->chain);
+		
+		/* destroy this tree item */
+		free(ti->str);
+		free(ti);
+	}
+}
+
+/* Top-level destroy function */
+void aw_tree_destroy(void)
+{
+	delete_tree(&tree_root);
+}
+
+/* Display the content of a subtree */
+static void tree_dump(struct fd_list * sub, int indent)
+{
+	struct fd_list * li;
+	for (li = sub->next; li != sub; li = li->next) {
+		struct tree_item * ti = (struct tree_item *)li;
+		char buf[1024];
+		snprintf(buf, sizeof(buf), "%*s%s", indent * 2, "", ti->str?:"*");
+		if (ti->leaf)
+			snprintf(buf+strlen(buf), sizeof(buf)-strlen(buf), " (flag:%x)", ti->flags);
+		fd_log_debug("%s", buf);
+		tree_dump(&ti->children, indent + 1);
+	}
+}
+
+/* Top-level function */
+void aw_tree_dump(void)
+{
+	fd_log_debug("[acl_wl] tree dump:");
+	fd_log_debug("(root)");
+	tree_dump(&tree_root, 1);
+	fd_log_debug("[acl_wl] end of dump");
+}
+
+/* Function to add a new entry in the tree */
+int aw_tree_add(char * name, int flags)
+{
+	struct split_name sn;
+	struct tree_item * ti;
+	struct fd_list * li, *senti;
+	int lbl, found;
+	
+	TRACE_ENTRY("%p %x", name, flags);
+	CHECK_PARAMS(name && *name);
+	
+	CHECK_FCT_DO( parse_name(name, &sn), 
+		{ 
+			fd_log_debug("The name '%s' contains too many labels, try a generic (*) or recompile with bigger AW_TREE_MAXDEPTH value (cur: %d)", name, AW_TREE_MAXDEPTH); 
+			return EINVAL; 
+		} );
+		
+	senti = &tree_root;
+	
+	for (lbl = sn.last_lbl; lbl > 0; lbl--) {
+		/* Check if the list is empty, we can directly create the new entry */
+		if (FD_IS_LIST_EMPTY(senti)) {
+			CHECK_MALLOC( ti = new_ti(sn.label[lbl].str, sn.label[lbl].len, 0, 0 /* flags are only set in the terminals */) );
+			/* Insert this label in the sentinel sublist */
+			fd_list_insert_after(senti, &ti->chain);
+			/* Update the sentinel */
+			senti = &ti->children;
+			/* loop to the next label */
+			continue;
+		}
+		
+		/* Check if we have a '*' element already that overlapses */
+		ti = (struct tree_item *)(senti->next);
+		if (ti->str == NULL) {
+			fd_log_debug("[acl_wl] Warning: entry '%s' is superseeded by a generic entry at label %d, ignoring.", name, lbl + 1);
+			return 0;
+		}
+		
+		/* Search this label in the ordered list */
+		found = 0;
+		for (li = senti->next; li != senti; li=li->next) {
+			int cmp, len;
+			ti = (struct tree_item *)li;
+			
+			cmp = strncasecmp(ti->str, sn.label[lbl].str, sn.label[lbl].len);
+			if (cmp > 0)
+				break;	/* the new label must be inserted before li */
+			if (cmp < 0)
+				continue;
+			
+			/* Check the lengths */
+			len = strlen(ti->str);
+			if (len > sn.label[lbl].len)
+				break;	/* the new label must be inserted before li */
+			if (len < sn.label[lbl].len)
+				continue;
+			
+			/* We already had this label */
+			found = 1;
+			senti = &ti->children;
+			break;
+		}
+		
+		if (found)
+			continue;
+		
+		/* Otherwise, we have to create a new ti, and add it before li */
+		CHECK_MALLOC( ti = new_ti(sn.label[lbl].str, sn.label[lbl].len, 0, 0 /* flags are only set in the terminals */) );
+		/* Insert this label in the sentinel sublist */
+		fd_list_insert_before(li, &ti->chain);
+		/* Update the sentinel */
+		senti = &ti->children;
+	}
+	
+	ti = NULL;
+	li = senti;
+	
+	/* At this point, senti points to the list where we are supposed to insert our last label. */
+	if (sn.label[0].str[0] == '*') {
+		if (!FD_IS_LIST_EMPTY(senti)) {
+			fd_log_debug("[acl_wl] Warning: entry '%s' overwrites previous more detailed entries, these are deleted.", name);
+			delete_tree(senti);
+		}
+		
+		/* Create the new entry */
+		CHECK_MALLOC( ti = new_ti(NULL, 0, flags, 1) );
+	} else {
+		if (!FD_IS_LIST_EMPTY(senti)) {
+			/* Check we don't have a '*' entry already */
+			ti = (struct tree_item *)(senti->next);
+			if (ti->str == NULL) {
+				fd_log_debug("[acl_wl] Warning: entry '%s' is superseeded by a generic entry at label 1, ignoring.", name);
+				return 0;
+			}
+			
+			/* Search the place for the new label */
+			for (li = senti->next; li != senti; li=li->next) {
+				int cmp, len;
+				ti = (struct tree_item *)li;
+
+				cmp = strncasecmp(ti->str, sn.label[0].str, sn.label[0].len);
+				if (cmp > 0)
+					break;	/* the new label must be inserted before li */
+				if (cmp < 0)
+					continue;
+
+				/* Check the lengths */
+				len = strlen(ti->str);
+				if (len > sn.label[0].len)
+					break;	/* the new label must be inserted before li */
+				if (len < sn.label[0].len)
+					continue;
+
+				/* We already had this label */
+				if (ti->leaf) {
+					fd_log_debug("[acl_wl] Warning: entry '%s' is duplicated, merging the flags.", name);
+					ti->flags |= flags;
+					return 0;
+				} else {
+					/* Just mark this entry as a valid leaf also */
+					ti->leaf = 1;
+					ti->flags = flags;
+					return 0;
+				}
+			}
+		}
+		
+		/* Create the new entry */
+		CHECK_MALLOC( ti = new_ti(sn.label[0].str, sn.label[0].len, flags, 1) );
+	}
+	
+	/* The new label is "ti", it is inserted before "li" */
+	fd_list_insert_before(li, &ti->chain);
+	
+	/* Done! */
+	return 0;
+}
+
+/* Search in the tree. On return, *result =  -1: not found; >=0: found with PI_SEC_* flags */
+int aw_tree_lookup(char * name, int * result)
+{
+	struct split_name sn;
+	int lbl, found;
+	struct tree_item * ti;
+	struct fd_list * senti, *li;
+	
+	TRACE_ENTRY("%p %p", name, result);
+	CHECK_PARAMS(name && result);
+	
+	/* Initialize */
+	*result = -1;
+	
+	/* Parse the name into labels */
+	CHECK_FCT_DO( parse_name(name, &sn), 
+		{ 
+			TRACE_DEBUG(INFO, "Too many labels in this name, it cannot be found in the tree, skipping."); 
+			return 0;
+		} );
+	
+	senti = &tree_root;
+	
+	for (lbl = sn.last_lbl; lbl >= 0; lbl--) {
+		/* Check if the list is empty, we can directly return */
+		if (FD_IS_LIST_EMPTY(senti)) {
+			/* The item is not found */
+			return 0;
+		}
+		
+		/* Check if we have a '*' element */
+		ti = (struct tree_item *)(senti->next);
+		if (ti->str == NULL) {
+			TRACE_DEBUG(ANNOYING, "[acl_wl] %s matched at label %d with a generic entry.", name, lbl + 1);
+			*result = ti->flags;
+			return 0;
+		}
+
+		/* Search this label in the ordered list */
+		found = 0;
+		for (li = senti->next; li != senti; li=li->next) {
+			int cmp, len;
+			ti = (struct tree_item *)li;
+			
+			cmp = strncasecmp(ti->str, sn.label[lbl].str, sn.label[lbl].len);
+			if (cmp > 0)
+				return 0;	/* the label was not found */
+			if (cmp < 0)
+				continue;
+			
+			/* Check the lengths */
+			len = strlen(ti->str);
+			if (len > sn.label[lbl].len)
+				return 0;	/* the label was not found */
+			if (len < sn.label[lbl].len)
+				continue;
+			
+			/* We found the label */
+			found = 1;
+			senti = &ti->children;
+			break;
+		}
+		
+		if (!found)
+			return 0; /* label not found */
+		
+		/* otherwise, continue, sentinel has been updated */
+	}
+	
+	/* At the end, ti points to the correct leaf */
+	if (!ti->leaf)
+		return 0;
+	
+	TRACE_DEBUG(ANNOYING, "[acl_wl] %s matched exactly.", name);
+	*result = ti->flags;
+	return 0;
+}
diff --git a/extensions/app_acct/CMakeLists.txt b/extensions/app_acct/CMakeLists.txt
new file mode 100644
index 0000000..433ca5d
--- /dev/null
+++ b/extensions/app_acct/CMakeLists.txt
@@ -0,0 +1,38 @@
+# The app_acct extension
+PROJECT("Simple Accounting server" C)
+
+########################
+# Search for libpg (postgresql package)
+FIND_PACKAGE(PostgreSQL REQUIRED)
+INCLUDE_DIRECTORIES(${POSTGRESQL_INCLUDE_DIR})
+
+########################
+# Parser files
+BISON_FILE(acct_conf.y)
+FLEX_FILE(acct_conf.l)
+SET_SOURCE_FILES_PROPERTIES(lex.acct_conf.c acct_conf.tab.c PROPERTIES COMPILE_FLAGS "-I ${CMAKE_CURRENT_SOURCE_DIR}")
+
+# List of source files
+SET( APP_ACCT_SRC
+	app_acct.h
+	app_acct.c
+	acct_db.c
+	acct_records.c
+)
+SET( APP_ACCT_SRC_GEN
+	lex.acct_conf.c
+	acct_conf.tab.c
+	acct_conf.tab.h
+)
+
+# Compile as a module
+FD_ADD_EXTENSION(app_acct ${APP_ACCT_SRC} ${APP_ACCT_SRC_GEN})
+TARGET_LINK_LIBRARIES(app_acct ${POSTGRESQL_LIBRARIES})
+
+
+####
+## INSTALL section ##
+
+INSTALL(TARGETS app_acct
+	LIBRARY DESTINATION ${INSTALL_EXTENSIONS_SUFFIX}
+	COMPONENT freeDiameter-accounting-server)
diff --git a/extensions/app_acct/acct_conf.l b/extensions/app_acct/acct_conf.l
new file mode 100644
index 0000000..c25de1a
--- /dev/null
+++ b/extensions/app_acct/acct_conf.l
@@ -0,0 +1,143 @@
+/*********************************************************************************************************
+* Software License Agreement (BSD License)                                                               *
+* Author: Sebastien Decugis <sdecugis@freediameter.net>							 *
+*													 *
+* Copyright (c) 2013, WIDE Project and NICT								 *
+* All rights reserved.											 *
+* 													 *
+* Redistribution and use of this software in source and binary forms, with or without modification, are  *
+* permitted provided that the following conditions are met:						 *
+* 													 *
+* * Redistributions of source code must retain the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer.										 *
+*    													 *
+* * Redistributions in binary form must reproduce the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer in the documentation and/or other						 *
+*   materials provided with the distribution.								 *
+* 													 *
+* * Neither the name of the WIDE Project or NICT nor the 						 *
+*   names of its contributors may be used to endorse or 						 *
+*   promote products derived from this software without 						 *
+*   specific prior written permission of WIDE Project and 						 *
+*   NICT.												 *
+* 													 *
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED *
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
+* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR *
+* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 	 *
+* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 	 *
+* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR *
+* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF   *
+* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.								 *
+*********************************************************************************************************/
+
+/* Lex extension's configuration parser.
+ *
+ */
+
+%{
+#include "app_acct.h"
+#include "acct_conf.tab.h"
+
+/* Update the column information */
+#define YY_USER_ACTION { 						\
+	yylloc->first_column = yylloc->last_column + 1; 		\
+	yylloc->last_column = yylloc->first_column + yyleng - 1;	\
+}
+
+/* Avoid warning with newer flex */
+#define YY_NO_INPUT
+
+%}
+
+%option bison-bridge bison-locations
+%option noyywrap
+%option nounput
+
+/* Quoted string. Multilines do not match. */
+qstring		\"[^\"\n]*\"
+
+%%
+
+	/* Update the line count */
+\n			{
+				yylloc->first_line++; 
+				yylloc->last_line++; 
+				yylloc->last_column=0; 
+			}
+	 
+	/* Eat all spaces but not new lines */
+([[:space:]]{-}[\n])+	;
+	/* Eat all comments */
+#.*$			;
+
+	/* Recognize any integer */
+[-]?[[:digit:]]+		{
+				/* Convert this to an integer value */
+				int ret=0;
+				ret = sscanf(yytext, "%i", &yylval->integer);
+				if (ret != 1) {
+					/* No matching: an error occurred */
+					fd_log_debug("Unable to convert the value '%s' to a valid number: %s", yytext, strerror(errno));
+					return LEX_ERROR; /* trig an error in yacc parser */
+					/* Maybe we could REJECT instead of failing here? */
+				}
+				return INTEGER;
+			}
+
+	/* Recognize quoted strings -- we do not support escaped \" in the string currently. */
+{qstring}		{
+				/* Match a quoted string. Let's be very permissive. */
+				yylval->string = strdup(yytext+1);
+				if (!yylval->string) {
+					fd_log_debug("Unable to copy the string '%s': %s", yytext, strerror(errno));
+					TRACE_DEBUG(INFO, "strdup failed");
+					return LEX_ERROR; /* trig an error in yacc parser */
+				}
+				yylval->string[strlen(yytext) - 2] = '\0';
+				return QSTRING;
+			}
+			
+	/* Recognize the tokens */	
+(?i:"ConnInfo")		{
+				return CONNINFO;
+			}
+
+(?i:"Table")		{
+				return TABLE;
+			}
+
+(?i:"Timestamp_field")	{
+				return TSFIELD;
+			}
+
+(?i:"Server_name_field") {
+				return SRVNFIELD;
+			}
+
+(?i:"field")		{
+				return FIELD;
+			}
+
+(?i:"required")		{
+				return REQUIRED;
+			}
+
+(?i:"multi")		{
+				return MULTI;
+			}
+
+
+			
+	/* Valid single characters for yyparse */
+[=;{}]			{ return yytext[0]; }
+
+	/* Unrecognized sequence, if it did not match any previous pattern */
+[^[:space:]"*=>;\n]+	{ 
+				fd_log_debug("Unrecognized text on line %d col %d: '%s'.", yylloc->first_line, yylloc->first_column, yytext);
+			 	return LEX_ERROR; 
+			}
+
+%%
diff --git a/extensions/app_acct/acct_conf.y b/extensions/app_acct/acct_conf.y
new file mode 100644
index 0000000..f79f1fa
--- /dev/null
+++ b/extensions/app_acct/acct_conf.y
@@ -0,0 +1,336 @@
+/*********************************************************************************************************
+* Software License Agreement (BSD License)                                                               *
+* Author: Sebastien Decugis <sdecugis@freediameter.net>							 *
+*													 *
+* Copyright (c) 2015, WIDE Project and NICT								 *
+* All rights reserved.											 *
+* 													 *
+* Redistribution and use of this software in source and binary forms, with or without modification, are  *
+* permitted provided that the following conditions are met:						 *
+* 													 *
+* * Redistributions of source code must retain the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer.										 *
+*    													 *
+* * Redistributions in binary form must reproduce the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer in the documentation and/or other						 *
+*   materials provided with the distribution.								 *
+* 													 *
+* * Neither the name of the WIDE Project or NICT nor the 						 *
+*   names of its contributors may be used to endorse or 						 *
+*   promote products derived from this software without 						 *
+*   specific prior written permission of WIDE Project and 						 *
+*   NICT.												 *
+* 													 *
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED *
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
+* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR *
+* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 	 *
+* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 	 *
+* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR *
+* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF   *
+* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.								 *
+*********************************************************************************************************/
+
+/* Yacc extension's configuration parser.
+ * See doc/app_acct.conf.sample for configuration file format
+ */
+
+/* For development only : */
+%debug 
+%error-verbose
+
+/* The parser receives the configuration file filename as parameter */
+%parse-param {char * conffile}
+
+/* Keep track of location */
+%locations 
+%pure-parser
+
+%{
+#include "app_acct.h"
+#include "acct_conf.tab.h"
+
+#include <string.h>
+#include <errno.h>
+
+/* Forward declaration */
+int yyparse(char * conffile);
+
+/* The Lex parser prototype */
+int acct_conflex(YYSTYPE *lvalp, YYLTYPE *llocp);
+
+/* the global configuration */
+struct acct_conf * acct_config = NULL;
+
+/* Initialize the blank configuration structure */
+int acct_conf_init(void)
+{
+	TRACE_ENTRY();
+	
+	CHECK_MALLOC( acct_config = malloc(sizeof(struct acct_conf)) );
+	memset(acct_config, 0, sizeof(struct acct_conf) );
+	fd_list_init(&acct_config->avps, NULL);
+	
+	return 0;
+}
+
+/* Validate and eventually display the content of the configuration file for debug */
+int acct_conf_check(char * conffile)
+{
+	CHECK_PARAMS(acct_config);
+	
+	if ( ! acct_config->conninfo) {
+		fd_log_debug("[app_acct] ERROR: 'ConnInfo' is missing in file '%s'."
+			" You can specify 'ConnInfo=\"\";' to use default parameters.", conffile);
+		return EINVAL;
+	}
+	if ( ! acct_config->tablename) {
+		fd_log_debug("[app_acct] ERROR: 'Table' value is missing in file '%s'.", conffile);
+		return EINVAL;
+	}
+
+	if (!TRACE_BOOL(FULL))
+		return 0;
+	
+	struct fd_list * li;
+		
+	fd_log_debug("[app_acct] Configuration dump:");
+	fd_log_debug(" Database:");
+	fd_log_debug("   ConnInfo ...... : '%s'", acct_config->conninfo ?: "<null>");
+	fd_log_debug("   Table name .... : '%s'", acct_config->tablename ?: "<null>");
+	fd_log_debug("   Timestamp field : '%s'", acct_config->tsfield ?: "<null>");
+	fd_log_debug("   Server name fld : '%s'", acct_config->srvnfield ?: "<null>");
+	fd_log_debug(" AVPs that will be saved to the database:");
+	for (li = acct_config->avps.next; li != &acct_config->avps; li = li->next) {
+		struct acct_conf_avp * a = (struct acct_conf_avp *)li;
+		fd_log_debug("   %-*s AVP%s saved in ", 30, a->avpname, a->required ? " [required]":"" );
+		if (a->multi) {
+			fd_log_debug("fields '%s[1..%d]' ", a->field?:a->avpname, a->multi);
+		} else {
+			fd_log_debug("field '%s' ", a->field?:a->avpname);
+		}
+		fd_log_debug("as ::%s", diam2db_types_mapping[a->avptype]);
+	}
+	fd_log_debug("[app_acct] Complete.");
+	return 0;
+}
+
+void acct_conf_free(void)
+{
+	TRACE_ENTRY();
+	
+	if (!acct_config)
+		return;
+		
+	/* Destroy the list */
+	while (!FD_IS_LIST_EMPTY(&acct_config->avps)) {
+		struct acct_conf_avp * a = (struct acct_conf_avp *)(acct_config->avps.next);
+		fd_list_unlink(&a->chain);
+		free(a->avpname);
+		free(a->field);
+		free(a);
+	}
+	
+	/* destroy other data */
+	free(acct_config->conninfo);
+	free(acct_config->tablename);
+	free(acct_config->tsfield);
+	free(acct_config->srvnfield);
+	
+	/* Done */
+	free(acct_config);
+	acct_config = NULL;
+}
+
+/* Parse the configuration file */
+int acct_conf_parse(char * conffile)
+{
+	extern FILE * acct_confin;
+	int ret;
+	
+	TRACE_ENTRY("%p", conffile);
+	
+	TRACE_DEBUG (FULL, "Parsing configuration file: %s...", conffile);
+	
+	acct_confin = fopen(conffile, "r");
+	if (acct_confin == NULL) {
+		ret = errno;
+		fd_log_debug("Unable to open extension configuration file %s for reading: %s", conffile, strerror(ret));
+		return ret;
+	}
+
+	ret = yyparse(conffile);
+
+	fclose(acct_confin);
+
+	if (ret != 0) {
+		TRACE_DEBUG (INFO, "Unable to parse the configuration file.");
+		return EINVAL;
+	}
+	
+	return 0;
+}
+
+/* Function to report the errors */
+void yyerror (YYLTYPE *ploc, char * conffile, char const *s)
+{
+	LOG_E( "Error in configuration parsing");
+	
+	if (ploc->first_line != ploc->last_line)
+		LOG_E("%s:%d.%d-%d.%d : %s", conffile, ploc->first_line, ploc->first_column, ploc->last_line, ploc->last_column, s);
+	else if (ploc->first_column != ploc->last_column)
+		LOG_E("%s:%d.%d-%d : %s", conffile, ploc->first_line, ploc->first_column, ploc->last_column, s);
+	else
+		LOG_E("%s:%d.%d : %s", conffile, ploc->first_line, ploc->first_column, s);
+}
+
+static struct acct_conf_avp avpdata;
+
+%}
+
+/* Values returned by lex for token */
+%union {
+	char 		*string;	/* The string is allocated by strdup in lex.*/
+	int		 integer;	/* Store integer values */
+}
+
+/* In case of error in the lexical analysis */
+%token 		LEX_ERROR
+
+/* Keywords */
+%token 		FIELD
+%token 		REQUIRED
+%token 		MULTI
+%token 		CONNINFO
+%token 		TABLE
+%token 		TSFIELD
+%token 		SRVNFIELD
+
+/* Tokens and types */
+/* A (de)quoted string (malloc'd in lex parser; it must be freed after use) */
+%token <string>	QSTRING
+
+/* An integer value */
+%token <integer> INTEGER
+
+
+
+/* -------------------------------------- */
+%%
+
+	/* The grammar definition */
+conffile:		/* empty grammar is OK for the parser (will be validated afterwards) */
+			| conffile avpline
+			| conffile conninfoline
+			| conffile tableline
+			| conffile tsfieldline
+			| conffile srvnfieldline
+			| conffile errors
+			{
+				yyerror(&yylloc, conffile, "An error occurred while parsing the configuration file.");
+				return EINVAL;
+			}
+			;
+
+			/* Catch lexical and syntax errors */
+errors:			LEX_ERROR
+			| error
+			;
+
+	/* The tokens */
+avpline:		{
+				memset(&avpdata, 0, sizeof(struct acct_conf_avp));
+			}
+			QSTRING avpcontents ';'
+			{
+				struct acct_conf_avp *new;
+				struct dict_object * dict;
+				struct dict_avp_data dictdata;
+				
+				/* Validate the avp name first */
+				CHECK_FCT_DO( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME_ALL_VENDORS, $2, &dict, ENOENT),
+					{ yyerror (&yylloc, conffile, "AVP definition not found in the dictionary. Was the appropriate dict_*.fdx extension loaded?"); YYERROR; } );
+				CHECK_FCT( fd_dict_getval( dict, &dictdata ));
+				
+				/* Create a new entry */
+				CHECK_MALLOC_DO( new = malloc(sizeof(struct acct_conf_avp)),
+					{ yyerror (&yylloc, conffile, "Out of memory"); YYERROR; } );
+				
+				/* Retrieve all the data from avpcontents parsing (field, required, multi) */	
+				memcpy(new, &avpdata, sizeof(struct acct_conf_avp));
+				
+				/* Initialize the other data */
+				fd_list_init(&new->chain, NULL);
+				new->avpname = $2;
+				new->avpobj = dict;
+				new->avptype = dictdata.avp_basetype;
+			
+				/* Add this new entry at the end of the list */
+				fd_list_insert_before( &acct_config->avps, &new->chain );
+			}
+			;
+			
+avpcontents:		/* Empty content is fine */
+			| '=' '{' avpflagline '}'
+			;
+			
+avpflagline:		/* Empty flags is also fine */
+			| avpflagline FIELD '=' QSTRING ';'
+			{
+				if (avpdata.field) {
+					yyerror (&yylloc, conffile, "Duplicate entry");
+					YYERROR;
+				}
+				avpdata.field = $4;
+			}
+			| avpflagline REQUIRED ';'
+			{
+				avpdata.required = 1;
+			}
+			| avpflagline MULTI '=' INTEGER ';'
+			{
+				avpdata.multi = (unsigned) $4;
+			}
+			;
+	
+conninfoline:		CONNINFO '=' QSTRING ';'
+			{
+				if (acct_config->conninfo) {
+					yyerror (&yylloc, conffile, "Duplicate entry");
+					YYERROR;
+				}
+				acct_config->conninfo = $3;
+			}
+			;
+
+tableline:		TABLE '=' QSTRING ';'
+			{
+				if (acct_config->tablename) {
+					yyerror (&yylloc, conffile, "Duplicate entry");
+					YYERROR;
+				}
+				acct_config->tablename = $3;
+			}
+			;
+
+tsfieldline:		TSFIELD '=' QSTRING ';'
+			{
+				if (acct_config->tsfield) {
+					yyerror (&yylloc, conffile, "Duplicate entry");
+					YYERROR;
+				}
+				acct_config->tsfield = $3;
+			}
+			;
+
+srvnfieldline:		SRVNFIELD '=' QSTRING ';'
+			{
+				if (acct_config->srvnfield) {
+					yyerror (&yylloc, conffile, "Duplicate entry");
+					YYERROR;
+				}
+				acct_config->srvnfield = $3;
+			}
+			;
diff --git a/extensions/app_acct/acct_db.c b/extensions/app_acct/acct_db.c
new file mode 100644
index 0000000..a444c94
--- /dev/null
+++ b/extensions/app_acct/acct_db.c
@@ -0,0 +1,341 @@
+/*********************************************************************************************************
+* Software License Agreement (BSD License)                                                               *
+* Author: Sebastien Decugis <sdecugis@freediameter.net>							 *
+*													 *
+* Copyright (c) 2013, WIDE Project and NICT								 *
+* All rights reserved.											 *
+* 													 *
+* Redistribution and use of this software in source and binary forms, with or without modification, are  *
+* permitted provided that the following conditions are met:						 *
+* 													 *
+* * Redistributions of source code must retain the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer.										 *
+*    													 *
+* * Redistributions in binary form must reproduce the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer in the documentation and/or other						 *
+*   materials provided with the distribution.								 *
+* 													 *
+* * Neither the name of the WIDE Project or NICT nor the 						 *
+*   names of its contributors may be used to endorse or 						 *
+*   promote products derived from this software without 						 *
+*   specific prior written permission of WIDE Project and 						 *
+*   NICT.												 *
+* 													 *
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED *
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
+* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR *
+* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 	 *
+* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 	 *
+* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR *
+* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF   *
+* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.								 *
+*********************************************************************************************************/
+
+/* Database interface module */
+
+/* There is one connection to the db per thread. 
+The connection is stored in the pthread_key_t variable */
+
+
+#include "app_acct.h"
+#include <libpq-fe.h>
+
+const char * diam2db_types_mapping[AVP_TYPE_MAX + 1] = {
+	"" 		/* AVP_TYPE_GROUPED */,
+	"bytea" 	/* AVP_TYPE_OCTETSTRING */,
+	"integer" 	/* AVP_TYPE_INTEGER32 */,
+	"bigint" 	/* AVP_TYPE_INTEGER64 */,
+	"integer" 	/* AVP_TYPE_UNSIGNED32 + cast */,
+	"bigint" 	/* AVP_TYPE_UNSIGNED64 + cast */,
+	"real" 		/* AVP_TYPE_FLOAT32 */,
+	"double precision" /* AVP_TYPE_FLOAT64 */
+};
+
+static const char * stmt = "acct_db_stmt";
+#ifndef TEST_DEBUG
+static 
+#endif /* TEST_DEBUG */
+pthread_key_t connk;
+static char * sql = NULL;   /* The buffer that will contain the SQL query */
+static int nbrecords = 0;
+
+
+/* Initialize the database context: connection to the DB, prepared statement to insert new records */
+int acct_db_init(void)
+{
+	struct acct_record_list emptyrecords;
+	struct fd_list * li;
+	size_t sql_allocd = 0; /* The malloc'd size of the buffer */
+	size_t sql_offset = 0; /* The actual data already written in this buffer */
+	int idx = 0;
+	PGresult * res;
+	PGconn *conn;
+	#define REALLOC_SIZE	1024	/* We extend the buffer by this amount */
+	
+	TRACE_ENTRY();
+	CHECK_PARAMS( acct_config && acct_config->conninfo && acct_config->tablename ); 
+	
+	CHECK_PARAMS_DO( PQisthreadsafe() == 1, {
+		fd_log_debug("You PostGreSQL installation is not thread-safe!");
+		return EINVAL;
+	} );			
+	
+	/* Use the information from acct_config to create the connection and prepare the query */
+	conn = PQconnectdb(acct_config->conninfo);
+	
+	/* Check to see that the backend connection was successfully made */
+	if (PQstatus(conn) != CONNECTION_OK) {
+		fd_log_debug("Connection to database failed: %s", PQerrorMessage(conn));
+		acct_db_free();
+		return EINVAL;
+	}
+	if (PQprotocolVersion(conn) < 3) {
+		fd_log_debug("Database protocol version is too old, version 3 is required for prepared statements.");
+		acct_db_free();
+		return EINVAL;
+	}
+	
+	TRACE_DEBUG(FULL, "Connection to database successful, server version %d.", PQserverVersion(conn));
+	
+	/* Now, prepare the request object */
+	
+	/* First, we build the list of AVP we will insert in the database */
+	CHECK_FCT( acct_rec_prepare(&emptyrecords) );
+	
+	/* Now, prepare the text of the request */
+	CHECK_MALLOC(sql = malloc(REALLOC_SIZE));
+	sql_allocd = REALLOC_SIZE;
+	
+	/* This macro hides the details of extending the buffer on each sprintf... */
+	#define ADD_EXTEND(args...) {									\
+		size_t p;										\
+		int loop = 0;										\
+		do {											\
+			p = snprintf(sql + sql_offset, sql_allocd - sql_offset, ##args);		\
+			if (p >= sql_allocd - sql_offset) {						\
+				/* Too short, extend the buffer and start again */			\
+				CHECK_MALLOC( sql = realloc(sql, sql_allocd + REALLOC_SIZE) );		\
+				sql_allocd += REALLOC_SIZE;						\
+				loop++;									\
+				ASSERT(loop < 100); /* detect infinite loops */				\
+				continue;								\
+			}										\
+			sql_offset += p;								\
+			break;										\
+		} while (1);										\
+	}
+	
+	/* This macro allows to add a value in the SQL buffer while escaping in properly */
+	#define ADD_ESCAPE(str) {									\
+		char * __s = (char *)str;								\
+		/* Check we have at least twice the size available +1 */				\
+		size_t p = strlen(__s);									\
+													\
+		while (sql_allocd - sql_offset < 2 * p + 1) {						\
+			/* Too short, extend the buffer */						\
+			CHECK_MALLOC( sql = realloc(sql, sql_allocd + REALLOC_SIZE) );			\
+			sql_allocd += REALLOC_SIZE;							\
+		}											\
+													\
+		/* Now add the escaped string */							\
+		p = PQescapeStringConn(conn, sql+sql_offset, __s, p, NULL);				\
+		sql_offset += p;									\
+	}
+	
+	/* INSERT INTO table (tsfield, field1, field2, ...) VALUES (now, $1::bytea, $2::integer, ...) */
+	ADD_EXTEND("INSERT INTO %s (", acct_config->tablename);
+	
+	if (acct_config->tsfield) {
+		ADD_EXTEND("\"");
+		ADD_ESCAPE(acct_config->tsfield);
+		ADD_EXTEND("\", ");
+	}
+	
+	if (acct_config->srvnfield) {
+		ADD_EXTEND("\"");
+		ADD_ESCAPE(acct_config->srvnfield);
+		ADD_EXTEND("\", ");
+	}
+	
+	for (li = emptyrecords.all.next; li != &emptyrecords.all; li = li->next) {
+		struct acct_record_item * i = (struct acct_record_item *)(li->o);
+		ADD_EXTEND("\"");
+		ADD_ESCAPE(i->param->field?:i->param->avpname);
+		if (i->index) {
+			ADD_EXTEND("%d", i->index);
+		}
+		if (li->next != &emptyrecords.all) {
+			ADD_EXTEND("\", ");
+		}
+	}
+	
+	ADD_EXTEND("\") VALUES (");
+	
+	if (acct_config->tsfield) {
+		++idx;
+		ADD_EXTEND("$%d, ", idx);
+	}
+	if (acct_config->srvnfield) {
+		ADD_EXTEND("'");
+		ADD_ESCAPE(fd_g_config->cnf_diamid);
+		ADD_EXTEND("', ");
+	}
+	
+	for (li = emptyrecords.all.next; li != &emptyrecords.all; li = li->next) {
+		struct acct_record_item * i = (struct acct_record_item *)(li->o);
+		++idx;
+		ADD_EXTEND("$%d::%s", idx, diam2db_types_mapping[i->param->avptype]);
+		
+		if (li->next != &emptyrecords.all) {
+			ADD_EXTEND(", ");
+		}
+	}
+	
+	ADD_EXTEND(");");
+	
+	TRACE_DEBUG(FULL, "Preparing the following SQL statement: '%s'", sql);
+	res = PQprepare(conn, stmt, sql, emptyrecords.nball, NULL);
+	if (PQresultStatus(res) != PGRES_COMMAND_OK) {
+		TRACE_DEBUG(INFO, "Preparing statement '%s' failed: %s",
+			sql, PQerrorMessage(conn));
+		PQclear(res);
+		return EINVAL;
+        }
+	PQclear(res);
+	nbrecords = emptyrecords.nball;
+	
+	acct_rec_empty(&emptyrecords);
+	
+	CHECK_POSIX( pthread_key_create(&connk, (void (*)(void*))PQfinish) );
+	CHECK_POSIX( pthread_setspecific(connk, conn) );
+	
+	/* Ok, ready */
+	return 0;
+}
+
+/* Terminate the connection to the DB */
+void acct_db_free(void)
+{	
+	CHECK_POSIX_DO(pthread_key_delete(connk) , );
+	free(sql);
+}
+
+/* When a new message has been received, insert the content of the parsed mapping into the DB (using prepared statement) */
+int acct_db_insert(struct acct_record_list * records)
+{
+	char 	**val;
+	int	 *val_len;
+	int 	 *val_isbin;
+	int	  idx = 0;
+	int	  size = 0;
+	PGresult *res;
+	struct fd_list *li;
+	PGconn *conn;
+	int new = 0;
+	
+	TRACE_ENTRY("%p", records);
+	CHECK_PARAMS( records );
+	
+	conn = pthread_getspecific(connk);
+	if (!conn) {
+		conn = PQconnectdb(acct_config->conninfo);
+		CHECK_POSIX( pthread_setspecific(connk, conn) );
+		
+		new = 1;
+	}
+	
+	/* First, check if the connection with the DB has not staled, and eventually try to fix it */
+	if (PQstatus(conn) != CONNECTION_OK) {
+		/* Attempt a reset */
+		PQreset(conn);
+		if (PQstatus(conn) != CONNECTION_OK) {
+			TRACE_DEBUG(INFO, "Lost connection to the database server, and attempt to reestablish it failed");
+			TODO("Terminate the freeDiameter instance completely?");
+			return ENOTCONN;
+		}
+	}
+	
+	if (new) {
+		/* Create the prepared statement for this ocnnection, it is not shared */
+		res = PQprepare(conn, stmt, sql, nbrecords, NULL);
+		if (PQresultStatus(res) != PGRES_COMMAND_OK) {
+			TRACE_DEBUG(INFO, "Preparing statement '%s' failed: %s",
+				sql, PQerrorMessage(conn));
+			PQclear(res);
+			return EINVAL;
+        	}
+		PQclear(res);
+	}
+	
+	size = 	acct_config->tsfield ? records->nball + 1 : records->nball;
+	
+	/* Alloc the arrays of parameters */
+	CHECK_MALLOC( val       = calloc(size, sizeof(const char *)) );
+	CHECK_MALLOC( val_len   = calloc(size, sizeof(const int)) );
+	CHECK_MALLOC( val_isbin = calloc(size, sizeof(const int)) );
+	
+	if (acct_config->tsfield) {
+		val[idx] = "now";
+		val_len[idx] = 3;
+		val_isbin[idx] = 0;
+		idx++;
+	}
+	
+	/* Now write all the map'd records in these arrays */
+	for (li = records->all.next; li != &records->all; li = li->next) {
+		struct acct_record_item * r = (struct acct_record_item *)(li->o);
+		if (r->value) {
+			val_isbin[idx] = 1; /* We always pass binary parameters */
+			switch (r->param->avptype) {
+				case AVP_TYPE_OCTETSTRING:
+					val[idx] = (void *)(r->value->os.data);
+					val_len[idx] = r->value->os.len;
+					break;
+					
+				case AVP_TYPE_INTEGER32:
+				case AVP_TYPE_UNSIGNED32:
+				case AVP_TYPE_FLOAT32:
+					r->scalar.v32 = htonl(r->value->u32);
+					val[idx] = &r->scalar.c;
+					val_len[idx] = sizeof(uint32_t);
+					break;
+					
+				case AVP_TYPE_INTEGER64:
+				case AVP_TYPE_UNSIGNED64:
+				case AVP_TYPE_FLOAT64:
+					r->scalar.v64 = htonll(r->value->u64);
+					val[idx] = &r->scalar.c;
+					val_len[idx] = sizeof(uint64_t);
+					break;
+				
+				default:
+					ASSERT(0); /* detect bugs */
+			}
+		}
+		
+		idx++;
+	}
+	
+	/* OK, now execute the SQL statement */
+	res = PQexecPrepared(conn, stmt, size, (const char * const *)val, val_len, val_isbin, 1 /* We actually don't care here */);
+	
+	/* Done with the parameters */
+	free(val);
+	free(val_len);
+	free(val_isbin);
+	
+	/* Now check the result code */
+	if (PQresultStatus(res) != PGRES_COMMAND_OK) {
+		TRACE_DEBUG(INFO, "An error occurred while INSERTing in the database: %s", PQerrorMessage(conn));
+		PQclear(res);
+		return EINVAL; /* It was probably a mistake in configuration file... */
+        }
+	PQclear(res);
+	
+	/* Ok, we are done */
+	return 0;
+}
+
+
diff --git a/extensions/app_acct/acct_records.c b/extensions/app_acct/acct_records.c
new file mode 100644
index 0000000..4f1b340
--- /dev/null
+++ b/extensions/app_acct/acct_records.c
@@ -0,0 +1,161 @@
+/*********************************************************************************************************
+* Software License Agreement (BSD License)                                                               *
+* Author: Sebastien Decugis <sdecugis@freediameter.net>							 *
+*													 *
+* Copyright (c) 2013, WIDE Project and NICT								 *
+* All rights reserved.											 *
+* 													 *
+* Redistribution and use of this software in source and binary forms, with or without modification, are  *
+* permitted provided that the following conditions are met:						 *
+* 													 *
+* * Redistributions of source code must retain the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer.										 *
+*    													 *
+* * Redistributions in binary form must reproduce the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer in the documentation and/or other						 *
+*   materials provided with the distribution.								 *
+* 													 *
+* * Neither the name of the WIDE Project or NICT nor the 						 *
+*   names of its contributors may be used to endorse or 						 *
+*   promote products derived from this software without 						 *
+*   specific prior written permission of WIDE Project and 						 *
+*   NICT.												 *
+* 													 *
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED *
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
+* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR *
+* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 	 *
+* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 	 *
+* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR *
+* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF   *
+* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.								 *
+*********************************************************************************************************/
+
+/* Functions to create a list of AVPs according to the configuration file */
+
+#include "app_acct.h"
+
+/* Prepare a list of acct_record entries from the configuration, without mapping any value at this time */
+int acct_rec_prepare(struct acct_record_list * records)
+{
+	struct fd_list * li;
+	TRACE_ENTRY("%p", records);
+	CHECK_PARAMS( records && acct_config );
+	
+	/* Prepare the records structure */
+	memset(records, 0, sizeof(struct acct_record_list));
+	fd_list_init(&records->all, records);
+	fd_list_init(&records->unmaped, records);
+	
+	/* for each entry in the configuration */
+	for (li = acct_config->avps.next; li != &acct_config->avps; li = li->next) {
+		struct acct_conf_avp * a = (struct acct_conf_avp *)li;
+		struct acct_record_item * new;
+		int i = a->multi ? 1 : 0;
+		/* Create as many records as the 'multi' parameter requires */
+		do {
+			CHECK_MALLOC( new = malloc(sizeof(struct acct_record_item)) );
+			memset(new, 0, sizeof(struct acct_record_item));
+			fd_list_init(&new->chain, new);
+			fd_list_init(&new->unmapd, new);
+			new->param = a;
+			new->index = i;
+			fd_list_insert_before(&records->all, &new->chain);
+			fd_list_insert_before(&records->unmaped, &new->unmapd);
+			records->nball++;
+			records->nbunmap++;
+			i++;
+		} while (i <= a->multi);
+	}
+	
+	return 0;
+}
+
+/* Find the AVPs from configuration inside a received message */
+int acct_rec_map(struct acct_record_list * records, struct msg * msg)
+{
+	struct avp * avp;
+	
+	TRACE_ENTRY("%p %p", records, msg);
+	
+	/* For each AVP in the message, search if we have a corresponding unmap'd record */
+	CHECK_FCT(  fd_msg_browse(msg, MSG_BRW_FIRST_CHILD, &avp, NULL)  );
+	while (avp) {
+		struct fd_list * li;
+		struct dict_object * model;
+		
+		CHECK_FCT( fd_msg_model(avp, &model) );
+		if (model != NULL) {	/* we ignore the AVPs we don't recognize */
+		
+			/* Search this model in the list */
+			for (li = records->unmaped.next; li != &records->unmaped; li = li->next) {
+				struct acct_record_item * r = (struct acct_record_item *)(li->o);
+				if (r->param->avpobj == model) {
+					/* It matches: save the AVP value and unlink this record from the unmap'd list */
+					struct avp_hdr * h;
+					CHECK_FCT( fd_msg_avp_hdr( avp, &h ) );
+					r->value = h->avp_value;
+					fd_list_unlink(&r->unmapd);
+					records->nbunmap -= 1;
+					break;
+				}
+			}
+
+			/* Continue only while there are some AVPs to map */
+			if (FD_IS_LIST_EMPTY(&records->unmaped))
+				break;
+		}
+		
+		/* Go to next AVP in the message */
+		CHECK_FCT( fd_msg_browse(avp, MSG_BRW_NEXT, &avp, NULL) );
+	}
+	
+	/* Done */
+	return 0;
+}
+
+/* Check that a mapped list is not empty and no required AVP is missing. Free the record list in case of error */
+int acct_rec_validate(struct acct_record_list * records)
+{
+	struct fd_list * li;
+	TRACE_ENTRY("%p", records);
+	CHECK_PARAMS( records );
+	
+	/* Check at least one AVP was mapped */
+	if (records->nball == records->nbunmap) {
+		fd_log_debug("The received ACR does not contain any AVP from the configuration file."
+				" This is an invalid situation. Please fix your configuration file."
+				" One way to ensure this does not happen is to include Session-Id in the database.");
+		acct_rec_empty(records);
+		return EINVAL;
+	}
+	
+	/* Now, check there is no required AVP unmap'd */
+	for (li = records->unmaped.next; li != &records->unmaped; li = li->next) {
+		struct acct_record_item * r = (struct acct_record_item *)(li->o);
+		if (r->param->required && (r->index <= 1)) {
+			fd_log_debug("The received ACR does not contain the required AVP '%s'.", r->param->avpname);
+			acct_rec_empty(records);
+			return EINVAL;
+		}
+	}
+	
+	/* The record list is OK */
+	return 0;
+}
+
+/* Free all the items in an acct_record_list returned by acct_rec_prepare */
+void acct_rec_empty(struct acct_record_list * records)
+{
+	TRACE_ENTRY("%p", records);
+	CHECK_PARAMS_DO( records, return );
+	
+	while (!FD_IS_LIST_EMPTY(&records->all)) {
+		struct acct_record_item * r = (struct acct_record_item *)(records->all.next);
+		fd_list_unlink( &r->chain );
+		fd_list_unlink( &r->unmapd );
+		free(r);
+	}
+}
diff --git a/extensions/app_acct/app_acct.c b/extensions/app_acct/app_acct.c
new file mode 100644
index 0000000..9465b75
--- /dev/null
+++ b/extensions/app_acct/app_acct.c
@@ -0,0 +1,155 @@
+/*********************************************************************************************************
+* Software License Agreement (BSD License)                                                               *
+* Author: Sebastien Decugis <sdecugis@freediameter.net>							 *
+*													 *
+* Copyright (c) 2011, WIDE Project and NICT								 *
+* All rights reserved.											 *
+* 													 *
+* Redistribution and use of this software in source and binary forms, with or without modification, are  *
+* permitted provided that the following conditions are met:						 *
+* 													 *
+* * Redistributions of source code must retain the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer.										 *
+*    													 *
+* * Redistributions in binary form must reproduce the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer in the documentation and/or other						 *
+*   materials provided with the distribution.								 *
+* 													 *
+* * Neither the name of the WIDE Project or NICT nor the 						 *
+*   names of its contributors may be used to endorse or 						 *
+*   promote products derived from this software without 						 *
+*   specific prior written permission of WIDE Project and 						 *
+*   NICT.												 *
+* 													 *
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED *
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
+* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR *
+* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 	 *
+* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 	 *
+* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR *
+* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF   *
+* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.								 *
+*********************************************************************************************************/
+
+/* The simple Accounting server for freeDiameter */
+
+#include "app_acct.h"
+
+/* Mandatory AVPs for the Accounting-Answer (any value in adding all the other AVPs?) */
+static struct {
+	struct dict_object * Accounting_Record_Number;
+	struct dict_object * Accounting_Record_Type;
+} acct_dict;
+
+
+/* Callback for incoming Base Accounting Accounting-Request messages */
+static int acct_cb( struct msg ** msg, struct avp * avp, struct session * sess, void * opaque, enum disp_action * act)
+{
+	struct msg * m;
+	struct avp * a = NULL;
+	struct avp_hdr * art=NULL, *arn=NULL; /* We keep a pointer on the Accounting-Record-{Type, Number} AVPs from the query */
+	struct acct_record_list rl;
+	
+	TRACE_ENTRY("%p %p %p %p", msg, avp, sess, act);
+	if (msg == NULL)
+		return EINVAL;
+	
+	m = *msg;
+	
+	/* Prepare a new record list */
+	CHECK_FCT( acct_rec_prepare( &rl ) );
+	
+	/* Maps the AVPs from the query with this record list */
+	CHECK_FCT( acct_rec_map( &rl, m ) );
+	
+	/* Check that at least one AVP was mapped */
+	CHECK_FCT( acct_rec_validate( &rl ) );
+	
+	/* Now, save these mapped AVPs in the database */
+	CHECK_FCT( acct_db_insert( &rl ) );
+	
+	acct_rec_empty( &rl );
+	
+	/* OK, we can send a positive reply now */
+	
+	/* Get Accounting-Record-{Number,Type} values */
+	CHECK_FCT( fd_msg_search_avp ( m, acct_dict.Accounting_Record_Type, &a) );
+	if (a) {
+		CHECK_FCT( fd_msg_avp_hdr( a, &art )  );
+	}
+	CHECK_FCT( fd_msg_search_avp ( m, acct_dict.Accounting_Record_Number, &a) );
+	if (a) {
+		CHECK_FCT( fd_msg_avp_hdr( a, &arn )  );
+	}
+	
+	/* Create the answer message */
+	CHECK_FCT( fd_msg_new_answer_from_req ( fd_g_config->cnf_dict, msg, 0 ) );
+	m = *msg;
+
+	/* Set the Origin-Host, Origin-Realm, Result-Code AVPs */
+	CHECK_FCT( fd_msg_rescode_set( m, "DIAMETER_SUCCESS", NULL, NULL, 1 ) );
+	
+	/* Add the mandatory AVPs in the ACA */
+	if (art) {
+		CHECK_FCT( fd_msg_avp_new ( acct_dict.Accounting_Record_Type, 0, &a ) );
+		CHECK_FCT( fd_msg_avp_setvalue( a, art->avp_value ) );
+		CHECK_FCT( fd_msg_avp_add( m, MSG_BRW_LAST_CHILD, a ) );
+	}
+	if (arn) {
+		CHECK_FCT( fd_msg_avp_new ( acct_dict.Accounting_Record_Number, 0, &a ) );
+		CHECK_FCT( fd_msg_avp_setvalue( a, arn->avp_value ) );
+		CHECK_FCT( fd_msg_avp_add( m, MSG_BRW_LAST_CHILD, a ) );
+	}
+	
+	/* Send the answer */
+	*act = DISP_ACT_SEND;
+	return 0;
+}
+	
+
+/* entry point */
+static int acct_entry(char * conffile)
+{
+	struct disp_when data;
+	
+	TRACE_ENTRY("%p", conffile);
+	
+#ifndef TEST_DEBUG /* We do this differently in the test scenario */
+	/* Initialize the configuration and parse the file */
+	CHECK_FCT( acct_conf_init() );
+	CHECK_FCT( acct_conf_parse(conffile) );
+	CHECK_FCT( acct_conf_check(conffile) );
+#endif /* TEST_DEBUG */
+	
+	/* Now initialize the database module */
+	CHECK_FCT( acct_db_init() );
+	
+	/* Search the AVPs we will need in this file */
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Accounting-Record-Number", &acct_dict.Accounting_Record_Number, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Accounting-Record-Type", &acct_dict.Accounting_Record_Type, ENOENT) );
+	
+	/* Register the dispatch callbacks */
+	memset(&data, 0, sizeof(data));
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_APPLICATION, APPLICATION_BY_NAME, "Diameter Base Accounting", &data.app, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_COMMAND, CMD_BY_NAME, "Accounting-Request", &data.command, ENOENT) );
+	CHECK_FCT( fd_disp_register( acct_cb, DISP_HOW_CC, &data, NULL, NULL ) );
+	
+	/* Advertise the support for the Diameter Base Accounting application in the peer */
+	CHECK_FCT( fd_disp_app_support ( data.app, NULL, 0, 1 ) );
+	
+	return 0;
+}
+
+/* Unload */
+void fd_ext_fini(void)
+{
+	/* Close the db connection */
+	acct_db_free();
+	
+	/* Destroy the configuration */
+	acct_conf_free();
+}
+
+EXTENSION_ENTRY("app_acct", acct_entry);
diff --git a/extensions/app_acct/app_acct.h b/extensions/app_acct/app_acct.h
new file mode 100644
index 0000000..a98a335
--- /dev/null
+++ b/extensions/app_acct/app_acct.h
@@ -0,0 +1,121 @@
+/*********************************************************************************************************
+* Software License Agreement (BSD License)                                                               *
+* Author: Sebastien Decugis <sdecugis@freediameter.net>							 *
+*													 *
+* Copyright (c) 2011, WIDE Project and NICT								 *
+* All rights reserved.											 *
+* 													 *
+* Redistribution and use of this software in source and binary forms, with or without modification, are  *
+* permitted provided that the following conditions are met:						 *
+* 													 *
+* * Redistributions of source code must retain the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer.										 *
+*    													 *
+* * Redistributions in binary form must reproduce the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer in the documentation and/or other						 *
+*   materials provided with the distribution.								 *
+* 													 *
+* * Neither the name of the WIDE Project or NICT nor the 						 *
+*   names of its contributors may be used to endorse or 						 *
+*   promote products derived from this software without 						 *
+*   specific prior written permission of WIDE Project and 						 *
+*   NICT.												 *
+* 													 *
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED *
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
+* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR *
+* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 	 *
+* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 	 *
+* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR *
+* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF   *
+* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.								 *
+*********************************************************************************************************/
+
+/* Header file for the app_acct extension. 
+ *
+ *  This extension is a simple Diameter Accounting server.
+ *
+ * It receives the Diameter Accounting-Request message, and sends its content in a 
+ * "buffer" postgreSQL database (see configuration sample file app_acct.conf.sample).
+ *
+ * The intent is that another application will then pick the records from this "buffer" database
+ * and process it accordingly to the requirements of the end application.
+ */
+ 
+#include <freeDiameter/extension.h>
+
+/* The structure corresponding to an AVP entry in the configuration file */
+struct acct_conf_avp {
+	/* Chain */
+	struct fd_list	 	 chain;		/* link in the global list */
+	
+	/* Raw information from the configuration file */
+	char 			*avpname;	/* the name of the AVP, as appear in the configuration file */
+	char			*field;		/* the field name in the database, or NULL if it is the same as avpname */
+	int			 required;	/* set to true if this AVP has to be in the message */
+	unsigned 		 multi;		/* the number of occurrences of this AVP we convert, or 0 if it was not specified */
+	
+	/* Parsed information */
+	struct dict_object 	*avpobj;	/* the dictionary object corresponding to this AVP */
+	enum dict_avp_basetype	 avptype;	/* this info is extracted from avpobj. GROUPED avps are not allowed yet */
+};
+
+/* This is described only inside acct_db.c */
+struct acct_db;
+
+/* The complete configuration */
+struct acct_conf {
+	/* AVPs */
+	struct fd_list	 avps;		/* the list of acct_conf_avp entries */
+	
+	/* Raw information */
+	char		*conninfo;	/* the connection string to the database, that is passed as is to the database library */
+	char 		*tablename;	/* the name of the table we are working with */
+	char 		*tsfield;	/* the name of the timestamp field, or NULL if not required */
+	char 		*srvnfield;	/* the name of the server name field, or NULL if not required */
+};
+
+/* A successfully parsed Accounting-Request produces a list of these: */
+struct acct_record_item {
+	struct fd_list		 chain;	/* link with all others */
+	struct fd_list		 unmapd;/* link with only unmap'd records */
+	struct acct_conf_avp 	*param;	/* the AVP entry this refers to. */
+	unsigned		 index;	/* in case of multi */
+	union avp_value		*value; /* If the AVP was found in the message, this points to its value. Otherwise, NULL */
+	union {
+		uint32_t v32	/* Storage area for network byte-order copy of the AVP value */;
+		uint64_t v64;
+		char	 c;	/* pointer that is passed to the database */
+	} 			 scalar;/* for scalar AVP (all types except OCTETSTRING) we copy in this area the value in network byte order */
+};
+
+/* The sentinel for a list of acct_record_items */
+struct acct_record_list {
+	struct fd_list	all;	/* The list of records */
+	int		nball;	/* The number of records in all */
+	struct fd_list	unmaped;/* Only the records without a value */
+	int		nbunmap;/* The number of unmap'd records */
+};
+
+/* Mapping of the data types between Diameter AVP and PQ types: */
+extern const char * diam2db_types_mapping[];
+
+/* In acct_conf.y */
+extern struct acct_conf * acct_config;	/* the global configuration */
+int acct_conf_init(void);
+int acct_conf_parse(char * conffile);
+int acct_conf_check(char * conffile);
+void acct_conf_free(void);
+
+/* In acct_db.c */
+int acct_db_init(void);
+int acct_db_insert(struct acct_record_list * records);
+void acct_db_free(void);
+
+/* In acct_records.c */
+int acct_rec_prepare(struct acct_record_list * records);
+int acct_rec_map(struct acct_record_list * records, struct msg * msg);
+int acct_rec_validate(struct acct_record_list * records);
+void acct_rec_empty(struct acct_record_list * records);
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);
+}
diff --git a/extensions/app_radgw/CMakeLists.txt b/extensions/app_radgw/CMakeLists.txt
new file mode 100644
index 0000000..fb91c2b
--- /dev/null
+++ b/extensions/app_radgw/CMakeLists.txt
@@ -0,0 +1,118 @@
+# The app_radgw extension
+PROJECT("RADIUS/Diameter extensible gateway application for freeDiameter" C)
+
+
+########### Main app_radgw extension #############
+
+# Parser files
+BISON_FILE(rgw_conf.y)
+FLEX_FILE(rgw_conf.l)
+SET_SOURCE_FILES_PROPERTIES(lex.rgw_conf.c rgw_conf.tab.c PROPERTIES COMPILE_FLAGS "-I ${CMAKE_CURRENT_SOURCE_DIR}")
+
+# List of source files
+SET( RGW_DEFAULT_SRC
+	radius.c
+	md5.c
+	rgw_msg_codes.c
+	rgw_msg_attrtype.c
+	rgw_main.c
+	lex.rgw_conf.c
+	rgw_conf.tab.c
+	rgw_conf.tab.h
+	rgw_clients.c
+	rgw_plugins.c
+	rgw_servers.c
+	rgw_worker.c
+)
+
+SET( RG_COMMON_HEADER
+	rgw_common.h
+	radius.h
+	md5.h
+	hostap_compat.h
+)
+
+# Compile these files as a freeDiameter extension.
+FD_ADD_EXTENSION(app_radgw ${RGW_DEFAULT_SRC} ${RG_COMMON_HEADER})
+
+
+########### RADIUS/Diameter translation agent plugins (support for RADIUS protocol) ############
+# Use the macro RGWX_ADD_PLUGIN(name files...) to create a plugin.
+# It is equivalent to add_library with the appropriate parameters
+# and naming conventions (.rgwx : Radius GateWay eXtension)
+MACRO(RGWX_ADD_PLUGIN PLGNAME)
+  ADD_LIBRARY(${PLGNAME} MODULE ${ARGN})
+  SET_TARGET_PROPERTIES(${PLGNAME} PROPERTIES PREFIX "" )
+  SET_TARGET_PROPERTIES(${PLGNAME} PROPERTIES SUFFIX ".rgwx" )
+  INSTALL(TARGETS ${PLGNAME}
+	LIBRARY DESTINATION ${INSTALL_EXTENSIONS_SUFFIX}
+	COMPONENT freeDiameter-radius-gateway)
+ENDMACRO(RGWX_ADD_PLUGIN)
+
+# Ask unless ALL_EXTENSIONS is set:
+MACRO(FD_OPTION_PLUGIN PLGVAR DESCR DEFLT)
+   IF (NOT ALL_EXTENSIONS)
+     OPTION(BUILD_${PLGVAR} ${DESCR} ${DEFLT})
+   ENDIF (NOT ALL_EXTENSIONS)
+   IF (BUILD_${PLGVAR} OR ALL_EXTENSIONS)
+     SET(${PLGVAR} TRUE)
+   ELSE (BUILD_${PLGVAR} OR ALL_EXTENSIONS)
+     SET(${PLGVAR} FALSE)
+   ENDIF (BUILD_${PLGVAR} OR ALL_EXTENSIONS)
+ENDMACRO(FD_OPTION_PLUGIN PLGVAR DESCR DEFLT)
+
+
+### Debug 
+# Example of plugin:
+
+FD_OPTION_PLUGIN(RGWX_SAMPLE "Build sample plugin? (for developers only)" OFF)
+ 	IF (RGWX_SAMPLE)
+ 	   RGWX_ADD_PLUGIN(sample ${RG_COMMON_HEADER} rgwx_sample.c)
+ 	ENDIF (RGWX_SAMPLE)
+
+# A plugin for debug: dumps RADIUS and Diameter messages state at the time the plugin is called.
+FD_OPTION_PLUGIN(RGWX_DEBUG "Build debug plugin? (display status of RADIUS and Diameter messages)" ON)
+ 	IF (RGWX_DEBUG)
+ 	   RGWX_ADD_PLUGIN(debug ${RG_COMMON_HEADER} rgwx_debug.c)
+ 	ENDIF (RGWX_DEBUG)
+
+
+### Authentication, Authorization messages translation.
+FD_OPTION_PLUGIN(RGWX_AUTH "Build Authentication & Authorization RADIUS translation plugin? (RFC2865, RFC3579)" ON)
+	IF (RGWX_AUTH)
+ 	   RGWX_ADD_PLUGIN(auth ${RG_COMMON_HEADER} rgwx_auth.c)
+	ENDIF (RGWX_AUTH)
+
+### SIP Authentication, Authorization messages translation.
+FD_OPTION_PLUGIN(RGWX_SIP "Build SIP RADIUS translation plugin? (RFC4740 or RFC5090)" OFF)
+        IF (RGWX_SIP)
+           RGWX_ADD_PLUGIN(sip ${RG_COMMON_HEADER} rgwx_sip.c)
+        ENDIF (RGWX_SIP)
+
+
+
+### Accounting messages translation.
+FD_OPTION_PLUGIN(RGWX_ACCT "Build Accounting RADIUS translation plugin? (RFC2866)" ON)
+	IF (RGWX_ACCT)
+ 	   RGWX_ADD_PLUGIN(acct ${RG_COMMON_HEADER} rgwx_acct.c)
+	ENDIF (RGWX_ACCT)
+
+
+### Generic plugin to handle some attributes (either delete them or simply echo them in the answer) 
+FD_OPTION_PLUGIN(RGWX_ECHODROP "Build 'echo/drop' plugin? (drop specific RADIUS attributes or echo them in RADIUS answer)" ON)
+  	IF (RGWX_ECHODROP)
+  	   BISON_FILE(rgwx_echodrop.y)
+  	   FLEX_FILE(rgwx_echodrop.l)
+  	   SET_SOURCE_FILES_PROPERTIES(lex.rgwx_echodrop.c rgwx_echodrop.tab.c PROPERTIES COMPILE_FLAGS "-I ${CMAKE_CURRENT_SOURCE_DIR}")
+ 	   RGWX_ADD_PLUGIN(echodrop ${RG_COMMON_HEADER} rgwx_echodrop.h rgwx_echodrop.c lex.rgwx_echodrop.c rgwx_echodrop.tab.c rgwx_echodrop.tab.h )
+  	ENDIF (RGWX_ECHODROP)
+	
+	
+####
+## INSTALL section ##
+
+INSTALL(TARGETS app_radgw
+	LIBRARY DESTINATION ${INSTALL_EXTENSIONS_SUFFIX}
+	COMPONENT freeDiameter-radius-gateway)
+	
+# Note that all compiled plugins are added by the RGWX_ADD_PLUGIN macro in the component freeDiameter-radius-gateway as well.
diff --git a/extensions/app_radgw/hostap_compat.h b/extensions/app_radgw/hostap_compat.h
new file mode 100644
index 0000000..9bee2ac
--- /dev/null
+++ b/extensions/app_radgw/hostap_compat.h
@@ -0,0 +1,194 @@
+/*********************************************************************************************************
+* Software License Agreement (BSD License)                                                               *
+* Author: Sebastien Decugis <sdecugis@freediameter.net>							 *
+*													 *
+* Copyright (c) 2011, WIDE Project and NICT								 *
+* All rights reserved.											 *
+* 													 *
+* Redistribution and use of this software in source and binary forms, with or without modification, are  *
+* permitted provided that the following conditions are met:						 *
+* 													 *
+* * Redistributions of source code must retain the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer.										 *
+*    													 *
+* * Redistributions in binary form must reproduce the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer in the documentation and/or other						 *
+*   materials provided with the distribution.								 *
+* 													 *
+* * Neither the name of the WIDE Project or NICT nor the 						 *
+*   names of its contributors may be used to endorse or 						 *
+*   promote products derived from this software without 						 *
+*   specific prior written permission of WIDE Project and 						 *
+*   NICT.												 *
+* 													 *
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED *
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
+* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR *
+* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 	 *
+* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 	 *
+* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR *
+* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF   *
+* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.								 *
+*********************************************************************************************************/
+
+/* This file contains compatibility bindings for hostap files.
+ Most of the definitions here come from different files from the hostap project.
+ 
+ We don't care for OS-specific definitions since we are only compatible with POSIX systems.
+ 
+ */
+
+#ifndef _HOSTAP_COMPAT_H
+#define _HOSTAP_COMPAT_H
+
+#include <sys/time.h>
+
+typedef uint64_t u64;
+typedef uint32_t u32;
+typedef uint16_t u16;
+typedef uint8_t u8;
+typedef int64_t s64;
+typedef int32_t s32;
+typedef int16_t s16;
+typedef int8_t s8;
+
+/* md5.c uses a different macro name than freeDiameter for endianness */
+#ifdef HOST_BIG_ENDIAN
+# define WORDS_BIGENDIAN HOST_BIG_ENDIAN
+#else /* HOST_BIG_ENDIAN */
+# undef WORDS_BIGENDIAN
+#endif /* HOST_BIG_ENDIAN */
+
+/* freeDiameter uses the POSIX API, so we don't provide alternatives. This may be changed later as needed */
+#define os_malloc(s) malloc((s))
+#define os_realloc(p, s) realloc((p), (s))
+#define os_free(p) free((p))
+
+#define os_memcpy(d, s, n) memcpy((d), (s), (n))
+#define os_memmove(d, s, n) memmove((d), (s), (n))
+#define os_memset(s, c, n) memset(s, c, n)
+#define os_memcmp(s1, s2, n) memcmp((s1), (s2), (n))
+
+#define os_strdup(s) strdup(s)
+#define os_strlen(s) strlen(s)
+#define os_strcasecmp(s1, s2) strcasecmp((s1), (s2))
+#define os_strncasecmp(s1, s2, n) strncasecmp((s1), (s2), (n))
+#define os_strchr(s, c) strchr((s), (c))
+#define os_strcmp(s1, s2) strcmp((s1), (s2))
+#define os_strncmp(s1, s2, n) strncmp((s1), (s2), (n))
+#define os_strncpy(d, s, n) strncpy((d), (s), (n))
+#define os_strrchr(s, c) strrchr((s), (c))
+#define os_strstr(h, n) strstr((h), (n))
+#define os_snprintf snprintf
+
+#define os_random() random()
+
+static __inline__ void * os_zalloc(size_t size)
+{
+	void *n = os_malloc(size);
+	if (n)
+		os_memset(n, 0, size);
+	return n;
+}
+
+typedef long os_time_t;
+struct os_time {
+	os_time_t sec;
+	os_time_t usec;
+};
+
+static __inline__ int os_get_time(struct os_time *t)
+{
+	int res;
+	struct timeval tv;
+	res = gettimeofday(&tv, NULL);
+	t->sec = tv.tv_sec;
+	t->usec = tv.tv_usec;
+	return res;
+}
+
+/* Macros for handling unaligned memory accesses */
+#define WPA_GET_BE16(a) ((u16) (((a)[0] << 8) | (a)[1]))
+#define WPA_PUT_BE16(a, val)			\
+	do {					\
+		(a)[0] = ((u16) (val)) >> 8;	\
+		(a)[1] = ((u16) (val)) & 0xff;	\
+	} while (0)
+
+#define WPA_GET_LE16(a) ((u16) (((a)[1] << 8) | (a)[0]))
+#define WPA_PUT_LE16(a, val)			\
+	do {					\
+		(a)[1] = ((u16) (val)) >> 8;	\
+		(a)[0] = ((u16) (val)) & 0xff;	\
+	} while (0)
+
+#define WPA_GET_BE24(a) ((((u32) (a)[0]) << 16) | (((u32) (a)[1]) << 8) | \
+			 ((u32) (a)[2]))
+#define WPA_PUT_BE24(a, val)					\
+	do {							\
+		(a)[0] = (u8) ((((u32) (val)) >> 16) & 0xff);	\
+		(a)[1] = (u8) ((((u32) (val)) >> 8) & 0xff);	\
+		(a)[2] = (u8) (((u32) (val)) & 0xff);		\
+	} while (0)
+
+#define WPA_GET_BE32(a) ((((u32) (a)[0]) << 24) | (((u32) (a)[1]) << 16) | \
+			 (((u32) (a)[2]) << 8) | ((u32) (a)[3]))
+#define WPA_PUT_BE32(a, val)					\
+	do {							\
+		(a)[0] = (u8) ((((u32) (val)) >> 24) & 0xff);	\
+		(a)[1] = (u8) ((((u32) (val)) >> 16) & 0xff);	\
+		(a)[2] = (u8) ((((u32) (val)) >> 8) & 0xff);	\
+		(a)[3] = (u8) (((u32) (val)) & 0xff);		\
+	} while (0)
+
+#define WPA_GET_LE32(a) ((((u32) (a)[3]) << 24) | (((u32) (a)[2]) << 16) | \
+			 (((u32) (a)[1]) << 8) | ((u32) (a)[0]))
+#define WPA_PUT_LE32(a, val)					\
+	do {							\
+		(a)[3] = (u8) ((((u32) (val)) >> 24) & 0xff);	\
+		(a)[2] = (u8) ((((u32) (val)) >> 16) & 0xff);	\
+		(a)[1] = (u8) ((((u32) (val)) >> 8) & 0xff);	\
+		(a)[0] = (u8) (((u32) (val)) & 0xff);		\
+	} while (0)
+
+#define WPA_GET_BE64(a) ((((u64) (a)[0]) << 56) | (((u64) (a)[1]) << 48) | \
+			 (((u64) (a)[2]) << 40) | (((u64) (a)[3]) << 32) | \
+			 (((u64) (a)[4]) << 24) | (((u64) (a)[5]) << 16) | \
+			 (((u64) (a)[6]) << 8) | ((u64) (a)[7]))
+#define WPA_PUT_BE64(a, val)				\
+	do {						\
+		(a)[0] = (u8) (((u64) (val)) >> 56);	\
+		(a)[1] = (u8) (((u64) (val)) >> 48);	\
+		(a)[2] = (u8) (((u64) (val)) >> 40);	\
+		(a)[3] = (u8) (((u64) (val)) >> 32);	\
+		(a)[4] = (u8) (((u64) (val)) >> 24);	\
+		(a)[5] = (u8) (((u64) (val)) >> 16);	\
+		(a)[6] = (u8) (((u64) (val)) >> 8);	\
+		(a)[7] = (u8) (((u64) (val)) & 0xff);	\
+	} while (0)
+
+#define WPA_GET_LE64(a) ((((u64) (a)[7]) << 56) | (((u64) (a)[6]) << 48) | \
+			 (((u64) (a)[5]) << 40) | (((u64) (a)[4]) << 32) | \
+			 (((u64) (a)[3]) << 24) | (((u64) (a)[2]) << 16) | \
+			 (((u64) (a)[1]) << 8) | ((u64) (a)[0]))
+
+
+/* Packing structures to avoid padding */
+#ifdef __GNUC__
+#define STRUCT_PACKED __attribute__ ((packed))
+#else
+#define STRUCT_PACKED
+#endif
+
+/* For md5.c file */
+#define INTERNAL_MD5
+#define CONFIG_CRYPTO_INTERNAL
+
+/* For radius.c file */
+#define CONFIG_IPV6
+#include <arpa/inet.h>
+
+
+#endif /* _HOSTAP_COMPAT_H */
diff --git a/extensions/app_radgw/md5.c b/extensions/app_radgw/md5.c
new file mode 100644
index 0000000..055fcf0
--- /dev/null
+++ b/extensions/app_radgw/md5.c
@@ -0,0 +1,399 @@
+/*********************************************************************************/
+/* freeDiameter author note:
+ *  The content from this file comes directly from the hostap project.
+ * It is redistributed under the terms of the BSD license, as allowed
+ * by the original copyright reproduced below.
+ *  In addition to this notice, only the #include directives have been modified.
+ */
+#include "rgw_common.h"
+/*********************************************************************************/
+
+ 
+/*
+ * MD5 hash implementation and interface functions
+ * Copyright (c) 2003-2005, Jouni Malinen <j@w1.fi>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Alternatively, this software may be distributed under the terms of BSD
+ * license.
+ *
+ * See README and COPYING for more details.
+ */
+
+
+/**
+ * hmac_md5_vector - HMAC-MD5 over data vector (RFC 2104)
+ * @key: Key for HMAC operations
+ * @key_len: Length of the key in bytes
+ * @num_elem: Number of elements in the data vector
+ * @addr: Pointers to the data areas
+ * @len: Lengths of the data blocks
+ * @mac: Buffer for the hash (16 bytes)
+ */
+void hmac_md5_vector(const u8 *key, size_t key_len, size_t num_elem,
+		     const u8 *addr[], const size_t *len, u8 *mac)
+{
+	u8 k_pad[64]; /* padding - key XORd with ipad/opad */
+	u8 tk[16];
+	const u8 *_addr[6];
+	size_t i, _len[6];
+
+	if (num_elem > 5) {
+		/*
+		 * Fixed limit on the number of fragments to avoid having to
+		 * allocate memory (which could fail).
+		 */
+		return;
+	}
+
+        /* if key is longer than 64 bytes reset it to key = MD5(key) */
+        if (key_len > 64) {
+		md5_vector(1, &key, &key_len, tk);
+		key = tk;
+		key_len = 16;
+        }
+
+	/* the HMAC_MD5 transform looks like:
+	 *
+	 * MD5(K XOR opad, MD5(K XOR ipad, text))
+	 *
+	 * where K is an n byte key
+	 * ipad is the byte 0x36 repeated 64 times
+	 * opad is the byte 0x5c repeated 64 times
+	 * and text is the data being protected */
+
+	/* start out by storing key in ipad */
+	os_memset(k_pad, 0, sizeof(k_pad));
+	os_memcpy(k_pad, key, key_len);
+
+	/* XOR key with ipad values */
+	for (i = 0; i < 64; i++)
+		k_pad[i] ^= 0x36;
+
+	/* perform inner MD5 */
+	_addr[0] = k_pad;
+	_len[0] = 64;
+	for (i = 0; i < num_elem; i++) {
+		_addr[i + 1] = addr[i];
+		_len[i + 1] = len[i];
+	}
+	md5_vector(1 + num_elem, _addr, _len, mac);
+
+	os_memset(k_pad, 0, sizeof(k_pad));
+	os_memcpy(k_pad, key, key_len);
+	/* XOR key with opad values */
+	for (i = 0; i < 64; i++)
+		k_pad[i] ^= 0x5c;
+
+	/* perform outer MD5 */
+	_addr[0] = k_pad;
+	_len[0] = 64;
+	_addr[1] = mac;
+	_len[1] = MD5_MAC_LEN;
+	md5_vector(2, _addr, _len, mac);
+}
+
+
+/**
+ * hmac_md5 - HMAC-MD5 over data buffer (RFC 2104)
+ * @key: Key for HMAC operations
+ * @key_len: Length of the key in bytes
+ * @data: Pointers to the data area
+ * @data_len: Length of the data area
+ * @mac: Buffer for the hash (16 bytes)
+ */
+void hmac_md5(const u8 *key, size_t key_len, const u8 *data, size_t data_len,
+	      u8 *mac)
+{
+	hmac_md5_vector(key, key_len, 1, &data, &data_len, mac);
+}
+
+
+#ifdef INTERNAL_MD5
+
+struct MD5Context {
+	u32 buf[4];
+	u32 bits[2];
+	u8 in[64];
+};
+
+#ifndef CONFIG_CRYPTO_INTERNAL
+static void MD5Init(struct MD5Context *context);
+static void MD5Update(struct MD5Context *context, unsigned char const *buf,
+			  unsigned len);
+static void MD5Final(unsigned char digest[16], struct MD5Context *context);
+#endif /* CONFIG_CRYPTO_INTERNAL */
+static void MD5Transform(u32 buf[4], u32 const in[16]);
+
+
+typedef struct MD5Context MD5_CTX;
+
+
+/**
+ * md5_vector - MD5 hash for data vector
+ * @num_elem: Number of elements in the data vector
+ * @addr: Pointers to the data areas
+ * @len: Lengths of the data blocks
+ * @mac: Buffer for the hash
+ */
+void md5_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac)
+{
+	MD5_CTX ctx;
+	size_t i;
+
+	MD5Init(&ctx);
+	for (i = 0; i < num_elem; i++)
+		MD5Update(&ctx, addr[i], len[i]);
+	MD5Final(mac, &ctx);
+}
+
+
+/* ===== start - public domain MD5 implementation ===== */
+/*
+ * This code implements the MD5 message-digest algorithm.
+ * The algorithm is due to Ron Rivest.  This code was
+ * written by Colin Plumb in 1993, no copyright is claimed.
+ * This code is in the public domain; do with it what you wish.
+ *
+ * Equivalent code is available from RSA Data Security, Inc.
+ * This code has been tested against that, and is equivalent,
+ * except that you don't need to include two pages of legalese
+ * with every copy.
+ *
+ * To compute the message digest of a chunk of bytes, declare an
+ * MD5Context structure, pass it to MD5Init, call MD5Update as
+ * needed on buffers full of bytes, and then call MD5Final, which
+ * will fill a supplied 16-byte array with the digest.
+ */
+
+#ifndef WORDS_BIGENDIAN
+#define byteReverse(buf, len)	/* Nothing */
+#else
+/*
+ * Note: this code is harmless on little-endian machines.
+ */
+static void byteReverse(unsigned char *buf, unsigned longs)
+{
+    u32 t;
+    do {
+	t = (u32) ((unsigned) buf[3] << 8 | buf[2]) << 16 |
+	    ((unsigned) buf[1] << 8 | buf[0]);
+	*(u32 *) buf = t;
+	buf += 4;
+    } while (--longs);
+}
+#endif
+
+/*
+ * Start MD5 accumulation.  Set bit count to 0 and buffer to mysterious
+ * initialization constants.
+ */
+void MD5Init(struct MD5Context *ctx)
+{
+    ctx->buf[0] = 0x67452301;
+    ctx->buf[1] = 0xefcdab89;
+    ctx->buf[2] = 0x98badcfe;
+    ctx->buf[3] = 0x10325476;
+
+    ctx->bits[0] = 0;
+    ctx->bits[1] = 0;
+}
+
+/*
+ * Update context to reflect the concatenation of another buffer full
+ * of bytes.
+ */
+void MD5Update(struct MD5Context *ctx, unsigned char const *buf, unsigned len)
+{
+    u32 t;
+
+    /* Update bitcount */
+
+    t = ctx->bits[0];
+    if ((ctx->bits[0] = t + ((u32) len << 3)) < t)
+	ctx->bits[1]++;		/* Carry from low to high */
+    ctx->bits[1] += len >> 29;
+
+    t = (t >> 3) & 0x3f;	/* Bytes already in shsInfo->data */
+
+    /* Handle any leading odd-sized chunks */
+
+    if (t) {
+	unsigned char *p = (unsigned char *) ctx->in + t;
+
+	t = 64 - t;
+	if (len < t) {
+	    os_memcpy(p, buf, len);
+	    return;
+	}
+	os_memcpy(p, buf, t);
+	byteReverse(ctx->in, 16);
+	MD5Transform(ctx->buf, (u32 *) ctx->in);
+	buf += t;
+	len -= t;
+    }
+    /* Process data in 64-byte chunks */
+
+    while (len >= 64) {
+	os_memcpy(ctx->in, buf, 64);
+	byteReverse(ctx->in, 16);
+	MD5Transform(ctx->buf, (u32 *) ctx->in);
+	buf += 64;
+	len -= 64;
+    }
+
+    /* Handle any remaining bytes of data. */
+
+    os_memcpy(ctx->in, buf, len);
+}
+
+/*
+ * Final wrapup - pad to 64-byte boundary with the bit pattern
+ * 1 0* (64-bit count of bits processed, MSB-first)
+ */
+void MD5Final(unsigned char digest[16], struct MD5Context *ctx)
+{
+    unsigned count;
+    unsigned char *p;
+
+    /* Compute number of bytes mod 64 */
+    count = (ctx->bits[0] >> 3) & 0x3F;
+
+    /* Set the first char of padding to 0x80.  This is safe since there is
+       always at least one byte free */
+    p = ctx->in + count;
+    *p++ = 0x80;
+
+    /* Bytes of padding needed to make 64 bytes */
+    count = 64 - 1 - count;
+
+    /* Pad out to 56 mod 64 */
+    if (count < 8) {
+	/* Two lots of padding:  Pad the first block to 64 bytes */
+	os_memset(p, 0, count);
+	byteReverse(ctx->in, 16);
+	MD5Transform(ctx->buf, (u32 *) ctx->in);
+
+	/* Now fill the next block with 56 bytes */
+	os_memset(ctx->in, 0, 56);
+    } else {
+	/* Pad block to 56 bytes */
+	os_memset(p, 0, count - 8);
+    }
+    byteReverse(ctx->in, 14);
+
+    /* Append length in bits and transform */
+    ((u32 *) ctx->in)[14] = ctx->bits[0];
+    ((u32 *) ctx->in)[15] = ctx->bits[1];
+
+    MD5Transform(ctx->buf, (u32 *) ctx->in);
+    byteReverse((unsigned char *) ctx->buf, 4);
+    os_memcpy(digest, ctx->buf, 16);
+    os_memset(ctx, 0, sizeof(*ctx));	/* In case it's sensitive */
+}
+
+/* The four core functions - F1 is optimized somewhat */
+
+/* #define F1(x, y, z) (x & y | ~x & z) */
+#define F1(x, y, z) (z ^ (x & (y ^ z)))
+#define F2(x, y, z) F1(z, x, y)
+#define F3(x, y, z) (x ^ y ^ z)
+#define F4(x, y, z) (y ^ (x | ~z))
+
+/* This is the central step in the MD5 algorithm. */
+#define MD5STEP(f, w, x, y, z, data, s) \
+	( w += f(x, y, z) + data,  w = w<<s | w>>(32-s),  w += x )
+
+/*
+ * The core of the MD5 algorithm, this alters an existing MD5 hash to
+ * reflect the addition of 16 longwords of new data.  MD5Update blocks
+ * the data and converts bytes into longwords for this routine.
+ */
+static void MD5Transform(u32 buf[4], u32 const in[16])
+{
+    register u32 a, b, c, d;
+
+    a = buf[0];
+    b = buf[1];
+    c = buf[2];
+    d = buf[3];
+
+    MD5STEP(F1, a, b, c, d, in[0] + 0xd76aa478, 7);
+    MD5STEP(F1, d, a, b, c, in[1] + 0xe8c7b756, 12);
+    MD5STEP(F1, c, d, a, b, in[2] + 0x242070db, 17);
+    MD5STEP(F1, b, c, d, a, in[3] + 0xc1bdceee, 22);
+    MD5STEP(F1, a, b, c, d, in[4] + 0xf57c0faf, 7);
+    MD5STEP(F1, d, a, b, c, in[5] + 0x4787c62a, 12);
+    MD5STEP(F1, c, d, a, b, in[6] + 0xa8304613, 17);
+    MD5STEP(F1, b, c, d, a, in[7] + 0xfd469501, 22);
+    MD5STEP(F1, a, b, c, d, in[8] + 0x698098d8, 7);
+    MD5STEP(F1, d, a, b, c, in[9] + 0x8b44f7af, 12);
+    MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1, 17);
+    MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7be, 22);
+    MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122, 7);
+    MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193, 12);
+    MD5STEP(F1, c, d, a, b, in[14] + 0xa679438e, 17);
+    MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821, 22);
+
+    MD5STEP(F2, a, b, c, d, in[1] + 0xf61e2562, 5);
+    MD5STEP(F2, d, a, b, c, in[6] + 0xc040b340, 9);
+    MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51, 14);
+    MD5STEP(F2, b, c, d, a, in[0] + 0xe9b6c7aa, 20);
+    MD5STEP(F2, a, b, c, d, in[5] + 0xd62f105d, 5);
+    MD5STEP(F2, d, a, b, c, in[10] + 0x02441453, 9);
+    MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681, 14);
+    MD5STEP(F2, b, c, d, a, in[4] + 0xe7d3fbc8, 20);
+    MD5STEP(F2, a, b, c, d, in[9] + 0x21e1cde6, 5);
+    MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6, 9);
+    MD5STEP(F2, c, d, a, b, in[3] + 0xf4d50d87, 14);
+    MD5STEP(F2, b, c, d, a, in[8] + 0x455a14ed, 20);
+    MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905, 5);
+    MD5STEP(F2, d, a, b, c, in[2] + 0xfcefa3f8, 9);
+    MD5STEP(F2, c, d, a, b, in[7] + 0x676f02d9, 14);
+    MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20);
+
+    MD5STEP(F3, a, b, c, d, in[5] + 0xfffa3942, 4);
+    MD5STEP(F3, d, a, b, c, in[8] + 0x8771f681, 11);
+    MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122, 16);
+    MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380c, 23);
+    MD5STEP(F3, a, b, c, d, in[1] + 0xa4beea44, 4);
+    MD5STEP(F3, d, a, b, c, in[4] + 0x4bdecfa9, 11);
+    MD5STEP(F3, c, d, a, b, in[7] + 0xf6bb4b60, 16);
+    MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70, 23);
+    MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6, 4);
+    MD5STEP(F3, d, a, b, c, in[0] + 0xeaa127fa, 11);
+    MD5STEP(F3, c, d, a, b, in[3] + 0xd4ef3085, 16);
+    MD5STEP(F3, b, c, d, a, in[6] + 0x04881d05, 23);
+    MD5STEP(F3, a, b, c, d, in[9] + 0xd9d4d039, 4);
+    MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5, 11);
+    MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16);
+    MD5STEP(F3, b, c, d, a, in[2] + 0xc4ac5665, 23);
+
+    MD5STEP(F4, a, b, c, d, in[0] + 0xf4292244, 6);
+    MD5STEP(F4, d, a, b, c, in[7] + 0x432aff97, 10);
+    MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7, 15);
+    MD5STEP(F4, b, c, d, a, in[5] + 0xfc93a039, 21);
+    MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3, 6);
+    MD5STEP(F4, d, a, b, c, in[3] + 0x8f0ccc92, 10);
+    MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47d, 15);
+    MD5STEP(F4, b, c, d, a, in[1] + 0x85845dd1, 21);
+    MD5STEP(F4, a, b, c, d, in[8] + 0x6fa87e4f, 6);
+    MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10);
+    MD5STEP(F4, c, d, a, b, in[6] + 0xa3014314, 15);
+    MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1, 21);
+    MD5STEP(F4, a, b, c, d, in[4] + 0xf7537e82, 6);
+    MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235, 10);
+    MD5STEP(F4, c, d, a, b, in[2] + 0x2ad7d2bb, 15);
+    MD5STEP(F4, b, c, d, a, in[9] + 0xeb86d391, 21);
+
+    buf[0] += a;
+    buf[1] += b;
+    buf[2] += c;
+    buf[3] += d;
+}
+/* ===== end - public domain MD5 implementation ===== */
+
+#endif /* INTERNAL_MD5 */
diff --git a/extensions/app_radgw/md5.h b/extensions/app_radgw/md5.h
new file mode 100644
index 0000000..bcbfdc3
--- /dev/null
+++ b/extensions/app_radgw/md5.h
@@ -0,0 +1,46 @@
+/*********************************************************************************/
+/* freeDiameter author note:
+ *  The content from this file comes directly from the hostap project.
+ * It is redistributed under the terms of the BSD license, as allowed
+ * by the original copyright reproduced below.
+ */
+
+/*********************************************************************************/
+
+/*
+ * MD5 hash implementation and interface functions
+ * Copyright (c) 2003-2005, Jouni Malinen <j@w1.fi>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Alternatively, this software may be distributed under the terms of BSD
+ * license.
+ *
+ * See README and COPYING for more details.
+ */
+
+#ifndef MD5_H
+#define MD5_H
+
+#define MD5_MAC_LEN 16
+
+void hmac_md5_vector(const u8 *key, size_t key_len, size_t num_elem,
+		     const u8 *addr[], const size_t *len, u8 *mac);
+void hmac_md5(const u8 *key, size_t key_len, const u8 *data, size_t data_len,
+	      u8 *mac);
+
+#ifdef CONFIG_CRYPTO_INTERNAL
+struct MD5Context;
+
+void MD5Init(struct MD5Context *context);
+void MD5Update(struct MD5Context *context, unsigned char const *buf,
+	       unsigned len);
+void MD5Final(unsigned char digest[16], struct MD5Context *context);
+#endif /* CONFIG_CRYPTO_INTERNAL */
+
+ /* Forward declaration: */
+void md5_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac);
+
+#endif /* MD5_H */
diff --git a/extensions/app_radgw/radius.c b/extensions/app_radgw/radius.c
new file mode 100644
index 0000000..44755eb
--- /dev/null
+++ b/extensions/app_radgw/radius.c
@@ -0,0 +1,1373 @@
+/*********************************************************************************************************
+* Software License Agreement (BSD License)                                                               *
+* Author: Sebastien Decugis <sdecugis@freediameter.net>							 *
+*													 *
+* Copyright (c) 2013, WIDE Project and NICT								 *
+* All rights reserved.											 *
+* 													 *
+* Redistribution and use of this software in source and binary forms, with or without modification, are  *
+* permitted provided that the following conditions are met:						 *
+* 													 *
+* * Redistributions of source code must retain the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer.										 *
+*    													 *
+* * Redistributions in binary form must reproduce the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer in the documentation and/or other						 *
+*   materials provided with the distribution.								 *
+* 													 *
+* * Neither the name of the WIDE Project or NICT nor the 						 *
+*   names of its contributors may be used to endorse or 						 *
+*   promote products derived from this software without 						 *
+*   specific prior written permission of WIDE Project and 						 *
+*   NICT.												 *
+* 													 *
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED *
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
+* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR *
+* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 	 *
+* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 	 *
+* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR *
+* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF   *
+* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.								 *
+*********************************************************************************************************/
+
+/* freeDiameter author note:
+ *  The content from this file comes for the main part from the hostap project.
+ * It is redistributed under the terms of the BSD license, as allowed
+ * by the original copyright reproduced below.
+ * The modifications to this file are placed under the copyright of the freeDiameter project.
+ */
+
+/*
+ * hostapd / RADIUS message processing
+ * Copyright (c) 2002-2008, Jouni Malinen <j@w1.fi>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Alternatively, this software may be distributed under the terms of BSD
+ * license.
+ *
+ * See README and COPYING for more details.
+ */
+
+/*********************************************************************************/
+#include "rgw.h"
+
+static struct radius_attr_hdr *
+radius_get_attr_hdr(struct radius_msg *msg, int idx)
+{
+	return (struct radius_attr_hdr *) (msg->buf + msg->attr_pos[idx]);
+}
+
+
+struct radius_msg *radius_msg_new(u8 code, u8 identifier)
+{
+	struct radius_msg *msg;
+
+	msg = os_malloc(sizeof(*msg));
+	if (msg == NULL)
+		return NULL;
+
+	if (radius_msg_initialize(msg, RADIUS_DEFAULT_MSG_SIZE)) {
+		os_free(msg);
+		return NULL;
+	}
+
+	radius_msg_set_hdr(msg, code, identifier);
+
+	return msg;
+}
+
+
+int radius_msg_initialize(struct radius_msg *msg, size_t init_len)
+{
+	if (msg == NULL || init_len < sizeof(struct radius_hdr))
+		return -1;
+
+	os_memset(msg, 0, sizeof(*msg));
+	msg->buf = os_zalloc(init_len);
+	if (msg->buf == NULL)
+		return -1;
+
+	msg->buf_size = init_len;
+	msg->hdr = (struct radius_hdr *) msg->buf;
+	msg->buf_used = sizeof(*msg->hdr);
+
+	msg->attr_pos =
+		os_zalloc(RADIUS_DEFAULT_ATTR_COUNT * sizeof(*msg->attr_pos));
+	if (msg->attr_pos == NULL) {
+		os_free(msg->buf);
+		msg->buf = NULL;
+		msg->hdr = NULL;
+		return -1;
+	}
+
+	msg->attr_size = RADIUS_DEFAULT_ATTR_COUNT;
+	msg->attr_used = 0;
+
+	return 0;
+}
+
+
+void radius_msg_set_hdr(struct radius_msg *msg, u8 code, u8 identifier)
+{
+	msg->hdr->code = code;
+	msg->hdr->identifier = identifier;
+}
+
+
+void radius_msg_free(struct radius_msg *msg)
+{
+	os_free(msg->buf);
+	msg->buf = NULL;
+	msg->hdr = NULL;
+	msg->buf_size = msg->buf_used = 0;
+
+	os_free(msg->attr_pos);
+	msg->attr_pos = NULL;
+	msg->attr_size = msg->attr_used = 0;
+}
+
+/* Destroy a message */
+void rgw_msg_free(struct rgw_radius_msg_meta ** msg)
+{
+	if (!msg || !*msg)
+		return;
+	
+	radius_msg_free(&(*msg)->radius);
+	free(*msg);
+	*msg = NULL;
+}
+
+
+
+struct radius_attr_type {
+	u8 type;
+	char *name;
+	enum {
+		RADIUS_ATTR_UNDIST, RADIUS_ATTR_TEXT, RADIUS_ATTR_IP,
+		RADIUS_ATTR_HEXDUMP, RADIUS_ATTR_INT32, RADIUS_ATTR_IPV6
+	} data_type;
+};
+
+static struct radius_attr_type radius_attrs[] =
+{
+	{ RADIUS_ATTR_USER_NAME, "User-Name", RADIUS_ATTR_TEXT },
+	{ RADIUS_ATTR_USER_PASSWORD, "User-Password", RADIUS_ATTR_UNDIST },
+	{ RADIUS_ATTR_NAS_IP_ADDRESS, "NAS-IP-Address", RADIUS_ATTR_IP },
+	{ RADIUS_ATTR_NAS_PORT, "NAS-Port", RADIUS_ATTR_INT32 },
+	{ RADIUS_ATTR_FRAMED_MTU, "Framed-MTU", RADIUS_ATTR_INT32 },
+	{ RADIUS_ATTR_REPLY_MESSAGE, "Reply-Message", RADIUS_ATTR_TEXT },
+	{ RADIUS_ATTR_STATE, "State", RADIUS_ATTR_UNDIST },
+	{ RADIUS_ATTR_CLASS, "Class", RADIUS_ATTR_UNDIST },
+	{ RADIUS_ATTR_VENDOR_SPECIFIC, "Vendor-Specific", RADIUS_ATTR_UNDIST },
+	{ RADIUS_ATTR_SESSION_TIMEOUT, "Session-Timeout", RADIUS_ATTR_INT32 },
+	{ RADIUS_ATTR_IDLE_TIMEOUT, "Idle-Timeout", RADIUS_ATTR_INT32 },
+	{ RADIUS_ATTR_TERMINATION_ACTION, "Termination-Action",
+	  RADIUS_ATTR_INT32 },
+	{ RADIUS_ATTR_CALLED_STATION_ID, "Called-Station-Id",
+	  RADIUS_ATTR_TEXT },
+	{ RADIUS_ATTR_CALLING_STATION_ID, "Calling-Station-Id",
+	  RADIUS_ATTR_TEXT },
+	{ RADIUS_ATTR_NAS_IDENTIFIER, "NAS-Identifier", RADIUS_ATTR_TEXT },
+	{ RADIUS_ATTR_PROXY_STATE, "Proxy-State", RADIUS_ATTR_UNDIST },
+	{ RADIUS_ATTR_ACCT_STATUS_TYPE, "Acct-Status-Type",
+	  RADIUS_ATTR_INT32 },
+	{ RADIUS_ATTR_ACCT_DELAY_TIME, "Acct-Delay-Time", RADIUS_ATTR_INT32 },
+	{ RADIUS_ATTR_ACCT_INPUT_OCTETS, "Acct-Input-Octets",
+	  RADIUS_ATTR_INT32 },
+	{ RADIUS_ATTR_ACCT_OUTPUT_OCTETS, "Acct-Output-Octets",
+	  RADIUS_ATTR_INT32 },
+	{ RADIUS_ATTR_ACCT_SESSION_ID, "Acct-Session-Id", RADIUS_ATTR_TEXT },
+	{ RADIUS_ATTR_ACCT_AUTHENTIC, "Acct-Authentic", RADIUS_ATTR_INT32 },
+	{ RADIUS_ATTR_ACCT_SESSION_TIME, "Acct-Session-Time",
+	  RADIUS_ATTR_INT32 },
+	{ RADIUS_ATTR_ACCT_INPUT_PACKETS, "Acct-Input-Packets",
+	  RADIUS_ATTR_INT32 },
+	{ RADIUS_ATTR_ACCT_OUTPUT_PACKETS, "Acct-Output-Packets",
+	  RADIUS_ATTR_INT32 },
+	{ RADIUS_ATTR_ACCT_TERMINATE_CAUSE, "Acct-Terminate-Cause",
+	  RADIUS_ATTR_INT32 },
+	{ RADIUS_ATTR_ACCT_MULTI_SESSION_ID, "Acct-Multi-Session-Id",
+	  RADIUS_ATTR_TEXT },
+	{ RADIUS_ATTR_ACCT_LINK_COUNT, "Acct-Link-Count", RADIUS_ATTR_INT32 },
+	{ RADIUS_ATTR_ACCT_INPUT_GIGAWORDS, "Acct-Input-Gigawords", 
+	  RADIUS_ATTR_INT32 },
+	{ RADIUS_ATTR_ACCT_OUTPUT_GIGAWORDS, "Acct-Output-Gigawords",
+	  RADIUS_ATTR_INT32 },
+	{ RADIUS_ATTR_EVENT_TIMESTAMP, "Event-Timestamp",
+	  RADIUS_ATTR_INT32 },
+	{ RADIUS_ATTR_NAS_PORT_TYPE, "NAS-Port-Type", RADIUS_ATTR_INT32 },
+	{ RADIUS_ATTR_TUNNEL_TYPE, "Tunnel-Type", RADIUS_ATTR_HEXDUMP },
+	{ RADIUS_ATTR_TUNNEL_MEDIUM_TYPE, "Tunnel-Medium-Type",
+	  RADIUS_ATTR_HEXDUMP },
+	{ RADIUS_ATTR_CONNECT_INFO, "Connect-Info", RADIUS_ATTR_TEXT },
+	{ RADIUS_ATTR_EAP_MESSAGE, "EAP-Message", RADIUS_ATTR_UNDIST },
+	{ RADIUS_ATTR_MESSAGE_AUTHENTICATOR, "Message-Authenticator",
+	  RADIUS_ATTR_UNDIST },
+	{ RADIUS_ATTR_TUNNEL_PRIVATE_GROUP_ID, "Tunnel-Private-Group-Id",
+	  RADIUS_ATTR_HEXDUMP },
+	{ RADIUS_ATTR_ACCT_INTERIM_INTERVAL, "Acct-Interim-Interval",
+	  RADIUS_ATTR_INT32 },
+	{ RADIUS_ATTR_CHARGEABLE_USER_IDENTITY, "Chargeable-User-Identity",
+	  RADIUS_ATTR_TEXT },
+	{ RADIUS_ATTR_NAS_IPV6_ADDRESS, "NAS-IPv6-Address", RADIUS_ATTR_IPV6 },
+};
+#define RADIUS_ATTRS (sizeof(radius_attrs) / sizeof(radius_attrs[0]))
+
+
+static struct radius_attr_type *radius_get_attr_type(u8 type)
+{
+	size_t i;
+
+	for (i = 0; i < RADIUS_ATTRS; i++) {
+		if (type == radius_attrs[i].type)
+			return &radius_attrs[i];
+	}
+
+	return NULL;
+}
+
+static char print_char_buf[5];
+
+static char * print_char(char c)
+{
+	if (c >= 32 && c < 127)
+		sprintf(print_char_buf, "%c", c);
+	else
+		sprintf(print_char_buf, "<%02x>", c);
+	return print_char_buf;
+}
+
+
+static char * radius_msg_dump_attr_val(struct radius_attr_hdr *hdr, char * outbuf, size_t buflen)
+{
+	struct radius_attr_type *attr;
+	int i, len;
+	unsigned char *pos;
+	u8 attrtype;
+	
+	memset(outbuf, 0, buflen);
+
+	attr = radius_get_attr_type(hdr->type);
+
+	if (attr == NULL)
+		attrtype = RADIUS_ATTR_HEXDUMP;
+	else
+		attrtype = attr->data_type;
+
+	len = hdr->length - sizeof(struct radius_attr_hdr);
+	pos = (unsigned char *) (hdr + 1);
+
+	switch (attrtype) {
+	case RADIUS_ATTR_TEXT:
+		snprintf(outbuf + strlen(outbuf), buflen - strlen(outbuf), "      Value: '");
+		for (i = 0; i < len; i++)
+			snprintf(outbuf + strlen(outbuf), buflen - strlen(outbuf), "%s", print_char(pos[i]));
+		snprintf(outbuf + strlen(outbuf), buflen - strlen(outbuf), "'");
+		break;
+
+	case RADIUS_ATTR_IP:
+		if (len == 4) {
+			struct in_addr addr;
+			os_memcpy(&addr, pos, 4);
+			snprintf(outbuf + strlen(outbuf), buflen - strlen(outbuf), "      Value: %s", inet_ntoa(addr));
+		} else
+			snprintf(outbuf + strlen(outbuf), buflen - strlen(outbuf), "      Invalid IP address length %d", len);
+		break;
+
+	case RADIUS_ATTR_IPV6:
+		if (len == 16) {
+			char buf[128];
+			const char *atxt;
+			struct in6_addr *addr = (struct in6_addr *) pos;
+			atxt = inet_ntop(AF_INET6, addr, buf, sizeof(buf));
+			snprintf(outbuf + strlen(outbuf), buflen - strlen(outbuf), "      Value: %s", atxt ? atxt : "?");
+		} else
+			snprintf(outbuf + strlen(outbuf), buflen - strlen(outbuf), "      Invalid IPv6 address length %d", len);
+		break;
+
+	case RADIUS_ATTR_INT32:
+		if (len == 4)
+			snprintf(outbuf + strlen(outbuf), buflen - strlen(outbuf), "      Value: %u", WPA_GET_BE32(pos));
+		else
+			snprintf(outbuf + strlen(outbuf), buflen - strlen(outbuf), "      Invalid INT32 length %d", len);
+		break;
+
+	case RADIUS_ATTR_HEXDUMP:
+	case RADIUS_ATTR_UNDIST:
+	default:
+		snprintf(outbuf + strlen(outbuf), buflen - strlen(outbuf), "      Value:");
+		for (i = 0; i < len; i++)
+			snprintf(outbuf + strlen(outbuf), buflen - strlen(outbuf), " %02x", pos[i]);
+		break;
+	}
+	
+	return outbuf;
+}
+
+/* Dump a message  */
+void rgw_msg_dump(struct rgw_radius_msg_meta * msg, int has_meta)
+{
+	unsigned char *auth;
+	char buf[256];
+	size_t i;
+	if (! TRACE_BOOL(FULL) )
+		return;
+	
+	auth =  &(msg->radius.hdr->authenticator[0]);
+	
+	fd_log_debug("------ RADIUS msg dump -------");
+	fd_log_debug(" id  : 0x%02hhx, code : %hhd (%s), length : %d", msg->radius.hdr->identifier, msg->radius.hdr->code, rgw_msg_code_str(msg->radius.hdr->code), ntohs(msg->radius.hdr->length));
+	fd_log_debug(" auth: %02hhx %02hhx %02hhx %02hhx  %02hhx %02hhx %02hhx %02hhx",
+			auth[0], auth[1], auth[2], auth[3], auth[4], auth[5], auth[6], auth[7]);
+	fd_log_debug("       %02hhx %02hhx %02hhx %02hhx  %02hhx %02hhx %02hhx %02hhx",
+			auth[8],  auth[9],  auth[10], auth[11], auth[12], auth[13], auth[14], auth[15]);
+	for (i = 0; i < msg->radius.attr_used; i++) {
+		struct radius_attr_hdr *attr = (struct radius_attr_hdr *)(msg->radius.buf + msg->radius.attr_pos[i]);
+		fd_log_debug("    - Type: 0x%02hhx (%s)       Len: %-3hhu", attr->type, rgw_msg_attrtype_str(attr->type), attr->length);
+		fd_log_debug("%s", radius_msg_dump_attr_val(attr, buf, sizeof(buf)));
+	}
+	if (has_meta && msg->ps_nb) {
+		fd_log_debug("---- hidden attributes:");
+		for (i = msg->ps_first; i < msg->ps_first + msg->ps_nb; i++) {
+			struct radius_attr_hdr *attr = (struct radius_attr_hdr *)(msg->radius.buf + msg->radius.attr_pos[i]);
+			fd_log_debug("    - Type: 0x%02hhx (%s)       Len: %-3hhu", attr->type, rgw_msg_attrtype_str(attr->type), attr->length);
+			fd_log_debug("%s", radius_msg_dump_attr_val(attr, buf, sizeof(buf)));
+		}
+	}
+	fd_log_debug("-----------------------------");
+}
+
+
+int radius_msg_finish(struct radius_msg *msg, const u8 *secret,
+		      size_t secret_len)
+{
+	if (secret) {
+		u8 auth[MD5_MAC_LEN];
+		struct radius_attr_hdr *attr;
+
+		os_memset(auth, 0, MD5_MAC_LEN);
+		attr = radius_msg_add_attr(msg,
+					   RADIUS_ATTR_MESSAGE_AUTHENTICATOR,
+					   auth, MD5_MAC_LEN);
+		if (attr == NULL) {
+			fd_log_debug("WARNING: Could not add Message-Authenticator");
+			return -1;
+		}
+		msg->hdr->length = htons(msg->buf_used);
+		hmac_md5(secret, secret_len, msg->buf, msg->buf_used,
+			 (u8 *) (attr + 1));
+	} else
+		msg->hdr->length = htons(msg->buf_used);
+
+	if (msg->buf_used > 0xffff) {
+		fd_log_debug("WARNING: too long RADIUS message (%lu)",
+		       (unsigned long) msg->buf_used);
+		return -1;
+	}
+	return 0;
+}
+
+
+int radius_msg_finish_srv(struct radius_msg *msg, const u8 *secret,
+			  size_t secret_len, const u8 *req_authenticator)
+{
+	u8 auth[MD5_MAC_LEN];
+	struct radius_attr_hdr *attr;
+	const u8 *addr[4];
+	size_t len[4];
+
+	if (msg->hdr->code != RADIUS_CODE_ACCOUNTING_RESPONSE) {
+	    os_memset(auth, 0, MD5_MAC_LEN);
+	    attr = radius_msg_add_attr(msg, RADIUS_ATTR_MESSAGE_AUTHENTICATOR,
+				       auth, MD5_MAC_LEN);
+	    if (attr == NULL) {
+		    fd_log_debug("WARNING: Could not add Message-Authenticator");
+		    return -1;
+	    }
+	    msg->hdr->length = htons(msg->buf_used);
+	    os_memcpy(msg->hdr->authenticator, req_authenticator,
+		      sizeof(msg->hdr->authenticator));
+	    hmac_md5(secret, secret_len, msg->buf, msg->buf_used,
+		     (u8 *) (attr + 1));
+	} else {
+	    msg->hdr->length = htons(msg->buf_used);
+	}
+
+	/* ResponseAuth = MD5(Code+ID+Length+RequestAuth+Attributes+Secret) */
+	addr[0] = (u8 *) msg->hdr;
+	len[0] = 1 + 1 + 2;
+	addr[1] = req_authenticator;
+	len[1] = MD5_MAC_LEN;
+	addr[2] = (u8 *) (msg->hdr + 1);
+	len[2] = msg->buf_used - sizeof(*msg->hdr);
+	addr[3] = secret;
+	len[3] = secret_len;
+	md5_vector(4, addr, len, msg->hdr->authenticator);
+
+	if (msg->buf_used > 0xffff) {
+		fd_log_debug("WARNING: too long RADIUS message (%lu)",
+		       (unsigned long) msg->buf_used);
+		return -1;
+	}
+	return 0;
+}
+
+
+void radius_msg_finish_acct(struct radius_msg *msg, const u8 *secret,
+			    size_t secret_len)
+{
+	const u8 *addr[2];
+	size_t len[2];
+
+	msg->hdr->length = htons(msg->buf_used);
+	os_memset(msg->hdr->authenticator, 0, MD5_MAC_LEN);
+	addr[0] = msg->buf;
+	len[0] = msg->buf_used;
+	addr[1] = secret;
+	len[1] = secret_len;
+	md5_vector(2, addr, len, msg->hdr->authenticator);
+
+	if (msg->buf_used > 0xffff) {
+		fd_log_debug("WARNING: too long RADIUS messages (%lu)",
+		       (unsigned long) msg->buf_used);
+	}
+}
+
+
+int radius_msg_add_attr_to_array(struct radius_msg *msg,
+					struct radius_attr_hdr *attr)
+{
+	if (msg->attr_used >= msg->attr_size) {
+		size_t *nattr_pos;
+		int nlen = msg->attr_size * 2;
+
+		nattr_pos = os_realloc(msg->attr_pos,
+				       nlen * sizeof(*msg->attr_pos));
+		if (nattr_pos == NULL)
+			return -1;
+
+		msg->attr_pos = nattr_pos;
+		msg->attr_size = nlen;
+	}
+
+	msg->attr_pos[msg->attr_used++] = (unsigned char *) attr - msg->buf;
+
+	return 0;
+}
+
+
+struct radius_attr_hdr *radius_msg_add_attr(struct radius_msg *msg, u8 type,
+					    const u8 *data, size_t data_len)
+{
+	size_t buf_needed;
+	struct radius_attr_hdr *attr;
+
+	if (data_len > RADIUS_MAX_ATTR_LEN) {
+		fd_log_debug("radius_msg_add_attr: too long attribute (%lu bytes)",
+		       (unsigned long) data_len);
+		return NULL;
+	}
+
+	buf_needed = msg->buf_used + sizeof(*attr) + data_len;
+
+	if (msg->buf_size < buf_needed) {
+		/* allocate more space for message buffer */
+		unsigned char *nbuf;
+		size_t nlen = msg->buf_size;
+
+		while (nlen < buf_needed)
+			nlen *= 2;
+		nbuf = os_realloc(msg->buf, nlen);
+		if (nbuf == NULL)
+			return NULL;
+		msg->buf = nbuf;
+		msg->hdr = (struct radius_hdr *) msg->buf;
+		os_memset(msg->buf + msg->buf_size, 0, nlen - msg->buf_size);
+		msg->buf_size = nlen;
+	}
+
+	attr = (struct radius_attr_hdr *) (msg->buf + msg->buf_used);
+	attr->type = type;
+	attr->length = sizeof(*attr) + data_len;
+	if (data_len > 0)
+		os_memcpy(attr + 1, data, data_len);
+
+	msg->buf_used += sizeof(*attr) + data_len;
+
+	if (radius_msg_add_attr_to_array(msg, attr))
+		return NULL;
+
+	return attr;
+}
+
+
+/* Modified version of radius_msg_parse */
+int rgw_msg_parse(unsigned char * buf, size_t len, struct rgw_radius_msg_meta ** msg)
+{
+	struct rgw_radius_msg_meta * temp_msg = NULL;
+	struct radius_hdr *hdr;
+	struct radius_attr_hdr *attr;
+	size_t msg_len;
+	unsigned char *pos, *end;
+	int ret = 0;
+	
+	TRACE_ENTRY("%p %zd %p", buf, len, msg);
+	
+	CHECK_PARAMS( buf && len >= sizeof(*hdr) && msg );
+	
+	*msg = NULL;
+	
+	/* Parse the RADIUS message */
+	hdr = (struct radius_hdr *) buf;
+	msg_len = ntohs(hdr->length);
+	if (msg_len < sizeof(*hdr) || msg_len > len) {
+		TRACE_DEBUG(INFO, "Invalid RADIUS message length");
+		return EINVAL;
+	}
+
+	if (msg_len < len) {
+		TRACE_DEBUG(INFO, "Ignored %lu extra bytes after RADIUS message",
+		       (unsigned long) len - msg_len);
+	}
+
+	CHECK_MALLOC( temp_msg = malloc(sizeof(struct rgw_radius_msg_meta)) );
+	memset(temp_msg, 0, sizeof(struct rgw_radius_msg_meta));
+	
+	if (radius_msg_initialize(&temp_msg->radius, msg_len)) {
+		TRACE_DEBUG(INFO, "Error in radius_msg_initialize, returning ENOMEM.");
+		free(temp_msg);
+		return ENOMEM;
+	}
+	
+	/* Store the received data in the alloc'd buffer */
+	memcpy(temp_msg->radius.buf, buf, msg_len);
+	temp_msg->radius.buf_size = temp_msg->radius.buf_used = msg_len;
+	
+	/* parse attributes */
+	pos = (unsigned char *) (temp_msg->radius.hdr + 1);
+	end = temp_msg->radius.buf + temp_msg->radius.buf_used;
+	
+	while (pos < end) {
+		if ((size_t) (end - pos) < sizeof(*attr)) {
+			TRACE_DEBUG(INFO, "Trucated attribute found in RADIUS buffer, EINVAL.");
+			ret = EINVAL;
+			break;
+		}
+			
+		attr = (struct radius_attr_hdr *) pos;
+	
+		if (pos + attr->length > end || attr->length < sizeof(*attr)) {
+			TRACE_DEBUG(INFO, "Trucated attribute found in RADIUS buffer, EINVAL.");
+			ret = EINVAL;
+			break;
+		}
+
+		if (radius_msg_add_attr_to_array(&temp_msg->radius, attr)) {
+			TRACE_DEBUG(INFO, "Error in radius_msg_add_attr_to_array, ENOMEM");
+			ret = ENOMEM;
+			break;
+		}
+		
+		if (attr->type == RADIUS_ATTR_PROXY_STATE)
+			temp_msg->ps_nb += 1;
+
+		pos += attr->length;
+	}
+	
+	if (ret != 0) {
+		radius_msg_free(&temp_msg->radius);
+		free(temp_msg);
+		return ret;
+	}
+	
+	/* Now move all the proxy-state attributes at the end of the attr_pos array */
+	if (temp_msg->ps_nb) {
+		size_t *temp_ps = NULL;
+		int n, new_n = 0, p = 0;
+		
+		CHECK_MALLOC( temp_ps = calloc(temp_msg->ps_nb, sizeof(size_t)) );
+		
+		/* Move all the Proxy-State attributes into the temp_ps array */
+		for (n=0; n < temp_msg->radius.attr_used; n++) {
+			struct radius_attr_hdr * attr = (struct radius_attr_hdr *)(temp_msg->radius.buf + temp_msg->radius.attr_pos[n]);
+			
+			if (attr->type == RADIUS_ATTR_PROXY_STATE) {
+				temp_ps[p++] = temp_msg->radius.attr_pos[n];
+			} else {
+				temp_msg->radius.attr_pos[new_n++] = temp_msg->radius.attr_pos[n];
+			}
+		}
+		temp_msg->radius.attr_used = new_n; /* hide the proxy-state to other modules */
+		temp_msg->ps_first = new_n;
+		
+		/* And back into the array */
+		memcpy(temp_msg->radius.attr_pos + new_n, temp_ps, p * sizeof(size_t));
+		free(temp_ps);
+	}
+	
+	*msg = temp_msg;
+	return 0;
+}
+
+
+
+int radius_msg_add_eap(struct radius_msg *msg, const u8 *data, size_t data_len)
+{
+	const u8 *pos = data;
+	size_t left = data_len;
+
+	while (left > 0) {
+		int len;
+		if (left > RADIUS_MAX_ATTR_LEN)
+			len = RADIUS_MAX_ATTR_LEN;
+		else
+			len = left;
+
+		if (!radius_msg_add_attr(msg, RADIUS_ATTR_EAP_MESSAGE,
+					 pos, len))
+			return 0;
+
+		pos += len;
+		left -= len;
+	}
+
+	return 1;
+}
+
+
+u8 *radius_msg_get_eap(struct radius_msg *msg, size_t *eap_len)
+{
+	u8 *eap, *pos;
+	size_t len, i;
+	struct radius_attr_hdr *attr;
+
+	if (msg == NULL)
+		return NULL;
+
+	len = 0;
+	for (i = 0; i < msg->attr_used; i++) {
+		attr = radius_get_attr_hdr(msg, i);
+		if (attr->type == RADIUS_ATTR_EAP_MESSAGE)
+			len += attr->length - sizeof(struct radius_attr_hdr);
+	}
+
+	if (len == 0)
+		return NULL;
+
+	eap = os_malloc(len);
+	if (eap == NULL)
+		return NULL;
+
+	pos = eap;
+	for (i = 0; i < msg->attr_used; i++) {
+		attr = radius_get_attr_hdr(msg, i);
+		if (attr->type == RADIUS_ATTR_EAP_MESSAGE) {
+			int flen = attr->length - sizeof(*attr);
+			os_memcpy(pos, attr + 1, flen);
+			pos += flen;
+		}
+	}
+
+	if (eap_len)
+		*eap_len = len;
+
+	return eap;
+}
+
+
+int radius_msg_verify_msg_auth(struct radius_msg *msg, const u8 *secret,
+			       size_t secret_len, const u8 *req_auth)
+{
+	u8 auth[MD5_MAC_LEN], orig[MD5_MAC_LEN];
+	u8 orig_authenticator[16];
+	struct radius_attr_hdr *attr = NULL, *tmp;
+	size_t i;
+
+	for (i = 0; i < msg->attr_used; i++) {
+		tmp = radius_get_attr_hdr(msg, i);
+		if (tmp->type == RADIUS_ATTR_MESSAGE_AUTHENTICATOR) {
+			if (attr != NULL) {
+				fd_log_debug("Multiple Message-Authenticator attributes in RADIUS message");
+				return 1;
+			}
+			attr = tmp;
+		}
+	}
+
+	if (attr == NULL) {
+		fd_log_debug("No Message-Authenticator attribute found");
+		return 1;
+	}
+
+	os_memcpy(orig, attr + 1, MD5_MAC_LEN);
+	os_memset(attr + 1, 0, MD5_MAC_LEN);
+	if (req_auth) {
+		os_memcpy(orig_authenticator, msg->hdr->authenticator,
+			  sizeof(orig_authenticator));
+		os_memcpy(msg->hdr->authenticator, req_auth,
+			  sizeof(msg->hdr->authenticator));
+	}
+	hmac_md5(secret, secret_len, msg->buf, msg->buf_used, auth);
+	os_memcpy(attr + 1, orig, MD5_MAC_LEN);
+	if (req_auth) {
+		os_memcpy(msg->hdr->authenticator, orig_authenticator,
+			  sizeof(orig_authenticator));
+	}
+
+	if (os_memcmp(orig, auth, MD5_MAC_LEN) != 0) {
+		fd_log_debug("Invalid Message-Authenticator!");
+		return 1;
+	}
+
+	return 0;
+}
+
+
+int radius_msg_verify(struct radius_msg *msg, const u8 *secret,
+		      size_t secret_len, struct radius_msg *sent_msg, int auth)
+{
+	const u8 *addr[4];
+	size_t len[4];
+	u8 hash[MD5_MAC_LEN];
+
+	if (sent_msg == NULL) {
+		fd_log_debug("No matching Access-Request message found");
+		return 1;
+	}
+
+	if (auth &&
+	    radius_msg_verify_msg_auth(msg, secret, secret_len,
+				       sent_msg->hdr->authenticator)) {
+		return 1;
+	}
+
+	/* ResponseAuth = MD5(Code+ID+Length+RequestAuth+Attributes+Secret) */
+	addr[0] = (u8 *) msg->hdr;
+	len[0] = 1 + 1 + 2;
+	addr[1] = sent_msg->hdr->authenticator;
+	len[1] = MD5_MAC_LEN;
+	addr[2] = (u8 *) (msg->hdr + 1);
+	len[2] = msg->buf_used - sizeof(*msg->hdr);
+	addr[3] = secret;
+	len[3] = secret_len;
+	md5_vector(4, addr, len, hash);
+	if (os_memcmp(hash, msg->hdr->authenticator, MD5_MAC_LEN) != 0) {
+		fd_log_debug("Response Authenticator invalid!");
+		return 1;
+	}
+
+	return 0;
+}
+
+
+int radius_msg_copy_attr(struct radius_msg *dst, struct radius_msg *src,
+			 u8 type)
+{
+	struct radius_attr_hdr *attr;
+	size_t i;
+	int count = 0;
+
+	for (i = 0; i < src->attr_used; i++) {
+		attr = radius_get_attr_hdr(src, i);
+		if (attr->type == type) {
+			if (!radius_msg_add_attr(dst, type, (u8 *) (attr + 1),
+						 attr->length - sizeof(*attr)))
+				return -1;
+			count++;
+		}
+	}
+
+	return count;
+}
+
+
+/* Create Request Authenticator. The value should be unique over the lifetime
+ * of the shared secret between authenticator and authentication server.
+ * Use one-way MD5 hash calculated from current timestamp and some data given
+ * by the caller. */
+void radius_msg_make_authenticator(struct radius_msg *msg,
+				   const u8 *data, size_t len)
+{
+	struct os_time tv;
+	long int l;
+	const u8 *addr[3];
+	size_t elen[3];
+
+	os_get_time(&tv);
+	l = os_random();
+	addr[0] = (u8 *) &tv;
+	elen[0] = sizeof(tv);
+	addr[1] = data;
+	elen[1] = len;
+	addr[2] = (u8 *) &l;
+	elen[2] = sizeof(l);
+	md5_vector(3, addr, elen, msg->hdr->authenticator);
+}
+
+
+/* Get Vendor-specific RADIUS Attribute from a parsed RADIUS message.
+ * Returns the Attribute payload and sets alen to indicate the length of the
+ * payload if a vendor attribute with subtype is found, otherwise returns NULL.
+ * The returned payload is allocated with os_malloc() and caller must free it
+ * by calling os_free().
+ */
+static u8 *radius_msg_get_vendor_attr(struct radius_msg *msg, u32 vendor,
+				      u8 subtype, size_t *alen)
+{
+	u8 *data, *pos;
+	size_t i, len;
+
+	if (msg == NULL)
+		return NULL;
+
+	for (i = 0; i < msg->attr_used; i++) {
+		struct radius_attr_hdr *attr = radius_get_attr_hdr(msg, i);
+		size_t left;
+		u32 vendor_id;
+		struct radius_attr_vendor *vhdr;
+
+		if (attr->type != RADIUS_ATTR_VENDOR_SPECIFIC)
+			continue;
+
+		left = attr->length - sizeof(*attr);
+		if (left < 4)
+			continue;
+
+		pos = (u8 *) (attr + 1);
+
+		os_memcpy(&vendor_id, pos, 4);
+		pos += 4;
+		left -= 4;
+
+		if (ntohl(vendor_id) != vendor)
+			continue;
+
+		while (left >= sizeof(*vhdr)) {
+			vhdr = (struct radius_attr_vendor *) pos;
+			if (vhdr->vendor_length > left ||
+			    vhdr->vendor_length < sizeof(*vhdr)) {
+				left = 0;
+				break;
+			}
+			if (vhdr->vendor_type != subtype) {
+				pos += vhdr->vendor_length;
+				left -= vhdr->vendor_length;
+				continue;
+			}
+
+			len = vhdr->vendor_length - sizeof(*vhdr);
+			data = os_malloc(len);
+			if (data == NULL)
+				return NULL;
+			os_memcpy(data, pos + sizeof(*vhdr), len);
+			if (alen)
+				*alen = len;
+			return data;
+		}
+	}
+
+	return NULL;
+}
+
+
+static u8 * decrypt_ms_key(const u8 *key, size_t len,
+			   const u8 *req_authenticator,
+			   const u8 *secret, size_t secret_len, size_t *reslen)
+{
+	u8 *plain, *ppos, *res;
+	const u8 *pos;
+	size_t left, plen;
+	u8 hash[MD5_MAC_LEN];
+	int i, first = 1;
+	const u8 *addr[3];
+	size_t elen[3];
+
+	/* key: 16-bit salt followed by encrypted key info */
+
+	if (len < 2 + 16)
+		return NULL;
+
+	pos = key + 2;
+	left = len - 2;
+	if (left % 16) {
+		fd_log_debug("Invalid ms key len %lu", (unsigned long) left);
+		return NULL;
+	}
+
+	plen = left;
+	ppos = plain = os_malloc(plen);
+	if (plain == NULL)
+		return NULL;
+	plain[0] = 0;
+
+	while (left > 0) {
+		/* b(1) = MD5(Secret + Request-Authenticator + Salt)
+		 * b(i) = MD5(Secret + c(i - 1)) for i > 1 */
+
+		addr[0] = secret;
+		elen[0] = secret_len;
+		if (first) {
+			addr[1] = req_authenticator;
+			elen[1] = MD5_MAC_LEN;
+			addr[2] = key;
+			elen[2] = 2; /* Salt */
+		} else {
+			addr[1] = pos - MD5_MAC_LEN;
+			elen[1] = MD5_MAC_LEN;
+		}
+		md5_vector(first ? 3 : 2, addr, elen, hash);
+		first = 0;
+
+		for (i = 0; i < MD5_MAC_LEN; i++)
+			*ppos++ = *pos++ ^ hash[i];
+		left -= MD5_MAC_LEN;
+	}
+
+	if (plain[0] == 0 || plain[0] > plen - 1) {
+		fd_log_debug("Failed to decrypt MPPE key");
+		os_free(plain);
+		return NULL;
+	}
+
+	res = os_malloc(plain[0]);
+	if (res == NULL) {
+		os_free(plain);
+		return NULL;
+	}
+	os_memcpy(res, plain + 1, plain[0]);
+	if (reslen)
+		*reslen = plain[0];
+	os_free(plain);
+	return res;
+}
+
+
+static void encrypt_ms_key(const u8 *key, size_t key_len, u16 salt,
+			   const u8 *req_authenticator,
+			   const u8 *secret, size_t secret_len,
+			   u8 *ebuf, size_t *elen)
+{
+	int i, len, first = 1;
+	u8 hash[MD5_MAC_LEN], saltbuf[2], *pos;
+	const u8 *addr[3];
+	size_t _len[3];
+
+	WPA_PUT_BE16(saltbuf, salt);
+
+	len = 1 + key_len;
+	if (len & 0x0f) {
+		len = (len & 0xf0) + 16;
+	}
+	os_memset(ebuf, 0, len);
+	ebuf[0] = key_len;
+	os_memcpy(ebuf + 1, key, key_len);
+
+	*elen = len;
+
+	pos = ebuf;
+	while (len > 0) {
+		/* b(1) = MD5(Secret + Request-Authenticator + Salt)
+		 * b(i) = MD5(Secret + c(i - 1)) for i > 1 */
+		addr[0] = secret;
+		_len[0] = secret_len;
+		if (first) {
+			addr[1] = req_authenticator;
+			_len[1] = MD5_MAC_LEN;
+			addr[2] = saltbuf;
+			_len[2] = sizeof(saltbuf);
+		} else {
+			addr[1] = pos - MD5_MAC_LEN;
+			_len[1] = MD5_MAC_LEN;
+		}
+		md5_vector(first ? 3 : 2, addr, _len, hash);
+		first = 0;
+
+		for (i = 0; i < MD5_MAC_LEN; i++)
+			*pos++ ^= hash[i];
+
+		len -= MD5_MAC_LEN;
+	}
+}
+
+
+struct radius_ms_mppe_keys *
+radius_msg_get_ms_keys(struct radius_msg *msg, struct radius_msg *sent_msg,
+		       const u8 *secret, size_t secret_len)
+{
+	u8 *key;
+	size_t keylen;
+	struct radius_ms_mppe_keys *keys;
+
+	if (msg == NULL || sent_msg == NULL)
+		return NULL;
+
+	keys = os_zalloc(sizeof(*keys));
+	if (keys == NULL)
+		return NULL;
+
+	key = radius_msg_get_vendor_attr(msg, RADIUS_VENDOR_ID_MICROSOFT,
+					 RADIUS_VENDOR_ATTR_MS_MPPE_SEND_KEY,
+					 &keylen);
+	if (key) {
+		keys->send = decrypt_ms_key(key, keylen,
+					    sent_msg->hdr->authenticator,
+					    secret, secret_len,
+					    &keys->send_len);
+		os_free(key);
+	}
+
+	key = radius_msg_get_vendor_attr(msg, RADIUS_VENDOR_ID_MICROSOFT,
+					 RADIUS_VENDOR_ATTR_MS_MPPE_RECV_KEY,
+					 &keylen);
+	if (key) {
+		keys->recv = decrypt_ms_key(key, keylen,
+					    sent_msg->hdr->authenticator,
+					    secret, secret_len,
+					    &keys->recv_len);
+		os_free(key);
+	}
+
+	return keys;
+}
+
+
+struct radius_ms_mppe_keys *
+radius_msg_get_cisco_keys(struct radius_msg *msg, struct radius_msg *sent_msg,
+			  const u8 *secret, size_t secret_len)
+{
+	u8 *key;
+	size_t keylen;
+	struct radius_ms_mppe_keys *keys;
+
+	if (msg == NULL || sent_msg == NULL)
+		return NULL;
+
+	keys = os_zalloc(sizeof(*keys));
+	if (keys == NULL)
+		return NULL;
+
+	key = radius_msg_get_vendor_attr(msg, RADIUS_VENDOR_ID_CISCO,
+					 RADIUS_CISCO_AV_PAIR, &keylen);
+	if (key && keylen == 51 &&
+	    os_memcmp(key, "leap:session-key=", 17) == 0) {
+		keys->recv = decrypt_ms_key(key + 17, keylen - 17,
+					    sent_msg->hdr->authenticator,
+					    secret, secret_len,
+					    &keys->recv_len);
+	}
+	os_free(key);
+
+	return keys;
+}
+
+
+int radius_msg_add_mppe_keys(struct radius_msg *msg,
+			     const u8 *req_authenticator,
+			     const u8 *secret, size_t secret_len,
+			     const u8 *send_key, size_t send_key_len,
+			     const u8 *recv_key, size_t recv_key_len)
+{
+	struct radius_attr_hdr *attr;
+	u32 vendor_id = htonl(RADIUS_VENDOR_ID_MICROSOFT);
+	u8 *buf;
+	struct radius_attr_vendor *vhdr;
+	u8 *pos;
+	size_t elen;
+	int hlen;
+	u16 salt;
+
+	hlen = sizeof(vendor_id) + sizeof(*vhdr) + 2;
+
+	/* MS-MPPE-Send-Key */
+	buf = os_malloc(hlen + send_key_len + 16);
+	if (buf == NULL) {
+		return 0;
+	}
+	pos = buf;
+	os_memcpy(pos, &vendor_id, sizeof(vendor_id));
+	pos += sizeof(vendor_id);
+	vhdr = (struct radius_attr_vendor *) pos;
+	vhdr->vendor_type = RADIUS_VENDOR_ATTR_MS_MPPE_SEND_KEY;
+	pos = (u8 *) (vhdr + 1);
+	salt = os_random() | 0x8000;
+	WPA_PUT_BE16(pos, salt);
+	pos += 2;
+	encrypt_ms_key(send_key, send_key_len, salt, req_authenticator, secret,
+		       secret_len, pos, &elen);
+	vhdr->vendor_length = hlen + elen - sizeof(vendor_id);
+
+	attr = radius_msg_add_attr(msg, RADIUS_ATTR_VENDOR_SPECIFIC,
+				   buf, hlen + elen);
+	os_free(buf);
+	if (attr == NULL) {
+		return 0;
+	}
+
+	/* MS-MPPE-Recv-Key */
+	buf = os_malloc(hlen + send_key_len + 16);
+	if (buf == NULL) {
+		return 0;
+	}
+	pos = buf;
+	os_memcpy(pos, &vendor_id, sizeof(vendor_id));
+	pos += sizeof(vendor_id);
+	vhdr = (struct radius_attr_vendor *) pos;
+	vhdr->vendor_type = RADIUS_VENDOR_ATTR_MS_MPPE_RECV_KEY;
+	pos = (u8 *) (vhdr + 1);
+	salt ^= 1;
+	WPA_PUT_BE16(pos, salt);
+	pos += 2;
+	encrypt_ms_key(recv_key, recv_key_len, salt, req_authenticator, secret,
+		       secret_len, pos, &elen);
+	vhdr->vendor_length = hlen + elen - sizeof(vendor_id);
+
+	attr = radius_msg_add_attr(msg, RADIUS_ATTR_VENDOR_SPECIFIC,
+				   buf, hlen + elen);
+	os_free(buf);
+	if (attr == NULL) {
+		return 0;
+	}
+
+	return 1;
+}
+
+
+/* Add User-Password attribute to a RADIUS message and encrypt it as specified
+ * in RFC 2865, Chap. 5.2 */
+struct radius_attr_hdr *
+radius_msg_add_attr_user_password(struct radius_msg *msg,
+				  const u8 *data, size_t data_len,
+				  const u8 *secret, size_t secret_len)
+{
+	u8 buf[128];
+	int padlen, i;
+	size_t buf_len, pos;
+	const u8 *addr[2];
+	size_t len[2];
+	u8 hash[16];
+
+	if (data_len > 128)
+		return NULL;
+
+	os_memcpy(buf, data, data_len);
+	buf_len = data_len;
+
+	padlen = data_len % 16;
+	if (padlen) {
+		padlen = 16 - padlen;
+		os_memset(buf + data_len, 0, padlen);
+		buf_len += padlen;
+	}
+
+	addr[0] = secret;
+	len[0] = secret_len;
+	addr[1] = msg->hdr->authenticator;
+	len[1] = 16;
+	md5_vector(2, addr, len, hash);
+
+	for (i = 0; i < 16; i++)
+		buf[i] ^= hash[i];
+	pos = 16;
+
+	while (pos < buf_len) {
+		addr[0] = secret;
+		len[0] = secret_len;
+		addr[1] = &buf[pos - 16];
+		len[1] = 16;
+		md5_vector(2, addr, len, hash);
+
+		for (i = 0; i < 16; i++)
+			buf[pos + i] ^= hash[i];
+
+		pos += 16;
+	}
+
+	return radius_msg_add_attr(msg, RADIUS_ATTR_USER_PASSWORD,
+				   buf, buf_len);
+}
+
+
+int radius_msg_get_attr(struct radius_msg *msg, u8 type, u8 *buf, size_t len)
+{
+	struct radius_attr_hdr *attr = NULL, *tmp;
+	size_t i, dlen;
+
+	for (i = 0; i < msg->attr_used; i++) {
+		tmp = radius_get_attr_hdr(msg, i);
+		if (tmp->type == type) {
+			attr = tmp;
+			break;
+		}
+	}
+
+	if (!attr)
+		return -1;
+
+	dlen = attr->length - sizeof(*attr);
+	if (buf)
+		os_memcpy(buf, (attr + 1), dlen > len ? len : dlen);
+	return dlen;
+}
+
+
+int radius_msg_get_attr_ptr(struct radius_msg *msg, u8 type, u8 **buf,
+			    size_t *len, const u8 *start)
+{
+	size_t i;
+	struct radius_attr_hdr *attr = NULL, *tmp;
+
+	for (i = 0; i < msg->attr_used; i++) {
+		tmp = radius_get_attr_hdr(msg, i);
+		if (tmp->type == type &&
+		    (start == NULL || (u8 *) tmp > start)) {
+			attr = tmp;
+			break;
+		}
+	}
+
+	if (!attr)
+		return -1;
+
+	*buf = (u8 *) (attr + 1);
+	*len = attr->length - sizeof(*attr);
+	return 0;
+}
+
+
+int radius_msg_count_attr(struct radius_msg *msg, u8 type, int min_len)
+{
+	size_t i;
+	int count;
+
+	for (count = 0, i = 0; i < msg->attr_used; i++) {
+		struct radius_attr_hdr *attr = radius_get_attr_hdr(msg, i);
+		if (attr->type == type &&
+		    attr->length >= sizeof(struct radius_attr_hdr) + min_len)
+			count++;
+	}
+
+	return count;
+}
+
+
+struct radius_tunnel_attrs {
+	int tag_used;
+	int type; /* Tunnel-Type */
+	int medium_type; /* Tunnel-Medium-Type */
+	int vlanid;
+};
+
+
+/**
+ * radius_msg_get_vlanid - Parse RADIUS attributes for VLAN tunnel information
+ * @msg: RADIUS message
+ * Returns: VLAN ID for the first tunnel configuration of -1 if none is found
+ */
+int radius_msg_get_vlanid(struct radius_msg *msg)
+{
+	struct radius_tunnel_attrs tunnel[RADIUS_TUNNEL_TAGS], *tun;
+	size_t i;
+	struct radius_attr_hdr *attr = NULL;
+	const u8 *data;
+	char buf[10];
+	size_t dlen;
+
+	os_memset(&tunnel, 0, sizeof(tunnel));
+
+	for (i = 0; i < msg->attr_used; i++) {
+		attr = radius_get_attr_hdr(msg, i);
+		data = (const u8 *) (attr + 1);
+		dlen = attr->length - sizeof(*attr);
+		if (attr->length < 3)
+			continue;
+		if (data[0] >= RADIUS_TUNNEL_TAGS)
+			tun = &tunnel[0];
+		else
+			tun = &tunnel[data[0]];
+
+		switch (attr->type) {
+		case RADIUS_ATTR_TUNNEL_TYPE:
+			if (attr->length != 6)
+				break;
+			tun->tag_used++;
+			tun->type = WPA_GET_BE24(data + 1);
+			break;
+		case RADIUS_ATTR_TUNNEL_MEDIUM_TYPE:
+			if (attr->length != 6)
+				break;
+			tun->tag_used++;
+			tun->medium_type = WPA_GET_BE24(data + 1);
+			break;
+		case RADIUS_ATTR_TUNNEL_PRIVATE_GROUP_ID:
+			if (data[0] < RADIUS_TUNNEL_TAGS) {
+				data++;
+				dlen--;
+			}
+			if (dlen >= sizeof(buf))
+				break;
+			os_memcpy(buf, data, dlen);
+			buf[dlen] = '\0';
+			tun->tag_used++;
+			tun->vlanid = atoi(buf);
+			break;
+		}
+	}
+
+	for (i = 0; i < RADIUS_TUNNEL_TAGS; i++) {
+		tun = &tunnel[i];
+		if (tun->tag_used &&
+		    tun->type == RADIUS_TUNNEL_TYPE_VLAN &&
+		    tun->medium_type == RADIUS_TUNNEL_MEDIUM_TYPE_802 &&
+		    tun->vlanid > 0)
+			return tun->vlanid;
+	}
+
+	return -1;
+}
+
+
+void radius_free_class(struct radius_class_data *c)
+{
+	size_t i;
+	if (c == NULL)
+		return;
+	for (i = 0; i < c->count; i++)
+		os_free(c->attr[i].data);
+	os_free(c->attr);
+	c->attr = NULL;
+	c->count = 0;
+}
+
+
+int radius_copy_class(struct radius_class_data *dst,
+		      const struct radius_class_data *src)
+{
+	size_t i;
+
+	if (src->attr == NULL)
+		return 0;
+
+	dst->attr = os_zalloc(src->count * sizeof(struct radius_attr_data));
+	if (dst->attr == NULL)
+		return -1;
+
+	dst->count = 0;
+
+	for (i = 0; i < src->count; i++) {
+		dst->attr[i].data = os_malloc(src->attr[i].len);
+		if (dst->attr[i].data == NULL)
+			break;
+		dst->count++;
+		os_memcpy(dst->attr[i].data, src->attr[i].data,
+			  src->attr[i].len);
+		dst->attr[i].len = src->attr[i].len;
+	}
+
+	return 0;
+}
diff --git a/extensions/app_radgw/radius.h b/extensions/app_radgw/radius.h
new file mode 100644
index 0000000..c278472
--- /dev/null
+++ b/extensions/app_radgw/radius.h
@@ -0,0 +1,331 @@
+/*********************************************************************************************************
+* Software License Agreement (BSD License)                                                               *
+* Author: Sebastien Decugis <sdecugis@freediameter.net>							 *
+*													 *
+* Copyright (c) 2013, WIDE Project and NICT								 *
+* All rights reserved.											 *
+* 													 *
+* Redistribution and use of this software in source and binary forms, with or without modification, are  *
+* permitted provided that the following conditions are met:						 *
+* 													 *
+* * Redistributions of source code must retain the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer.										 *
+*    													 *
+* * Redistributions in binary form must reproduce the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer in the documentation and/or other						 *
+*   materials provided with the distribution.								 *
+* 													 *
+* * Neither the name of the WIDE Project or NICT nor the 						 *
+*   names of its contributors may be used to endorse or 						 *
+*   promote products derived from this software without 						 *
+*   specific prior written permission of WIDE Project and 						 *
+*   NICT.												 *
+* 													 *
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED *
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
+* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR *
+* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 	 *
+* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 	 *
+* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR *
+* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF   *
+* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.								 *
+*********************************************************************************************************/
+
+/*********************************************************************************/
+/* freeDiameter author note:
+ *  The content from this file comes mostly from the hostap project.
+ * It is redistributed under the terms of the BSD license, as allowed
+ * by the original copyright reproduced below.
+ * The changes to this file are placed under the copyright of the freeDiameter project.
+ */
+
+/*
+ * hostapd / RADIUS message processing
+ * Copyright (c) 2002-2007, Jouni Malinen <j@w1.fi>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Alternatively, this software may be distributed under the terms of BSD
+ * license.
+ *
+ * See README and COPYING for more details.
+ */
+/*********************************************************************************/
+
+
+#ifndef RADIUS_H
+#define RADIUS_H
+
+/* RFC 2865 - RADIUS */
+
+#ifdef _MSC_VER
+#pragma pack(push, 1)
+#endif /* _MSC_VER */
+
+struct radius_hdr {
+	u8 code;
+	u8 identifier;
+	u16 length; /* including this header */
+	u8 authenticator[16];
+	/* followed by length-20 octets of attributes */
+} STRUCT_PACKED;
+
+enum { RADIUS_CODE_ACCESS_REQUEST = 1,
+       RADIUS_CODE_ACCESS_ACCEPT = 2,
+       RADIUS_CODE_ACCESS_REJECT = 3,
+       RADIUS_CODE_ACCOUNTING_REQUEST = 4,
+       RADIUS_CODE_ACCOUNTING_RESPONSE = 5,
+       RADIUS_CODE_ACCESS_CHALLENGE = 11,
+       RADIUS_CODE_STATUS_SERVER = 12,
+       RADIUS_CODE_STATUS_CLIENT = 13,
+       RADIUS_CODE_RESERVED = 255
+};
+
+struct radius_attr_hdr {
+	u8 type;
+	u8 length; /* including this header */
+	/* followed by length-2 octets of attribute value */
+} STRUCT_PACKED;
+
+#define RADIUS_MAX_ATTR_LEN (255 - sizeof(struct radius_attr_hdr))
+
+enum { RADIUS_ATTR_USER_NAME = 1,
+       RADIUS_ATTR_USER_PASSWORD = 2,
+       RADIUS_ATTR_NAS_IP_ADDRESS = 4,
+       RADIUS_ATTR_NAS_PORT = 5,
+       RADIUS_ATTR_FRAMED_MTU = 12,
+       RADIUS_ATTR_REPLY_MESSAGE = 18,
+       RADIUS_ATTR_STATE = 24,
+       RADIUS_ATTR_CLASS = 25,
+       RADIUS_ATTR_VENDOR_SPECIFIC = 26,
+       RADIUS_ATTR_SESSION_TIMEOUT = 27,
+       RADIUS_ATTR_IDLE_TIMEOUT = 28,
+       RADIUS_ATTR_TERMINATION_ACTION = 29,
+       RADIUS_ATTR_CALLED_STATION_ID = 30,
+       RADIUS_ATTR_CALLING_STATION_ID = 31,
+       RADIUS_ATTR_NAS_IDENTIFIER = 32,
+       RADIUS_ATTR_PROXY_STATE = 33,
+       RADIUS_ATTR_ACCT_STATUS_TYPE = 40,
+       RADIUS_ATTR_ACCT_DELAY_TIME = 41,
+       RADIUS_ATTR_ACCT_INPUT_OCTETS = 42,
+       RADIUS_ATTR_ACCT_OUTPUT_OCTETS = 43,
+       RADIUS_ATTR_ACCT_SESSION_ID = 44,
+       RADIUS_ATTR_ACCT_AUTHENTIC = 45,
+       RADIUS_ATTR_ACCT_SESSION_TIME = 46,
+       RADIUS_ATTR_ACCT_INPUT_PACKETS = 47,
+       RADIUS_ATTR_ACCT_OUTPUT_PACKETS = 48,
+       RADIUS_ATTR_ACCT_TERMINATE_CAUSE = 49,
+       RADIUS_ATTR_ACCT_MULTI_SESSION_ID = 50,
+       RADIUS_ATTR_ACCT_LINK_COUNT = 51,
+       RADIUS_ATTR_ACCT_INPUT_GIGAWORDS = 52,
+       RADIUS_ATTR_ACCT_OUTPUT_GIGAWORDS = 53,
+       RADIUS_ATTR_EVENT_TIMESTAMP = 55,
+       RADIUS_ATTR_NAS_PORT_TYPE = 61,
+       RADIUS_ATTR_TUNNEL_TYPE = 64,
+       RADIUS_ATTR_TUNNEL_MEDIUM_TYPE = 65,
+       RADIUS_ATTR_CONNECT_INFO = 77,
+       RADIUS_ATTR_EAP_MESSAGE = 79,
+       RADIUS_ATTR_MESSAGE_AUTHENTICATOR = 80,
+       RADIUS_ATTR_TUNNEL_PRIVATE_GROUP_ID = 81,
+       RADIUS_ATTR_ACCT_INTERIM_INTERVAL = 85,
+       RADIUS_ATTR_CHARGEABLE_USER_IDENTITY = 89,
+       RADIUS_ATTR_NAS_IPV6_ADDRESS = 95
+};
+
+
+/* Termination-Action */
+#define RADIUS_TERMINATION_ACTION_DEFAULT 0
+#define RADIUS_TERMINATION_ACTION_RADIUS_REQUEST 1
+
+/* NAS-Port-Type */
+#define RADIUS_NAS_PORT_TYPE_IEEE_802_11 19
+
+/* Acct-Status-Type */
+#define RADIUS_ACCT_STATUS_TYPE_START 1
+#define RADIUS_ACCT_STATUS_TYPE_STOP 2
+#define RADIUS_ACCT_STATUS_TYPE_INTERIM_UPDATE 3
+#define RADIUS_ACCT_STATUS_TYPE_ACCOUNTING_ON 7
+#define RADIUS_ACCT_STATUS_TYPE_ACCOUNTING_OFF 8
+
+/* Acct-Authentic */
+#define RADIUS_ACCT_AUTHENTIC_RADIUS 1
+#define RADIUS_ACCT_AUTHENTIC_LOCAL 2
+#define RADIUS_ACCT_AUTHENTIC_REMOTE 3
+
+/* Acct-Terminate-Cause */
+#define RADIUS_ACCT_TERMINATE_CAUSE_USER_REQUEST 1
+#define RADIUS_ACCT_TERMINATE_CAUSE_LOST_CARRIER 2
+#define RADIUS_ACCT_TERMINATE_CAUSE_LOST_SERVICE 3
+#define RADIUS_ACCT_TERMINATE_CAUSE_IDLE_TIMEOUT 4
+#define RADIUS_ACCT_TERMINATE_CAUSE_SESSION_TIMEOUT 5
+#define RADIUS_ACCT_TERMINATE_CAUSE_ADMIN_RESET 6
+#define RADIUS_ACCT_TERMINATE_CAUSE_ADMIN_REBOOT 7
+#define RADIUS_ACCT_TERMINATE_CAUSE_PORT_ERROR 8
+#define RADIUS_ACCT_TERMINATE_CAUSE_NAS_ERROR 9
+#define RADIUS_ACCT_TERMINATE_CAUSE_NAS_REQUEST 10
+#define RADIUS_ACCT_TERMINATE_CAUSE_NAS_REBOOT 11
+#define RADIUS_ACCT_TERMINATE_CAUSE_PORT_UNNEEDED 12
+#define RADIUS_ACCT_TERMINATE_CAUSE_PORT_PREEMPTED 13
+#define RADIUS_ACCT_TERMINATE_CAUSE_PORT_SUSPENDED 14
+#define RADIUS_ACCT_TERMINATE_CAUSE_SERVICE_UNAVAILABLE 15
+#define RADIUS_ACCT_TERMINATE_CAUSE_CALLBACK 16
+#define RADIUS_ACCT_TERMINATE_CAUSE_USER_ERROR 17
+#define RADIUS_ACCT_TERMINATE_CAUSE_HOST_REQUEST 18
+
+#define RADIUS_TUNNEL_TAGS 32
+
+/* Tunnel-Type */
+#define RADIUS_TUNNEL_TYPE_PPTP 1
+#define RADIUS_TUNNEL_TYPE_L2TP 3
+#define RADIUS_TUNNEL_TYPE_IPIP 7
+#define RADIUS_TUNNEL_TYPE_GRE 10
+#define RADIUS_TUNNEL_TYPE_VLAN 13
+
+/* Tunnel-Medium-Type */
+#define RADIUS_TUNNEL_MEDIUM_TYPE_IPV4 1
+#define RADIUS_TUNNEL_MEDIUM_TYPE_IPV6 2
+#define RADIUS_TUNNEL_MEDIUM_TYPE_802 6
+
+
+struct radius_attr_vendor {
+	u8 vendor_type;
+	u8 vendor_length;
+} STRUCT_PACKED;
+
+#define RADIUS_VENDOR_ID_CISCO 9
+#define RADIUS_CISCO_AV_PAIR 1
+
+/* RFC 2548 - Microsoft Vendor-specific RADIUS Attributes */
+#define RADIUS_VENDOR_ID_MICROSOFT 311
+
+enum { RADIUS_VENDOR_ATTR_MS_MPPE_SEND_KEY = 16,
+       RADIUS_VENDOR_ATTR_MS_MPPE_RECV_KEY = 17
+};
+
+#ifdef _MSC_VER
+#pragma pack(pop)
+#endif /* _MSC_VER */
+
+struct radius_ms_mppe_keys {
+	u8 *send;
+	size_t send_len;
+	u8 *recv;
+	size_t recv_len;
+};
+
+
+/* RADIUS message structure for new and parsed messages */
+struct radius_msg {
+	unsigned char *buf;
+	size_t buf_size; /* total size allocated for buf */
+	size_t buf_used; /* bytes used in buf */
+
+	struct radius_hdr *hdr;
+
+	size_t *attr_pos; /* array of indexes to attributes (number of bytes
+			   * from buf to the beginning of
+			   * struct radius_attr_hdr). */
+	size_t attr_size; /* total size of the attribute pointer array */
+	size_t attr_used; /* total number of attributes in the array */
+};
+
+
+/* Default size to be allocated for new RADIUS messages */
+#define RADIUS_DEFAULT_MSG_SIZE 1024
+
+/* Default size to be allocated for attribute array */
+#define RADIUS_DEFAULT_ATTR_COUNT 16
+
+
+/* MAC address ASCII format for IEEE 802.1X use
+ * (draft-congdon-radius-8021x-20.txt) */
+#define RADIUS_802_1X_ADDR_FORMAT "%02X-%02X-%02X-%02X-%02X-%02X"
+/* MAC address ASCII format for non-802.1X use */
+#define RADIUS_ADDR_FORMAT "%02x%02x%02x%02x%02x%02x"
+
+struct radius_msg *radius_msg_new(u8 code, u8 identifier);
+int radius_msg_initialize(struct radius_msg *msg, size_t init_len);
+void radius_msg_set_hdr(struct radius_msg *msg, u8 code, u8 identifier);
+void radius_msg_free(struct radius_msg *msg);
+int radius_msg_finish(struct radius_msg *msg, const u8 *secret,
+		      size_t secret_len);
+int radius_msg_finish_srv(struct radius_msg *msg, const u8 *secret,
+			  size_t secret_len, const u8 *req_authenticator);
+void radius_msg_finish_acct(struct radius_msg *msg, const u8 *secret,
+			    size_t secret_len);
+struct radius_attr_hdr *radius_msg_add_attr(struct radius_msg *msg, u8 type,
+					    const u8 *data, size_t data_len);
+int radius_msg_add_eap(struct radius_msg *msg, const u8 *data,
+		       size_t data_len);
+u8 *radius_msg_get_eap(struct radius_msg *msg, size_t *len);
+int radius_msg_verify(struct radius_msg *msg, const u8 *secret,
+		      size_t secret_len, struct radius_msg *sent_msg,
+		      int auth);
+int radius_msg_verify_msg_auth(struct radius_msg *msg, const u8 *secret,
+			       size_t secret_len, const u8 *req_auth);
+int radius_msg_copy_attr(struct radius_msg *dst, struct radius_msg *src,
+			 u8 type);
+void radius_msg_make_authenticator(struct radius_msg *msg,
+				   const u8 *data, size_t len);
+struct radius_ms_mppe_keys *
+radius_msg_get_ms_keys(struct radius_msg *msg, struct radius_msg *sent_msg,
+		       const u8 *secret, size_t secret_len);
+struct radius_ms_mppe_keys *
+radius_msg_get_cisco_keys(struct radius_msg *msg, struct radius_msg *sent_msg,
+			  const u8 *secret, size_t secret_len);
+int radius_msg_add_mppe_keys(struct radius_msg *msg,
+			     const u8 *req_authenticator,
+			     const u8 *secret, size_t secret_len,
+			     const u8 *send_key, size_t send_key_len,
+			     const u8 *recv_key, size_t recv_key_len);
+struct radius_attr_hdr *
+radius_msg_add_attr_user_password(struct radius_msg *msg,
+				  const u8 *data, size_t data_len,
+				  const u8 *secret, size_t secret_len);
+int radius_msg_get_attr(struct radius_msg *msg, u8 type, u8 *buf, size_t len);
+int radius_msg_get_vlanid(struct radius_msg *msg);
+
+static inline int radius_msg_add_attr_int32(struct radius_msg *msg, u8 type,
+					    u32 value)
+{
+	u32 val = htonl(value);
+	return radius_msg_add_attr(msg, type, (u8 *) &val, 4) != NULL;
+}
+
+int radius_msg_add_attr_to_array(struct radius_msg *msg, struct radius_attr_hdr *attr);
+static inline int radius_msg_get_attr_int32(struct radius_msg *msg, u8 type,
+					    u32 *value)
+{
+	u32 val;
+	int res;
+	res = radius_msg_get_attr(msg, type, (u8 *) &val, 4);
+	if (res != 4)
+		return -1;
+
+	*value = ntohl(val);
+	return 0;
+}
+int radius_msg_get_attr_ptr(struct radius_msg *msg, u8 type, u8 **buf,
+			    size_t *len, const u8 *start);
+int radius_msg_count_attr(struct radius_msg *msg, u8 type, int min_len);
+
+
+struct radius_attr_data {
+	u8 *data;
+	size_t len;
+};
+
+struct radius_class_data {
+	struct radius_attr_data *attr;
+	size_t count;
+};
+
+void radius_free_class(struct radius_class_data *c);
+int radius_copy_class(struct radius_class_data *dst,
+		      const struct radius_class_data *src);
+
+#endif /* RADIUS_H */
diff --git a/extensions/app_radgw/rgw.h b/extensions/app_radgw/rgw.h
new file mode 100644
index 0000000..b6c0911
--- /dev/null
+++ b/extensions/app_radgw/rgw.h
@@ -0,0 +1,134 @@
+/*********************************************************************************************************
+* Software License Agreement (BSD License)                                                               *
+* Author: Sebastien Decugis <sdecugis@freediameter.net>							 *
+*													 *
+* Copyright (c) 2013, WIDE Project and NICT								 *
+* All rights reserved.											 *
+* 													 *
+* Redistribution and use of this software in source and binary forms, with or without modification, are  *
+* permitted provided that the following conditions are met:						 *
+* 													 *
+* * Redistributions of source code must retain the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer.										 *
+*    													 *
+* * Redistributions in binary form must reproduce the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer in the documentation and/or other						 *
+*   materials provided with the distribution.								 *
+* 													 *
+* * Neither the name of the WIDE Project or NICT nor the 						 *
+*   names of its contributors may be used to endorse or 						 *
+*   promote products derived from this software without 						 *
+*   specific prior written permission of WIDE Project and 						 *
+*   NICT.												 *
+* 													 *
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED *
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
+* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR *
+* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 	 *
+* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 	 *
+* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR *
+* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF   *
+* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.								 *
+*********************************************************************************************************/
+
+/* This file contains the definitions for the app_radgw internal use. */
+  
+#ifndef _RGW_H
+#define _RGW_H
+
+/* include the common definitions */
+#include "rgw_common.h"
+
+/* RADIUS messages + metadata */
+struct rgw_radius_msg_meta {
+
+	/* The RADIUS message */
+	struct radius_msg 	radius;
+	
+	/* Metadata */
+	struct {
+		/* The port it was sent from, in network byte order */
+		unsigned	port :16;
+		
+		/* received on ACCT or AUTH port? */
+		unsigned	serv_type :2;
+		
+		/* The message has a valid Message-Authenticator attribute */
+		unsigned	valid_mac :1;
+	};
+	
+	/* For Proxy-State attributes: */
+	int	ps_first;	/* The index of the first Proxy-State attribute in radius.attr_pos. It is always >= radius.attr_used */
+	int	ps_nb;		/* The number of Proxy-State attributes. The real radius.attr_pos size is attr_used + ps_nb */
+};
+void rgw_msg_free(struct rgw_radius_msg_meta ** msg);
+int rgw_msg_parse(unsigned char * buf, size_t len, struct rgw_radius_msg_meta ** msg);
+void rgw_msg_dump(struct rgw_radius_msg_meta * msg, int has_meta);
+
+/* Local RADIUS server(s) configuration */
+struct rgw_serv {
+	unsigned	disabled	:1;
+	unsigned	ip_disabled	:1;
+	unsigned	ip6_disabled	:1;
+	unsigned	:13; /* padding */
+	
+	uint16_t	port;	/* stored in network byte order */
+	
+	struct in_addr	ip_endpoint;
+	struct in6_addr	ip6_endpoint;
+};
+
+extern struct rgw_servs {
+	struct rgw_serv	auth_serv;
+	struct rgw_serv	acct_serv;
+} rgw_servers;
+
+int rgw_servers_init(void);
+int rgw_servers_start(void);
+void rgw_servers_dump(void);
+int rgw_servers_send(int type, unsigned char *buf, size_t buflen, struct sockaddr *to, uint16_t to_port);
+void rgw_servers_fini(void);
+
+
+/* Clients management */
+enum rgw_cli_type { RGW_CLI_NAS, RGW_CLI_PXY };
+int rgw_clients_auth_check(struct rgw_radius_msg_meta * msg, struct rgw_client * cli, uint8_t * req_auth);
+int rgw_clients_add( struct sockaddr * ip_port, unsigned char ** key, size_t keylen, enum rgw_cli_type type );
+int rgw_clients_getkey(struct rgw_client * cli, unsigned char **key, size_t *key_len);
+int rgw_clients_gettype(struct rgw_client * cli, enum rgw_cli_type *type);
+int rgw_clients_search(struct sockaddr * ip_port, struct rgw_client ** ref);
+int rgw_clients_check_dup(struct rgw_radius_msg_meta **msg, struct rgw_client *cli);
+int rgw_clients_create_origin(struct rgw_radius_msg_meta *msg, struct rgw_client * cli, struct msg ** diam);
+int rgw_client_finish_send(struct radius_msg ** msg, struct rgw_radius_msg_meta * req, struct rgw_client * cli);
+int rgw_client_finish_nosend(struct rgw_radius_msg_meta * req, struct rgw_client * cli);
+void rgw_clients_dispose(struct rgw_client ** ref);
+void rgw_clients_dump(void);
+int rgw_clients_init(void);
+void rgw_clients_fini(void);
+int rgw_client_session_add(struct rgw_client * cli, struct session *sess, char * dest_realm, char * dest_host, application_id_t appid);
+int rgw_client_session_stop(struct rgw_client * cli, struct session * sess, int32_t reason);
+
+
+/* Management of plugins */
+int rgw_plg_add( char * plgfile, char * conffile, int port, unsigned char ** codes_array, size_t codes_sz );
+void rgw_plg_dump(void);
+void rgw_plg_start_cache(void);
+int rgw_plg_loop_req(struct rgw_radius_msg_meta **rad, struct msg **diam_msg, struct rgw_client * cli);
+int rgw_plg_loop_ans(struct rgw_radius_msg_meta *req, struct msg **diam_ans, struct radius_msg ** rad_ans, struct rgw_client * cli);
+void rgw_plg_fini(void);
+
+
+/* Parse configuration file */
+int rgw_conf_handle(char * conffile);
+
+
+/* Worker module, process incoming RADIUS messages (in separated threads) */
+int rgw_work_start(void);
+int rgw_work_add(struct rgw_radius_msg_meta * msg, struct rgw_client * client);
+void rgw_work_fini(void);
+
+
+#endif /* _RGW_H */
+  
diff --git a/extensions/app_radgw/rgw_clients.c b/extensions/app_radgw/rgw_clients.c
new file mode 100644
index 0000000..10922ce
--- /dev/null
+++ b/extensions/app_radgw/rgw_clients.c
@@ -0,0 +1,1181 @@
+/*********************************************************************************************************
+* Software License Agreement (BSD License)                                                               *
+* Author: Sebastien Decugis <sdecugis@freediameter.net>							 *
+*													 *
+* Copyright (c) 2013, WIDE Project and NICT								 *
+* All rights reserved.											 *
+* 													 *
+* Redistribution and use of this software in source and binary forms, with or without modification, are  *
+* permitted provided that the following conditions are met:						 *
+* 													 *
+* * Redistributions of source code must retain the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer.										 *
+*    													 *
+* * Redistributions in binary form must reproduce the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer in the documentation and/or other						 *
+*   materials provided with the distribution.								 *
+* 													 *
+* * Neither the name of the WIDE Project or NICT nor the 						 *
+*   names of its contributors may be used to endorse or 						 *
+*   promote products derived from this software without 						 *
+*   specific prior written permission of WIDE Project and 						 *
+*   NICT.												 *
+* 													 *
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED *
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
+* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR *
+* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 	 *
+* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 	 *
+* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR *
+* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF   *
+* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.								 *
+*********************************************************************************************************/
+
+/* Manage the list of RADIUS clients, along with their shared secrets. */
+
+/* Probably some changes are needed to support RADIUS Proxies */
+
+#include "rgw.h"
+
+#define REVERSE_DNS_SIZE_MAX	512 /* length of our buffer for reverse DNS */
+#define DUPLICATE_CHECK_LIFETIME 60 /* number of seconds that the received RADIUS records are kept for duplicate checking . TODO: make it configurable if needed */
+
+/* Ordered lists of clients. The order relationship is a memcmp on the address zone. 
+   For same addresses, the port is compared.
+   The same address cannot be added twice, once with a 0-port and once with another port value.
+ */
+static struct fd_list cli_ip = FD_LIST_INITIALIZER(cli_ip);
+static struct fd_list cli_ip6 = FD_LIST_INITIALIZER(cli_ip6);
+
+/* Lock to protect the previous lists. We use a rwlock because this list is mostly static, to allow parallel reading */
+static pthread_rwlock_t cli_rwl = PTHREAD_RWLOCK_INITIALIZER;
+
+/* Structure describing one received RADIUS message, for duplicate checks purpose. */
+struct req_info {
+	uint16_t	port; 	/* UDP source port of the request */
+	uint8_t		id;	/* The identifier in the request header */
+	uint8_t		auth[16]; /* Request authenticator, since some RADIUS clients do not implement the id mechanism properly. */
+	struct radius_msg *ans; /* The replied answer if any, in case the previous answer got lost. */
+	
+	int		nbdup;  /* Number of times this request was received as a duplicate */
+	struct fd_list	by_id;	  /* The list of requests ordered by their id, port, and auth */
+	time_t 		received; /* When was the last duplicate received? */
+	struct fd_list  by_time;  /* The list of requests ordered by the 'received' value . */
+};
+
+static pthread_t dbt_expire = (pthread_t)NULL; /* The thread that will remove old requests information from all clients (one thread for all) */
+
+/* Structure describing one client */
+struct rgw_client {
+	/* Link information in global list (cli_ip or cli_ip6) */
+	struct fd_list		chain;
+	
+	/* Reference count */
+	int			refcount;
+	
+	/* The address and optional port (alloc'd during configuration file parsing). */
+	union {
+		struct sockaddr		*sa; /* generic pointer */
+		struct sockaddr_in	*sin;
+		struct sockaddr_in6	*sin6;
+	};
+	
+	/* The FQDN, realm, and optional aliases */
+	int			 is_local; /* true if the RADIUS client runs on the same host -- we use Diameter Identity in that case */
+	enum rgw_cli_type 	 type; /* is it a proxy ? */
+	DiamId_t		 fqdn; /* malloc'd here */
+	size_t			 fqdn_len;
+	DiamId_t		 realm; /* references another string, do not free */
+	size_t			 realm_len;
+	struct {
+		os0_t		 name;
+		size_t		 len;
+	}			*aliases; /* Received aliases */
+	size_t			 aliases_nb;
+	
+	/* The secret key data. */
+	struct {
+		unsigned char * data;
+		size_t		len;
+	} 			key;
+	
+	/* information of previous msg received, for duplicate checks. */
+	struct {
+		pthread_mutex_t dupl_lock;    /* The mutex protecting the following lists */
+		struct fd_list 	dupl_by_id;   /* The list of req_info structures ordered by their id, port, and auth */
+		struct fd_list 	dupl_by_time; /* The list of req_info structures ordered by their time (approximative) */
+	} dupl_info[2]; /*[0] for auth, [1] for acct. */
+};
+
+
+/* Create a new req_info structure and initialize its data from a RADIUS request message */
+static struct req_info * dupl_new_req_info(struct rgw_radius_msg_meta *msg) {
+	struct req_info * ret = NULL;
+	CHECK_MALLOC_DO( ret = malloc(sizeof(struct req_info)), return NULL );
+	memset(ret, 0, sizeof(struct req_info));
+	ret->port = msg->port;
+	ret->id   = msg->radius.hdr->identifier;
+	memcpy(&ret->auth[0], &msg->radius.hdr->authenticator[0], 16);
+	fd_list_init(&ret->by_id, ret);
+	fd_list_init(&ret->by_time, ret);
+	ret->received = time(NULL);
+	return ret;
+}
+
+/* Destroy a req_info structure, after it has been unlinked */
+static void dupl_free_req_info(struct req_info * r) {
+	CHECK_PARAMS_DO( r && FD_IS_LIST_EMPTY(&r->by_id) && FD_IS_LIST_EMPTY(&r->by_time), return );
+	if (r->ans) {
+		/* Free this RADIUS message */
+		radius_msg_free(r->ans);
+		free(r->ans);
+	}
+	
+	/* Use r->nbdup for some purpose? */
+	
+	free(r);
+}
+
+/* The core of the purge thread */
+static int dupl_purge_list(struct fd_list * clients) {
+
+	struct fd_list *li = NULL;
+	
+	for (li = clients->next; li != clients; li = li->next) {
+		struct rgw_client * client = (struct rgw_client *)li;
+		int p;
+		
+		for (p=0; p<=1; p++) {
+		
+			/* Lock this list */
+			time_t now;
+			CHECK_POSIX( pthread_mutex_lock(&client->dupl_info[p].dupl_lock) );
+			
+			now = time(NULL);
+			
+			while (!FD_IS_LIST_EMPTY(&client->dupl_info[p].dupl_by_time)) {
+			
+				/* Check the first item in the list */
+				struct req_info * r = (struct req_info *)(client->dupl_info[p].dupl_by_time.next->o);
+				
+				if (now - r->received > DUPLICATE_CHECK_LIFETIME) {
+				
+					TRACE_DEBUG(ANNOYING + 1, "Purging RADIUS request (id: %02hhx, port: %hu, dup #%d, age %ld secs)", r->id, ntohs(r->port), r->nbdup, (long)(now - r->received));
+					
+					/* Remove this record */
+					fd_list_unlink(&r->by_time);
+					fd_list_unlink(&r->by_id);
+					dupl_free_req_info(r);
+				} else {
+					/* We are done for this list */
+					break;
+				}
+			}
+			
+			CHECK_POSIX( pthread_mutex_unlock(&client->dupl_info[p].dupl_lock) );
+		}
+	}
+	return 0;
+}
+
+/* Thread that purges old RADIUS requests */
+static void * dupl_th(void * arg) {
+	/* Set the thread name */
+	fd_log_threadname ( "app_radgw:duplicate_purge" );
+	
+	/* The thread will be canceled */
+	while (1) {
+		
+		/* We don't use a cond var, we simply wake up every 5 seconds. If the size of the duplicate cache is critical, it might be changed */
+		sleep(5);
+		
+		/* When we wake up, we will check all clients duplicate lists one by one */
+		CHECK_POSIX_DO( pthread_rwlock_rdlock(&cli_rwl), break );
+		
+		CHECK_FCT_DO( dupl_purge_list(&cli_ip), break );
+		CHECK_FCT_DO( dupl_purge_list(&cli_ip6), break );
+		
+		CHECK_POSIX_DO( pthread_rwlock_unlock(&cli_rwl), break );
+	
+		/* Loop */
+	}
+	
+	/* If we reach this part, some fatal error was encountered */
+	CHECK_FCT_DO(fd_core_shutdown(), );
+	TRACE_DEBUG(FULL, "Thread terminated");	
+	return NULL;
+}
+
+
+/* create a new rgw_client. the arguments are MOVED into the structure (to limit malloc & free calls). */
+static int client_create(struct rgw_client ** res, struct sockaddr ** ip_port, unsigned char ** key, size_t keylen, enum rgw_cli_type type )
+{
+	struct rgw_client *tmp = NULL;
+	DiamId_t fqdn;
+	size_t fqdn_len = 0;
+	int ret, i;
+	int loc = 0;
+	
+	/* Check if the IP address is local */
+	if (   ( ((*ip_port)->sa_family == AF_INET ) && (   IN_IS_ADDR_LOOPBACK( &((struct sockaddr_in  *)(*ip_port))->sin_addr ) ) )
+	     ||( ((*ip_port)->sa_family == AF_INET6) && (  IN6_IS_ADDR_LOOPBACK( &((struct sockaddr_in6 *)(*ip_port))->sin6_addr) ) )) {
+		/* The client is local */
+		loc = 1;
+	} else {
+		char buf[255];
+	
+		/* Search FQDN for the client */
+		ret = getnameinfo( *ip_port, sizeof(struct sockaddr_storage), &buf[0], sizeof(buf), NULL, 0, 0 );
+		if (ret) {
+			TRACE_DEBUG(INFO, "Unable to resolve peer name: %s", gai_strerror(ret));
+			return EINVAL;
+		}
+		fqdn = &buf[0];
+		CHECK_FCT_DO( ret = fd_os_validate_DiameterIdentity(&fqdn, &fqdn_len, 1),
+			{
+				TRACE_DEBUG(INFO, "Unable to use resolved peer name '%s' as DiameterIdentity: %s", buf, strerror(ret));
+				return ret;
+			} );
+	}
+	
+	/* Create the new object */
+	CHECK_MALLOC( tmp = malloc(sizeof (struct rgw_client)) );
+	memset(tmp, 0, sizeof(struct rgw_client));
+	fd_list_init(&tmp->chain, NULL);
+	
+	/* Initialize the duplicate list info */
+	for (i=0; i<=1; i++) {
+		CHECK_POSIX( pthread_mutex_init(&tmp->dupl_info[i].dupl_lock, NULL) );
+		fd_list_init(&tmp->dupl_info[i].dupl_by_id, NULL);
+		fd_list_init(&tmp->dupl_info[i].dupl_by_time, NULL);
+	}
+	tmp->type = type;
+	
+	if (loc) {
+		tmp->is_local = 1;
+	} else {
+		/* Copy the fqdn */
+		tmp->fqdn = fqdn;
+		tmp->fqdn_len = fqdn_len;
+
+		/* Find an appropriate realm */
+		tmp->realm = strchr(fqdn, '.');
+		if (tmp->realm) {
+			tmp->realm += 1;
+			tmp->realm_len = tmp->fqdn_len - (tmp->realm - fqdn);
+		}
+		if ((!tmp->realm) || (*tmp->realm == '\0')) { /* in case the fqdn was "localhost." for example, if it is possible... */
+			tmp->realm = fd_g_config->cnf_diamrlm;
+			tmp->realm_len = fd_g_config->cnf_diamrlm_len;
+		}
+	}
+	
+	/* move the sa info reference */
+	tmp->sa = *ip_port;
+	*ip_port = NULL;
+	
+	/* move the key material */
+	tmp->key.data = *key;
+	tmp->key.len = keylen;
+	*key = NULL;
+	
+	/* Done! */
+	*res = tmp;
+	return 0;
+}
+
+/* Decrease refcount on a client; the lock must be held when this function is called. */
+static void client_unlink(struct rgw_client * client)
+{
+	client->refcount -= 1;
+	
+	if (client->refcount <= 0) {
+		int idx;
+		/* to be sure: the refcount should be 0 only when client_fini is called */
+		ASSERT( FD_IS_LIST_EMPTY(&client->chain) );
+		
+		/* Free the data */
+		for (idx = 0; idx < client->aliases_nb; idx++)
+			free(client->aliases[idx].name);
+		free(client->aliases);
+		free(client->fqdn);
+		free(client->sa);
+		free(client->key.data);
+		
+		/* Free the duplicate info */
+		for (idx=0; idx <= 1; idx++){
+			CHECK_POSIX_DO( pthread_mutex_lock( &client->dupl_info[idx].dupl_lock ), /* continue */ );
+			
+			while (!FD_IS_LIST_EMPTY(&client->dupl_info[idx].dupl_by_id)) {
+				struct req_info * r = (struct req_info *)(client->dupl_info[idx].dupl_by_id.next->o);
+				fd_list_unlink( &r->by_id );
+				fd_list_unlink( &r->by_time );
+				dupl_free_req_info(r);
+			}
+			
+			CHECK_POSIX_DO( pthread_mutex_unlock( &client->dupl_info[idx].dupl_lock ), /* continue */ );
+
+		}
+		
+		free(client);
+	}
+}
+
+
+/* Macro to avoid duplicating the code in the next function */
+#define client_search_family( _family_ )												\
+		case AF_INET##_family_: {												\
+			struct sockaddr_in##_family_ * sin##_family_ = (struct sockaddr_in##_family_ *)ip_port;				\
+			for (ref = cli_ip##_family_.next; ref != &cli_ip##_family_; ref = ref->next) {					\
+				cmp = memcmp(&sin##_family_->sin##_family_##_addr, 							\
+					     &((struct rgw_client *)ref)->sin##_family_->sin##_family_##_addr, 				\
+					     sizeof(struct in##_family_##_addr));							\
+				if (cmp > 0) continue; /* search further in the list */							\
+				if (cmp < 0) break; /* this IP is not in the list */							\
+				/* Now compare the ports as follow: */									\
+				     /* If the ip_port we are searching does not contain a port, just return the first match result */	\
+				if ( (sin##_family_->sin##_family_##_port == 0) 							\
+				     /* If the entry in the list does not contain a port, return it as a match */			\
+				  || (((struct rgw_client *)ref)->sin##_family_->sin##_family_##_port == 0) 				\
+				     /* If both ports are equal, it is a match */							\
+				  || (sin##_family_->sin##_family_##_port == 								\
+				  		((struct rgw_client *)ref)->sin##_family_->sin##_family_##_port)) {			\
+					*res = (struct rgw_client *)ref;								\
+					return EEXIST;											\
+				}													\
+				/* Otherwise, the list is ordered by port value (byte order does not matter */				\
+				if (sin##_family_->sin##_family_##_port 								\
+					> ((struct rgw_client *)ref)->sin##_family_->sin##_family_##_port) continue;			\
+				else break;												\
+			}														\
+			*res = (struct rgw_client *)(ref->prev);									\
+			return ENOENT;													\
+		}
+/* Function to look for an existing rgw_client, or the previous element. 
+   The cli_rwl must be held for reading (at least) when calling this function. 
+   Returns ENOENT if the matching client does not exist, and res points to the previous element in the list. 
+   Returns EEXIST if the matching client is found, and res points to this element. 
+   Returns other error code on other error. */
+static int client_search(struct rgw_client ** res, struct sockaddr * ip_port )
+{
+	int cmp;
+	struct fd_list *ref = NULL;
+	
+	CHECK_PARAMS(res && ip_port);
+	
+	switch (ip_port->sa_family) {
+		client_search_family()
+				break;
+		
+		client_search_family( 6 )
+				break;
+	}
+	
+	/* We're never supposed to reach this point */
+	ASSERT(0);
+	return EINVAL;
+}
+
+int rgw_clients_getkey(struct rgw_client * cli, unsigned char **key, size_t *key_len)
+{
+	CHECK_PARAMS( cli && key && key_len );
+	*key = cli->key.data;
+	*key_len = cli->key.len;
+	return 0;
+}
+
+int rgw_clients_gettype(struct rgw_client * cli, enum rgw_cli_type *type)
+{
+	CHECK_PARAMS( cli && type );
+	*type = cli->type;
+	return 0;
+}
+
+
+int rgw_clients_search(struct sockaddr * ip_port, struct rgw_client ** ref)
+{
+	int ret = 0;
+	
+	TRACE_ENTRY("%p %p", ip_port, ref);
+	
+	CHECK_PARAMS(ip_port && ref);
+	
+	CHECK_POSIX( pthread_rwlock_rdlock(&cli_rwl) );
+
+	ret = client_search(ref, ip_port);
+	if (ret == EEXIST) {
+		(*ref)->refcount ++;
+		ret = 0;
+	} else {
+		*ref = NULL;
+	}
+	
+	CHECK_POSIX( pthread_rwlock_unlock(&cli_rwl) );
+	
+	return ret;
+}
+
+int rgw_clients_check_dup(struct rgw_radius_msg_meta **msg, struct rgw_client *cli)
+{
+	int p, dup = 0;
+	struct fd_list * li;
+	struct req_info * r;
+	
+	TRACE_ENTRY("%p %p", msg, cli);
+	
+	CHECK_PARAMS( msg && cli );
+	
+	if ((*msg)->serv_type == RGW_PLG_TYPE_AUTH)
+		p = 0;
+	else
+		p = 1;
+	
+	CHECK_POSIX( pthread_mutex_lock( &cli->dupl_info[p].dupl_lock ) );
+	
+	/* Search if we have this message in our list */
+	for (li = cli->dupl_info[p].dupl_by_id.next; li != &cli->dupl_info[p].dupl_by_id; li = li->next) {
+		int cmp = 0;
+		r = (struct req_info *)(li->o);
+		if (r->id < (*msg)->radius.hdr->identifier)
+			continue;
+		if (r->id > (*msg)->radius.hdr->identifier)
+			break;
+		if (r->port < (*msg)->port)
+			continue;
+		if (r->port > (*msg)->port)
+			break;
+		cmp = memcmp(&r->auth[0], &(*msg)->radius.hdr->authenticator[0], 16);
+		if (cmp < 0)
+			continue;
+		if (cmp > 0)
+			break;
+		dup = 1;
+		break;
+	}
+	
+	if (dup) {
+		time_t now = time(NULL);
+		r->nbdup += 1;
+		TRACE_DEBUG(INFO, "Received duplicated RADIUS message (id: %02hhx, port: %hu, dup #%d, previously seen %ld secs ago).", 
+				r->id, ntohs(r->port), r->nbdup, (long)(now - r->received));
+		
+		if (r->ans) {
+			/* Resend the answer */
+			CHECK_FCT_DO( rgw_servers_send((*msg)->serv_type, r->ans->buf, r->ans->buf_used, cli->sa, r->port),  );
+			
+			/* Should we delete 'r' so that a further duplicate will again be converted to Diameter? */
+		}
+		
+		/* Update the timestamp */
+		r->received = now;
+		fd_list_unlink(&r->by_time);
+		fd_list_insert_before(&cli->dupl_info[p].dupl_by_time, &r->by_time); /* Move as last entry, since it is the most recent */
+		
+		/* Delete the request message */
+		rgw_msg_free(msg);
+		
+	} else {
+		/* The message was not a duplicate, we save it */
+		/* li currently points the the next entry in list_by_id */
+		CHECK_MALLOC_DO( r= dupl_new_req_info(*msg), { CHECK_POSIX_DO(pthread_mutex_unlock( &cli->dupl_info[p].dupl_lock ), ); return ENOMEM; } );
+		fd_list_insert_before(li, &r->by_id);
+		fd_list_insert_before(&cli->dupl_info[p].dupl_by_time, &r->by_time); /* it is the most recent */
+	}
+		
+	CHECK_POSIX( pthread_mutex_unlock( &cli->dupl_info[p].dupl_lock ) );
+	
+	return 0;
+}
+
+/* Check if the message has a valid authenticator, and update the meta-data accordingly */
+int rgw_clients_auth_check(struct rgw_radius_msg_meta * msg, struct rgw_client * cli, uint8_t * req_auth)
+{
+	unsigned char * key;
+	size_t keylen;
+	int count;
+	
+	TRACE_ENTRY("%p %p %p", msg, cli, req_auth);
+	
+	CHECK_PARAMS(msg && cli);
+	
+	CHECK_FCT(rgw_clients_getkey(cli, &key, &keylen));
+	
+	count = radius_msg_count_attr(&msg->radius, RADIUS_ATTR_MESSAGE_AUTHENTICATOR, 0);
+	if (count > 1) {
+		TRACE_DEBUG(INFO, "Too many Message-Authenticator attributes (%d), discarding message.", count);
+		return EINVAL;
+	}
+	if (count == 0) {
+		TRACE_DEBUG(FULL, "Message does not contain a Message-Authenticator attributes.");
+		msg->valid_mac = 0;
+	} else {
+		if (radius_msg_verify_msg_auth( &msg->radius, key, keylen, req_auth )) {
+			TRACE_DEBUG(INFO, "Invalid Message-Authenticator received, discarding message.");
+			return EINVAL;
+		}
+		msg->valid_mac = 1;
+	}
+	
+	return 0;
+}
+
+static struct dict_object * cache_orig_host = NULL;
+static struct dict_object * cache_orig_realm = NULL;
+static struct dict_object * cache_route_record = NULL;
+
+int rgw_clients_init(void)
+{
+	TRACE_ENTRY();
+	CHECK_FCT( fd_dict_search(fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Origin-Host", &cache_orig_host, ENOENT) );
+	CHECK_FCT( fd_dict_search(fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Origin-Realm", &cache_orig_realm, ENOENT) );
+	CHECK_FCT( fd_dict_search(fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Route-Record", &cache_route_record, ENOENT) );
+	
+	/* Create the thread that will purge old RADIUS duplicates */
+	CHECK_POSIX( pthread_create( &dbt_expire, NULL, dupl_th, NULL) );
+	
+	return 0;
+}
+
+
+/* The following function checks if a RADIUS message contains a valid NAS identifier, and initializes an empty Diameter
+ message with the appropriate routing information */
+/* Check that the NAS-IP-Adress or NAS-Identifier is coherent with the IP the packet was received from */
+/* Also update the client list of aliases if needed */
+int rgw_clients_create_origin(struct rgw_radius_msg_meta *msg, struct rgw_client * cli, struct msg ** diam)
+{
+	int idx;
+	int valid_nas_info = 0;
+	struct radius_attr_hdr *nas_ip = NULL, *nas_ip6 = NULL, *nas_id = NULL;
+	size_t nas_id_len;
+	char * oh_str = NULL; size_t oh_strlen = 0; int oh_free = 0;
+	char * or_str = NULL; size_t or_strlen = 0;
+	char * rr_str = NULL; size_t rr_strlen = 0;
+	char buf[REVERSE_DNS_SIZE_MAX]; /* to store DNS lookups results */
+	
+	struct avp *avp = NULL;
+	union avp_value avp_val;
+	
+	TRACE_ENTRY("%p %p %p", msg, cli, diam);
+	CHECK_PARAMS(msg && cli && diam && (*diam == NULL));
+	
+	/* Find the relevant attributes, if any */
+	for (idx = 0; idx < msg->radius.attr_used; idx++) {
+		struct radius_attr_hdr * attr = (struct radius_attr_hdr *)(msg->radius.buf + msg->radius.attr_pos[idx]);
+		size_t attr_len = attr->length - sizeof(struct radius_attr_hdr);
+		
+		if ((attr->type == RADIUS_ATTR_NAS_IP_ADDRESS) && (attr_len = 4)) {
+			nas_ip = attr;
+			continue;
+		}
+			
+		if ((attr->type == RADIUS_ATTR_NAS_IDENTIFIER) && (attr_len > 0)) {
+			nas_id = attr;
+			nas_id_len = attr_len;
+			continue;
+		}
+			
+		if ((attr->type == RADIUS_ATTR_NAS_IPV6_ADDRESS) && (attr_len = 16)) {
+			nas_ip6 = attr;
+			continue;
+		}
+	}
+		
+	if (!nas_ip && !nas_ip6 && !nas_id) {
+		TRACE_DEBUG(FULL, "The message does not contain any NAS identification attribute.");
+		
+		/* Get information on this peer */
+		CHECK_FCT( rgw_clients_get_origin(cli, &oh_str, &oh_strlen, &or_str, &or_strlen) );
+		
+		goto diameter;
+	}
+	
+	/* Check if the message was received from the IP in NAS-IP-Address attribute */
+	if (nas_ip && (cli->sa->sa_family == AF_INET) && !memcmp(nas_ip+1, &cli->sin->sin_addr, sizeof(struct in_addr))) {
+		TRACE_DEBUG(FULL, "NAS-IP-Address contains the same address as the message was received from.");
+		valid_nas_info |= 1;
+	}
+	if (nas_ip6 && (cli->sa->sa_family == AF_INET6) && !memcmp(nas_ip6+1, &cli->sin6->sin6_addr, sizeof(struct in6_addr))) {
+		TRACE_DEBUG(FULL, "NAS-IPv6-Address contains the same address as the message was received from.");
+		valid_nas_info |= 2;
+	}
+	
+	
+	/*
+			In RADIUS it would be possible for a rogue NAS to forge the NAS-IP-
+			Address attribute value.  Diameter/RADIUS translation agents MUST
+			check a received NAS-IP-Address or NAS-IPv6-Address attribute against
+			the source address of the RADIUS packet.  If they do not match and
+			the Diameter/RADIUS translation agent does not know whether the
+			packet was sent by a RADIUS proxy or NAS (e.g., no Proxy-State
+			attribute), then by default it is assumed that the source address
+			corresponds to a RADIUS proxy, and that the NAS Address is behind
+			that proxy, potentially with some additional RADIUS proxies in
+			between.  The Diameter/RADIUS translation agent MUST insert entries
+			in the Route-Record AVP corresponding to the apparent route.  This
+			implies doing a reverse lookup on the source address and NAS-IP-
+			Address or NAS-IPv6-Address attributes to determine the corresponding
+			FQDNs.
+
+			If the source address and the NAS-IP-Address or NAS-IPv6-Address do
+			not match, and the Diameter/RADIUS translation agent knows that it is
+			talking directly to the NAS (e.g., there are no RADIUS proxies
+			between it and the NAS), then the error should be logged, and the
+			packet MUST be discarded.
+
+			Diameter agents and servers MUST check whether the NAS-IP-Address AVP
+			corresponds to an entry in the Route-Record AVP.  This is done by
+			doing a reverse lookup (PTR RR) for the NAS-IP-Address to retrieve
+			the corresponding FQDN, and by checking for a match with the Route-
+			Record AVP.  If no match is found, then an error is logged, but no
+			other action is taken.
+	*/
+	if (nas_ip || nas_ip6) {
+		if (!valid_nas_info) {
+			if ((!cli->is_local) && (cli->type == RGW_CLI_NAS)) {
+				TRACE_DEBUG(INFO, "Message received with a NAS-IP-Address or NAS-IPv6-Address different from the sender's. Please configure as Proxy if this is expected. Message discarded.");
+				return EINVAL;
+			} else {
+				int ret;
+				sSS ss;
+				/* the peer is configured as a proxy, or running on localhost, so accept the message */
+				
+				/* In that case, the cli will be stored as Route-Record and the NAS-IP-Address as origin */
+				if (!cli->is_local) {
+					rr_str = cli->fqdn;
+					rr_strlen = cli->fqdn_len;
+				}
+				
+				/* We must DNS-reverse the NAS-IP*-Address */
+				memset(&ss, 0 , sizeof(sSS));
+				if (nas_ip) {
+					sSA4 * sin = (sSA4 *)&ss;
+					sin->sin_family = AF_INET;
+					memcpy(&sin->sin_addr, nas_ip + 1, sizeof(struct in_addr));
+				} else {
+					sSA6 * sin6 = (sSA6 *)&ss;
+					sin6->sin6_family = AF_INET6;
+					memcpy(&sin6->sin6_addr, nas_ip6 + 1, sizeof(struct in6_addr));
+				}
+				CHECK_SYS_DO( getnameinfo( (sSA *)&ss, sSAlen(&ss), &buf[0], sizeof(buf), NULL, 0, NI_NAMEREQD),
+					{
+						if (cli->is_local) {
+							CHECK_FCT( rgw_clients_get_origin(cli, &oh_str, &oh_strlen, &or_str, &or_strlen) );
+							goto diameter;
+						}
+						
+						TRACE_DEBUG(INFO, "The NAS-IP*-Address cannot be DNS reversed in order to create the Origin-Host AVP; rejecting the message (translation is impossible).");
+						return EINVAL;
+					} );
+					
+				oh_str = &buf[0];
+				CHECK_FCT_DO( ret = fd_os_validate_DiameterIdentity(&oh_str, &oh_strlen, 1),
+					{
+						if (cli->is_local) {
+							CHECK_FCT( rgw_clients_get_origin(cli, &oh_str, &oh_strlen, &or_str, &or_strlen) );
+							goto diameter;
+						}
+						
+						TRACE_DEBUG(INFO, "Unable to use resolved client name '%s' as DiameterIdentity: %s", buf, strerror(ret));
+						return ret;
+					} );
+				oh_free = 1;
+				
+				or_str = strchr(oh_str, '.');
+				if (or_str) {
+					or_str ++; /* move after the first dot */
+					if (*or_str == '\0')
+						or_str = NULL; /* Discard this realm, we will use the local realm later */
+					else
+						or_strlen = oh_strlen - (or_str - oh_str);
+				}
+			}
+		} else {
+			/* The attribute matches the source address, just use this in origin-host */
+			CHECK_FCT( rgw_clients_get_origin(cli, &oh_str, &oh_strlen, &or_str, &or_strlen) );
+		}
+		
+		goto diameter; /* we ignore the nas_id in that case */
+	}
+	
+	/* We don't have a NAS-IP*-Address attribute if we are here */
+	if (cli->is_local) {
+		/* Simple: we use our own configuration */
+		CHECK_FCT( rgw_clients_get_origin(cli, &oh_str, &oh_strlen, &or_str, &or_strlen) );
+		goto diameter;
+	}
+	
+	/* At this point, we only have nas_id, and the client is not local */
+	ASSERT(nas_id);
+	
+	{
+		int found, ret;
+		struct addrinfo hint, *res, *ptr;
+		
+		/*
+			In RADIUS it would be possible for a rogue NAS to forge the NAS-
+			Identifier attribute.  Diameter/RADIUS translation agents SHOULD
+			attempt to check a received NAS-Identifier attribute against the
+			source address of the RADIUS packet, by doing an A/AAAA RR query.  If
+			the NAS-Identifier attribute contains an FQDN, then such a query
+			would resolve to an IP address matching the source address.  However,
+			the NAS-Identifier attribute is not required to contain an FQDN, so
+			such a query could fail.  If it fails, an error should be logged, but
+			no action should be taken, other than a reverse lookup on the source
+			address and insert the resulting FQDN into the Route-Record AVP.
+
+			Diameter agents and servers SHOULD check whether a NAS-Identifier AVP
+			corresponds to an entry in the Route-Record AVP.  If no match is
+			found, then an error is logged, but no other action is taken.
+		*/
+		
+		/* first, check if the nas_id is the fqdn of the peer or a known alias */
+		if (!fd_os_almostcasesrch(nas_id + 1, nas_id_len, 
+						cli->fqdn, cli->fqdn_len, NULL)) {
+			TRACE_DEBUG(FULL, "NAS-Identifier contains the fqdn of the client");
+			found = 1;
+		} else {
+			for (idx = 0; idx < cli->aliases_nb; idx++) {
+				if (!fd_os_cmp(nas_id + 1, nas_id_len, 
+						cli->aliases[idx].name, cli->aliases[idx].len)) {
+					TRACE_DEBUG(FULL, "NAS-Identifier valid value found in the cache");
+					found = 1;
+					break;
+				}
+			}
+		}
+		
+		if (found) {
+			/* The NAS-Identifier matches the source IP */
+			CHECK_FCT( rgw_clients_get_origin(cli, &oh_str, &oh_strlen, &or_str, &or_strlen) );
+
+			goto diameter;
+		}
+		
+		/* Attempt DNS resolution of the identifier */
+		ASSERT( nas_id_len < sizeof(buf) );
+		memcpy(buf, nas_id + 1, nas_id_len);
+		buf[nas_id->length - sizeof(struct radius_attr_hdr)] = '\0';
+		
+		/* Now check if this alias is valid for this peer */
+		memset(&hint, 0, sizeof(hint));
+		hint.ai_flags  = AI_CANONNAME;
+		ret = getaddrinfo(buf, NULL, &hint, &res);
+		if (ret == 0) {
+			strncpy(buf, res->ai_canonname, sizeof(buf));
+			/* The name was resolved correctly, does it match the IP of the client? */
+			for (ptr = res; ptr != NULL; ptr = ptr->ai_next) {
+				if (cli->sa->sa_family != ptr->ai_family)
+					continue;
+				if (memcmp(cli->sa, ptr->ai_addr, sSAlen(cli->sa)))
+					continue;
+				
+				found = 1;
+				break;
+			}
+			freeaddrinfo(res);
+			
+			if (!found) {
+				if (cli->type == RGW_CLI_NAS) {
+					TRACE_DEBUG(INFO, "The NAS-Identifier value '%.*s' resolves to a different IP than the client's, discarding the message. Configure this client as a Proxy if this message should be valid.", 
+						(int)nas_id_len, (char *)(nas_id + 1));
+					return EINVAL;
+				} else {
+					/* This identifier matches a different IP, assume it is a proxied message */
+					if (!cli->is_local) {
+						rr_str = cli->fqdn;
+						rr_strlen = cli->fqdn_len;
+					}
+					oh_str = &buf[0]; /* The canonname resolved */
+					oh_strlen = 0;
+					CHECK_FCT_DO( ret = fd_os_validate_DiameterIdentity(&oh_str, &oh_strlen, 1),
+						{
+							TRACE_DEBUG(INFO, "Unable to use resolved client name '%s' as DiameterIdentity: %s", buf, strerror(ret));
+							return ret;
+						} );
+					oh_free = 1;
+					or_str = strchr(oh_str, '.');
+					if (or_str) {
+						or_str ++; /* move after the first dot */
+						if (*or_str == '\0')
+							or_str = NULL; /* Discard this realm, we will use the local realm later */
+						else
+							or_strlen = oh_strlen - (or_str - oh_str);
+					}
+				}
+			} else {
+				/* It is a valid alias, save it */
+				CHECK_MALLOC( cli->aliases = realloc(cli->aliases, (cli->aliases_nb + 1) * sizeof(cli->aliases[0])) );
+				
+				CHECK_MALLOC( cli->aliases[cli->aliases_nb + 1].name = os0dup(nas_id + 1, nas_id_len ) );
+				cli->aliases[cli->aliases_nb + 1].len = nas_id_len;
+
+				cli->aliases_nb ++;
+				TRACE_DEBUG(FULL, "Saved valid alias for client: '%.*s' -> '%s'", (int)nas_id_len, (char *)(nas_id + 1), cli->fqdn);
+				CHECK_FCT( rgw_clients_get_origin(cli, &oh_str, &oh_strlen, &or_str, &or_strlen) );
+			}
+		} else {
+			/* Error resolving the name */
+			TRACE_DEBUG(INFO, "NAS-Identifier '%s' cannot be resolved: %s. Ignoring...", buf, gai_strerror(ret));
+			/* Assume this is a valid identifier for the client */
+			CHECK_FCT( rgw_clients_get_origin(cli, &oh_str, &oh_strlen, &or_str, &or_strlen) );
+		}
+	}
+	
+	/* Now, let's create the empty Diameter message with Origin-Host, -Realm, and Route-Record if needed. */
+diameter:
+	ASSERT(oh_str); /* If it is not defined here, there is a bug... */
+	if (!or_str) {
+		or_str = fd_g_config->cnf_diamrlm; /* Use local realm in that case */
+		or_strlen = fd_g_config->cnf_diamrlm_len;
+	}
+	
+	/* Create an empty Diameter message so that extensions can store their AVPs */
+	CHECK_FCT(  fd_msg_new ( NULL, MSGFL_ALLOC_ETEID, diam )  );
+	
+	/* Add the Origin-Host as next AVP */
+	CHECK_FCT( fd_msg_avp_new ( cache_orig_host, 0, &avp ) );
+	memset(&avp_val, 0, sizeof(avp_val));
+	avp_val.os.data = (unsigned char *)oh_str;
+	avp_val.os.len = oh_strlen;
+	CHECK_FCT( fd_msg_avp_setvalue ( avp, &avp_val ) );
+	CHECK_FCT( fd_msg_avp_add ( *diam, MSG_BRW_LAST_CHILD, avp) );
+	
+	/* Add the Origin-Realm as next AVP */
+	CHECK_FCT( fd_msg_avp_new ( cache_orig_realm, 0, &avp ) );
+	memset(&avp_val, 0, sizeof(avp_val));
+	avp_val.os.data = (unsigned char *)or_str;
+	avp_val.os.len = or_strlen;
+	CHECK_FCT( fd_msg_avp_setvalue ( avp, &avp_val ) );
+	CHECK_FCT( fd_msg_avp_add ( *diam, MSG_BRW_LAST_CHILD, avp) );
+	
+	if (rr_str) {
+		CHECK_FCT( fd_msg_avp_new ( cache_route_record, 0, &avp ) );
+		memset(&avp_val, 0, sizeof(avp_val));
+		avp_val.os.data = (unsigned char *)rr_str;
+		avp_val.os.len = rr_strlen;
+		CHECK_FCT( fd_msg_avp_setvalue ( avp, &avp_val ) );
+		CHECK_FCT( fd_msg_avp_add ( *diam, MSG_BRW_LAST_CHILD, avp) );
+	}
+	
+	if (oh_free)
+		free(oh_str);
+	
+	/* Done! */
+	return 0;
+}
+
+int rgw_clients_get_origin(struct rgw_client *cli, DiamId_t *fqdn, size_t *fqdnlen, DiamId_t *realm, size_t *realmlen)
+{
+	TRACE_ENTRY("%p %p %p %p %p", cli, fqdn, fqdnlen, realm, realmlen);
+	CHECK_PARAMS(cli && fqdn && fqdnlen);
+	
+	if (cli->is_local) {
+		*fqdn = fd_g_config->cnf_diamid;
+		*fqdnlen = fd_g_config->cnf_diamid_len;
+		if (realm)
+			*realm= fd_g_config->cnf_diamrlm;
+		if (realmlen)
+			*realmlen= fd_g_config->cnf_diamrlm_len;
+	} else {
+		*fqdn = cli->fqdn;
+		*fqdnlen = cli->fqdn_len;
+		if (realm)
+			*realm= cli->realm;
+		if (realmlen)
+			*realmlen= cli->realm_len;
+	}
+		
+	return 0;
+}
+
+char * rgw_clients_id(struct rgw_client *cli)
+{
+	return cli->is_local ? "(local)" : cli->fqdn;
+}
+
+
+void rgw_clients_dispose(struct rgw_client ** ref)
+{
+	TRACE_ENTRY("%p", ref);
+	CHECK_PARAMS_DO(ref, return);
+	
+	CHECK_POSIX_DO( pthread_rwlock_wrlock(&cli_rwl),  );
+	client_unlink(*ref);
+	*ref = NULL;
+	CHECK_POSIX_DO( pthread_rwlock_unlock(&cli_rwl), );
+}
+
+int rgw_clients_add( struct sockaddr * ip_port, unsigned char ** key, size_t keylen, enum rgw_cli_type type )
+{
+	struct rgw_client * prev = NULL, *new = NULL;
+	int ret;
+	
+	TRACE_ENTRY("%p %p %zu", ip_port, key, keylen);
+	
+	CHECK_PARAMS( ip_port && key && *key && keylen );
+	CHECK_PARAMS( (ip_port->sa_family == AF_INET) || (ip_port->sa_family == AF_INET6) );
+	CHECK_PARAMS( (type == RGW_CLI_NAS) || (type == RGW_CLI_PXY) );
+	
+	/* Dump the entry in debug mode */
+	if (TRACE_BOOL(FULL + 1 )) {
+		char sa_buf[sSA_DUMP_STRLEN];
+		fd_sa_sdump_numeric(sa_buf, ip_port);
+		TRACE_DEBUG(FULL, "Adding %s:", (type == RGW_CLI_NAS) ? "NAS" : "PROXY"  );
+		TRACE_DEBUG(FULL, "\tIP : %s", sa_buf );
+		TRACE_BUFFER(FD_LOG_DEBUG, FULL, "\tKey: [", *key, keylen, "]" );
+	}
+	
+	/* Lock the lists */
+	CHECK_POSIX( pthread_rwlock_wrlock(&cli_rwl) );
+	
+	/* Check if the same entry does not already exist */
+	ret = client_search(&prev, ip_port );
+	if (ret == ENOENT) {
+		/* No duplicate found, Ok to add */
+		CHECK_FCT_DO( ret = client_create( &new, &ip_port, key, keylen, type ), goto end );
+		fd_list_insert_after(&prev->chain, &new->chain);
+		new->refcount++;
+		ret = 0;
+		goto end;
+	}
+	
+	if (ret == EEXIST) {
+		char sa_buf[sSA_DUMP_STRLEN];
+		/* Check if the key is the same, then skip or return an error */
+		if ((keylen == prev->key.len ) && ( ! memcmp(*key, prev->key.data, keylen) ) && (type == prev->type)) {
+			TRACE_DEBUG(INFO, "Skipping duplicate client description");
+			ret = 0;
+			goto end;
+		}
+		
+		fd_log_error("ERROR: Conflicting RADIUS clients descriptions!");
+		TRACE_ERROR("Previous entry: %s", (prev->type == RGW_CLI_NAS) ? "NAS" : "PROXY");
+		fd_sa_sdump_numeric(sa_buf, prev->sa);
+		TRACE_ERROR("\tIP : %s", sa_buf);
+		TRACE_BUFFER(FD_LOG_ERROR, NONE, "\tKey: [", prev->key.data, prev->key.len, "]" );
+		TRACE_ERROR("Conflicting entry: %s", (type == RGW_CLI_NAS) ? "NAS" : "PROXY");
+		fd_sa_sdump_numeric(sa_buf, ip_port);
+		TRACE_ERROR("\tIP : %s", sa_buf);
+		TRACE_BUFFER(FD_LOG_ERROR, NONE, "\tKey: [", *key, keylen, "]" );
+	}
+end:
+	/* release the lists */
+	CHECK_POSIX( pthread_rwlock_unlock(&cli_rwl) );
+	
+	return ret;
+}
+
+static void dump_cli_list(struct fd_list *senti)
+{
+	struct rgw_client * client = NULL;
+	struct fd_list *ref = NULL;
+	
+	for (ref = senti->next; ref != senti; ref = ref->next) {
+		char sa_buf[sSA_DUMP_STRLEN];
+		client = (struct rgw_client *)ref;
+		fd_sa_sdump_numeric(sa_buf, client->sa);
+		LOG_D("  - %s%s", sa_buf, (client->type == RGW_CLI_NAS) ? "" : " [PROXY]" );
+	}
+}
+
+void rgw_clients_dump(void)
+{
+	if ( ! TRACE_BOOL(FULL) )
+		return;
+	
+	CHECK_POSIX_DO( pthread_rwlock_rdlock(&cli_rwl), /* ignore error */ );
+	
+	if (!FD_IS_LIST_EMPTY(&cli_ip))
+		fd_log_debug(" RADIUS IP clients list:");
+	dump_cli_list(&cli_ip);
+		
+	if (!FD_IS_LIST_EMPTY(&cli_ip6))
+		fd_log_debug(" RADIUS IPv6 clients list:");
+	dump_cli_list(&cli_ip6);
+		
+	CHECK_POSIX_DO( pthread_rwlock_unlock(&cli_rwl), /* ignore error */ );
+}
+
+void rgw_clients_fini(void)
+{
+	struct fd_list * client;
+	
+	TRACE_ENTRY();
+	
+	CHECK_POSIX_DO( pthread_rwlock_wrlock(&cli_rwl), /* ignore error */ );
+	
+	CHECK_FCT_DO( fd_thr_term(&dbt_expire), /* continue */ );
+
+	/* empty the lists */
+	while ( ! FD_IS_LIST_EMPTY(&cli_ip) ) {
+		client = cli_ip.next;
+		fd_list_unlink(client);
+		client_unlink((struct rgw_client *)client);
+	}
+	while (! FD_IS_LIST_EMPTY(&cli_ip6)) {
+		client = cli_ip6.next;
+		fd_list_unlink(client);
+		client_unlink((struct rgw_client *)client);
+	}
+	
+	CHECK_POSIX_DO( pthread_rwlock_unlock(&cli_rwl), /* ignore error */ );
+	
+}
+
+int rgw_client_finish_send(struct radius_msg ** msg, struct rgw_radius_msg_meta * req, struct rgw_client * cli)
+{
+	int p;
+	struct fd_list * li;
+	
+	TRACE_ENTRY("%p %p %p", msg, req, cli);
+	CHECK_PARAMS( msg && *msg && cli );
+	
+	if (!req) {
+		/* We don't support this case yet */
+		ASSERT(0);
+		return ENOTSUP;
+	}
+	
+	/* Add all the Proxy-States back in the message */
+	for (p = 0; p < req->ps_nb; p++) {
+		struct radius_attr_hdr * attr = (struct radius_attr_hdr *)(req->radius.buf + req->radius.attr_pos[req->ps_first + p]);
+		
+		if (radius_msg_add_attr_to_array(*msg, attr)) {
+			TRACE_DEBUG(INFO, "Error in radius_msg_add_attr_to_array, ENOMEM");
+			radius_msg_free(*msg);
+			free(*msg);
+			*msg = NULL;
+			return ENOMEM;
+		}
+	}
+	
+	/* Add the Message-Authenticator if needed, and other final tasks */
+	if (radius_msg_finish_srv(*msg, cli->key.data, cli->key.len, req->radius.hdr->authenticator)) {
+		TRACE_DEBUG(INFO, "An error occurred while preparing the RADIUS answer");
+		radius_msg_free(*msg);
+		free(*msg);
+		*msg = NULL;
+		return EINVAL;
+	}
+	
+	/* Debug */
+	TRACE_DEBUG(FULL, "RADIUS message ready for sending:");
+	rgw_msg_dump((struct rgw_radius_msg_meta *)*msg, 0);
+
+	/* Send the message */
+	CHECK_FCT( rgw_servers_send(req->serv_type, (*msg)->buf, (*msg)->buf_used, cli->sa, req->port) );
+
+	/* update the duplicate cache */
+	if (req->serv_type == RGW_PLG_TYPE_AUTH)
+		p = 0;
+	else
+		p = 1;
+	
+	CHECK_POSIX( pthread_mutex_lock( &cli->dupl_info[p].dupl_lock ) );
+	
+	/* Search this message in our list */
+	for (li = cli->dupl_info[p].dupl_by_id.next; li != &cli->dupl_info[p].dupl_by_id; li = li->next) {
+		int cmp = 0;
+		struct req_info * r = (struct req_info *)(li->o);
+		if (r->id < req->radius.hdr->identifier)
+			continue;
+		if (r->id > req->radius.hdr->identifier)
+			break;
+		if (r->port < req->port)
+			continue;
+		if (r->port > req->port)
+			break;
+		cmp = memcmp(&r->auth[0], &req->radius.hdr->authenticator[0], 16);
+		if (cmp < 0)
+			continue;
+		if (cmp > 0)
+			break;
+		
+		/* We have the request in our duplicate cache */
+		/* This should not happen, but just in case... */
+		if (r->ans) {
+			radius_msg_free(r->ans);
+			free(r->ans);
+		}
+		
+		/* Now save the message */
+		r->ans = *msg;
+		*msg = NULL;
+		
+		/* Update the timestamp */
+		{
+			time_t now = time(NULL);
+			r->received = now;
+			fd_list_unlink(&r->by_time); /* Move as last entry, since it is the most recent */
+			fd_list_insert_before(&cli->dupl_info[p].dupl_by_time, &r->by_time);
+		}
+		break;
+	}
+		
+	CHECK_POSIX( pthread_mutex_unlock( &cli->dupl_info[p].dupl_lock ) );
+	
+	/* If we have not found the request in our list, the purge time is probably too small */
+	if (*msg) {
+		TODO("Augment the purge time...");
+		/* If we receive the duplicate request again, it will be converted to Diameter... */
+		radius_msg_free(*msg);
+		free(*msg);
+		*msg = NULL;
+	}
+	
+	/* Finished */
+	return 0;
+}
+
+/* Call this function when a RADIUS request has explicitely no answer (mainly accounting) so 
+that we purge the duplicate cache and allow further message to be translated again.
+This is useful for example when a temporary error occurred in Diameter (like UNABLE_TO_DELIVER) */
+int rgw_client_finish_nosend(struct rgw_radius_msg_meta * req, struct rgw_client * cli)
+{
+	int p;
+	struct fd_list * li;
+	
+	TRACE_ENTRY("%p %p", req, cli);
+	CHECK_PARAMS( req && cli );
+	
+	/* update the duplicate cache */
+	if (req->serv_type == RGW_PLG_TYPE_AUTH)
+		p = 0;
+	else
+		p = 1;
+	
+	CHECK_POSIX( pthread_mutex_lock( &cli->dupl_info[p].dupl_lock ) );
+	
+	/* Search this message in our list */
+	for (li = cli->dupl_info[p].dupl_by_id.next; li != &cli->dupl_info[p].dupl_by_id; li = li->next) {
+		int cmp = 0;
+		struct req_info * r = (struct req_info *)(li->o);
+		if (r->id < req->radius.hdr->identifier)
+			continue;
+		if (r->id > req->radius.hdr->identifier)
+			break;
+		if (r->port < req->port)
+			continue;
+		if (r->port > req->port)
+			break;
+		cmp = memcmp(&r->auth[0], &req->radius.hdr->authenticator[0], 16);
+		if (cmp < 0)
+			continue;
+		if (cmp > 0)
+			break;
+		
+		/* We have the request in our duplicate cache, remove it */
+		fd_list_unlink(&r->by_id);
+		fd_list_unlink(&r->by_time);
+		dupl_free_req_info(r);
+		break;
+	}
+		
+	CHECK_POSIX( pthread_mutex_unlock( &cli->dupl_info[p].dupl_lock ) );
+	
+	/* Finished */
+	return 0;
+}
+
diff --git a/extensions/app_radgw/rgw_common.h b/extensions/app_radgw/rgw_common.h
new file mode 100644
index 0000000..bfb700a
--- /dev/null
+++ b/extensions/app_radgw/rgw_common.h
@@ -0,0 +1,287 @@
+/*********************************************************************************************************
+* Software License Agreement (BSD License)                                                               *
+* Author: Sebastien Decugis <sdecugis@freediameter.net>							 *
+*													 *
+* Copyright (c) 2013, WIDE Project and NICT								 *
+* All rights reserved.											 *
+* 													 *
+* Redistribution and use of this software in source and binary forms, with or without modification, are  *
+* permitted provided that the following conditions are met:						 *
+* 													 *
+* * Redistributions of source code must retain the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer.										 *
+*    													 *
+* * Redistributions in binary form must reproduce the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer in the documentation and/or other						 *
+*   materials provided with the distribution.								 *
+* 													 *
+* * Neither the name of the WIDE Project or NICT nor the 						 *
+*   names of its contributors may be used to endorse or 						 *
+*   promote products derived from this software without 						 *
+*   specific prior written permission of WIDE Project and 						 *
+*   NICT.												 *
+* 													 *
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED *
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
+* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR *
+* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 	 *
+* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 	 *
+* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR *
+* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF   *
+* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.								 *
+*********************************************************************************************************/
+
+/* This file contains definitions for both app_radgw extension and its plugins. */
+
+#ifndef _RGW_COMMON_H
+#define _RGW_COMMON_H
+
+/* Include definitions from the freeDiameter framework */
+#include <freeDiameter/extension.h>
+
+/* Include hostap files for RADIUS processings */
+#include "hostap_compat.h"
+#include "md5.h"
+#include "radius.h"
+
+
+/**************************************************************/
+/*              Interface with gateway's plug-ins             */
+/**************************************************************/
+/* This structure is private for each plugin */
+struct rgwp_config;
+
+/* This structure points to a RADIUS client description, the definition is not known to plugins */
+struct rgw_client;
+
+int    rgw_clients_getkey(struct rgw_client * cli, unsigned char **key, size_t *key_len);
+char * rgw_clients_id(struct rgw_client *cli);
+int    rgw_clients_get_origin(struct rgw_client *cli, DiamId_t *fqdn, size_t *fqdnlen, DiamId_t *realm, size_t *realmlen);
+
+/* Each plugin must provide the following structure. */
+extern struct rgw_api {
+	/* The name of the plugin */
+	const char * rgwp_name;
+
+	/* Parse the configuration file. It may be called several times with different configurations.
+	    Called even if no configuration file is passed (with NULL conf_file parameter then) */
+	int (*rgwp_conf_parse) ( char * conf_file, struct rgwp_config ** state );
+	
+	/* Cleanup the configuration state when the daemon is exiting (called even if state is NULL). */
+	void (*rgwp_conf_free) (struct rgwp_config * state);
+
+	/* handle an incoming RADIUS message */
+	int	(*rgwp_rad_req) ( struct rgwp_config * conf, struct radius_msg * rad_req, struct radius_msg ** rad_ans, struct msg ** diam_fw, struct rgw_client * cli );
+	/* ret >0: critical error (errno), log and exit.
+	   ret 0: continue; 
+	   ret -1: stop processing this message
+	   ret -2: reply the content of rad_ans to the RADIUS client immediatly
+	 */
+	
+	/* handle the corresponding Diameter answer */
+	int	(*rgwp_diam_ans) ( struct rgwp_config * conf, struct msg ** diam_ans, struct radius_msg ** rad_fw, struct rgw_client * cli );
+	/* ret 0: continue; ret >0: error; ret: -1 ... (tbd) */
+	
+} rgwp_descriptor;
+
+
+
+/**************************************************************/
+/*              Additional definitions                        */
+/**************************************************************/
+/* Type of message / server */
+#define RGW_PLG_TYPE_AUTH	1
+#define RGW_PLG_TYPE_ACCT	2
+
+/* Class attribute prefix to store the Auth Application Id (required to send STR) */
+#define CLASS_AAI_PREFIX 	"fD/rgwx/aai:"
+
+/* Attributes missing from radius.h (not used in EAP) */
+enum { RADIUS_ATTR_CHAP_PASSWORD = 3,
+	RADIUS_ATTR_SERVICE_TYPE = 6,
+	RADIUS_ATTR_FRAMED_PROTOCOL = 7,
+	RADIUS_ATTR_FRAMED_IP_ADDRESS = 8,
+	RADIUS_ATTR_FRAMED_IP_NETMASK = 9,
+	RADIUS_ATTR_FRAMED_ROUTING = 10,
+	RADIUS_ATTR_FILTER_ID = 11,
+	RADIUS_ATTR_FRAMED_COMPRESSION = 13,
+	RADIUS_ATTR_LOGIN_IP_HOST = 14,
+	RADIUS_ATTR_LOGIN_SERVICE = 15,
+	RADIUS_ATTR_LOGIN_TCP_PORT = 16,
+	RADIUS_ATTR_CALLBACK_NUMBER = 19,
+	RADIUS_ATTR_CALLBACK_ID = 20,
+	RADIUS_ATTR_FRAMED_ROUTE = 22,
+	RADIUS_ATTR_FRAMED_IPX_NETWORK = 23,
+	RADIUS_ATTR_LOGIN_LAT_SERVICE = 34,
+	RADIUS_ATTR_LOGIN_LAT_NODE = 35,
+	RADIUS_ATTR_LOGIN_LAT_GROUP = 36,
+	RADIUS_ATTR_FRAMED_APPLETALK_LINK = 37,
+	RADIUS_ATTR_FRAMED_APPLETALK_NETWORK = 38,
+	RADIUS_ATTR_FRAMED_APPLETALK_ZONE = 39,
+	RADIUS_ATTR_CHAP_CHALLENGE = 60,
+	RADIUS_ATTR_PORT_LIMIT = 62,
+	RADIUS_ATTR_LOGIN_LAT_PORT = 63,
+	RADIUS_ATTR_TUNNEL_CLIENT_ENDPOINT = 66,
+	RADIUS_ATTR_TUNNEL_SERVER_ENDPOINT = 67,
+	RADIUS_ATTR_TUNNEL_PASSWORD = 69,
+	RADIUS_ATTR_ARAP_PASSWORD = 70,
+	RADIUS_ATTR_ARAP_FEATURES = 71,
+	RADIUS_ATTR_ARAP_ZONE_ACCESS = 72,
+	RADIUS_ATTR_ARAP_SECURITY = 73,
+	RADIUS_ATTR_ARAP_SECURITY_DATA = 74,
+	RADIUS_ATTR_PASSWORD_RETRY = 75,
+	RADIUS_ATTR_PROMPT = 76,
+	RADIUS_ATTR_CONFIGURATION_TOKEN = 78,
+	RADIUS_ATTR_TUNNEL_ASSIGNMENT_ID = 82,
+	RADIUS_ATTR_TUNNEL_PREFERENCE = 83,
+	RADIUS_ATTR_ARAP_CHALLENGE_RESPONSE = 84,
+	RADIUS_ATTR_NAS_PORT_ID = 87,
+	RADIUS_ATTR_FRAMED_POOL = 88,
+	RADIUS_ATTR_TUNNEL_CLIENT_AUTH_ID = 90,
+	RADIUS_ATTR_TUNNEL_SERVER_AUTH_ID = 91,
+	RADIUS_ATTR_ORIGINATING_LINE_INFO = 94,
+	RADIUS_ATTR_FRAMED_INTERFACE_ID = 96,
+	RADIUS_ATTR_FRAMED_IPV6_PREFIX = 97,
+	RADIUS_ATTR_LOGIN_IPV6_HOST = 98,
+	RADIUS_ATTR_FRAMED_IPV6_ROUTE = 99,
+	RADIUS_ATTR_FRAMED_IPV6_POOL = 100,
+	RADIUS_ATTR_ERROR_CAUSE = 101,
+	RADIUS_ATTR_EAP_KEY_NAME = 102,
+	RADIUS_ATTR_DIGEST_RESPONSE = 103,
+	RADIUS_ATTR_DIGEST_REALM = 104,
+	RADIUS_ATTR_DIGEST_NONCE = 105,
+	RADIUS_ATTR_DIGEST_RESPONSE_AUTH=106,
+	RADIUS_ATTR_DIGEST_NEXTNONCE = 107,
+	RADIUS_ATTR_DIGEST_METHOD = 108,
+	RADIUS_ATTR_DIGEST_URI = 109,
+	RADIUS_ATTR_DIGEST_QOP = 110,
+	RADIUS_ATTR_DIGEST_ALGORITHM = 111,
+	RADIUS_ATTR_DIGEST_ENTITY_BODY_HASH=112,
+	RADIUS_ATTR_DIGEST_CNONCE = 113,
+	RADIUS_ATTR_DIGEST_NONCE_COUNT = 114,
+	RADIUS_ATTR_DIGEST_USERNAME = 115,
+	RADIUS_ATTR_DIGEST_HA1 = 121,
+	RADIUS_ATTR_SIP_AOR = 122
+};
+
+enum {  DIAM_ATTR_USER_NAME = 1,
+	DIAM_ATTR_USER_PASSWORD = 2,
+	DIAM_ATTR_NAS_IP_ADDRESS = 4,
+	DIAM_ATTR_NAS_PORT = 5,
+	DIAM_ATTR_SERVICE_TYPE = 6,
+	DIAM_ATTR_FRAMED_PROTOCOL = 7,
+	DIAM_ATTR_FRAMED_IP_ADDRESS = 8,
+	DIAM_ATTR_FRAMED_IP_NETMASK = 9,
+	DIAM_ATTR_FRAMED_ROUTING = 10,
+	DIAM_ATTR_FILTER_ID = 11,
+	DIAM_ATTR_FRAMED_MTU = 12,
+	DIAM_ATTR_FRAMED_COMPRESSION = 13,
+	DIAM_ATTR_LOGIN_IP_HOST = 14,
+	DIAM_ATTR_LOGIN_SERVICE = 15,
+	DIAM_ATTR_LOGIN_TCP_PORT = 16,
+	DIAM_ATTR_REPLY_MESSAGE = 18,
+	DIAM_ATTR_CALLBACK_NUMBER = 19,
+	DIAM_ATTR_CALLBACK_ID = 20,
+	DIAM_ATTR_FRAMED_ROUTE = 22,
+	DIAM_ATTR_FRAMED_IPX_NETWORK = 23,
+	DIAM_ATTR_STATE = 24,
+	DIAM_ATTR_CLASS = 25,
+	DIAM_ATTR_IDLE_TIMEOUT = 28,
+	DIAM_ATTR_NAS_IDENTIFIER = 32,
+	DIAM_ATTR_LOGIN_LAT_SERVICE = 34,
+	DIAM_ATTR_LOGIN_LAT_NODE = 35,
+	DIAM_ATTR_LOGIN_LAT_GROUP = 36,
+	DIAM_ATTR_FRAMED_APPLETALK_LINK = 37,
+	DIAM_ATTR_FRAMED_APPLETALK_NETWORK = 38,
+	DIAM_ATTR_FRAMED_APPLETALK_ZONE = 39,
+	DIAM_ATTR_ACCT_SESSION_ID = 44,
+	DIAM_ATTR_ACCT_MULTI_SESSION_ID = 50,
+	DIAM_ATTR_EVENT_TIMESTAMP = 55,
+	DIAM_ATTR_NAS_PORT_TYPE = 61,
+	DIAM_ATTR_PORT_LIMIT = 62,
+	DIAM_ATTR_LOGIN_LAT_PORT = 63,
+	DIAM_ATTR_TUNNEL_TYPE = 64,
+	DIAM_ATTR_TUNNEL_MEDIUM_TYPE = 65,
+	DIAM_ATTR_TUNNEL_CLIENT_ENDPOINT = 66,
+	DIAM_ATTR_TUNNEL_SERVER_ENDPOINT = 67,
+	DIAM_ATTR_TUNNEL_PASSWORD = 69,
+	DIAM_ATTR_ARAP_FEATURES = 71,
+	DIAM_ATTR_ARAP_ZONE_ACCESS = 72,
+	DIAM_ATTR_ARAP_SECURITY = 73,
+	DIAM_ATTR_ARAP_SECURITY_DATA = 74,
+	DIAM_ATTR_PASSWORD_RETRY = 75,
+	DIAM_ATTR_PROMPT = 76,
+	DIAM_ATTR_CONFIGURATION_TOKEN = 78,
+	DIAM_ATTR_TUNNEL_PRIVATE_GROUP_ID = 81,
+	DIAM_ATTR_TUNNEL_ASSIGNMENT_ID = 82,
+	DIAM_ATTR_TUNNEL_PREFERENCE = 83,
+	DIAM_ATTR_ARAP_CHALLENGE_RESPONSE = 84,
+	DIAM_ATTR_ACCT_INTERIM_INTERVAL = 85,
+	DIAM_ATTR_NAS_PORT_ID = 87,
+	DIAM_ATTR_FRAMED_POOL = 88,
+	DIAM_ATTR_TUNNEL_CLIENT_AUTH_ID = 90,
+	DIAM_ATTR_TUNNEL_SERVER_AUTH_ID = 91,
+	DIAM_ATTR_NAS_IPV6_ADDRESS = 95,
+	DIAM_ATTR_FRAMED_INTERFACE_ID = 96,
+	DIAM_ATTR_FRAMED_IPV6_PREFIX = 97,
+	DIAM_ATTR_LOGIN_IPV6_HOST = 98,
+	DIAM_ATTR_FRAMED_IPV6_ROUTE = 99,
+	DIAM_ATTR_FRAMED_IPV6_POOL = 100,
+	DIAM_ATTR_EAP_KEY_NAME = 102,
+	DIAM_ATTR_DIGEST_RESPONSE = 103,
+	DIAM_ATTR_DIGEST_REALM = 104,
+	DIAM_ATTR_DIGEST_NONCE = 105,
+	DIAM_ATTR_DIGEST_RESPONSE_AUTH=106,
+	DIAM_ATTR_DIGEST_NEXTNONCE = 107,
+	DIAM_ATTR_DIGEST_METHOD = 108,
+	DIAM_ATTR_DIGEST_URI = 109,
+	DIAM_ATTR_DIGEST_QOP = 110,
+	DIAM_ATTR_DIGEST_ALGORITHM = 111,
+	DIAM_ATTR_DIGEST_ENTITY_BODY_HASH=112,
+	DIAM_ATTR_DIGEST_CNONCE = 113,
+	DIAM_ATTR_DIGEST_NONCE_COUNT = 114,
+	DIAM_ATTR_DIGEST_USERNAME = 115,
+	DIAM_ATTR_DIGEST_HA1 = 121,
+	DIAM_ATTR_SIP_AOR = 122,
+	DIAM_ATTR_AUTH_APPLICATION_ID = 258,
+	DIAM_ATTR_ACCT_APPLICATION_ID = 259,
+	DIAM_ATTR_VENDOR_SPECIFIC_APPLICATION_ID = 260,
+	DIAM_ATTR_SESSION_ID = 263,
+	DIAM_ATTR_ORIGIN_HOST = 264,
+	DIAM_ATTR_MULTI_ROUND_TIMEOUT = 272,
+	DIAM_ATTR_AUTH_REQUEST_TYPE = 274,
+	DIAM_ATTR_AUTH_GRACE_PERIOD = 276,
+	DIAM_ATTR_AUTH_SESSION_STATE = 277,
+	DIAM_ATTR_ORIGIN_STATE_ID = 278,
+	DIAM_ATTR_FAILED_AVP = 279,
+	DIAM_ATTR_ERROR_MESSAGE = 281,
+	DIAM_ATTR_ROUTE_RECORD = 282,
+	DIAM_ATTR_PROXY_INFO = 284,
+	DIAM_ATTR_ACCOUNTING_SUB_SESSION_ID = 287,
+	DIAM_ATTR_ERROR_REPORTING_HOST = 294,
+	DIAM_ATTR_TERMINATION_CAUSE = 295,
+	DIAM_ATTR_ORIGIN_REALM = 296,
+	DIAM_ATTR_SIP_AUTH_DATA_ITEM = 376,
+	DIAM_ATTR_SIP_AUTHENTICATION_SCHEME = 377,
+	DIAM_ATTR_SIP_AUTHENTICATE = 379,
+	DIAM_ATTR_SIP_NUMBER_AUTH_ITEMS = 382,
+	DIAM_ATTR_NAS_FILTER_RULE = 400,
+	DIAM_ATTR_TUNNELING = 401,
+	DIAM_ATTR_QOS_FILTER_RULE = 407,
+	DIAM_ATTR_ORIGIN_AAA_PROTOCOL = 408,
+	DIAM_ATTR_EAP_PAYLOAD = 462,
+	DIAM_ATTR_EAP_REISSUED_PAYLOAD = 463,
+	DIAM_ATTR_EAP_MASTER_SESSION_KEY = 464,
+	DIAM_ATTR_ACCOUNTING_EAP_AUTH_METHOD = 465,
+	DIAM_ATTR_ACCOUNTING_RECORD_TYPE = 480,
+	DIAM_ATTR_ACCOUNTING_REALTIME_REQUIRED = 483,
+	DIAM_ATTR_ACCOUNTING_RECORD_NUMBER = 485
+};
+
+const char * rgw_msg_attrtype_str(unsigned char c);
+const char * rgw_msg_code_str(unsigned char c);
+
+#endif /* _RGW_COMMON_H */
+  
diff --git a/extensions/app_radgw/rgw_conf.l b/extensions/app_radgw/rgw_conf.l
new file mode 100644
index 0000000..8afd779
--- /dev/null
+++ b/extensions/app_radgw/rgw_conf.l
@@ -0,0 +1,277 @@
+/*********************************************************************************************************
+* Software License Agreement (BSD License)                                                               *
+* Author: Sebastien Decugis <sdecugis@freediameter.net>							 *
+*													 *
+* Copyright (c) 2013, WIDE Project and NICT								 *
+* All rights reserved.											 *
+* 													 *
+* Redistribution and use of this software in source and binary forms, with or without modification, are  *
+* permitted provided that the following conditions are met:						 *
+* 													 *
+* * Redistributions of source code must retain the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer.										 *
+*    													 *
+* * Redistributions in binary form must reproduce the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer in the documentation and/or other						 *
+*   materials provided with the distribution.								 *
+* 													 *
+* * Neither the name of the WIDE Project or NICT nor the 						 *
+*   names of its contributors may be used to endorse or 						 *
+*   promote products derived from this software without 						 *
+*   specific prior written permission of WIDE Project and 						 *
+*   NICT.												 *
+* 													 *
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED *
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
+* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR *
+* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 	 *
+* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 	 *
+* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR *
+* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF   *
+* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.								 *
+*********************************************************************************************************/
+/* Lex configuration parser for radius_gw extension.
+ *
+ */
+
+%{
+#include "rgw.h"
+#include "rgw_conf.tab.h"
+
+/* Update the column information */
+#define YY_USER_ACTION { 						\
+	yylloc->first_column = yylloc->last_column + 1; 		\
+	yylloc->last_column = yylloc->first_column + yyleng - 1;	\
+}
+
+/* %option noinput ? */
+#define YY_NO_INPUT
+%}
+
+%option bison-bridge bison-locations
+%option noyywrap
+%option nounput
+
+/* Use the following start condition to parse an URI */
+%x	IN_PLG
+%x	IN_CLI1
+%x	IN_CLI2
+%x	EXPECT_IP4
+%x	EXPECT_IP6
+%x	EXPECT_DECINT
+
+/* Quoted string. Multilines do not match. */
+qstring		\"[^\"\n]*\"
+
+/* Used to match IP, IP6, and port */
+IP4		[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}
+IP6		[[:xdigit:]]*:[[:xdigit:]]*:[[:xdigit:].:]*
+BR_PORT		[[][0-9]+[]]
+
+
+%%
+
+	/* All sections */
+<*>\n			{ 
+				/* Update the line count */
+				yylloc->first_line++; 
+				yylloc->last_line++; 
+				yylloc->last_column=0; 
+			} 
+
+<*>([[:space:]]{-}[\n])+	; /* Eat all spaces, not new lines */
+<*>#.*$			; /* Eat all comments */
+
+<*>{qstring}		{
+				/* First copy the string without the quotes for use in the yacc parser */
+				yylval->string = strdup(yytext+1);
+				if (yylval->string == NULL) {
+					fd_log_debug("Unable to allocate memory: %s", strerror(errno));
+					return LEX_ERROR; /* trig an error in yacc parser */
+				}
+
+				yylval->string[yyleng-2] = '\0';
+				
+				/* the yacc parser will check the string is valid */
+				return QSTRING;
+			}
+
+
+	/* Extension section */			
+(?i:"RGWX")		{ BEGIN(IN_PLG); return PLG_PREFIX; 		}
+
+<IN_PLG>(?i:"auth")	{ return AUTH; }
+<IN_PLG>(?i:"acct")	{ return ACCT; }
+
+<IN_PLG,IN_CLI2>[[:xdigit:]]+	{
+				/* Convert this to an integer value */
+				int ret = sscanf(yytext, "%x", &yylval->integer);
+				if (ret != 1) {
+					/* No matching: an error occurred */
+					fd_log_debug("Unable to convert the value '%s' to a valid number: %s", yytext, strerror(errno));
+					return LEX_ERROR; /* trig an error in yacc parser */
+					/* Maybe we could REJECT instead of failing here? */
+				}
+				return INTEGER;
+			}
+
+<IN_PLG>[:]		{ return yytext[0]; }
+
+
+	/* Client section */
+(?i:"nas"|"cli")	{ BEGIN(IN_CLI1); yylval->integer=RGW_CLI_NAS; return NAS_OR_PXY; 		}
+(?i:"pxy")		{ BEGIN(IN_CLI1); yylval->integer=RGW_CLI_PXY; return NAS_OR_PXY; 		}
+
+	/* Match an IP (4 or 6) and optional port */
+<IN_CLI1>({IP4}|{IP6}){BR_PORT}?	{
+				char * work;
+				char * port;
+				unsigned short p = 0;
+				
+				work = strdup(yytext);
+				if ( work == NULL ) {
+					fd_log_debug("Unable to allocate memory: %s", strerror(errno));
+					return LEX_ERROR; /* trig an error in yacc parser */
+				}
+				
+				if ((port = strchr(work, '[')) != NULL) {
+					*port = '\0';
+					port++;
+					if (sscanf(port, "%hu]", &p) != 1) {
+						fd_log_debug("'%s' is not a valid port: %s", port, strerror(errno));
+						free(work);
+						return LEX_ERROR; /* trig an error in yacc parser */
+					}
+				}
+				
+				/* Do we have an IP or IPv6? Let's check if we have ':' char somewhere in the beginning */
+				if (memchr(work, ':', 5) != NULL) {
+					struct sockaddr_in6 * sin6 = NULL;
+				
+					sin6 = malloc(sizeof(struct sockaddr_in6));
+					if (sin6 == NULL) {
+						fd_log_debug("Unable to allocate memory: %s", strerror(errno));
+						free(work);
+						return LEX_ERROR; /* trig an error in yacc parser */
+					}
+					
+					memset(sin6, 0, sizeof(struct sockaddr_in6));
+					sin6->sin6_family = AF_INET6;
+					if (inet_pton(AF_INET6, work, &sin6->sin6_addr) != 1) {
+						fd_log_debug("'%s' is not a valid IPv6 address: %s", work, strerror(errno));
+						free(work);
+						free(sin6);
+						return LEX_ERROR; /* trig an error in yacc parser */
+					}
+					sin6->sin6_port = htons(p);
+					yylval->ss = (struct sockaddr *)sin6;
+				} else {
+					struct sockaddr_in * sin = NULL;
+				
+					sin = malloc(sizeof(struct sockaddr_in));
+					if (sin == NULL) {
+						fd_log_debug("Unable to allocate memory: %s", strerror(errno));
+						free(work);
+						return LEX_ERROR; /* trig an error in yacc parser */
+					}
+					
+					memset(sin, 0, sizeof(struct sockaddr_in));
+					sin->sin_family = AF_INET;
+					if (inet_pton(AF_INET, work, &sin->sin_addr) != 1) {
+						fd_log_debug("'%s' is not a valid IP address: %s", work, strerror(errno));
+						free(work);
+						free(sin);
+						return LEX_ERROR; /* trig an error in yacc parser */
+					}
+					
+					sin->sin_port = htons(p);
+					yylval->ss = (struct sockaddr *)sin;
+				}
+				free(work);
+				return IP;
+			}
+
+
+<IN_CLI1>"/"		{ BEGIN(IN_CLI2); return '/';	 		}
+
+
+	/* Servers section */
+(?i:"auth_server_enable")	{ BEGIN(EXPECT_DECINT); return AUTH_ENABLE; 	}
+(?i:"auth_server_port")		{ BEGIN(EXPECT_DECINT); return AUTH_PORT; 	}
+(?i:"auth_server_ip4")		{ BEGIN(EXPECT_IP4); return AUTH_IP4; 		}
+(?i:"auth_server_ip6")		{ BEGIN(EXPECT_IP6); return AUTH_IP6; 		}
+(?i:"acct_server_enable")	{ BEGIN(EXPECT_DECINT); return ACCT_ENABLE; 	}
+(?i:"acct_server_port")		{ BEGIN(EXPECT_DECINT); return ACCT_PORT; 	}
+(?i:"acct_server_ip4")		{ BEGIN(EXPECT_IP4); return ACCT_IP4; 		}
+(?i:"acct_server_ip6")		{ BEGIN(EXPECT_IP6); return ACCT_IP6; 		}
+
+<EXPECT_DECINT>[[:digit:]]+	{
+					/* Match an integer (not hexa) */
+					int ret = sscanf(yytext, "%d", &yylval->integer);
+					if (ret != 1) {
+						/* No matching: an error occurred */
+						fd_log_debug("Unable to convert the value '%s' to a valid number: %s", yytext, strerror(errno));
+						return LEX_ERROR; /* trig an error in yacc parser */
+						/* Maybe we could REJECT instead of failing here? */
+					}
+					return INTEGER;
+				}
+
+<EXPECT_IP4,EXPECT_IP6>(?i:"disable")	{ return DISABLED; 				}
+				
+<EXPECT_IP4>{IP4}		{
+					struct sockaddr_in * sin = NULL;
+				
+					sin = malloc(sizeof(struct sockaddr_in));
+					if (sin == NULL) {
+						fd_log_debug("Unable to allocate memory: %s", strerror(errno));
+						return LEX_ERROR; /* trig an error in yacc parser */
+					}
+					
+					memset(sin, 0, sizeof(struct sockaddr_in));
+					sin->sin_family = AF_INET;
+					if (inet_pton(AF_INET, yytext, &sin->sin_addr) != 1) {
+						fd_log_debug("'%s' is not a valid IP address: %s", yytext, strerror(errno));
+						free(sin);
+						return LEX_ERROR; /* trig an error in yacc parser */
+					}
+					yylval->ss = (struct sockaddr *)sin;
+					return IP;
+				}
+
+<EXPECT_IP6>{IP6}		{
+					struct sockaddr_in6 * sin6 = NULL;
+				
+					sin6 = malloc(sizeof(struct sockaddr_in6));
+					if (sin6 == NULL) {
+						fd_log_debug("Unable to allocate memory: %s", strerror(errno));
+						return LEX_ERROR; /* trig an error in yacc parser */
+					}
+					
+					memset(sin6, 0, sizeof(struct sockaddr_in6));
+					sin6->sin6_family = AF_INET6;
+					if (inet_pton(AF_INET6, yytext, &sin6->sin6_addr) != 1) {
+						fd_log_debug("'%s' is not a valid IPv6 address: %s", yytext, strerror(errno));
+						free(sin6);
+						return LEX_ERROR; /* trig an error in yacc parser */
+					}
+					yylval->ss = (struct sockaddr *)sin6;
+					return IP;
+				}
+
+	
+	/* Valid single characters for yyparse in all contexts */
+<*>[=]			{ return yytext[0]; }
+<*>[;]			{ BEGIN(INITIAL); return yytext[0]; }
+
+	/* Unrecognized token */
+<*>[[:alnum:]]+		|	/* This rule is only useful to print a complete token in error messages */
+	/* Unrecognized character */
+<*>.			{ 
+				fd_log_debug("Unrecognized text on line %d col %d: '%s'.", yylloc->first_line, yylloc->first_column, yytext);
+			 	return LEX_ERROR; 
+			}
+
+%%
diff --git a/extensions/app_radgw/rgw_conf.y b/extensions/app_radgw/rgw_conf.y
new file mode 100644
index 0000000..53ab746
--- /dev/null
+++ b/extensions/app_radgw/rgw_conf.y
@@ -0,0 +1,404 @@
+/*********************************************************************************************************
+* Software License Agreement (BSD License)                                                               *
+* Author: Sebastien Decugis <sdecugis@freediameter.net>							 *
+*													 *
+* Copyright (c) 2013, WIDE Project and NICT								 *
+* All rights reserved.											 *
+* 													 *
+* Redistribution and use of this software in source and binary forms, with or without modification, are  *
+* permitted provided that the following conditions are met:						 *
+* 													 *
+* * Redistributions of source code must retain the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer.										 *
+*    													 *
+* * Redistributions in binary form must reproduce the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer in the documentation and/or other						 *
+*   materials provided with the distribution.								 *
+* 													 *
+* * Neither the name of the WIDE Project or NICT nor the 						 *
+*   names of its contributors may be used to endorse or 						 *
+*   promote products derived from this software without 						 *
+*   specific prior written permission of WIDE Project and 						 *
+*   NICT.												 *
+* 													 *
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED *
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
+* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR *
+* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 	 *
+* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 	 *
+* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR *
+* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF   *
+* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.								 *
+*********************************************************************************************************/
+
+/* Yacc extension's configuration parser.
+ * See doc/app_radgw.conf.sample for configuration file format
+ */
+
+/* For development only : */
+%debug 
+%error-verbose
+
+/* The parser receives the configuration file filename as parameter */
+%parse-param {char * conffile}
+
+/* Keep track of location */
+%locations 
+%pure-parser
+
+%{
+#include "rgw.h"
+#include "rgw_conf.tab.h"	/* bison is not smart enough to define the YYLTYPE before including this code, so... */
+
+#include <sys/socket.h>
+#include <arpa/inet.h>
+#include <netdb.h>
+
+/* Forward declaration */
+int yyparse(char * conffile);
+
+/* Parse the configuration file */
+int rgw_conf_handle(char * conffile)
+{
+	extern FILE * rgw_confin;
+	int ret;
+	
+	rgw_confin = fopen(conffile, "r");
+	if (rgw_confin == NULL) {
+		ret = errno;
+		fd_log_debug("Unable to open extension configuration file %s for reading: %s", conffile, strerror(ret));
+		return ret;
+	}
+
+	ret = rgw_confparse(conffile);
+
+	fclose(rgw_confin);
+
+	if (ret != 0) {
+		return EINVAL;
+	}
+	
+	return 0;
+}
+
+/* The Lex parser prototype */
+int rgw_conflex(YYSTYPE *lvalp, YYLTYPE *llocp);
+
+/* Function to report the errors */
+void yyerror (YYLTYPE *ploc, char * conffile, char const *s)
+{
+	if (ploc->first_line != ploc->last_line)
+		fd_log_debug("%s:%d.%d-%d.%d : %s", conffile, ploc->first_line, ploc->first_column, ploc->last_line, ploc->last_column, s);
+	else if (ploc->first_column != ploc->last_column)
+		fd_log_debug("%s:%d.%d-%d : %s", conffile, ploc->first_line, ploc->first_column, ploc->last_column, s);
+	else
+		fd_log_debug("%s:%d.%d : %s", conffile, ploc->first_line, ploc->first_column, s);
+}
+
+/* Very simple byte stack management */
+static unsigned char * buf = NULL;
+static size_t buf_sz = 0;
+static size_t buf_rsz = 0;
+static inline int buf_add(unsigned char val) /* add a value in the array */
+{
+	buf_sz++;
+	
+	if (buf_sz > buf_rsz) {
+		void * rez=NULL;
+		buf_rsz += 256;
+		rez = realloc(buf, buf_rsz);
+		if (rez == NULL) {
+			fd_log_debug("Error on memory allocation: %s", strerror(errno));
+			return 0;
+		}
+		buf = (unsigned char *)rez;
+	}
+	buf[buf_sz - 1] = val;
+	return 1;   
+}
+static inline void buf_reinit(void)
+{
+	free(buf);
+	buf = NULL;
+	buf_sz = 0;
+	buf_rsz = 0;
+}
+
+static int port = 0;
+static char * plgconffile = NULL;
+
+%}
+
+/* Values returned by lex for token */
+%union {
+	char 		*string;	/* The string is allocated by strdup in lex.*/
+	int		 integer;	/* Store integer values */
+	struct sockaddr *ss;		/* sockaddr to free after use (alloc in lex) */
+}
+
+/* typed data */
+%token <string>	QSTRING
+%token <integer> INTEGER
+%token <ss>	IP
+
+%type <string>	FINDFILEEXT
+
+%token <integer> NAS_OR_PXY
+
+/* simple tokens */
+%token		DISABLED
+%token		AUTH
+%token		ACCT
+
+%token 		PLG_PREFIX
+
+%token		AUTH_ENABLE
+%token		AUTH_PORT
+%token		AUTH_IP4
+%token		AUTH_IP6
+%token		ACCT_ENABLE
+%token		ACCT_PORT
+%token		ACCT_IP4
+%token		ACCT_IP6
+
+/* In case of error in the lexical analysis */
+%token 		LEX_ERROR
+
+
+/* -------------------------------------- */
+%%
+
+	/* The grammar definition */
+conffile:		/* empty grammar is OK */
+			| conffile plugin
+			| conffile clientdef
+			| conffile authserv
+			| conffile acctserv
+			;
+
+				
+/* -------------------------------------- */
+FINDFILEEXT:		QSTRING
+			{
+				char * fname = $1;
+				FILE * fd;
+				
+				/* First, check if the file exists */
+				fd = fopen(fname, "r");
+				if ((fd == NULL) && (*fname != '/')) {
+					char * bkp = fname;
+					CHECK_MALLOC_DO( fname = malloc( strlen(bkp) + strlen(DEFAULT_EXTENSIONS_PATH) + 2 ),
+						{ yyerror (&yylloc, conffile, "Not enough memory"); YYERROR; } );
+					sprintf(fname, DEFAULT_EXTENSIONS_PATH "/%s", bkp);
+					free(bkp);
+					fd = fopen(fname, "r");
+				}
+				if (fd == NULL) {
+					int ret = errno;
+					TRACE_DEBUG(INFO, "Unable to open file %s for reading: %s", fname, strerror(ret));
+					yyerror (&yylloc, conffile, "Error adding plugin"); 
+					YYERROR;
+				}
+				fclose(fd);
+				
+				$$ = fname;
+			}
+			;
+/* -------------------------------------- */
+plugin:			{
+				/* Reset the parameters */
+				buf_reinit();
+				port = RGW_PLG_TYPE_AUTH | RGW_PLG_TYPE_ACCT ;
+				free(plgconffile); plgconffile = NULL;
+			}
+			PLG_PREFIX '=' FINDFILEEXT plg_attributes ';'
+			{
+				/* Add this extension in the list */
+				if ( rgw_plg_add( $4, plgconffile, port, &buf, buf_sz ) ) {
+					yyerror (&yylloc, conffile, "Error parsing / adding extension !");
+					YYERROR;
+				}
+				
+				/* Free the array */
+				buf_reinit();
+				
+				/* stop conffile from being freed here */
+				plgconffile = NULL;
+			}
+			;
+
+plg_attributes:		/* empty */
+			| plg_attributes ':' QSTRING
+			{
+				plgconffile = $3;
+			}
+			| plg_attributes ':' AUTH
+			{
+				port = RGW_PLG_TYPE_AUTH;
+			}
+			| plg_attributes ':' ACCT
+			{
+				port = RGW_PLG_TYPE_ACCT;
+			}
+			| plg_attributes ':' extcodes_list
+			;
+
+extcodes_list:		/* empty */
+			| extcodes_list INTEGER
+			{
+				if ($2 < 0 || $2 > 255) {
+					yyerror (&yylloc, conffile, "Invalid command code value!");
+					YYERROR;
+				}
+				if ( ! buf_add((unsigned char)$2) ) {
+					yyerror (&yylloc, conffile, "Error allocating memory!");
+					YYERROR;
+				}
+			}
+			;
+				
+/* -------------------------------------- */
+
+clientdef:		{
+				buf_reinit();
+			}
+			NAS_OR_PXY '=' IP '/' clisecret_key ';'
+			{
+				/* Add this client */
+				if ( rgw_clients_add( $4, &buf, buf_sz, $2 ) ) {
+					yyerror (&yylloc, conffile, "Error parsing / adding client !");
+					YYERROR;
+				}
+				
+				/* reinit the buffer */
+				buf_reinit();
+			}
+			;
+
+clisecret_key:		/* empty */
+			| clisecret_key QSTRING
+			{
+				int i;
+				size_t len = strlen($2);
+				for (i = 0; i < len; i++) {
+					if ( ! buf_add( $2 [i] ) ) {
+						yyerror (&yylloc, conffile, "Memory allocation error.");
+						YYERROR;
+					}
+				}
+				
+				free($2);
+			}
+			| clisecret_key INTEGER
+			{
+				if ( $2 < 0 || $2 > 255 ) {
+					yyerror (&yylloc, conffile, "Invalid value in key.");
+					YYERROR;
+				}
+				
+				if ( ! buf_add( $2 ) ) {
+					yyerror (&yylloc, conffile, "Memory allocation error.");
+					YYERROR;
+				}
+			}
+			;
+
+/* -------------------------------------- */
+
+authserv:		AUTH_ENABLE '=' INTEGER ';'
+			{
+				if ($3 == 0) {
+					rgw_servers.auth_serv.disabled = 1;
+				} else {
+					rgw_servers.auth_serv.disabled = 0;
+				}
+			}
+			| AUTH_PORT '=' INTEGER ';'
+			{
+				if ($3 <= 0 || $3 > 65535) {
+					yyerror (&yylloc, conffile, "Invalid port number !");
+					YYERROR;
+				}
+					
+				rgw_servers.auth_serv.port = htons($3);
+			}
+			| AUTH_IP4 '=' DISABLED ';'
+			{
+				rgw_servers.auth_serv.ip_disabled = 1;
+			}
+			| AUTH_IP4 '=' IP ';'
+			{
+				if (((struct sockaddr *)($3))->sa_family != AF_INET) {
+					yyerror (&yylloc, conffile, "Invalid address specification !");
+					YYERROR;
+				}
+				memcpy( & rgw_servers.auth_serv.ip_endpoint, &((struct sockaddr_in *)($3))->sin_addr, sizeof(struct in_addr) );
+				free($3);
+				rgw_servers.auth_serv.ip_disabled = 0;
+			}
+			| AUTH_IP6 '=' DISABLED ';'
+			{
+				rgw_servers.auth_serv.ip6_disabled = 1;
+			}
+			| AUTH_IP6 '=' IP ';'
+			{
+				if (((struct sockaddr *)($3)) -> sa_family != AF_INET6) {
+					yyerror (&yylloc, conffile, "Invalid address specification !");
+					YYERROR;
+				}
+				memcpy( & rgw_servers.auth_serv.ip6_endpoint, &((struct sockaddr_in6 *)($3))->sin6_addr, sizeof(struct in6_addr) );
+				free($3);
+				rgw_servers.auth_serv.ip6_disabled = 0;
+			}
+			;
+
+/* -------------------------------------- */
+
+acctserv:		ACCT_ENABLE '=' INTEGER ';'
+			{
+				if ($3 == 0) {
+					rgw_servers.acct_serv.disabled = 1;
+				} else {
+					rgw_servers.acct_serv.disabled = 0;
+				}
+			}
+			| ACCT_PORT '=' INTEGER ';'
+			{
+				if ($3 <= 0 || $3 > 65535) {
+					yyerror (&yylloc, conffile, "Invalid port number !");
+					YYERROR;
+				}
+					
+				rgw_servers.acct_serv.port = htons($3);
+			}
+			| ACCT_IP4 '=' DISABLED ';'
+			{
+				rgw_servers.acct_serv.ip_disabled = 1;
+			}
+			| ACCT_IP4 '=' IP ';'
+			{
+				if (((struct sockaddr *)($3)) -> sa_family != AF_INET) {
+					yyerror (&yylloc, conffile, "Invalid address specification !");
+					YYERROR;
+				}
+				memcpy( & rgw_servers.auth_serv.ip_endpoint, &((struct sockaddr_in *)($3))->sin_addr, sizeof(struct in_addr) );
+				free($3);
+				rgw_servers.acct_serv.ip_disabled = 0;
+			}
+			| ACCT_IP6 '=' DISABLED ';'
+			{
+				rgw_servers.acct_serv.ip6_disabled = 1;
+			}
+			| ACCT_IP6 '=' IP ';'
+			{
+				if (((struct sockaddr *)($3)) -> sa_family != AF_INET6) {
+					yyerror (&yylloc, conffile, "Invalid address specification !");
+					YYERROR;
+				}
+				memcpy( & rgw_servers.auth_serv.ip6_endpoint, &((struct sockaddr_in6 *)($3))->sin6_addr, sizeof(struct in6_addr) );
+				free($3);
+				rgw_servers.acct_serv.ip6_disabled = 0;
+			}
+			;
diff --git a/extensions/app_radgw/rgw_main.c b/extensions/app_radgw/rgw_main.c
new file mode 100644
index 0000000..9276ef1
--- /dev/null
+++ b/extensions/app_radgw/rgw_main.c
@@ -0,0 +1,76 @@
+/*********************************************************************************************************
+* Software License Agreement (BSD License)                                                               *
+* Author: Sebastien Decugis <sdecugis@freediameter.net>							 *
+*													 *
+* Copyright (c) 2013, WIDE Project and NICT								 *
+* All rights reserved.											 *
+* 													 *
+* Redistribution and use of this software in source and binary forms, with or without modification, are  *
+* permitted provided that the following conditions are met:						 *
+* 													 *
+* * Redistributions of source code must retain the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer.										 *
+*    													 *
+* * Redistributions in binary form must reproduce the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer in the documentation and/or other						 *
+*   materials provided with the distribution.								 *
+* 													 *
+* * Neither the name of the WIDE Project or NICT nor the 						 *
+*   names of its contributors may be used to endorse or 						 *
+*   promote products derived from this software without 						 *
+*   specific prior written permission of WIDE Project and 						 *
+*   NICT.												 *
+* 													 *
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED *
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
+* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR *
+* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 	 *
+* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 	 *
+* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR *
+* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF   *
+* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.								 *
+*********************************************************************************************************/
+/* 
+ * Main file of the app_radgw extension.
+ */
+
+#include "rgw.h"
+
+/* Extension entry point called by freeDiameter */
+static int rgw_main(char * conffile) 
+{
+	CHECK_FCT( rgw_clients_init() );
+	
+	CHECK_FCT( rgw_servers_init() );
+	
+	CHECK_FCT( rgw_conf_handle(conffile) );
+	
+	LOG_D( "Extension RADIUS Gateway initialized with configuration: '%s'", conffile);
+	rgw_servers_dump();
+	rgw_clients_dump();
+	rgw_plg_dump();
+	
+	/* Start making extension list accelerators */
+	rgw_plg_start_cache();
+	
+	/* Start the worker threads */
+	CHECK_FCT( rgw_work_start() );
+	
+	/* Start the servers */
+	CHECK_FCT( rgw_servers_start() );
+	
+	return 0;
+}
+
+/* Unload */
+void fd_ext_fini(void)
+{
+	rgw_servers_fini();
+	rgw_work_fini();
+	rgw_plg_fini();
+	rgw_clients_fini();
+}
+
+EXTENSION_ENTRY("app_radgw", rgw_main);
diff --git a/extensions/app_radgw/rgw_msg_attrtype.c b/extensions/app_radgw/rgw_msg_attrtype.c
new file mode 100644
index 0000000..b14e54c
--- /dev/null
+++ b/extensions/app_radgw/rgw_msg_attrtype.c
@@ -0,0 +1,300 @@
+/*********************************************************************************************************
+* Software License Agreement (BSD License)                                                               *
+* Author: Sebastien Decugis <sdecugis@freediameter.net>							 *
+*													 *
+* Copyright (c) 2011, WIDE Project and NICT								 *
+* All rights reserved.											 *
+* 													 *
+* Redistribution and use of this software in source and binary forms, with or without modification, are  *
+* permitted provided that the following conditions are met:						 *
+* 													 *
+* * Redistributions of source code must retain the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer.										 *
+*    													 *
+* * Redistributions in binary form must reproduce the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer in the documentation and/or other						 *
+*   materials provided with the distribution.								 *
+* 													 *
+* * Neither the name of the WIDE Project or NICT nor the 						 *
+*   names of its contributors may be used to endorse or 						 *
+*   promote products derived from this software without 						 *
+*   specific prior written permission of WIDE Project and 						 *
+*   NICT.												 *
+* 													 *
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED *
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
+* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR *
+* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 	 *
+* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 	 *
+* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR *
+* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF   *
+* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.								 *
+*********************************************************************************************************/
+#include "rgw_common.h"
+
+/* The content of this file was semi-automatically generated from the IANA registry. */
+
+/*  Name of RADIUS attribute from its code */
+const char * rgw_msg_attrtype_str(unsigned char c) {
+		/* 1         User-Name                                 */
+	if ( c == 1) return "User-Name ";
+		/* 2         User-Password                             */
+	if ( c == 2) return "User-Password ";
+		/* 3         CHAP-Password                             */
+	if ( c == 3) return "CHAP-Password ";
+		/* 4         NAS-IP-Address                            */
+	if ( c == 4) return "NAS-IP-Address ";
+		/* 5         NAS-Port                                  */
+	if ( c == 5) return "NAS-Port ";
+		/* 6         Service-Type                              */
+	if ( c == 6) return "Service-Type ";
+		/* 7         Framed-Protocol                           */
+	if ( c == 7) return "Framed-Protocol ";
+		/* 8         Framed-IP-Address                         */
+	if ( c == 8) return "Framed-IP-Address ";
+		/* 9         Framed-IP-Netmask                         */
+	if ( c == 9) return "Framed-IP-Netmask ";
+		/* 10        Framed-Routing                            */
+	if ( c == 10) return "Framed-Routing ";
+		/* 11        Filter-Id                                 */
+	if ( c == 11) return "Filter-Id ";
+		/* 12        Framed-MTU                                */
+	if ( c == 12) return "Framed-MTU ";
+		/* 13        Framed-Compression                        */
+	if ( c == 13) return "Framed-Compression ";
+		/* 14        Login-IP-Host                             */
+	if ( c == 14) return "Login-IP-Host ";
+		/* 15        Login-Service                             */
+	if ( c == 15) return "Login-Service ";
+		/* 16        Login-TCP-Port                            */
+	if ( c == 16) return "Login-TCP-Port ";
+		/* 17        Unassigned */
+	if ( c == 17) return "Unassigned ";
+		/* 18        Reply-Message                             */
+	if ( c == 18) return "Reply-Message ";
+		/* 19        Callback-Number                           */
+	if ( c == 19) return "Callback-Number ";
+		/* 20        Callback-Id                               */
+	if ( c == 20) return "Callback-Id ";
+		/* 21        Unassigned */
+	if ( c == 21) return "Unassigned ";
+		/* 22        Framed-Route                              */
+	if ( c == 22) return "Framed-Route ";
+		/* 23        Framed-IPX-Network                        */
+	if ( c == 23) return "Framed-IPX-Network ";
+		/* 24        State                                     */
+	if ( c == 24) return "State ";
+		/* 25        Class                                     */
+	if ( c == 25) return "Class ";
+		/* 26        Vendor-Specific                           */
+	if ( c == 26) return "Vendor-Specific ";
+		/* 27        Session-Timeout                           */
+	if ( c == 27) return "Session-Timeout ";
+		/* 28        Idle-Timeout                              */
+	if ( c == 28) return "Idle-Timeout ";
+		/* 29        Termination-Action                        */
+	if ( c == 29) return "Termination-Action ";
+		/* 30        Called-Station-Id                         */
+	if ( c == 30) return "Called-Station-Id ";
+		/* 31        Calling-Station-Id                        */
+	if ( c == 31) return "Calling-Station-Id ";
+		/* 32        NAS-Identifier                            */
+	if ( c == 32) return "NAS-Identifier ";
+		/* 33        Proxy-State                               */
+	if ( c == 33) return "Proxy-State ";
+		/* 34        Login-LAT-Service                         */
+	if ( c == 34) return "Login-LAT-Service ";
+		/* 35        Login-LAT-Node                            */
+	if ( c == 35) return "Login-LAT-Node ";
+		/* 36        Login-LAT-Group                           */
+	if ( c == 36) return "Login-LAT-Group ";
+		/* 37        Framed-AppleTalk-Link                     */
+	if ( c == 37) return "Framed-AppleTalk-Link ";
+		/* 38        Framed-AppleTalk-Network                  */
+	if ( c == 38) return "Framed-AppleTalk-Network ";
+		/* 39        Framed-AppleTalk-Zone                     */
+	if ( c == 39) return "Framed-AppleTalk-Zone ";
+		/* 40        Acct-Status-Type                         [RFC2866] */
+	if ( c == 40) return "Acct-Status-Type [RFC2866]";
+		/* 41        Acct-Delay-Time                          [RFC2866] */
+	if ( c == 41) return "Acct-Delay-Time [RFC2866]";
+		/* 42        Acct-Input-Octets                        [RFC2866] */
+	if ( c == 42) return "Acct-Input-Octets [RFC2866]";
+		/* 43        Acct-Output-Octets                       [RFC2866] */
+	if ( c == 43) return "Acct-Output-Octets [RFC2866]";
+		/* 44        Acct-Session-Id                          [RFC2866] */
+	if ( c == 44) return "Acct-Session-Id [RFC2866]";
+		/* 45        Acct-Authentic                           [RFC2866] */
+	if ( c == 45) return "Acct-Authentic [RFC2866]";
+		/* 46        Acct-Session-Time                        [RFC2866] */
+	if ( c == 46) return "Acct-Session-Time [RFC2866]";
+		/* 47        Acct-Input-Packets                       [RFC2866] */
+	if ( c == 47) return "Acct-Input-Packets [RFC2866]";
+		/* 48        Acct-Output-Packets                      [RFC2866] */
+	if ( c == 48) return "Acct-Output-Packets [RFC2866]";
+		/* 49        Acct-Terminate-Cause                     [RFC2866] */
+	if ( c == 49) return "Acct-Terminate-Cause [RFC2866]";
+		/* 50        Acct-Multi-Session-Id                    [RFC2866] */
+	if ( c == 50) return "Acct-Multi-Session-Id [RFC2866]";
+		/* 51        Acct-Link-Count                          [RFC2866] */
+	if ( c == 51) return "Acct-Link-Count [RFC2866]";
+		/* 52        Acct-Input-Gigawords                     [RFC2869] */
+	if ( c == 52) return "Acct-Input-Gigawords [RFC2869]";
+		/* 53        Acct-Output-Gigawords                    [RFC2869] */
+	if ( c == 53) return "Acct-Output-Gigawords [RFC2869]";
+		/* 54        Unassigned */
+	if ( c == 54) return "Unassigned ";
+		/* 55        Event-Timestamp                          [RFC2869] */
+	if ( c == 55) return "Event-Timestamp [RFC2869]";
+		/* 56        Egress-VLANID                            [RFC4675] */
+	if ( c == 56) return "Egress-VLANID [RFC4675]";
+		/* 57        Ingress-Filters                          [RFC4675] */
+	if ( c == 57) return "Ingress-Filters [RFC4675]";
+		/* 58        Egress-VLAN-Name                         [RFC4675] */
+	if ( c == 58) return "Egress-VLAN-Name [RFC4675]";
+		/* 59        User-Priority-Table                      [RFC4675] */
+	if ( c == 59) return "User-Priority-Table [RFC4675]";
+		/* 60        CHAP-Challenge */
+	if ( c == 60) return "CHAP-Challenge ";
+		/* 61        NAS-Port-Type */
+	if ( c == 61) return "NAS-Port-Type ";
+		/* 62        Port-Limit */
+	if ( c == 62) return "Port-Limit ";
+		/* 63        Login-LAT-Port */
+	if ( c == 63) return "Login-LAT-Port ";
+		/* 64        Tunnel-Type                              [RFC2868] */
+	if ( c == 64) return "Tunnel-Type [RFC2868]";
+		/* 65        Tunnel-Medium-Type                       [RFC2868] */
+	if ( c == 65) return "Tunnel-Medium-Type [RFC2868]";
+		/* 66        Tunnel-Client-Endpoint                   [RFC2868] */
+	if ( c == 66) return "Tunnel-Client-Endpoint [RFC2868]";
+		/* 67        Tunnel-Server-Endpoint                   [RFC2868] */
+	if ( c == 67) return "Tunnel-Server-Endpoint [RFC2868]";
+		/* 68        Acct-Tunnel-Connection                   [RFC2867] */
+	if ( c == 68) return "Acct-Tunnel-Connection [RFC2867]";
+		/* 69        Tunnel-Password                          [RFC2868] */
+	if ( c == 69) return "Tunnel-Password [RFC2868]";
+		/* 70        ARAP-Password                            [RFC2869] */
+	if ( c == 70) return "ARAP-Password [RFC2869]";
+		/* 71        ARAP-Features                            [RFC2869] */
+	if ( c == 71) return "ARAP-Features [RFC2869]";
+		/* 72        ARAP-Zone-Access                         [RFC2869] */
+	if ( c == 72) return "ARAP-Zone-Access [RFC2869]";
+		/* 73        ARAP-Security                            [RFC2869] */
+	if ( c == 73) return "ARAP-Security [RFC2869]";
+		/* 74        ARAP-Security-Data                       [RFC2869] */
+	if ( c == 74) return "ARAP-Security-Data [RFC2869]";
+		/* 75        Password-Retry                           [RFC2869] */
+	if ( c == 75) return "Password-Retry [RFC2869]";
+		/* 76        Prompt                                   [RFC2869] */
+	if ( c == 76) return "Prompt [RFC2869]";
+		/* 77        Connect-Info                             [RFC2869] */
+	if ( c == 77) return "Connect-Info [RFC2869]";
+		/* 78        Configuration-Token                      [RFC2869] */
+	if ( c == 78) return "Configuration-Token [RFC2869]";
+		/* 79        EAP-Message                              [RFC2869] */
+	if ( c == 79) return "EAP-Message [RFC2869]";
+		/* 80        Message-Authenticator                    [RFC2869] */
+	if ( c == 80) return "Message-Authenticator [RFC2869]";
+		/* 81        Tunnel-Private-Group-ID                  [RFC2868] */
+	if ( c == 81) return "Tunnel-Private-Group-ID [RFC2868]";
+		/* 82        Tunnel-Assignment-ID                     [RFC2868] */
+	if ( c == 82) return "Tunnel-Assignment-ID [RFC2868]";
+		/* 83        Tunnel-Preference                        [RFC2868] */
+	if ( c == 83) return "Tunnel-Preference [RFC2868]";
+		/* 84        ARAP-Challenge-Response                  [RFC2869] */
+	if ( c == 84) return "ARAP-Challenge-Response [RFC2869]";
+		/* 85        Acct-Interim-Interval                    [RFC2869] */
+	if ( c == 85) return "Acct-Interim-Interval [RFC2869]";
+		/* 86        Acct-Tunnel-Packets-Lost                 [RFC2867] */
+	if ( c == 86) return "Acct-Tunnel-Packets-Lost [RFC2867]";
+		/* 87        NAS-Port-Id                              [RFC2869] */
+	if ( c == 87) return "NAS-Port-Id [RFC2869]";
+		/* 88        Framed-Pool                              [RFC2869] */
+	if ( c == 88) return "Framed-Pool [RFC2869]";
+		/* 89        CUI                                      [RFC4372] */
+	if ( c == 89) return "CUI [RFC4372]";
+		/* 90        Tunnel-Client-Auth-ID                    [RFC2868] */
+	if ( c == 90) return "Tunnel-Client-Auth-ID [RFC2868]";
+		/* 91        Tunnel-Server-Auth-ID                    [RFC2868] */
+	if ( c == 91) return "Tunnel-Server-Auth-ID [RFC2868]";
+		/* 92        NAS-Filter-Rule                          [RFC4849] */
+	if ( c == 92) return "NAS-Filter-Rule [RFC4849]";
+		/* 93        Unassigned */
+	if ( c == 93) return "Unassigned ";
+		/* 94        Originating-Line-Info                    [RFC4005] */
+	if ( c == 94) return "Originating-Line-Info [RFC4005]";
+		/* 95        NAS-IPv6-Address                         [RFC3162] */
+	if ( c == 95) return "NAS-IPv6-Address [RFC3162]";
+		/* 96        Framed-Interface-Id                      [RFC3162] */
+	if ( c == 96) return "Framed-Interface-Id [RFC3162]";
+		/* 97        Framed-IPv6-Prefix                       [RFC3162] */
+	if ( c == 97) return "Framed-IPv6-Prefix [RFC3162]";
+		/* 98        Login-IPv6-Host                          [RFC3162] */
+	if ( c == 98) return "Login-IPv6-Host [RFC3162]";
+		/* 99        Framed-IPv6-Route                        [RFC3162] */
+	if ( c == 99) return "Framed-IPv6-Route [RFC3162]";
+		/* 100       Framed-IPv6-Pool                         [RFC3162] */
+	if ( c == 100) return "Framed-IPv6-Pool [RFC3162]";
+		/* 101       Error-Cause Attribute                    [RFC3576] */
+	if ( c == 101) return "Error-Cause Attribute[RFC3576]";
+		/* 102       EAP-Key-Name                             [RFC4072] */
+	if ( c == 102) return "EAP-Key-Name [RFC4072]";
+		/* 103       Digest-Response                          [RFC5090] */
+	if ( c == 103) return "Digest-Response [RFC5090]";
+		/* 104       Digest-Realm                             [RFC5090] */
+	if ( c == 104) return "Digest-Realm [RFC5090]";
+		/* 105       Digest-Nonce                             [RFC5090]   */
+	if ( c == 105) return "Digest-Nonce [RFC5090]";
+		/* 106       Digest-Response-Auth                     [RFC5090] */
+	if ( c == 106) return "Digest-Response-Auth [RFC5090]";
+		/* 107       Digest-Nextnonce                         [RFC5090] */
+	if ( c == 107) return "Digest-Nextnonce [RFC5090]";
+		/* 108       Digest-Method                            [RFC5090] */
+	if ( c == 108) return "Digest-Method [RFC5090]";
+		/* 109       Digest-URI                               [RFC5090]  */
+	if ( c == 109) return "Digest-URI [RFC5090]";
+		/* 110       Digest-Qop                               [RFC5090]  */
+	if ( c == 110) return "Digest-Qop [RFC5090]";
+		/* 111       Digest-Algorithm                         [RFC5090]  */
+	if ( c == 111) return "Digest-Algorithm [RFC5090]";
+		/* 112       Digest-Entity-Body-Hash                  [RFC5090]  */
+	if ( c == 112) return "Digest-Entity-Body-Hash [RFC5090]";
+		/* 113       Digest-CNonce                            [RFC5090]  */
+	if ( c == 113) return "Digest-CNonce [RFC5090]";
+		/* 114       Digest-Nonce-Count                       [RFC5090]  */
+	if ( c == 114) return "Digest-Nonce-Count [RFC5090]";
+		/* 115       Digest-Username                          [RFC5090]  */
+	if ( c == 115) return "Digest-Username [RFC5090]";
+		/* 116       Digest-Opaque                            [RFC5090]  */
+	if ( c == 116) return "Digest-Opaque [RFC5090]";
+		/* 117       Digest-Auth-Param                        [RFC5090]  */
+	if ( c == 117) return "Digest-Auth-Param [RFC5090]";
+		/* 118       Digest-AKA-Auts                          [RFC5090]  */
+	if ( c == 118) return "Digest-AKA-Auts [RFC5090]";
+		/* 119       Digest-Domain                            [RFC5090]  */
+	if ( c == 119) return "Digest-Domain [RFC5090]";
+		/* 120       Digest-Stale                             [RFC5090]  */
+	if ( c == 120) return "Digest-Stale [RFC5090]";
+		/* 121       Digest-HA1                               [RFC5090]  */
+	if ( c == 121) return "Digest-HA1 [RFC5090]";
+		/* 122       SIP-AOR                                  [RFC5090]  */
+	if ( c == 122) return "SIP-AOR [RFC5090]";
+		/* 123       Delegated-IPv6-Prefix                    [RFC4818] */
+	if ( c == 123) return "Delegated-IPv6-Prefix [RFC4818]";
+		/* 124       MIP6-Feature-Vector                      [RFC5447] */
+	if ( c == 124) return "MIP6-Feature-Vector [RFC5447]";
+		/* 125       MIP6-Home-Link-Prefix                    [RFC5447] */
+	if ( c == 125) return "MIP6-Home-Link-Prefix [RFC5447]";
+		/* 126-191   Unassigned */
+	if ((c >= 126) && (c <= 191)) return "Unassigned ";
+		/* 192-223   Experimental Use                         [RFC3575] */
+	if ((c >= 192) && (c <= 223)) return "Experimental Use[RFC3575]";
+		/* 224-240   Implementation Specific                  [RFC3575] */
+	if ((c >= 224) && (c <= 240)) return "Implementation Specific[RFC3575]";
+		/* 241-255   Reserved                                 [RFC3575]    */
+	if ((c >= 241)) return "Reserved [RFC3575]";
+	/* fallback */ return "[Unknown]";
+}
diff --git a/extensions/app_radgw/rgw_msg_codes.c b/extensions/app_radgw/rgw_msg_codes.c
new file mode 100644
index 0000000..19b3e72
--- /dev/null
+++ b/extensions/app_radgw/rgw_msg_codes.c
@@ -0,0 +1,120 @@
+/*********************************************************************************************************
+* Software License Agreement (BSD License)                                                               *
+* Author: Sebastien Decugis <sdecugis@freediameter.net>							 *
+*													 *
+* Copyright (c) 2011, WIDE Project and NICT								 *
+* All rights reserved.											 *
+* 													 *
+* Redistribution and use of this software in source and binary forms, with or without modification, are  *
+* permitted provided that the following conditions are met:						 *
+* 													 *
+* * Redistributions of source code must retain the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer.										 *
+*    													 *
+* * Redistributions in binary form must reproduce the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer in the documentation and/or other						 *
+*   materials provided with the distribution.								 *
+* 													 *
+* * Neither the name of the WIDE Project or NICT nor the 						 *
+*   names of its contributors may be used to endorse or 						 *
+*   promote products derived from this software without 						 *
+*   specific prior written permission of WIDE Project and 						 *
+*   NICT.												 *
+* 													 *
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED *
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
+* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR *
+* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 	 *
+* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 	 *
+* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR *
+* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF   *
+* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.								 *
+*********************************************************************************************************/
+#include "rgw_common.h"
+
+/* The content of this file was semi-automatically generated from the IANA registry. */
+
+/*  Name of RADIUS command from its command code */
+const char * rgw_msg_code_str(unsigned char c) {
+		/* 1        Access-Request                           [RFC2865] */
+	if ( c == 1) return "Access-Request [RFC2865]";
+		/* 2        Access-Accept                            [RFC2865] */
+	if ( c == 2) return "Access-Accept [RFC2865]";
+		/* 3        Access-Reject                            [RFC2865] */
+	if ( c == 3) return "Access-Reject [RFC2865]";
+		/* 4        Accounting-Request                       [RFC2865] */
+	if ( c == 4) return "Accounting-Request [RFC2865]";
+		/* 5        Accounting-Response                      [RFC2865] */
+	if ( c == 5) return "Accounting-Response [RFC2865]";
+		/* 6        Accounting-Status                        [RFC3575] */
+	if ( c == 6) return "Accounting-Status [RFC3575]";
+		/* 7        Password-Request                         [RFC3575] */
+	if ( c == 7) return "Password-Request [RFC3575]";
+		/* 8        Password-Ack                             [RFC3575] */
+	if ( c == 8) return "Password-Ack [RFC3575]";
+		/* 9        Password-Reject                          [RFC3575] */
+	if ( c == 9) return "Password-Reject [RFC3575]";
+		/* 10       Accounting-Message                       [RFC3575] */
+	if ( c == 10) return "Accounting-Message [RFC3575]";
+		/* 11       Access-Challenge                         [RFC2865] */
+	if ( c == 11) return "Access-Challenge [RFC2865]";
+		/* 12       Status-Server (experimental)             [RFC2865] */
+	if ( c == 12) return "Status-Server (experimental)[RFC2865]";
+		/* 13       Status-Client (experimental)             [RFC2865] */
+	if ( c == 13) return "Status-Client (experimental)[RFC2865]";
+		/* 21       Resource-Free-Request                    [RFC3575] */
+	if ( c == 21) return "Resource-Free-Request [RFC3575]";
+		/* 22       Resource-Free-Response                   [RFC3575] */
+	if ( c == 22) return "Resource-Free-Response [RFC3575]";
+		/* 23       Resource-Query-Request                   [RFC3575] */
+	if ( c == 23) return "Resource-Query-Request [RFC3575]";
+		/* 24       Resource-Query-Response                  [RFC3575] */
+	if ( c == 24) return "Resource-Query-Response [RFC3575]";
+		/* 25       Alternate-Resource-Reclaim-Request       [RFC3575] */
+	if ( c == 25) return "Alternate-Resource-Reclaim-Request [RFC3575]";
+		/* 26       NAS-Reboot-Request                       [RFC3575] */
+	if ( c == 26) return "NAS-Reboot-Request [RFC3575]";
+		/* 27       NAS-Reboot-Response                      [RFC3575] */
+	if ( c == 27) return "NAS-Reboot-Response [RFC3575]";
+		/* 28       Reserved */
+	if ( c == 28) return "Reserved ";
+		/* 29       Next-Passcode                            [RFC3575] */
+	if ( c == 29) return "Next-Passcode [RFC3575]";
+		/* 30       New-Pin                                  [RFC3575] */
+	if ( c == 30) return "New-Pin [RFC3575]";
+		/* 31       Terminate-Session                        [RFC3575] */
+	if ( c == 31) return "Terminate-Session [RFC3575]";
+		/* 32       Password-Expired                         [RFC3575] */
+	if ( c == 32) return "Password-Expired [RFC3575]";
+		/* 33       Event-Request                            [RFC3575] */
+	if ( c == 33) return "Event-Request [RFC3575]";
+		/* 34       Event-Response                           [RFC3575] */
+	if ( c == 34) return "Event-Response [RFC3575]";
+		/* 40       Disconnect-Request                       [RFC3575][RFC5176] */
+	if ( c == 40) return "Disconnect-Request [RFC3575][RFC5176]";
+		/* 41       Disconnect-ACK                           [RFC3575][RFC5176] */
+	if ( c == 41) return "Disconnect-ACK [RFC3575][RFC5176]";
+		/* 42       Disconnect-NAK                           [RFC3575][RFC5176] */
+	if ( c == 42) return "Disconnect-NAK [RFC3575][RFC5176]";
+		/* 43       CoA-Request                              [RFC3575][RFC5176] */
+	if ( c == 43) return "CoA-Request [RFC3575][RFC5176]";
+		/* 44       CoA-ACK                                  [RFC3575][RFC5176] */
+	if ( c == 44) return "CoA-ACK [RFC3575][RFC5176]";
+		/* 45       CoA-NAK                                  [RFC3575][RFC5176] */
+	if ( c == 45) return "CoA-NAK [RFC3575][RFC5176]";
+		/* 50       IP-Address-Allocate                      [RFC3575] */
+	if ( c == 50) return "IP-Address-Allocate [RFC3575]";
+		/* 51       IP-Address-Release                       [RFC3575] */
+	if ( c == 51) return "IP-Address-Release [RFC3575]";
+		/* 52-249   Unassigned */
+	if ((c >= 52) && (c <= 249)) return "Unassigned ";
+		/* 250-253  Experimental Use                         [RFC3575] */
+	if ((c >= 250) && (c <= 253)) return "Experimental Use[RFC3575]";
+		/* 254      Reserved                                 [RFC3575] */
+	if ( c == 254) return "Reserved [RFC3575]";
+		/* 255      Reserved                                 [RFC3575] */
+	if ( c == 255) return "Reserved [RFC3575]";
+	/* fallback */ return "[Unknown]";
+}
diff --git a/extensions/app_radgw/rgw_plugins.c b/extensions/app_radgw/rgw_plugins.c
new file mode 100644
index 0000000..3bd4526
--- /dev/null
+++ b/extensions/app_radgw/rgw_plugins.c
@@ -0,0 +1,491 @@
+/*********************************************************************************************************
+* Software License Agreement (BSD License)                                                               *
+* Author: Sebastien Decugis <sdecugis@freediameter.net>							 *
+*													 *
+* Copyright (c) 2013, WIDE Project and NICT								 *
+* All rights reserved.											 *
+* 													 *
+* Redistribution and use of this software in source and binary forms, with or without modification, are  *
+* permitted provided that the following conditions are met:						 *
+* 													 *
+* * Redistributions of source code must retain the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer.										 *
+*    													 *
+* * Redistributions in binary form must reproduce the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer in the documentation and/or other						 *
+*   materials provided with the distribution.								 *
+* 													 *
+* * Neither the name of the WIDE Project or NICT nor the 						 *
+*   names of its contributors may be used to endorse or 						 *
+*   promote products derived from this software without 						 *
+*   specific prior written permission of WIDE Project and 						 *
+*   NICT.												 *
+* 													 *
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED *
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
+* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR *
+* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 	 *
+* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 	 *
+* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR *
+* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF   *
+* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.								 *
+*********************************************************************************************************/
+
+/* Manage the list of plugins that provide handlers for RADIUS messages and attributes */
+
+#include "rgw.h"
+#include <dlfcn.h>
+#include <libgen.h>
+
+/* List of plugins, in the order they appear in the configuration file. */
+static struct fd_list plg_list = FD_LIST_INITIALIZER(plg_list);
+
+/* A plugin entry */
+struct plg_descr {
+	struct fd_list		 chain; 	/* chaining in plg_list */
+	
+	void 			*dlo;		/* pointer returned by dlopen for the extension, to use with dlclose later */
+	struct rgw_api		*descriptor;	/* Points to the resolved plugin's rgwp_descriptor */
+	struct rgwp_config 	*cs;		/* the (private) state returned by rgwp_conf_parse */
+	
+	int			 type;		/* this extension is called for messages received on this(these) server port(s) only */
+	unsigned char 		*cc;		/* array of command codes, or NULL for all cc */
+	size_t			 cc_len; 	/* size of the previous array */
+};
+
+/* Accelerators for each command code (one for each port). These accelerators are built on-demand, as a cache, after start_cache function has been called.  */
+static struct fd_list plg_accel_auth = FD_LIST_INITIALIZER(plg_accel_auth);
+static struct fd_list plg_accel_acct = FD_LIST_INITIALIZER(plg_accel_acct);
+
+/* Accelerator list item, one per command code value (only the ones actually used) */
+struct plg_accel {
+	struct fd_list		chain;	/* link in the plg_accel_* list. List ordered by ccode. */
+	unsigned char		ccode;	/* the command code for this accelerator. We don't handle extended CC yet */
+	struct fd_list		plugins;/* head for the list of plg_accel_item, corresponding to the extensions to be called for this command code. */
+};
+
+/* Accelerator item */
+struct plg_accel_item {
+	struct fd_list		chain; 	/* link in the plg_accel "plugins" list */
+	struct plg_descr *	plg;	/* pointer to the plugin */
+	/* Note: we can further optimize by caching the location of plg->descriptor->rgwp_rad_req etc... at this level. */
+};
+
+/* RWlock to protect all the previous lists */
+static pthread_rwlock_t plg_lock = PTHREAD_RWLOCK_INITIALIZER;
+
+/* Has start_cache been called? */
+static int cache_started = 0;
+
+
+/* The read lock must be held before calling this function */
+static int get_accelerator(struct fd_list ** list, unsigned char ccode, int type)
+{
+	struct fd_list *refer, *search;
+	struct plg_accel * accel = NULL;
+	struct plg_accel_item * item = NULL;
+	int upgraded = 0;
+	
+	TRACE_ENTRY("%p %hhu %i", list, ccode, type);
+	
+	CHECK_PARAMS( cache_started && list && ((type == RGW_PLG_TYPE_AUTH) || (type == RGW_PLG_TYPE_ACCT)) );
+	
+	if (type == RGW_PLG_TYPE_AUTH)
+		refer = &plg_accel_auth;
+	else
+		refer = &plg_accel_acct;
+restart:	
+	/* Check if we have already an accelerator for this ccode */
+	for (search = refer->next; search != refer; search = search->next) {
+		struct plg_accel * loc = (struct plg_accel *)search;
+		
+		if (loc->ccode < ccode)
+			continue;
+		
+		if (loc->ccode > ccode)
+			break; /* we don't have an accelerator for this value yet */
+		
+		/* We found the matching accelerator, just return this list */
+		*list = &loc->plugins;
+		return 0;
+	}
+	
+	/* We must create the accelerator list, then save it just before "search" */
+	
+	/* First , upgrade the lock to write lock, and restart the search. This is the only robust solution to avoid deadlocks */
+	if (! upgraded) {
+		CHECK_POSIX( pthread_rwlock_unlock(&plg_lock) );
+		CHECK_POSIX( pthread_rwlock_wrlock(&plg_lock) );
+		upgraded = 1;
+		goto restart;
+	}
+	
+	/* Now create the new element */
+	CHECK_MALLOC( accel = malloc(sizeof(struct plg_accel)) );
+	memset(accel, 0, sizeof(struct plg_accel) );
+	fd_list_init(&accel->chain, NULL);
+	fd_list_init(&accel->plugins, accel);
+	accel->ccode = ccode;
+	
+	/* Check each extension from the global list for this port and ccode */
+	for (refer = plg_list.next; refer != &plg_list; refer = refer->next) {
+		struct plg_descr * loc = (struct plg_descr *)refer;
+		
+		/* Skip if this extension is not registered for this port */
+		if (! (loc->type & type) )
+			continue;
+		
+		/* Check if the ccode is there */
+		if (loc->cc) {
+			int i;
+			int match = 0;
+			for (i=0; i< loc->cc_len; i++) {
+				if (loc->cc[i] < ccode)
+					continue;
+				if (loc->cc[i] == ccode)
+					match = 1;
+				break;
+			}
+			if (!match)
+				continue;
+		}
+		
+		/* Ok, this extension must be called for this port / ccode, add to the accelerator */
+		CHECK_MALLOC( item = malloc(sizeof(struct plg_accel_item)) );
+		memset(item, 0, sizeof(struct plg_accel_item));
+		fd_list_init(&item->chain, NULL);
+		item->plg = loc;
+		/* Add as last element of the accelerator */
+		fd_list_insert_before(&accel->plugins, &item->chain);
+	}
+	
+	/* Now, save this accelerator entry in the global list */
+	fd_list_insert_before(search, &accel->chain);
+	*list = &accel->plugins;
+	
+	return 0;
+}
+
+
+int rgw_plg_add( char * plgfile, char * conffile, int type, unsigned char ** codes_array, size_t codes_sz )
+{
+	struct plg_descr * new;
+	
+	TRACE_ENTRY("%p %p %d %p %zi", plgfile, conffile, type, codes_array, codes_sz);
+	
+	CHECK_PARAMS( plgfile && type && codes_array && (cache_started == 0) );
+	
+	CHECK_MALLOC( new = malloc(sizeof(struct plg_descr)) );
+	memset(new, 0, sizeof(struct plg_descr));
+	
+	fd_list_init(&new->chain, new);
+	
+	/* Try and load the plugin */
+	TRACE_DEBUG(FULL, "Loading plugin: %s", plgfile);
+	new->dlo = dlopen(plgfile, RTLD_NOW | RTLD_GLOBAL);
+	if (new->dlo == NULL) {
+		/* An error occured */
+		fd_log_debug("Loading of plugin '%s' failed: %s", plgfile, dlerror());
+		goto error;
+	}
+	
+	/* Resolve the descriptor */
+	new->descriptor = dlsym( new->dlo, "rgwp_descriptor" );
+	if (new->descriptor == NULL) {
+		/* An error occured */
+		fd_log_debug("Unable to resolve 'rgwp_descriptor' in plugin '%s': %s", plgfile, dlerror());
+		goto error;
+	}
+	
+	TRACE_DEBUG(FULL, "Plugin '%s' found in file '%s'", new->descriptor->rgwp_name, plgfile);
+	
+	/* Now parse the configuration file, this will initialize all plugin states and store it in the "cs" pointer (the plugin must be re-entrant, so no global state) */
+	if (new->descriptor->rgwp_conf_parse) {
+		CHECK_FCT_DO( (*(new->descriptor->rgwp_conf_parse))(conffile, &new->cs), 
+			{
+				fd_log_debug("An error occurred while parsing configuration file '%s' in plugin '%s', aborting...", conffile, plgfile);
+				goto error;
+			} );
+	}
+	
+	/* Now sort the array (very simple algorithm, but this list is usually small) of command codes and save */
+	if (*codes_array && codes_sz) {
+		int i;
+		
+		new->cc = *codes_array;
+		*codes_array = NULL;
+		
+		for (i = 0; i < codes_sz - 1; i++) {
+			int j, idx = i, min = new->cc[i];
+			
+			/* find the smallest remaining element */
+			for (j = i + 1; j < codes_sz; j++) {
+				if (min > new->cc[j]) {
+					min = new->cc[j];
+					idx = j;
+				}
+			}
+			
+			/* swap if needed */
+			if (idx != i) {
+				int tmp = new->cc[i];
+				new->cc[i] = new->cc[idx];
+				new->cc[idx] = tmp;
+			}
+		}
+		new->cc_len = codes_sz;
+	}
+		
+	new->type = type;
+	
+	/* And save this new extension in the list. We don't need to lock at this point because we are single threaded. */
+	fd_list_insert_before(&plg_list, &new->chain);
+	
+	return 0;
+	
+	
+error:
+	if (new && new->dlo)
+		dlclose(new->dlo);
+	if (new)
+		free(new);	
+	return EINVAL;
+}
+
+void rgw_plg_dump(void)
+{
+	struct plg_descr * plg;
+	struct fd_list * ptr, *ptraccel;
+	
+	if ( ! TRACE_BOOL(FULL) )
+		return;
+	
+	CHECK_POSIX_DO( pthread_rwlock_rdlock(&plg_lock), );
+	
+	if ( ! FD_IS_LIST_EMPTY( &plg_list ) )
+		fd_log_debug("[app_radgw]  --- List of registered plugins:");
+	for (ptr = plg_list.next; ptr != &plg_list; ptr = ptr->next) {
+		char buf[1024];
+		plg = (struct plg_descr *)ptr;
+		
+		snprintf(buf, sizeof(buf), "  %-25s ( %p ) - types: %s%s, codes: ", 
+			 plg->descriptor->rgwp_name, 
+			 plg->cs,
+			 plg->type & RGW_PLG_TYPE_AUTH ? "Au" : "  ",
+			 plg->type & RGW_PLG_TYPE_ACCT ? "Ac" : "  ");
+		
+		if (plg->cc) {
+			int i;
+			
+			for (i = 0; i < plg->cc_len; i++) {
+				snprintf(buf+strlen(buf), sizeof(buf)-strlen(buf), "%02hhx ", plg->cc[i]);
+			}
+			fd_log_debug("%s", buf);
+		} else {
+			fd_log_debug("%s*", buf);
+		}
+	}
+	
+	CHECK_POSIX_DO( pthread_rwlock_unlock(&plg_lock), );
+	
+	/* Dump the list of accelerators */
+	if ( ! TRACE_BOOL(FULL + 1) )
+		return;
+	
+	CHECK_POSIX_DO( pthread_rwlock_rdlock(&plg_lock), );
+	if ( !FD_IS_LIST_EMPTY( &plg_accel_auth ) || !FD_IS_LIST_EMPTY( &plg_accel_acct ))
+		fd_log_debug("  --- Accelerators:");
+	
+	for (ptraccel = plg_accel_auth.next; ptraccel != &plg_accel_auth; ptraccel = ptraccel->next) {
+		struct plg_accel * accel = (struct plg_accel *)ptraccel;
+		fd_log_debug("  auth, code %02hhu:", accel->ccode);
+
+		for (ptr = accel->plugins.next; ptr != &accel->plugins; ptr = ptr->next) {
+			struct plg_accel_item * item = (struct plg_accel_item *)ptr;
+			fd_log_debug("     %-15s (%p)", item->plg->descriptor->rgwp_name, item->plg->cs);
+		}
+	}
+	for (ptraccel = plg_accel_acct.next; ptraccel != &plg_accel_acct; ptraccel = ptraccel->next) {
+		struct plg_accel * accel = (struct plg_accel *)ptraccel;
+		fd_log_debug("  acct, code %02hhu:", accel->ccode);
+
+		for (ptr = accel->plugins.next; ptr != &accel->plugins; ptr = ptr->next) {
+			struct plg_accel_item * item = (struct plg_accel_item *)ptr;
+			fd_log_debug("     %-15s (%p)", item->plg->descriptor->rgwp_name, item->plg->cs);
+		}
+	}
+	
+	
+	CHECK_POSIX_DO( pthread_rwlock_unlock(&plg_lock), );
+	
+}
+
+void rgw_plg_start_cache(void)
+{
+	cache_started++;
+}
+
+int rgw_plg_loop_req(struct rgw_radius_msg_meta **rad, struct msg **diam_msg, struct rgw_client * cli)
+{
+	int ret = 0;
+	struct fd_list * head = NULL, *li;
+	struct radius_msg * rad_ans = NULL;
+	
+	TRACE_ENTRY("%p %p %p", rad, diam_msg, cli);
+	CHECK_PARAMS( rad && *rad && diam_msg && *diam_msg && cli);
+	
+	/* First, get the list of extensions for this message */
+	CHECK_POSIX( pthread_rwlock_rdlock( &plg_lock) );
+	CHECK_FCT_DO( ret = get_accelerator(&head, (*rad)->radius.hdr->code, (*rad)->serv_type), 
+		{ CHECK_POSIX( pthread_rwlock_unlock( &plg_lock) ); return ret; } );
+	
+	/* Loop in the list of extensions */
+	for (li = head->next; li != head; li = li->next) {
+		struct plg_descr * plg = ((struct plg_accel_item *) li)->plg;
+		
+		if (plg->descriptor->rgwp_rad_req) {
+			TRACE_DEBUG(ANNOYING, "Calling next plugin: %s", plg->descriptor->rgwp_name);
+			ret = (*plg->descriptor->rgwp_rad_req)(plg->cs, &(*rad)->radius, &rad_ans, diam_msg, cli);
+			if (ret)
+				break;
+		} else {
+			TRACE_DEBUG(ANNOYING, "Skipping extension '%s' (NULL callback)", plg->descriptor->rgwp_name);
+		}					
+	}
+	
+	CHECK_POSIX( pthread_rwlock_unlock( &plg_lock) );
+	
+	/* If no error encountered, we're done here */
+	if (ret == 0)
+		return 0;
+	
+	/* Destroy the Diameter temp message, if any */
+	if (*diam_msg) {
+		CHECK_FCT_DO( fd_msg_free(*diam_msg), );
+		*diam_msg = NULL;
+	}
+	
+	/* Send the radius message back if required */
+	if ((ret == -2) && rad_ans && rad) {
+		CHECK_FCT_DO( rgw_client_finish_send(&rad_ans, *rad, cli), /* It failed, it can't be helped... */);
+	}
+	
+	if (ret > 0) {
+		/* Critical error, log and exit */
+		TRACE_DEBUG(NONE, "An error occurred while handling a RADIUS message from '%s': %s", rgw_clients_id(cli), strerror(ret));
+		return ret;
+	}
+	
+	/* Now, discard the message and return */
+	rgw_msg_free(rad);
+	return 0;
+}
+
+/* Loop in the extension list (same as req) to convert data from diam_ans to rad_ans */
+int rgw_plg_loop_ans(struct rgw_radius_msg_meta *req, struct msg **diam_ans, struct radius_msg ** rad_ans, struct rgw_client * cli)
+{
+	int ret = 0;
+	struct fd_list * head = NULL, *li;
+	
+	TRACE_ENTRY("%p %p %p %p", req, diam_ans, rad_ans, cli);
+	CHECK_PARAMS( req && diam_ans && *diam_ans && rad_ans && *rad_ans && cli);
+	
+	/* Get the list of extensions of the RADIUS request */
+	CHECK_POSIX( pthread_rwlock_rdlock( &plg_lock) );
+	CHECK_FCT_DO( ret = get_accelerator(&head, req->radius.hdr->code, req->serv_type), 
+		{ CHECK_POSIX( pthread_rwlock_unlock( &plg_lock) ); return ret; } );
+	
+	/* Loop in the list of extensions */
+	for (li = head->next; li != head; li = li->next) {
+		struct plg_descr * plg = ((struct plg_accel_item *) li)->plg;
+		
+		if (plg->descriptor->rgwp_diam_ans) {
+			TRACE_DEBUG(ANNOYING, "Calling next plugin: %s", plg->descriptor->rgwp_name);
+			ret = (*plg->descriptor->rgwp_diam_ans)(plg->cs, diam_ans, rad_ans, (void *)cli);
+			if (ret)
+				break;
+		} else {
+			TRACE_DEBUG(ANNOYING, "Skipping extension '%s' (NULL callback)", plg->descriptor->rgwp_name);
+		}					
+	}
+	
+	CHECK_POSIX( pthread_rwlock_unlock( &plg_lock) );
+	
+	/* If no error encountered, we're done here */
+	if (ret == 0)
+		return 0;
+	
+	/* Destroy the temporary RADIUS answer */
+	if (*rad_ans) {
+		radius_msg_free(*rad_ans);
+		free(*rad_ans);
+		*rad_ans = NULL;
+	}
+	
+	if (ret > 0) {
+		/* Critical error, log and exit */
+		fd_log_debug("[app_radgw] An error occurred while handling a DIAMETER answer to a converted RADIUS request, turn on DEBUG for details: %s", strerror(ret));
+		return ret;
+	}
+	
+	/* We might define other return values with special meaning here (ret == -1, ...) for example create a new Diameter request */
+	
+	/* -1: just abord the translation with no more processing. */
+	
+	return 0;
+}
+
+void rgw_plg_fini(void)
+{
+	struct fd_list * item, *subitem;
+	
+	TRACE_ENTRY();
+	
+	CHECK_POSIX_DO( pthread_rwlock_rdlock( &plg_lock), /* continue anyway */ );
+	
+	/* Remove all elements from all accelerators */
+	while ( ! FD_IS_LIST_EMPTY(&plg_accel_auth) ) {
+		item = plg_accel_auth.next;
+		fd_list_unlink(item);
+		{
+			struct plg_accel * accel = (struct plg_accel *)item;
+			while ( ! FD_IS_LIST_EMPTY(&accel->plugins) ) {
+				subitem = accel->plugins.next;
+				fd_list_unlink(subitem);
+				free(subitem);
+			}
+		}
+		free(item);
+	}
+	while ( ! FD_IS_LIST_EMPTY(&plg_accel_acct) ) {
+		item = plg_accel_acct.next;
+		fd_list_unlink(item);
+		{
+			struct plg_accel * accel = (struct plg_accel *)item;
+			while ( ! FD_IS_LIST_EMPTY(&accel->plugins) ) {
+				subitem = accel->plugins.next;
+				fd_list_unlink(subitem);
+				free(subitem);
+			}
+		}
+		free(item);
+	}
+	
+	/* Now destroy all plugins information */
+	while ( ! FD_IS_LIST_EMPTY(&plg_list) ) {
+		struct plg_descr * plg = (struct plg_descr *) plg_list.next;
+		fd_list_unlink(&plg->chain);
+		free(plg->cc);
+		if (plg->descriptor && plg->descriptor->rgwp_conf_free ) {
+			TRACE_DEBUG(INFO, "RADIUS/Diameter gateway plugin '%s' cleaning up...", plg->descriptor->rgwp_name);
+			(*plg->descriptor->rgwp_conf_free)(plg->cs);
+		}
+		if (plg->dlo)
+			dlclose(plg->dlo);
+		free(plg);
+	}
+	
+	CHECK_POSIX_DO( pthread_rwlock_unlock( &plg_lock), );
+}
diff --git a/extensions/app_radgw/rgw_servers.c b/extensions/app_radgw/rgw_servers.c
new file mode 100644
index 0000000..d524f20
--- /dev/null
+++ b/extensions/app_radgw/rgw_servers.c
@@ -0,0 +1,304 @@
+/*********************************************************************************************************
+* Software License Agreement (BSD License)                                                               *
+* Author: Sebastien Decugis <sdecugis@freediameter.net>							 *
+*													 *
+* Copyright (c) 2013, WIDE Project and NICT								 *
+* All rights reserved.											 *
+* 													 *
+* Redistribution and use of this software in source and binary forms, with or without modification, are  *
+* permitted provided that the following conditions are met:						 *
+* 													 *
+* * Redistributions of source code must retain the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer.										 *
+*    													 *
+* * Redistributions in binary form must reproduce the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer in the documentation and/or other						 *
+*   materials provided with the distribution.								 *
+* 													 *
+* * Neither the name of the WIDE Project or NICT nor the 						 *
+*   names of its contributors may be used to endorse or 						 *
+*   promote products derived from this software without 						 *
+*   specific prior written permission of WIDE Project and 						 *
+*   NICT.												 *
+* 													 *
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED *
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
+* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR *
+* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 	 *
+* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 	 *
+* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR *
+* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF   *
+* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.								 *
+*********************************************************************************************************/
+
+/* Manage the RADIUS server(s): opening sockets, receiving messages, ... */
+
+#include "rgw.h"
+
+#define RADIUS_MAX_MSG_LEN 	3000
+#define RADIUS_AUTH_PORT	1812
+#define RADIUS_ACCT_PORT	1813
+
+/* Declare the rgw_servers */
+struct rgw_servs rgw_servers;
+
+void rgw_servers_dump(void)
+{
+	char ipstr[INET6_ADDRSTRLEN];
+	
+	LOG_D(" auth server:");
+	LOG_D("    disabled..... : %s", rgw_servers.auth_serv.disabled ? "TRUE":"false");
+	LOG_D("    IP disabled.. : %s", rgw_servers.auth_serv.ip_disabled ? "TRUE":"false");
+	LOG_D("    IPv6 disabled : %s", rgw_servers.auth_serv.ip6_disabled ? "TRUE":"false");
+	LOG_D("    port......... : %hu", ntohs(rgw_servers.auth_serv.port));
+	inet_ntop(AF_INET, &rgw_servers.auth_serv.ip_endpoint,ipstr,sizeof(ipstr));
+	LOG_D("    IP bind...... : %s", ipstr);
+	inet_ntop(AF_INET6, &rgw_servers.auth_serv.ip6_endpoint,ipstr,sizeof(ipstr));
+	LOG_D("    IPv6 bind.... : %s", ipstr);
+
+	LOG_D(" acct server:");
+	LOG_D("    disabled..... : %s", rgw_servers.acct_serv.disabled ? "TRUE":"false");
+	LOG_D("    IP disabled.. : %s", rgw_servers.acct_serv.ip_disabled ? "TRUE":"false");
+	LOG_D("    IPv6 disabled : %s", rgw_servers.acct_serv.ip6_disabled ? "TRUE":"false");
+	LOG_D("    port......... : %hu", ntohs(rgw_servers.acct_serv.port));
+	inet_ntop(AF_INET, &rgw_servers.acct_serv.ip_endpoint,ipstr,sizeof(ipstr));
+	LOG_D("    IP bind...... : %s", ipstr);
+	inet_ntop(AF_INET6, &rgw_servers.acct_serv.ip6_endpoint,ipstr,sizeof(ipstr));
+	LOG_D("    IPv6 bind.... : %s", ipstr);
+
+}
+
+static struct servers_data {
+	int	type; /* auth or acct */
+	int	family; /* AF_INET or AF_INET6 */
+	int	sock; /* the socket number */
+	pthread_t th; /* the running server thread, or NULL */
+	char    name[10];
+} SERVERS[4];
+
+int rgw_servers_init(void)
+{
+	memset(&rgw_servers, 0, sizeof(rgw_servers));
+	memset(&SERVERS[0], 0, sizeof(SERVERS));
+
+	rgw_servers.auth_serv.port = htons(RADIUS_AUTH_PORT);
+	rgw_servers.acct_serv.port = htons(RADIUS_ACCT_PORT);
+	
+	return 0;
+}
+
+static void * server_thread(void * param)
+{
+	struct servers_data * me = (struct servers_data *)param;
+	
+	TRACE_ENTRY("%p", param);
+	
+	CHECK_PARAMS_DO(param, return NULL);
+	
+	/* Set the thread name */
+	{
+		char buf[48];
+		snprintf(buf, sizeof(buf), "radgw/%s serv", me->name);
+		fd_log_threadname ( buf );
+	}
+	
+	/* Now loop on this socket, parse and queue each message received, until thread is cancelled. */
+	while (1) {
+		struct sockaddr_storage from;
+		char sa_buf[sSA_DUMP_STRLEN];
+		socklen_t fromlen = sizeof(from);
+		int len;
+		struct rgw_client * nas_info = NULL;
+		uint16_t port = 0;
+		unsigned char buf[RADIUS_MAX_MSG_LEN];
+		struct rgw_radius_msg_meta *msg = NULL;
+		
+		pthread_testcancel();
+		
+		/* receive the next message */
+		CHECK_SYS_DO( len = recvfrom( me->sock, &buf[0], sizeof(buf), 0, (struct sockaddr *) &from, &fromlen),  break );
+		
+		/* Get the port */
+		port = sSAport(&from);
+		if (!port) {
+			LOG_E("Invalid port (family: %d), discarding received %d bytes...", from.ss_family, len);
+			continue;
+		}
+		
+		fd_sa_sdump_numeric(sa_buf, (sSA*)&from);
+		LOG_D("RADIUS: RCV %dB from %s", len, sa_buf);
+		
+		/* Search the associated client definition, if any */
+		CHECK_FCT_DO( rgw_clients_search((struct sockaddr *) &from, &nas_info),
+			{
+				LOG_E("Discarding %d bytes received from unknown IP: %s", len, sa_buf);
+				continue;
+			} );
+				
+		
+		/* parse the message, loop if message is invalid */
+		CHECK_FCT_DO( rgw_msg_parse(&buf[0], len, &msg), 
+			{
+				DiamId_t cliname = NULL;
+				size_t clisz;
+				CHECK_FCT_DO( rgw_clients_get_origin(nas_info, &cliname, &clisz, NULL, NULL), );
+				LOG_E( "Discarding invalid RADIUS message from '%s'", cliname);
+				rgw_clients_dispose(&nas_info);
+				continue; 
+			} );
+		
+		msg->serv_type = me->type;
+		msg->port = port;
+		
+		rgw_msg_dump(msg, 1);
+		
+		/* queue the message for a worker thread */
+		CHECK_FCT_DO( rgw_work_add(msg, nas_info), break );
+		
+		/* Then wait for next incoming message */
+	}
+	
+	TRACE_DEBUG(INFO, "Server thread terminated.");
+	return NULL;
+}
+
+/* Set the socket options for UDP sockets, before bind is called */
+static int _udp_setsockopt(int family, int sk)
+{
+	int ret = 0;
+	int opt;
+	
+	/* In case of v6 address, force the v6only option, we use a different socket for v4 */
+	#ifdef IPV6_V6ONLY
+	if (family == AF_INET6) {
+		opt = 1;
+		ret = setsockopt(sk, IPPROTO_IPV6, IPV6_V6ONLY, &opt, sizeof(opt));
+		if (ret != 0) {
+			ret = errno;
+			TRACE_DEBUG(INFO, "Unable to set the socket IPV6_V6ONLY option: %s", strerror(ret));
+			return ret;
+		}
+	}
+	#endif /* IPV6_V6ONLY */
+	
+	return 0;
+}
+
+/* We reuse the same logic for all 4 possible servers (IP / IPv6, Auth / Acct ports) */
+#define UDPSERV( _type_, _portval_, _family_ ) {								\
+	/* Check that this type / family are not disabled by configuration */					\
+	if ( (! rgw_servers. _type_ ## _serv.disabled) 								\
+		&& ( ! rgw_servers. _type_ ## _serv.ip ## _family_ ## _disabled ) ) {				\
+			struct sockaddr_in ## _family_	 sin ## _family_ ;					\
+			/* Create the socket */									\
+			CHECK_SYS( SERVERS[idx].sock = socket(AF_INET ## _family_, SOCK_DGRAM, 0) );		\
+			/* Set the parameters for bind into "sin" or "sin6" */					\
+			memset(& sin ## _family_, 0, sizeof(struct sockaddr_in ## _family_));			\
+			sin ## _family_ . sin ## _family_ ## _family = AF_INET ## _family_;			\
+			sin ## _family_ . sin ## _family_ ## _port = rgw_servers. _type_ ## _serv . port;	\
+			memcpy( &sin ## _family_ .sin ## _family_ ## _addr, 					\
+					&rgw_servers. _type_ ## _serv . ip ## _family_ ## _endpoint,		\
+					sizeof(struct in ## _family_ ## _addr) );				\
+			/* This sockopt must be set before binding */						\
+			TRACE_DEBUG(ANNOYING, "Setting socket options...");					\
+			CHECK_FCT( _udp_setsockopt(AF_INET ## _family_, SERVERS[idx].sock) );			\
+			/* OK, now, bind */									\
+			TRACE_DEBUG(ANNOYING, "Binding " #_type_ " ip" #_family_ " server...");			\
+			CHECK_SYS( bind( SERVERS[idx].sock,							\
+					(struct sockaddr *)&sin ## _family_,					\
+					sizeof(struct sockaddr_in ## _family_) ) );				\
+			/* Save the server information in SERVERS structure */					\
+			SERVERS[idx].type = _portval_;								\
+			SERVERS[idx].family = AF_INET ## _family_;						\
+			snprintf(&SERVERS[idx].name[0], sizeof(SERVERS[idx].name), # _type_ "/ip" #_family_);	\
+			/* Create the server thread */								\
+			CHECK_POSIX( pthread_create(&SERVERS[idx].th, NULL, server_thread, &SERVERS[idx]) );	\
+			idx++;											\
+	}													\
+}
+
+int rgw_servers_start(void)
+{
+	int idx = 0;
+	
+	TRACE_ENTRY();
+	
+	UDPSERV( auth, RGW_PLG_TYPE_AUTH,  );
+	UDPSERV( auth, RGW_PLG_TYPE_AUTH, 6 );
+	UDPSERV( acct, RGW_PLG_TYPE_ACCT,  );
+	UDPSERV( acct, RGW_PLG_TYPE_ACCT, 6 );
+	
+	TRACE_DEBUG(FULL, "%d UDP servers started succesfully.", idx);
+	return 0;
+}
+
+/* Send a RADIUS message */
+int rgw_servers_send(int type, unsigned char *buf, size_t buflen, struct sockaddr *to, uint16_t to_port)
+{
+	int idx = 0;
+	int ret = 0;
+	struct sockaddr_storage sto;
+	char sa_buf[sSA_DUMP_STRLEN];
+	
+	/* Find the appropriate socket to use (not sure if it is important) */
+	for (idx = 0; idx < sizeof(SERVERS) / sizeof(SERVERS[0]); idx++) {
+		if ( SERVERS[idx].sock && (type == SERVERS[idx].type) && (to->sa_family == SERVERS[idx].family) ) {
+			ret = 1;
+			break;
+		}
+	}
+	
+	if (!ret) {
+		LOG_E( "Trying to send a message from a disabled server: %s / %s", 
+				(type == RGW_PLG_TYPE_AUTH) ? "Auth" : "Acct",
+				(to->sa_family == AF_INET)  ? "IP (v4)" : "IPv6");
+		return EINVAL;
+	}
+	
+	/* Prepare the destination info */
+	memset(&sto, 0, sizeof(sto));
+	if (to->sa_family == AF_INET) {
+		memcpy(&sto, to, sizeof(struct sockaddr_in));
+		((struct sockaddr_in *)&sto)->sin_port = to_port;
+	} else {
+		memcpy(&sto, to, sizeof(struct sockaddr_in6));
+		((struct sockaddr_in6 *)&sto)->sin6_port = to_port;
+	}
+	
+	fd_sa_sdump_numeric(sa_buf, (sSA*)&sto);
+	LOG_D("RADIUS: SND %zdB   to %s", buflen, sa_buf);
+	
+	/* Send */
+	ret = sendto(SERVERS[idx].sock, buf, buflen, 0, (struct sockaddr *)&sto, sSAlen(&sto));
+	if (ret < 0) {
+		ret = errno;
+		TRACE_DEBUG(INFO, "An error prevented sending of a RADIUS message: %s", strerror(ret));
+		return ret;
+	}
+	if (ret != buflen) {
+		TRACE_DEBUG(INFO, "Incomplete send: %d bytes / %zd", ret, buflen);
+		return EAGAIN;
+	}
+	
+	/* Done :) */
+	return 0;
+}
+
+void rgw_servers_fini(void)
+{
+	int idx = 0;
+	
+	for (idx = 0; idx < sizeof(SERVERS) / sizeof(SERVERS[0]); idx++) {
+		if (SERVERS[idx].sock == 0)
+			break;
+		
+		CHECK_FCT_DO( fd_thr_term(&SERVERS[idx].th), /* continue */ );
+		close(SERVERS[idx].sock);
+		SERVERS[idx].sock = 0;
+	}
+	
+}
+
+
diff --git a/extensions/app_radgw/rgw_worker.c b/extensions/app_radgw/rgw_worker.c
new file mode 100644
index 0000000..25cb146
--- /dev/null
+++ b/extensions/app_radgw/rgw_worker.c
@@ -0,0 +1,346 @@
+/*********************************************************************************************************
+* Software License Agreement (BSD License)                                                               *
+* Author: Sebastien Decugis <sdecugis@freediameter.net>							 *
+*													 *
+* Copyright (c) 2013, WIDE Project and NICT								 *
+* All rights reserved.											 *
+* 													 *
+* Redistribution and use of this software in source and binary forms, with or without modification, are  *
+* permitted provided that the following conditions are met:						 *
+* 													 *
+* * Redistributions of source code must retain the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer.										 *
+*    													 *
+* * Redistributions in binary form must reproduce the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer in the documentation and/or other						 *
+*   materials provided with the distribution.								 *
+* 													 *
+* * Neither the name of the WIDE Project or NICT nor the 						 *
+*   names of its contributors may be used to endorse or 						 *
+*   promote products derived from this software without 						 *
+*   specific prior written permission of WIDE Project and 						 *
+*   NICT.												 *
+* 													 *
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED *
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
+* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR *
+* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 	 *
+* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 	 *
+* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR *
+* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF   *
+* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.								 *
+*********************************************************************************************************/
+
+/* Manage incoming RADIUS messages. */
+
+#include "rgw.h"
+
+/* How many threads to handle messages in parallel ? */
+#define NB_WORKERS	2
+
+static pthread_t workers[NB_WORKERS];
+static struct fifo * work_stack = NULL;
+
+/* Data that is stacked */
+struct work_item {
+	struct rgw_radius_msg_meta * msg;
+	struct rgw_client 	   * cli;
+};
+
+/* Data stored in freeDiameter while pending Diameter answer */
+struct pending_answer {
+	struct rgw_radius_msg_meta * rad;  /* the RADIUS message that was received and translated */
+	struct rgw_client          * cli;  /* the client it was received from */
+};
+
+/* Callback when a Diameter answer is received */
+static void receive_diam_answer(void * paback, struct msg **ans);
+
+/* Worker thread, processing incoming RADIUS messages (after parsing) */
+static void * work_th(void * arg)
+{
+	TRACE_ENTRY("%p", arg);
+	
+	/* Set the thread name */
+	{
+		char buf[48];
+		snprintf(buf, sizeof(buf), "radgw/worker #%ld", (long)arg);
+		fd_log_threadname ( buf );
+	}
+	
+	while (1) { /* The thread will be cancelled */
+		
+		struct rgw_radius_msg_meta * msg;
+		struct rgw_client * cli;
+		struct msg * diam_msg;
+		int pb, a;
+		struct pending_answer * pa;
+	
+		/* Get the next incoming RADIUS message */
+		{
+			struct work_item * wi = NULL;
+			
+			CHECK_FCT_DO( fd_fifo_get(work_stack, &wi), break );
+
+			msg = wi->msg;
+			cli = wi->cli;
+			free(wi);
+		}
+		
+		TRACE_DEBUG(ANNOYING, "Processing next RADIUS message: %p received on client: %p", msg, cli);
+	
+		/* process the data */
+		
+		/* Check authenticator, if any */
+		CHECK_FCT_DO( rgw_clients_auth_check(msg, cli, NULL),
+			{
+				/* An error occurred, discard message */
+				rgw_msg_free(&msg);
+				rgw_clients_dispose(&cli);
+				continue;
+			}  );
+		
+		/* Check duplicate */
+		CHECK_FCT_DO( rgw_clients_check_dup(&msg, cli),
+			{
+				/* An error occurred, discard message */
+				rgw_msg_free(&msg);
+				rgw_clients_dispose(&cli);
+				continue;
+			}  );
+		if (msg == NULL) {
+			rgw_clients_dispose(&cli);
+			continue; /* the message was a duplicate */
+		}
+		
+		diam_msg = NULL;
+		/* Note: after this point, the radius message buffer may not be consistent with the array of attributes anymore. */
+	
+		/* Check that IP is coherent with the identity in the message, and create an empty message with only Origin information */
+		CHECK_FCT_DO( rgw_clients_create_origin(msg, cli, &diam_msg),
+			{
+				/* An error occurred, discard message */
+				if (diam_msg) {
+					CHECK_FCT_DO( fd_msg_free(diam_msg), );
+				}
+				rgw_msg_free(&msg);
+				rgw_clients_dispose(&cli);
+				continue;
+			}  );
+		
+		/* Pass the message to the list of registered plugins */
+		CHECK_FCT_DO( rgw_plg_loop_req(&msg, &diam_msg, cli), 
+			{
+				/* An error occurred, discard message */
+				if (diam_msg) {
+					CHECK_FCT_DO( fd_msg_free(diam_msg), );
+					diam_msg = NULL;
+				}
+				rgw_msg_free(&msg);
+				rgw_clients_dispose(&cli);
+				continue;
+			}  );
+		if (msg == NULL) { /* Error or RADIUS answer locally generated */
+			rgw_clients_dispose(&cli);
+			if (diam_msg) {
+				CHECK_FCT_DO( fd_msg_free(diam_msg), );
+				diam_msg = NULL;
+			}
+			continue; /* the message was handled already */
+		}
+		
+		pb = 0;
+		
+		/* Check the created Diameter message -- it will be invalid if no callback has handled the RADIUS message */
+		if ((diam_msg == NULL) || ( fd_msg_parse_rules(diam_msg, fd_g_config->cnf_dict, NULL) ) ) {
+			fd_log_debug("[radgw] No or invalid Diameter message was generated after processing the RADIUS command %hhd (%s)."
+					" It may indicate a gateway configuration problem, or implementation issue in a plugin.",
+					msg->radius.hdr->code, rgw_msg_code_str(msg->radius.hdr->code));
+			/* We should also dump the conflicting rule here to help debug? */
+			pb++;
+		}
+		
+		/* Check if the full content of the RADIUS message was handled */
+		for (a = 0; a < msg->radius.attr_used; a++) {
+			struct radius_attr_hdr *attr = (struct radius_attr_hdr *)(msg->radius.buf + msg->radius.attr_pos[a]);
+			pb++;
+			fd_log_debug("[radgw] No plugin available to handle attribute %hhd (%s) in command %hhd (%s)! Translation aborted.",
+					attr->type, rgw_msg_attrtype_str(attr->type),
+					msg->radius.hdr->code, rgw_msg_code_str(msg->radius.hdr->code));
+		}
+		
+		if (pb) {
+			/* Something went wrong during the conversion */
+			if (diam_msg) {
+				CHECK_FCT_DO( fd_msg_free(diam_msg), );
+				diam_msg = NULL;
+			}
+			
+			rgw_msg_free(&msg);
+			rgw_clients_dispose(&cli);
+			
+			TRACE_DEBUG(INFO, "%d problem(s) occurred while translating a RADIUS message, data discarded.", pb);
+			continue;
+		}
+		
+		/* Send the Diameter message and register for receiving the answer */
+		CHECK_MALLOC_DO( pa = malloc(sizeof(struct pending_answer)), break );
+		memset(pa, 0, sizeof(*pa));
+		pa->rad = msg;
+		pa->cli = cli;
+		
+		CHECK_FCT_DO( fd_msg_send( &diam_msg, receive_diam_answer, pa), 
+			{
+				/* If an error occurs, log and destroy the data */
+				fd_log_debug("An error occurred while sending Diameter message, please turn Debug on for detail.");
+
+				if (diam_msg) {
+					CHECK_FCT_DO( fd_msg_free(diam_msg), );
+					diam_msg = NULL;
+				}
+
+				rgw_msg_free(&msg);
+				rgw_clients_dispose(&cli);
+				
+				free(pa);
+				
+				continue;
+			} );
+		
+		/* Done! */
+	}
+	
+	TRACE_DEBUG(INFO, "Thread terminated!");
+	return NULL;
+}
+
+static void receive_diam_answer(void * paback, struct msg **ans)
+{
+	struct pending_answer * pa = (struct pending_answer *)paback;
+	struct radius_msg * rad_ans;
+	struct avp *avp;
+	struct avp_hdr  *ahdr;
+	int pb = 0;
+	
+	TRACE_ENTRY("%p %p", pa, ans);
+	CHECK_PARAMS_DO( pa && ans, return );
+	
+	/* Create an empty RADIUS answer message */
+	CHECK_MALLOC_DO( rad_ans = radius_msg_new(0, pa->rad->radius.hdr->identifier), goto out );
+	
+	/* Pass the Diameter answer to the same extensions as the request */
+	CHECK_FCT_DO( rgw_plg_loop_ans(pa->rad, ans, &rad_ans, pa->cli), goto out );
+
+	if (*ans != NULL) {
+
+		/* Now check what AVPs remain in the diameter answer. If AVPs with the 'M' flag are here, we have a problem... */
+		CHECK_FCT_DO( fd_msg_browse(*ans, MSG_BRW_FIRST_CHILD, &avp, NULL), { avp = NULL; pb++; } );
+		while (avp) {
+			CHECK_FCT_DO( fd_msg_avp_hdr ( avp, &ahdr ), { pb++; continue; } );
+			if (ahdr->avp_flags & AVP_FLAG_MANDATORY) {
+				if (ahdr->avp_flags & AVP_FLAG_VENDOR) {
+					TRACE_DEBUG(FULL, "Remaining Mandatory Vendor AVP, code %d", ahdr->avp_code);
+					pb++;
+				} else {
+					switch (ahdr->avp_code) {
+						/* A few AVPs can be safely ignored here: */
+						case DIAM_ATTR_SESSION_ID:
+						case DIAM_ATTR_ROUTE_RECORD:
+						case DIAM_ATTR_PROXY_INFO:
+
+
+							/* just ignore */
+							break;
+
+						default:
+							LOG_D("Remaining Mandatory AVP, code %d", ahdr->avp_code);
+							pb++;
+					}
+				}
+			}
+			CHECK_FCT_DO( fd_msg_browse(avp, MSG_BRW_NEXT, &avp, NULL), { pb++; break; } );
+		}
+
+		if (pb) {
+			TRACE_DEBUG(INFO, "[radgw] WARNING: %d mandatory AVP in the Diameter answer have not been translated to RADIUS! Please use debug.rgwx for more information.", pb);
+		}
+	}
+	
+	
+out:
+	/* Now try and send the RADIUS answer */
+	if (rad_ans) {
+		CHECK_FCT_DO( rgw_client_finish_send(&rad_ans, pa->rad, pa->cli), );	
+	} else {
+		/* Remove the request from the duplicate cache */
+		CHECK_FCT_DO( rgw_client_finish_nosend(pa->rad, pa->cli), );
+	}
+
+	/* Clear the Diameter message */
+	if (*ans) {
+		CHECK_FCT_DO( fd_msg_free(*ans),  );
+		*ans = NULL;
+	}
+	
+	/* Clear the RADIUS request */
+	if (pa->rad) {
+		rgw_msg_free(&pa->rad);
+	}
+	
+	/* Release reference on the client */
+	rgw_clients_dispose(&pa->cli);
+	
+	/* Clear the answer data */
+	free(pa);
+	
+	/* Finished */
+	return;
+}
+
+int rgw_work_start(void)
+{
+	long i;
+	TRACE_ENTRY();
+	
+	memset(workers, 0, sizeof(workers));
+	
+	CHECK_FCT( fd_fifo_new ( &work_stack, 30 ) );
+	
+	/* Create the worker thread(s) */
+	for (i = 0; i < NB_WORKERS; i++) {
+		CHECK_POSIX( pthread_create(&workers[i], NULL, work_th, (void *)i) );
+	}
+	
+	return 0;
+}
+
+int rgw_work_add(struct rgw_radius_msg_meta * msg, struct rgw_client * client)
+{
+	struct work_item * new;
+	
+	CHECK_MALLOC( new = malloc(sizeof(struct work_item)) );
+	memset(new, 0, sizeof(struct work_item));
+	
+	new->msg = msg;
+	new->cli = client;
+	
+	CHECK_FCT( fd_fifo_post(work_stack, &new) );
+	
+	return 0;
+}
+
+void rgw_work_fini(void)
+{
+	int i;
+	TRACE_ENTRY();
+	
+	for (i = 0; i < NB_WORKERS; i++) {
+		fd_thr_term(&workers[i]);
+	}
+	
+	TODO("Empty the stack, what to do about the RADIUS messages?");
+	
+	return;
+}
diff --git a/extensions/app_radgw/rgwx_acct.c b/extensions/app_radgw/rgwx_acct.c
new file mode 100644
index 0000000..f9f1480
--- /dev/null
+++ b/extensions/app_radgw/rgwx_acct.c
@@ -0,0 +1,1463 @@
+/*********************************************************************************************************
+* Software License Agreement (BSD License)                                                               *
+* Author: Sebastien Decugis <sdecugis@freediameter.net>							 *
+*													 *
+* Copyright (c) 2013, WIDE Project and NICT								 *
+* All rights reserved.											 *
+* 													 *
+* Redistribution and use of this software in source and binary forms, with or without modification, are  *
+* permitted provided that the following conditions are met:						 *
+* 													 *
+* * Redistributions of source code must retain the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer.										 *
+*    													 *
+* * Redistributions in binary form must reproduce the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer in the documentation and/or other						 *
+*   materials provided with the distribution.								 *
+* 													 *
+* * Neither the name of the WIDE Project or NICT nor the 						 *
+*   names of its contributors may be used to endorse or 						 *
+*   promote products derived from this software without 						 *
+*   specific prior written permission of WIDE Project and 						 *
+*   NICT.												 *
+* 													 *
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED *
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
+* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR *
+* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 	 *
+* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 	 *
+* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR *
+* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF   *
+* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.								 *
+*********************************************************************************************************/
+
+/* RADIUS Accounting-Request messages translation plugin */
+
+#include "rgw_common.h"
+
+
+/* Other constants we use */
+#define AI_ACCT			3	/* Diameter Base Accounting application */
+#define CC_AC			271	/* ACR/ACA */
+#define ACV_ART_START_RECORD		2	/* START_RECORD */
+#define ACV_ART_INTERIM_RECORD		3	/* INTERIM_RECORD */
+#define ACV_ART_STOP_RECORD		4	/* STOP_RECORD */
+#define ACV_ART_AUTHORIZE_AUTHENTICATE	3	/* AUTHORIZE_AUTHENTICATE */
+
+
+/* The state we keep for this plugin */
+struct rgwp_config {
+	struct {
+		struct dict_object * Accounting_Record_Number;	/* Accounting-Record-Number */
+		struct dict_object * Accounting_Record_Type;	/* Accounting-Record-Type */
+		struct dict_object * Acct_Application_Id;	/* Acct-Application-Id */
+		struct dict_object * Acct_Delay_Time;		/* Acct-Delay-Time */
+		struct dict_object * Accounting_Input_Octets;	/* Accounting-Input-Octets */
+		struct dict_object * Accounting_Output_Octets;	/* Accounting-Output-Octets */
+		struct dict_object * Accounting_Input_Packets;	/* Accounting-Input-Packets */
+		struct dict_object * Accounting_Output_Packets;	/* Accounting-Output-Packets */
+		struct dict_object * Acct_Link_Count;		/* Acct-Link-Count */
+		struct dict_object * Acct_Authentic;		/* Acct-Authentic */
+		struct dict_object * Acct_Multi_Session_Id;	/* Acct-Multi-Session-Id */
+		struct dict_object * Acct_Session_Id;		/* Acct-Session-Id */
+		struct dict_object * Acct_Session_Time;		/* Acct-Session-Time */
+		
+		struct dict_object * ARAP_Password;		/* ARAP-Password */
+		struct dict_object * ARAP_Security;		/* ARAP-Security */
+		struct dict_object * ARAP_Security_Data;	/* ARAP-Security-Data */
+		struct dict_object * Auth_Application_Id;	/* Auth-Application-Id */
+		struct dict_object * Auth_Request_Type;		/* Auth-Request-Type */
+		struct dict_object * Authorization_Lifetime;	/* Authorization-Lifetime */
+		struct dict_object * Callback_Number;		/* Callback-Number */
+		struct dict_object * Callback_Id;		/* Callback-Id */
+		struct dict_object * Called_Station_Id;		/* Called-Station-Id */
+		struct dict_object * Calling_Station_Id;	/* Calling-Station-Id */
+		struct dict_object * Class;			/* Class */
+		struct dict_object * CHAP_Algorithm;		/* CHAP-Algorithm */
+		struct dict_object * CHAP_Auth;			/* CHAP-Auth */
+		struct dict_object * CHAP_Challenge;		/* CHAP-Challenge */
+		struct dict_object * CHAP_Ident;		/* CHAP-Ident */
+		struct dict_object * CHAP_Response;		/* CHAP-Response */
+		struct dict_object * Connect_Info;		/* Connect-Info */
+		struct dict_object * Destination_Host;		/* Destination-Host */
+		struct dict_object * Destination_Realm;		/* Destination-Realm */
+		struct dict_object * EAP_Payload;		/* EAP-Payload */
+		struct dict_object * Error_Message;		/* Error-Message */
+		struct dict_object * Error_Reporting_Host;	/* Error-Reporting-Host */
+		struct dict_object * Event_Timestamp;		/* Event-Timestamp */
+		struct dict_object * Failed_AVP;		/* Failed-AVP */
+		struct dict_object * Framed_AppleTalk_Link;	/* Framed-AppleTalk-Link */
+		struct dict_object * Framed_AppleTalk_Network;	/* Framed-AppleTalk-Network */
+		struct dict_object * Framed_AppleTalk_Zone;	/* Framed-AppleTalk-Zone */
+		struct dict_object * Framed_Compression;	/* Framed-Compression */
+		struct dict_object * Framed_IP_Address;		/* Framed-IP-Address */
+		struct dict_object * Framed_IP_Netmask;		/* Framed-IP-Netmask */
+		struct dict_object * Framed_Interface_Id;	/* Framed-Interface-Id */
+		struct dict_object * Framed_IPv6_Prefix;	/* Framed-IPv6-Prefix */
+		struct dict_object * Framed_IPX_Network;	/* Framed-IPX-Network */
+		struct dict_object * Framed_MTU;		/* Framed-MTU */
+		struct dict_object * Framed_Protocol;		/* Framed-Protocol */
+		struct dict_object * Framed_Pool;		/* Framed-Pool */
+		struct dict_object * Framed_IPv6_Route;		/* Framed-IPv6-Route */
+		struct dict_object * Framed_IPv6_Pool;		/* Framed-IPv6-Pool */
+		struct dict_object * Framed_Route;		/* Framed-Route */
+		struct dict_object * Framed_Routing;		/* Framed-Routing */
+		struct dict_object * Filter_Id;			/* Filter-Id */
+		struct dict_object * Idle_Timeout;		/* Idle-Timeout */
+		struct dict_object * Login_IP_Host;		/* Login-IP-Host */
+		struct dict_object * Login_IPv6_Host;		/* Login-IPv6-Host */
+		struct dict_object * Login_LAT_Group;		/* Login-LAT-Group */
+		struct dict_object * Login_LAT_Node;		/* Login-LAT-Node */
+		struct dict_object * Login_LAT_Port;		/* Login-LAT-Port */
+		struct dict_object * Login_LAT_Service;		/* Login-LAT-Service */
+		struct dict_object * Login_Service;		/* Login-Service */
+		struct dict_object * Login_TCP_Port;		/* Login-TCP-Port */
+		struct dict_object * NAS_Identifier;		/* NAS-Identifier */
+		struct dict_object * NAS_IP_Address;		/* NAS-IP-Address */
+		struct dict_object * NAS_IPv6_Address;		/* NAS-IPv6-Address */
+		struct dict_object * NAS_Port;			/* NAS-Port */
+		struct dict_object * NAS_Port_Id;		/* NAS-Port-Id */
+		struct dict_object * NAS_Port_Type;		/* NAS-Port-Type */
+		struct dict_object * Origin_AAA_Protocol;	/* Origin-AAA-Protocol */
+		struct dict_object * Origin_Host;		/* Origin-Host */
+		struct dict_object * Origin_Realm;		/* Origin-Realm */
+		struct dict_object * Originating_Line_Info;	/* Originating-Line-Info */
+		struct dict_object * Port_Limit;		/* Port-Limit */
+		struct dict_object * Re_Auth_Request_Type;	/* Re-Auth-Request-Type */
+		struct dict_object * Result_Code;		/* Result-Code */
+		struct dict_object * Service_Type;		/* Service-Type */
+		struct dict_object * Session_Id;		/* Session-Id */
+		struct dict_object * Session_Timeout;		/* Session-Timeout */
+		struct dict_object * State;			/* State */
+		struct dict_object * Termination_Cause;		/* Termination-Cause */
+		struct dict_object * Tunneling;			/* Tunneling */
+		struct dict_object * Tunnel_Type;		/* Tunnel-Type */
+		struct dict_object * Tunnel_Assignment_Id;	/* Tunnel-Assignment-Id */
+		struct dict_object * Tunnel_Medium_Type;	/* Tunnel-Medium-Type */
+		struct dict_object * Tunnel_Client_Endpoint;	/* Tunnel-Client-Endpoint */
+		struct dict_object * Tunnel_Server_Endpoint;	/* Tunnel-Server-Endpoint */
+		struct dict_object * Tunnel_Private_Group_Id;	/* Tunnel-Private-Group-Id */
+		struct dict_object * Tunnel_Preference;		/* Tunnel-Preference */
+		struct dict_object * Tunnel_Client_Auth_Id;	/* Tunnel-Client-Auth-Id */
+		struct dict_object * Tunnel_Server_Auth_Id;	/* Tunnel-Server-Auth-Id */
+		struct dict_object * User_Name;			/* User-Name */
+		
+		struct dict_object * Session_Termination_Request;/* STR */
+	} dict; /* cache of the dictionary objects we use */
+	struct session_handler * sess_hdl; /* We store RADIUS request authenticator information in the session */
+	char * confstr;
+	
+	int ignore_nai;
+};
+
+/* The state we store in the session */
+struct sess_state {
+	application_id_t auth_appl;	/* Auth-Application-Id used for this session, if available (stored in a Class attribute) */
+	int		 send_str;	/* If not 0, we must send a STR when the ACA is received. */
+	uint32_t	 term_cause;	/* If not 0, the Termination-Cause to put in the STR. */
+};
+
+static DECLARE_FD_DUMP_PROTOTYPE(acct_conf_session_state_dump, struct sess_state * st)
+{
+	return fd_dump_extend( FD_DUMP_STD_PARAMS, "[rgwx sess_state](@%p): aai:%x str:%d TC:%u", st, st->auth_appl, st->send_str, st->term_cause);
+}
+
+/* Initialize the plugin */
+static int acct_conf_parse(char * conffile, struct rgwp_config ** state)
+{
+	struct rgwp_config * new;
+	struct dict_object * app;
+	
+	TRACE_ENTRY("%p %p", conffile, state);
+	CHECK_PARAMS( state );
+	
+	CHECK_MALLOC( new = malloc(sizeof(struct rgwp_config)) );
+	memset(new, 0, sizeof(struct rgwp_config));
+	
+	CHECK_FCT( fd_sess_handler_create( &new->sess_hdl, (void *)free, acct_conf_session_state_dump, NULL ) );
+	new->confstr = conffile;
+	
+	if (conffile && strstr(conffile, "nonai"))
+		new->ignore_nai = 1;
+	
+	/* Resolve all dictionary objects we use */
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Accounting-Record-Number", &new->dict.Accounting_Record_Number, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Accounting-Record-Type", &new->dict.Accounting_Record_Type, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Acct-Application-Id", &new->dict.Acct_Application_Id, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Acct-Delay-Time", &new->dict.Acct_Delay_Time, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Accounting-Input-Octets", &new->dict.Accounting_Input_Octets, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Accounting-Output-Octets", &new->dict.Accounting_Output_Octets, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Accounting-Input-Packets", &new->dict.Accounting_Input_Packets, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Accounting-Output-Packets", &new->dict.Accounting_Output_Packets, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Acct-Authentic", &new->dict.Acct_Authentic, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Acct-Link-Count", &new->dict.Acct_Link_Count, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Acct-Multi-Session-Id", &new->dict.Acct_Multi_Session_Id, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Acct-Session-Id", &new->dict.Acct_Session_Id, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Acct-Session-Time", &new->dict.Acct_Session_Time, ENOENT) );
+	
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "ARAP-Password", &new->dict.ARAP_Password, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "ARAP-Security", &new->dict.ARAP_Security, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "ARAP-Security-Data", &new->dict.ARAP_Security_Data, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Auth-Application-Id", &new->dict.Auth_Application_Id, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Auth-Request-Type", &new->dict.Auth_Request_Type, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Authorization-Lifetime", &new->dict.Authorization_Lifetime, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Callback-Number", &new->dict.Callback_Number, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Callback-Id", &new->dict.Callback_Id, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Called-Station-Id", &new->dict.Called_Station_Id, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Calling-Station-Id", &new->dict.Calling_Station_Id, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Class", &new->dict.Class, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Connect-Info", &new->dict.Connect_Info, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Destination-Host", &new->dict.Destination_Host, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Destination-Realm", &new->dict.Destination_Realm, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "EAP-Payload", &new->dict.EAP_Payload, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Error-Message", &new->dict.Error_Message, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Error-Reporting-Host", &new->dict.Error_Reporting_Host, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Event-Timestamp", &new->dict.Event_Timestamp, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Failed-AVP", &new->dict.Failed_AVP, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Framed-AppleTalk-Link", &new->dict.Framed_AppleTalk_Link, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Framed-AppleTalk-Network", &new->dict.Framed_AppleTalk_Network, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Framed-AppleTalk-Zone", &new->dict.Framed_AppleTalk_Zone, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Framed-Compression", &new->dict.Framed_Compression, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Framed-IP-Address", &new->dict.Framed_IP_Address, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Framed-IP-Netmask", &new->dict.Framed_IP_Netmask, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Framed-Interface-Id", &new->dict.Framed_Interface_Id, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Framed-IPv6-Prefix", &new->dict.Framed_IPv6_Prefix, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Framed-IPX-Network", &new->dict.Framed_IPX_Network, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Framed-MTU", &new->dict.Framed_MTU, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Framed-Protocol", &new->dict.Framed_Protocol, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Framed-Pool", &new->dict.Framed_Pool, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Framed-Route", &new->dict.Framed_Route, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Framed-IPv6-Route", &new->dict.Framed_IPv6_Route, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Framed-IPv6-Pool", &new->dict.Framed_IPv6_Pool, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Framed-Routing", &new->dict.Framed_Routing, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Filter-Id", &new->dict.Filter_Id, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Idle-Timeout", &new->dict.Idle_Timeout, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Login-IP-Host", &new->dict.Login_IP_Host, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Login-IPv6-Host", &new->dict.Login_IPv6_Host, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Login-LAT-Group", &new->dict.Login_LAT_Group, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Login-LAT-Node", &new->dict.Login_LAT_Node, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Login-LAT-Port", &new->dict.Login_LAT_Port, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Login-LAT-Service", &new->dict.Login_LAT_Service, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Login-Service", &new->dict.Login_Service, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Login-TCP-Port", &new->dict.Login_TCP_Port, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "NAS-Identifier", &new->dict.NAS_Identifier, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "NAS-IP-Address", &new->dict.NAS_IP_Address, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "NAS-IPv6-Address", &new->dict.NAS_IPv6_Address, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "NAS-Port", &new->dict.NAS_Port, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "NAS-Port-Id", &new->dict.NAS_Port_Id, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "NAS-Port-Type", &new->dict.NAS_Port_Type, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Origin-AAA-Protocol", &new->dict.Origin_AAA_Protocol, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Origin-Host", &new->dict.Origin_Host, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Origin-Realm", &new->dict.Origin_Realm, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Originating-Line-Info", &new->dict.Originating_Line_Info, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Port-Limit", &new->dict.Port_Limit, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Re-Auth-Request-Type", &new->dict.Re_Auth_Request_Type, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Result-Code", &new->dict.Result_Code, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Service-Type", &new->dict.Service_Type, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Session-Id", &new->dict.Session_Id, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Session-Timeout", &new->dict.Session_Timeout, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "State", &new->dict.State, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Termination-Cause", &new->dict.Termination_Cause, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Tunneling", &new->dict.Tunneling, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Tunnel-Assignment-Id", &new->dict.Tunnel_Assignment_Id, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Tunnel-Type", &new->dict.Tunnel_Type, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Tunnel-Medium-Type", &new->dict.Tunnel_Medium_Type, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Tunnel-Client-Endpoint", &new->dict.Tunnel_Client_Endpoint, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Tunnel-Server-Endpoint", &new->dict.Tunnel_Server_Endpoint, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Tunnel-Private-Group-Id", &new->dict.Tunnel_Private_Group_Id, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Tunnel-Preference", &new->dict.Tunnel_Preference, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Tunnel-Client-Auth-Id", &new->dict.Tunnel_Client_Auth_Id, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Tunnel-Server-Auth-Id", &new->dict.Tunnel_Server_Auth_Id, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "User-Name", &new->dict.User_Name, ENOENT) );
+	
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_COMMAND, CMD_BY_NAME, "Session-Termination-Request", &new->dict.Session_Termination_Request, ENOENT) );
+	
+	/* This plugin provides the following Diameter authentication applications support: */
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_APPLICATION, APPLICATION_BY_NAME, "Diameter Base Accounting", &app, ENOENT) );
+	CHECK_FCT( fd_disp_app_support ( app, NULL, 0, 1 ) );
+	
+	*state = new;
+	return 0;
+}
+
+/* deinitialize */
+static void acct_conf_free(struct rgwp_config * state)
+{
+	TRACE_ENTRY("%p", state);
+	CHECK_PARAMS_DO( state, return );
+	CHECK_FCT_DO( fd_sess_handler_destroy( &state->sess_hdl, NULL ),  );
+	free(state);
+	return;
+}
+
+/* Incoming RADIUS request */
+static int acct_rad_req( struct rgwp_config * cs, struct radius_msg * rad_req, struct radius_msg ** rad_ans, struct msg ** diam_fw, struct rgw_client * cli )
+{
+	int idx;
+	int send_str=0;
+	uint32_t str_cause=0;
+	uint32_t e2eid = 0;
+	application_id_t auth_appl=0;
+	int got_id = 0;
+	uint32_t status_type;
+	uint32_t termination_action = 0;
+	uint32_t gigawords_in=0, gigawords_out=0;
+	size_t nattr_used = 0;
+	union avp_value value;
+	struct avp ** avp_tun = NULL, *avp = NULL;
+	struct session * sess;
+	
+	const char * prefix = "Diameter/";
+	size_t pref_len;
+	os0_t si = NULL;
+	size_t si_len = 0;
+	os0_t un = NULL;
+	size_t un_len = 0;
+	
+	TRACE_ENTRY("%p %p %p %p %p", cs, rad_req, rad_ans, diam_fw, cli);
+	CHECK_PARAMS(rad_req && (rad_req->hdr->code == RADIUS_CODE_ACCOUNTING_REQUEST) && rad_ans && diam_fw && *diam_fw);
+	
+	pref_len = strlen(prefix);
+	
+	/*
+	      Either NAS-IP-Address or NAS-Identifier MUST be present in a
+	      RADIUS Accounting-Request.  It SHOULD contain a NAS-Port or NAS-
+	      Port-Type attribute or both unless the service does not involve a
+	      port or the NAS does not distinguish among its ports.
+	*/
+	/* We also enforce that the message contains a CLASS attribute with Diameter/ prefix containing the Session-Id. */
+	for (idx = 0; idx < rad_req->attr_used; idx++) {
+		struct radius_attr_hdr * attr = (struct radius_attr_hdr *)(rad_req->buf + rad_req->attr_pos[idx]);
+		uint8_t * v = (uint8_t *)(attr + 1);
+		size_t attr_len = attr->length - sizeof(struct radius_attr_hdr);
+		
+		switch (attr->type) {
+			case RADIUS_ATTR_NAS_IP_ADDRESS:
+			case RADIUS_ATTR_NAS_IDENTIFIER:
+			case RADIUS_ATTR_NAS_IPV6_ADDRESS:
+				got_id = 1;
+				break;
+				
+			case RADIUS_ATTR_TERMINATION_ACTION:
+				CHECK_PARAMS( attr->length == 6 );
+				termination_action  = (v[0] << 24)
+					           | (v[1] << 16)
+					           | (v[2] <<  8)
+					           |  v[3] ;
+				break;
+				
+			case RADIUS_ATTR_ACCT_INPUT_GIGAWORDS:
+				CHECK_PARAMS( attr->length == 6 );
+				gigawords_in  = (v[0] << 24)
+					           | (v[1] << 16)
+					           | (v[2] <<  8)
+					           |  v[3] ;
+				break;
+				
+			case RADIUS_ATTR_ACCT_OUTPUT_GIGAWORDS:
+				CHECK_PARAMS( attr->length == 6 );
+				gigawords_out  = (v[0] << 24)
+					           | (v[1] << 16)
+					           | (v[2] <<  8)
+					           |  v[3] ;
+				break;
+				
+			case RADIUS_ATTR_CLASS:
+				if ((attr_len > pref_len ) && ! strncmp((char *)v, prefix, pref_len)) {
+					int i;
+					si = v + pref_len;
+					si_len = attr_len - pref_len;
+					TRACE_DEBUG(ANNOYING, "Found Class attribute with '%s' prefix (attr #%d), SI:'%.*s'.", prefix, idx, (int)si_len, si);
+					/* Remove from the message */
+					for (i = idx + 1; i < rad_req->attr_used; i++)
+						rad_req->attr_pos[i - 1] = rad_req->attr_pos[i];
+					rad_req->attr_used -= 1;
+				}
+				break;
+
+			case RADIUS_ATTR_USER_NAME:
+				if (attr_len) {
+					un = v;
+					un_len = attr_len;
+					TRACE_DEBUG(ANNOYING, "Found a User-Name attribute: '%.*s'", (int)un_len, un);
+				}
+				break;
+			
+		}
+	}
+	
+	/* Check basic information is there */
+	if (!got_id || radius_msg_get_attr_int32(rad_req, RADIUS_ATTR_ACCT_STATUS_TYPE, &status_type)) {
+		TRACE_DEBUG(INFO, "[acct.rgwx] RADIUS Account-Request from %s did not contain a NAS ip/identifier or Acct-Status-Type attribute, reject.", rgw_clients_id(cli));
+		return EINVAL;
+	}
+	
+	/*
+	      -- RFC2866:
+	      In Accounting-Request Packets, the Authenticator value is a 16
+	      octet MD5 [5] checksum, called the Request Authenticator.
+
+	      The NAS and RADIUS accounting server share a secret.  The Request
+	      Authenticator field in Accounting-Request packets contains a one-
+	      way MD5 hash calculated over a stream of octets consisting of the
+	      Code + Identifier + Length + 16 zero octets + request attributes +
+	      shared secret (where + indicates concatenation).  The 16 octet MD5
+	      hash value is stored in the Authenticator field of the
+	      Accounting-Request packet.
+
+	      Note that the Request Authenticator of an Accounting-Request can
+	      not be done the same way as the Request Authenticator of a RADIUS
+	      Access-Request, because there is no User-Password attribute in an
+	      Accounting-Request.
+	      
+	      
+	      -- RFC5080:
+	      The Request Authenticator field MUST contain the correct data, as
+	      given by the above calculation.  Invalid packets are silently
+	      discarded.  Note that some early implementations always set the
+	      Request Authenticator to all zeros.  New implementations of RADIUS
+	      clients MUST use the above algorithm to calculate the Request
+	      Authenticator field.  New RADIUS server implementations MUST
+	      silently discard invalid packets.
+	      
+	*/	
+	{
+		uint8_t save[MD5_MAC_LEN];
+		uint8_t * secret;
+		size_t secret_len;
+		
+		/* Get the shared secret */
+		CHECK_FCT(rgw_clients_getkey(cli, &secret, &secret_len));
+		
+		/* Copy the received Request Authenticator */
+		memcpy(&save[0], &rad_req->hdr->authenticator[0], MD5_MAC_LEN);
+		
+		/* Compute the same authenticator */
+		radius_msg_finish_acct(rad_req, secret, secret_len);
+		
+		/* And now compare with the received value */
+		if (memcmp(&save[0], &rad_req->hdr->authenticator[0], MD5_MAC_LEN)) {
+			/* Invalid authenticator */
+			TRACE_BUFFER(FD_LOG_DEBUG, FULL+1, "Received ReqAuth: ", &save[0], MD5_MAC_LEN, "" );
+			TRACE_BUFFER(FD_LOG_DEBUG, FULL+1, "Expected ReqAuth: ", &rad_req->hdr->authenticator[0], MD5_MAC_LEN, "" );
+			TRACE_DEBUG(INFO, "[acct.rgwx] Invalid Request Authenticator in Account-Request from %s, discarding the message.", rgw_clients_id(cli));
+			return EINVAL;
+		}
+	}
+	
+	
+	/* Handle the Accounting-On case: nothing to do, just reply OK */
+	if (status_type == RADIUS_ACCT_STATUS_TYPE_ACCOUNTING_ON) {
+		TRACE_DEBUG(FULL, "[acct.rgwx] Received Accounting-On Acct-Status-Type attribute, replying without translation to Diameter.");
+		CHECK_MALLOC( *rad_ans = radius_msg_new(RADIUS_CODE_ACCOUNTING_RESPONSE, rad_req->hdr->identifier) );
+		return -2;
+	}
+	
+	if (status_type == RADIUS_ACCT_STATUS_TYPE_ACCOUNTING_OFF) {
+		TRACE_DEBUG(FULL, "[acct.rgwx] Received Accounting-Off Acct-Status-Type attribute, we must terminate all active sessions.");
+		TODO("RADIUS side is rebooting, send STR on all sessions???");
+		return ENOTSUP;
+	}
+	
+	/* Check if we got a valid session information, otherwise the server will not be able to handle the data... */
+	if (!si) {
+		TRACE_DEBUG(INFO, "[acct.rgwx] RADIUS Account-Request from %s did not contain a CLASS attribute with Diameter session information, reject.", rgw_clients_id(cli));
+		return EINVAL;
+	}
+	
+	/* Add the Destination-Realm */
+	CHECK_FCT( fd_msg_avp_new ( cs->dict.Destination_Realm, 0, &avp ) );
+	idx = 0;
+	if (un && ! cs->ignore_nai) {
+		/* Is there an '@' in the user name? We don't care for decorated NAI here */
+		for (idx = un_len - 2; idx > 0; idx--) {
+			if (un[idx] == '@') {
+				idx++;
+				break;
+			}
+		}
+	}
+	if (idx == 0) {
+		/* Not found in the User-Name => we use the local domain of this gateway */
+		value.os.data = (uint8_t *)fd_g_config->cnf_diamrlm;
+		value.os.len  = fd_g_config->cnf_diamrlm_len;
+	} else {
+		value.os.data = un + idx;
+		value.os.len  = un_len - idx;
+	}
+	CHECK_FCT( fd_msg_avp_setvalue ( avp, &value ) );
+	CHECK_FCT( fd_msg_avp_add ( *diam_fw, MSG_BRW_FIRST_CHILD, avp) );
+	
+	/* Create the Session-Id AVP */
+	{
+		CHECK_FCT( fd_sess_fromsid_msg ( si, si_len, &sess, NULL) );
+		
+		TRACE_DEBUG(FULL, "[acct.rgwx] Translating new accounting message for session '%.*s'...", (int)si_len, si);
+		
+		/* Add the Session-Id AVP as first AVP */
+		CHECK_FCT( fd_msg_avp_new ( cs->dict.Session_Id, 0, &avp ) );
+		value.os.data = (unsigned char *)si;
+		value.os.len = si_len;
+		CHECK_FCT( fd_msg_avp_setvalue ( avp, &value ) );
+		CHECK_FCT( fd_msg_avp_add ( *diam_fw, MSG_BRW_FIRST_CHILD, avp) );
+		CHECK_FCT( fd_msg_sess_set(*diam_fw, sess) );
+	}
+	
+		
+	/* Add the command code */
+	{
+		struct msg_hdr * header = NULL;
+		CHECK_FCT( fd_msg_hdr ( *diam_fw, &header ) );
+		header->msg_flags = CMD_FLAG_REQUEST | CMD_FLAG_PROXIABLE;
+		header->msg_code = CC_AC;
+		header->msg_appl = AI_ACCT;
+		
+		/* Add the Acct-Application-Id */
+		CHECK_FCT( fd_msg_avp_new ( cs->dict.Acct_Application_Id, 0, &avp ) );
+		value.i32 = header->msg_appl;
+		CHECK_FCT( fd_msg_avp_setvalue ( avp, &value ) );
+		CHECK_FCT( fd_msg_avp_add ( *diam_fw, MSG_BRW_LAST_CHILD, avp) );
+		
+		/* save the end to end id */
+		e2eid = header->msg_eteid;
+	}
+	
+	/* Convert the RADIUS attributes, as they appear in the message */
+	for (idx = 0; idx < rad_req->attr_used; idx++) {
+		struct radius_attr_hdr * attr = (struct radius_attr_hdr *)(rad_req->buf + rad_req->attr_pos[idx]);
+
+		switch (attr->type) {
+			/*	
+			      Any attribute valid in a RADIUS Access-Request or Access-Accept
+			      packet is valid in a RADIUS Accounting-Request packet, except that
+			      the following attributes MUST NOT be present in an Accounting-
+			      Request:  User-Password, CHAP-Password, Reply-Message, State.
+			*/
+			case RADIUS_ATTR_USER_PASSWORD:
+			case RADIUS_ATTR_CHAP_PASSWORD:
+			case RADIUS_ATTR_REPLY_MESSAGE:
+			case RADIUS_ATTR_STATE:
+			case RADIUS_ATTR_MESSAGE_AUTHENTICATOR:
+			case RADIUS_ATTR_EAP_MESSAGE:
+				TRACE_DEBUG(INFO, "[acct.rgwx] RADIUS Account-Request contains a forbidden attribute (%hhd), reject.", attr->type);
+				return EINVAL;
+				
+			
+			/* This macro converts a RADIUS attribute to a Diameter AVP of type OctetString */
+			#define CONV2DIAM_STR( _dictobj_ )	\
+				CHECK_PARAMS( attr->length >= 2 );						\
+				/* Create the AVP with the specified dictionary model */			\
+				CHECK_FCT( fd_msg_avp_new ( cs->dict._dictobj_, 0, &avp ) );			\
+				value.os.len = attr->length - 2;						\
+				value.os.data = (unsigned char *)(attr + 1);					\
+				CHECK_FCT( fd_msg_avp_setvalue ( avp, &value ) );				\
+				/* Add the AVP in the Diameter message. */					\
+				CHECK_FCT( fd_msg_avp_add ( *diam_fw, MSG_BRW_LAST_CHILD, avp) );		\
+				
+			/* Same thing, for scalar AVPs of 32 bits */
+			#define CONV2DIAM_32B( _dictobj_ )	\
+				CHECK_PARAMS( attr->length == 6 );						\
+				CHECK_FCT( fd_msg_avp_new ( cs->dict._dictobj_, 0, &avp ) );			\
+				{										\
+					uint8_t * v = (uint8_t *)(attr + 1);					\
+					value.u32  = (v[0] << 24)						\
+					           | (v[1] << 16)						\
+					           | (v[2] <<  8)						\
+					           |  v[3] ;							\
+				}										\
+				CHECK_FCT( fd_msg_avp_setvalue ( avp, &value ) );				\
+				CHECK_FCT( fd_msg_avp_add ( *diam_fw, MSG_BRW_LAST_CHILD, avp) );		\
+				
+			/* And the 64b version */
+			#define CONV2DIAM_64B( _dictobj_ )	\
+				CHECK_PARAMS( attr->length == 10);						\
+				CHECK_FCT( fd_msg_avp_new ( cs->dict._dictobj_, 0, &avp ) );			\
+				{										\
+					uint8_t * v = (uint8_t *)(attr + 1);					\
+					value.u64  = ((uint64_t)(v[0]) << 56)					\
+					           | ((uint64_t)(v[1]) << 48)					\
+					           | ((uint64_t)(v[2]) << 40)					\
+					           | ((uint64_t)(v[3]) << 32)					\
+					           | ((uint64_t)(v[4]) << 24)					\
+					           | ((uint64_t)(v[5]) << 16)					\
+					           | ((uint64_t)(v[6]) <<  8)					\
+					           |  (uint64_t)(v[7]) ;					\
+				}										\
+				CHECK_FCT( fd_msg_avp_setvalue ( avp, &value ) );				\
+				CHECK_FCT( fd_msg_avp_add ( *diam_fw, MSG_BRW_LAST_CHILD, avp) );		\
+				
+			
+			/* Attributes as listed in RFC2866, section 5.13  and RFC4005, section 10.2.1 */
+			case RADIUS_ATTR_USER_NAME:
+				CONV2DIAM_STR( User_Name );
+				break;
+				
+			case RADIUS_ATTR_NAS_IP_ADDRESS:
+				CONV2DIAM_STR( NAS_IP_Address );
+				break;
+				
+			case RADIUS_ATTR_NAS_PORT:
+				CONV2DIAM_32B( NAS_Port );
+				break;
+				
+			case RADIUS_ATTR_SERVICE_TYPE:
+				CONV2DIAM_32B( Service_Type );
+				break;
+				
+			case RADIUS_ATTR_FRAMED_PROTOCOL:
+				CONV2DIAM_32B( Framed_Protocol );
+				break;
+				
+			case RADIUS_ATTR_FRAMED_IP_ADDRESS:
+				CONV2DIAM_STR( Framed_IP_Address );
+				break;
+				
+			case RADIUS_ATTR_FRAMED_IP_NETMASK:
+				CONV2DIAM_STR( Framed_IP_Netmask );
+				break;
+				
+			case RADIUS_ATTR_FRAMED_ROUTING:
+				CONV2DIAM_32B( Framed_Routing );
+				break;
+				
+			case RADIUS_ATTR_FILTER_ID:
+				CONV2DIAM_STR( Filter_Id );
+				break;
+				
+			case RADIUS_ATTR_FRAMED_MTU:
+				CONV2DIAM_32B( Framed_MTU );
+				break;
+			
+			case RADIUS_ATTR_FRAMED_COMPRESSION:
+				CONV2DIAM_32B( Framed_Compression );
+				break;
+			
+			case RADIUS_ATTR_LOGIN_IP_HOST:
+				CONV2DIAM_STR( Login_IP_Host );
+				break;
+				
+			case RADIUS_ATTR_LOGIN_SERVICE:
+				CONV2DIAM_32B( Login_Service );
+				break;
+				
+			case RADIUS_ATTR_LOGIN_TCP_PORT:
+				CONV2DIAM_32B( Login_TCP_Port );
+				break;
+				
+			case RADIUS_ATTR_CALLBACK_NUMBER:
+				CONV2DIAM_STR( Callback_Number );
+				break;
+				
+			case RADIUS_ATTR_CALLBACK_ID:
+				CONV2DIAM_STR( Callback_Id );
+				break;
+				
+			case RADIUS_ATTR_FRAMED_ROUTE:
+				CONV2DIAM_STR( Framed_Route );
+				break;
+				
+			case RADIUS_ATTR_FRAMED_IPX_NETWORK:
+				CONV2DIAM_32B( Framed_IPX_Network );
+				break;
+				
+			case RADIUS_ATTR_CLASS:
+				CONV2DIAM_STR( Class );
+				/* In addition, save the data in the session if it is "our" CLASS_AAI_PREFIX Class attribute */
+				{
+					char buf[32];
+					char * attr_val, *auth_val;
+					attr_val = (char *)(attr + 1);
+					auth_val = attr_val + CONSTSTRLEN(CLASS_AAI_PREFIX);
+					if (	(attr->length > sizeof(struct radius_attr_hdr) + CONSTSTRLEN(CLASS_AAI_PREFIX)  )
+						&& (attr->length < sizeof(struct radius_attr_hdr) + CONSTSTRLEN(CLASS_AAI_PREFIX) + sizeof(buf))
+						&& ! strncmp(attr_val, CLASS_AAI_PREFIX, CONSTSTRLEN(CLASS_AAI_PREFIX))) {
+					
+						memset(buf, 0, sizeof(buf));
+						memcpy(buf, auth_val, attr->length - sizeof(struct radius_attr_hdr) - CONSTSTRLEN(CLASS_AAI_PREFIX));
+						if (sscanf(buf, "%u", &auth_appl) == 1) {
+							TRACE_DEBUG(ANNOYING, "Found Class attribute with '%s' prefix (attr #%d), AAI:%u.", CLASS_AAI_PREFIX, idx, auth_appl);
+						}
+					}
+				}
+				break;
+			
+			case RADIUS_ATTR_VENDOR_SPECIFIC:
+				if (attr->length >= 6) {
+					uint32_t vendor_id;
+					uint8_t * c = (uint8_t *)(attr + 1);
+					
+					vendor_id = c[0] << 24 | c[1] << 16 | c[2] << 8 | c[3];
+					c += 4;
+					
+					switch (vendor_id) {
+						
+						/* For the vendors we KNOW they follow the VSA recommended format, we convert following the rules of RFC4005 (9.6.2) */
+						case RADIUS_VENDOR_ID_MICROSOFT : /* RFC 2548 */
+						/* other vendors ? */
+						{
+							size_t left;
+							struct radius_attr_vendor *vtlv;
+							
+							left = attr->length - 6;
+							vtlv = (struct radius_attr_vendor *)c;
+						
+							while ((left >= 2) && (vtlv->vendor_length <= left)) {
+								/* Search our dictionary for corresponding Vendor's AVP */
+								struct dict_avp_request req;
+								struct dict_object * avp_model = NULL;
+								memset(&req, 0, sizeof(struct dict_avp_request));
+								req.avp_vendor = vendor_id;
+								req.avp_code = vtlv->vendor_type;
+								
+								CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_CODE_AND_VENDOR, &req, &avp_model, 0) );
+								if (!avp_model) {
+									TRACE_DEBUG(FULL, "Unknown attribute (vendor 0x%x, code 0x%x) ignored.", req.avp_vendor, req.avp_code);
+								} else {
+									CHECK_FCT( fd_msg_avp_new ( avp_model, 0, &avp ) );
+									value.os.len = vtlv->vendor_length - 2;
+									value.os.data = (unsigned char *)(vtlv + 1);
+									CHECK_FCT( fd_msg_avp_setvalue ( avp, &value ) );
+									CHECK_FCT( fd_msg_avp_add ( *diam_fw, MSG_BRW_LAST_CHILD, avp) );
+								}
+								c += vtlv->vendor_length;
+								left -= vtlv->vendor_length;
+								vtlv = (struct radius_attr_vendor *)c;
+							}
+						}
+						break;
+						
+						/* Other vendors we KNOw how to convert the attributes would be added here... */
+						/* case RADIUS_VENDOR_ID_CISCO :
+							break; */
+						/* case RADIUS_VENDOR_ID_IETF : (extended RADIUS attributes)
+							break; */
+						
+						/* When we don't know, just discard the attribute... VSA are optional with regards to RADIUS anyway */
+						default:
+							/* do nothing */
+							TRACE_DEBUG(FULL, "VSA attribute from vendor %d discarded", vendor_id);
+							
+					}
+				}
+				break;
+				
+			case RADIUS_ATTR_SESSION_TIMEOUT:
+				/* Translation depends on Termination-Action : rfc4005#section-9.2.1 */
+				if (termination_action != RADIUS_TERMINATION_ACTION_RADIUS_REQUEST) {
+					CONV2DIAM_32B( Session_Timeout );
+				} else {
+					CONV2DIAM_32B( Authorization_Lifetime );
+					/* And add this additional AVP */
+					CHECK_FCT( fd_msg_avp_new ( cs->dict.Re_Auth_Request_Type, 0, &avp ) );
+					value.u32 = ACV_ART_AUTHORIZE_AUTHENTICATE;
+					CHECK_FCT( fd_msg_avp_setvalue ( avp, &value ) );
+					CHECK_FCT( fd_msg_avp_add ( *diam_fw, MSG_BRW_LAST_CHILD, avp) );
+				}
+				break;
+				
+			case RADIUS_ATTR_IDLE_TIMEOUT:
+				CONV2DIAM_32B( Idle_Timeout );
+				break;
+			
+			case RADIUS_ATTR_TERMINATION_ACTION:
+				/* Just remove */
+				break;
+			
+			case RADIUS_ATTR_CALLED_STATION_ID:
+				CONV2DIAM_STR( Called_Station_Id );
+				break;
+			
+			case RADIUS_ATTR_CALLING_STATION_ID:
+				CONV2DIAM_STR( Calling_Station_Id );
+				break;
+			
+			case RADIUS_ATTR_NAS_IDENTIFIER:
+				CONV2DIAM_STR( NAS_Identifier );
+				break;
+			
+			/* Proxy-State is handled by echo_drop.rgwx plugin, we ignore it here */
+			
+			case RADIUS_ATTR_LOGIN_LAT_SERVICE:
+				CONV2DIAM_STR( Login_LAT_Service );
+				break;
+			
+			case RADIUS_ATTR_LOGIN_LAT_NODE:
+				CONV2DIAM_STR( Login_LAT_Node );
+				break;
+			
+			case RADIUS_ATTR_LOGIN_LAT_GROUP:
+				CONV2DIAM_STR( Login_LAT_Group );
+				break;
+			
+			case RADIUS_ATTR_FRAMED_APPLETALK_LINK:
+				CONV2DIAM_32B( Framed_AppleTalk_Link );
+				break;
+				
+			case RADIUS_ATTR_FRAMED_APPLETALK_NETWORK:
+				CONV2DIAM_32B( Framed_AppleTalk_Network );
+				break;
+				
+			case RADIUS_ATTR_FRAMED_APPLETALK_ZONE:
+				CONV2DIAM_STR( Framed_AppleTalk_Zone );
+				break;
+			
+			case RADIUS_ATTR_ACCT_STATUS_TYPE:
+				/*
+				      -  If the RADIUS message received is an Accounting-Request, the
+        				 Acct-Status-Type attribute value must be converted to a
+        				 Accounting-Record-Type AVP value.  If the Acct-Status-Type
+        				 attribute value is STOP, the local server MUST issue a
+        				 Session-Termination-Request message once the Diameter
+        				 Accounting-Answer message has been received.
+				*/
+				switch (status_type) {
+					case RADIUS_ACCT_STATUS_TYPE_START:
+						value.u32 = ACV_ART_START_RECORD;
+						break;
+					case RADIUS_ACCT_STATUS_TYPE_STOP:
+						value.u32 = ACV_ART_STOP_RECORD;
+						send_str = 1; /* Register this info in the session */
+						break;
+					case RADIUS_ACCT_STATUS_TYPE_INTERIM_UPDATE:
+						value.u32 = ACV_ART_INTERIM_RECORD;
+						break;
+					default:
+						TRACE_DEBUG(INFO, "Unknown RADIUS_ATTR_ACCT_STATUS_TYPE value %d, aborting...", status_type);
+						return ENOTSUP;
+				}
+				CHECK_FCT( fd_msg_avp_new ( cs->dict.Accounting_Record_Type, 0, &avp ) );
+				CHECK_FCT( fd_msg_avp_setvalue ( avp, &value ) );
+				CHECK_FCT( fd_msg_avp_add ( *diam_fw, MSG_BRW_LAST_CHILD, avp) );
+				
+				/* While here, we also add the Accouting-Record-Number AVP.
+					  The Accounting-Record-Number AVP (AVP Code 485) is of type Unsigned32
+					   and identifies this record within one session.  As Session-Id AVPs
+					   are globally unique, the combination of Session-Id and Accounting-
+					   Record-Number AVPs is also globally unique, and can be used in
+					   matching accounting records with confirmations.  An easy way to
+					   produce unique numbers is to set the value to 0 for records of type
+					   EVENT_RECORD and START_RECORD, and set the value to 1 for the first
+					   INTERIM_RECORD, 2 for the second, and so on until the value for
+					   STOP_RECORD is one more than for the last INTERIM_RECORD.
+					   
+				  -- we actually use the end-to-end id of the message here, which remains constant
+				    if we send a duplicate, so it has the same properties as the suggested algorithm.
+				    Anyway, it assumes that we are not converting twice the same RADIUS message.
+				   . */
+				CHECK_FCT( fd_msg_avp_new ( cs->dict.Accounting_Record_Number, 0, &avp ) );
+				value.u32 = e2eid;
+				CHECK_FCT( fd_msg_avp_setvalue ( avp, &value ) );
+				CHECK_FCT( fd_msg_avp_add ( *diam_fw, MSG_BRW_LAST_CHILD, avp) );
+				
+				break;
+			
+			case RADIUS_ATTR_ACCT_DELAY_TIME:
+				CONV2DIAM_32B( Acct_Delay_Time );
+				break;
+				
+			/*
+			      -  If the RADIUS message contains the Accounting-Input-Octets,
+        			 Accounting-Input-Packets, Accounting-Output-Octets, or
+        			 Accounting-Output-Packets, these attributes must be converted
+        			 to the Diameter equivalents.  Further, if the Acct-Input-
+        			 Gigawords or Acct-Output-Gigawords attributes are present,
+        			 these must be used to properly compute the Diameter accounting
+        			 AVPs.
+			*/
+			case RADIUS_ATTR_ACCT_INPUT_OCTETS:
+				memset(&value, 0, sizeof(value));
+				{
+					uint8_t * v = (uint8_t *)(attr + 1);
+					value.u64  = (v[0] << 24)
+					           | (v[1] << 16)
+					           | (v[2] <<  8)
+					           |  v[3] ;
+				}
+				value.u64 += ((uint64_t)gigawords_in << 32);
+				CHECK_FCT( fd_msg_avp_new ( cs->dict.Accounting_Input_Octets, 0, &avp ) );
+				CHECK_FCT( fd_msg_avp_setvalue ( avp, &value ) );
+				CHECK_FCT( fd_msg_avp_add ( *diam_fw, MSG_BRW_LAST_CHILD, avp) );
+				break;
+				
+			case RADIUS_ATTR_ACCT_OUTPUT_OCTETS:
+				memset(&value, 0, sizeof(value));
+				{
+					uint8_t * v = (uint8_t *)(attr + 1);
+					value.u64  = (v[0] << 24)
+					           | (v[1] << 16)
+					           | (v[2] <<  8)
+					           |  v[3] ;
+				}
+				value.u64 += ((uint64_t)gigawords_out << 32);
+				CHECK_FCT( fd_msg_avp_new ( cs->dict.Accounting_Output_Octets, 0, &avp ) );
+				CHECK_FCT( fd_msg_avp_setvalue ( avp, &value ) );
+				CHECK_FCT( fd_msg_avp_add ( *diam_fw, MSG_BRW_LAST_CHILD, avp) );
+				break;
+				
+			case RADIUS_ATTR_ACCT_SESSION_ID:
+				CONV2DIAM_STR( Acct_Session_Id );
+				break;
+				
+			case RADIUS_ATTR_ACCT_AUTHENTIC:
+				CONV2DIAM_32B( Acct_Authentic );
+				break;
+				
+			case RADIUS_ATTR_ACCT_SESSION_TIME:
+				CONV2DIAM_32B( Acct_Session_Time );
+				break;
+				
+			case RADIUS_ATTR_ACCT_INPUT_PACKETS:
+				memset(&value, 0, sizeof(value));
+				{
+					uint8_t * v = (uint8_t *)(attr + 1);
+					value.u64  = (v[0] << 24)
+					           | (v[1] << 16)
+					           | (v[2] <<  8)
+					           |  v[3] ;
+				}
+				/* value.u64 += (gigawords_in << 32); */
+				CHECK_FCT( fd_msg_avp_new ( cs->dict.Accounting_Input_Packets, 0, &avp ) );
+				CHECK_FCT( fd_msg_avp_setvalue ( avp, &value ) );
+				CHECK_FCT( fd_msg_avp_add ( *diam_fw, MSG_BRW_LAST_CHILD, avp) );
+				break;
+				
+			case RADIUS_ATTR_ACCT_OUTPUT_PACKETS:
+				memset(&value, 0, sizeof(value));
+				{
+					uint8_t * v = (uint8_t *)(attr + 1);
+					value.u64  = (v[0] << 24)
+					           | (v[1] << 16)
+					           | (v[2] <<  8)
+					           |  v[3] ;
+				}
+				/* value.u64 += (gigawords_out << 32); */
+				CHECK_FCT( fd_msg_avp_new ( cs->dict.Accounting_Output_Packets, 0, &avp ) );
+				CHECK_FCT( fd_msg_avp_setvalue ( avp, &value ) );
+				CHECK_FCT( fd_msg_avp_add ( *diam_fw, MSG_BRW_LAST_CHILD, avp) );
+				break;
+				
+			/*
+			      -  If the Accounting message contains an Acct-Termination-Cause
+        			 attribute, it should be translated to the equivalent
+        			 Termination-Cause AVP value.
+			*/
+			case RADIUS_ATTR_ACCT_TERMINATE_CAUSE:
+				/* rfc4005#section-9.3.5 */
+				{
+					uint8_t * v = (uint8_t *)(attr + 1);
+					str_cause  = (v[0] << 24)
+					           | (v[1] << 16)
+					           | (v[2] <<  8)
+					           |  v[3] ;
+				}
+				str_cause += 10; /* This seems to be the rule, we can modify later if needed */
+				break;
+
+			case RADIUS_ATTR_ACCT_MULTI_SESSION_ID:
+				CONV2DIAM_STR( Acct_Multi_Session_Id );
+				break;
+				
+			case RADIUS_ATTR_ACCT_LINK_COUNT:
+				CONV2DIAM_32B( Acct_Link_Count );
+				break;
+				
+			/* CHAP-Challenge is not present in Accounting-Request */
+			
+			case RADIUS_ATTR_NAS_PORT_TYPE:
+				CONV2DIAM_32B( NAS_Port_Type );
+				break;
+			
+			case RADIUS_ATTR_PORT_LIMIT:
+				CONV2DIAM_32B( Port_Limit );
+				break;
+			
+			case RADIUS_ATTR_LOGIN_LAT_PORT:
+				CONV2DIAM_STR( Login_LAT_Port );
+				break;
+			
+			/* RFC 3162 */	
+			case RADIUS_ATTR_NAS_IPV6_ADDRESS:
+				CONV2DIAM_STR( NAS_IPv6_Address );
+				break;
+				
+			case RADIUS_ATTR_FRAMED_INTERFACE_ID:
+				CONV2DIAM_64B( Framed_Interface_Id );
+				break;
+				
+			case RADIUS_ATTR_FRAMED_IPV6_PREFIX:
+				CONV2DIAM_STR( Framed_IPv6_Prefix );
+				break;
+				
+			case RADIUS_ATTR_LOGIN_IPV6_HOST:
+				CONV2DIAM_STR( Login_IPv6_Host );
+				break;
+				
+			case RADIUS_ATTR_FRAMED_IPV6_ROUTE:
+				CONV2DIAM_STR( Framed_IPv6_Route );
+				break;
+				
+			case RADIUS_ATTR_FRAMED_IPV6_POOL:
+				CONV2DIAM_STR( Framed_IPv6_Pool );
+				break;
+				
+			/* RFC 2868 */
+			/* Prepare the top-level Tunneling AVP for each tag values, as needed, and add to the Diameter message.
+				This macro is called when an AVP is added inside the group, so we will not have empty grouped AVPs */
+			#define AVP_TUN_PREPARE() {										\
+						if (avp_tun == NULL) {								\
+							CHECK_MALLOC( avp_tun = calloc(sizeof(struct avp *), 32 ) );		\
+						}										\
+						tag = *(uint8_t *)(attr + 1);							\
+						if (tag > 0x1F) tag = 0;							\
+						if (avp_tun[tag] == NULL) {							\
+							CHECK_FCT( fd_msg_avp_new ( cs->dict.Tunneling, 0, &avp_tun[tag] ) );	\
+							CHECK_FCT( fd_msg_avp_add (*diam_fw, MSG_BRW_LAST_CHILD, avp_tun[tag]));\
+						}										\
+					}
+			
+			/* Convert an attribute to an OctetString AVP and add inside the Tunneling AVP corresponding to the tag */
+			#define CONV2DIAM_TUN_STR( _dictobj_ ) {						\
+				uint8_t tag;									\
+				CHECK_PARAMS( attr->length >= 3);						\
+				AVP_TUN_PREPARE();								\
+				CHECK_FCT( fd_msg_avp_new ( cs->dict._dictobj_, 0, &avp ) );			\
+				value.os.len = attr->length - (tag ? 3 : 2);					\
+				value.os.data = ((unsigned char *)(attr + 1)) + (tag ? 1 : 0);			\
+				CHECK_FCT( fd_msg_avp_setvalue ( avp, &value ) );				\
+				CHECK_FCT( fd_msg_avp_add ( avp_tun[tag], MSG_BRW_LAST_CHILD, avp) );		\
+				}
+				
+			/* Convert an attribute to a scalar AVP and add inside the Tunneling AVP corresponding to the tag */
+			#define CONV2DIAM_TUN_24B( _dictobj_ ) {						\
+				uint8_t tag;									\
+				CHECK_PARAMS( attr->length == 6);						\
+				AVP_TUN_PREPARE();								\
+				CHECK_FCT( fd_msg_avp_new ( cs->dict._dictobj_, 0, &avp ) );			\
+				{										\
+					uint8_t * v = (uint8_t *)(attr + 1);					\
+					value.u32 = (v[1] << 16) | (v[2] <<8) | v[3] ;				\
+				}										\
+				CHECK_FCT( fd_msg_avp_setvalue ( avp, &value ) );				\
+				CHECK_FCT( fd_msg_avp_add ( avp_tun[tag], MSG_BRW_LAST_CHILD, avp) );		\
+				}
+
+			/*
+			      -  If the RADIUS message contains Tunnel information [RADTunnels],
+        			 the attributes or tagged groups should each be converted to a
+        			 Diameter Tunneling Grouped AVP set.  If the tunnel information
+        			 contains a Tunnel-Password attribute, the RADIUS encryption
+        			 must be resolved, and the password forwarded, by using Diameter
+        			 security methods.
+				    -> If the RADIUS message does not use properly the Tag info, result is unpredictable here.. 
+			*/
+			case RADIUS_ATTR_TUNNEL_TYPE:
+				CONV2DIAM_TUN_24B( Tunnel_Type );
+				break;
+			
+			case RADIUS_ATTR_TUNNEL_MEDIUM_TYPE:
+				CONV2DIAM_TUN_24B( Tunnel_Medium_Type );
+				break;
+			
+			case RADIUS_ATTR_TUNNEL_CLIENT_ENDPOINT:
+				CONV2DIAM_TUN_STR( Tunnel_Client_Endpoint );
+				break;
+			
+			case RADIUS_ATTR_TUNNEL_SERVER_ENDPOINT:
+				CONV2DIAM_TUN_STR( Tunnel_Server_Endpoint );
+				break;
+			
+			/* Tunnel-Password never present in an Accounting-Request */
+
+			case RADIUS_ATTR_TUNNEL_PRIVATE_GROUP_ID:
+				CONV2DIAM_TUN_STR( Tunnel_Private_Group_Id );
+				break;
+			
+			case RADIUS_ATTR_TUNNEL_ASSIGNMENT_ID:
+				CONV2DIAM_TUN_STR( Tunnel_Assignment_Id );
+				break;
+			
+			/* Tunnel-Reference never present in an Accounting-Request */
+			
+			case RADIUS_ATTR_TUNNEL_CLIENT_AUTH_ID:
+				CONV2DIAM_TUN_STR( Tunnel_Client_Auth_Id );
+				break;
+			
+			case RADIUS_ATTR_TUNNEL_SERVER_AUTH_ID:
+				CONV2DIAM_TUN_STR( Tunnel_Server_Auth_Id );
+				break;
+			
+		/* RFC 2869 */
+			/*
+			                                      Acct-Input-Gigawords, Acct-Output-
+			   Gigawords, Event-Timestamp, and NAS-Port-Id may have 0-1 instances in
+			   an Accounting-Request packet.  Connect-Info may have 0+ instances in
+			   an Accounting-Request packet.  The other attributes added in this
+			   document must not be present in an Accounting-Request.
+			*/
+			case RADIUS_ATTR_ACCT_INPUT_GIGAWORDS:
+				break; /* we already saved the value in gigawords_in */
+				
+			case RADIUS_ATTR_ACCT_OUTPUT_GIGAWORDS:
+				break; /* we already saved the value in gigawords_out */
+				
+			case RADIUS_ATTR_EVENT_TIMESTAMP:
+				/* RADIUS: 
+				      The Value field is four octets encoding an unsigned integer with
+				      the number of seconds since January 1, 1970 00:00 UTC.
+				   Diameter:
+				      The Time format is derived from the OctetString AVP Base Format.
+				      The string MUST contain four octets, in the same format as the
+				      first four bytes are in the NTP timestamp format.  The NTP
+				      Timestamp format is defined in Chapter 3 of [RFC4330].
+
+				      This represents the number of seconds since 0h on 1 January 1900
+				      with respect to the Coordinated Universal Time (UTC).
+				      
+				      -- RFC4330:
+					 NTP timestamps are represented as a 64-bit unsigned
+					   fixed-point number, in seconds relative to 0h on 1 January 1900.  The
+					   integer part is in the first 32 bits, and the fraction part in the
+					   last 32 bits.  In the fraction part, the non-significant low-order
+					   bits are not specified and are ordinarily set to 0.
+				*/
+				{
+					uint32_t ts;
+					
+					uint8_t * v = (uint8_t *)(attr + 1);
+					/* Read the RADIUS attribute value */
+					ts  = (v[0] << 24)
+					           | (v[1] << 16)
+					           | (v[2] <<  8)
+					           |  v[3] ;
+					
+					/* Add the 70 missing years */
+					ts += 2208988800U; /* 60 * 60 * 24 * ( 365 * 70 + 17 ) */
+					
+					/* Convert to network byte order */
+					ts = htonl(ts);
+					
+					 /* Diameter Time datatype is derived from OctetString */
+					value.os.data = (void *) &ts;
+					value.os.len = sizeof(uint32_t);
+					
+					CHECK_FCT( fd_msg_avp_new ( cs->dict.Event_Timestamp, 0, &avp ) );
+					CHECK_FCT( fd_msg_avp_setvalue ( avp, &value ) );
+					CHECK_FCT( fd_msg_avp_add ( *diam_fw, MSG_BRW_LAST_CHILD, avp) );
+				}
+				break;
+			
+			case RADIUS_ATTR_NAS_PORT_ID:
+				CONV2DIAM_STR( NAS_Port_Id );
+				break;
+						
+			case RADIUS_ATTR_CONNECT_INFO:
+				CONV2DIAM_STR( Connect_Info );
+				break;
+			
+			case RADIUS_ATTR_FRAMED_POOL: /* To follow the IPv6 version */
+				CONV2DIAM_STR( Framed_Pool );
+				break;
+				
+			
+		/* RFC 3579 */
+			/*
+			 The EAP-Message and Message-Authenticator attributes specified in
+			   this document MUST NOT be present in an Accounting-Request.
+			*/				
+			case RADIUS_ATTR_ORIGINATING_LINE_INFO:
+				CONV2DIAM_STR( Originating_Line_Info );
+				break;
+				
+		/* Default */		
+			default: /* unknown attribute */
+				/* We just keep the attribute in the RADIUS message */
+				rad_req->attr_pos[nattr_used++] = rad_req->attr_pos[idx];
+		}
+	}
+	
+	/* Update the radius message to remove all handled attributes */
+	rad_req->attr_used = nattr_used;
+	
+	/* Store useful information in the session */
+	{
+		struct sess_state * st;
+		
+		CHECK_MALLOC( st = malloc(sizeof(struct sess_state)) );
+		memset(st, 0, sizeof(struct sess_state));
+		st->auth_appl = auth_appl;
+		if (auth_appl) { /* We use the value 0 for servers which indicated NO STATE MAINTAINED, hence have no need for STR */
+			st->send_str = send_str;
+		}
+		st->term_cause = str_cause;
+		CHECK_FCT( fd_sess_state_store( cs->sess_hdl, sess, &st ) );
+	}
+	
+	return 0;
+}
+
+/* Callback when an STA is received after having sent an STR. */
+static void handle_sta(void * data, struct msg ** answer)
+{
+	struct rgwp_config * cs = data;
+	struct avp *avp;
+	struct avp_hdr *ahdr;
+	
+	CHECK_PARAMS_DO( data && answer && *answer, goto out );
+	
+	/* Check the Diameter error code */
+	CHECK_FCT_DO( fd_msg_search_avp (*answer, cs->dict.Result_Code, &avp), goto out );
+	CHECK_PARAMS_DO( avp, goto out );
+	CHECK_FCT_DO( fd_msg_avp_hdr ( avp, &ahdr ), goto out );
+	if (ahdr->avp_value->u32 != ER_DIAMETER_SUCCESS)
+		goto out;
+	
+	/* OK, discard the message without complaining */
+	fd_msg_free(*answer);
+	*answer = NULL;
+		
+out:
+	if (answer && *answer) {
+		char * buf = NULL; size_t buflen;
+		CHECK_MALLOC_DO( fd_msg_dump_treeview(&buf, &buflen, NULL, *answer, NULL, 0, 1), );
+		TRACE_DEBUG(INFO, "Received the following problematic STA message, discarding anyway: %s", buf ?: "<error>");
+		free(buf);
+		
+		fd_msg_free(*answer);
+		*answer = NULL;
+	}
+	return;
+}
+
+static int acct_diam_ans( struct rgwp_config * cs, struct msg ** diam_ans, struct radius_msg ** rad_fw, struct rgw_client * cli )
+{
+	struct session * sess;
+	struct sess_state * st = NULL, stloc;
+	struct avp *avp, *next;
+	struct avp_hdr *ahdr, *oh, *or;
+	os0_t sid = NULL;
+	size_t sidlen;
+	
+	TRACE_ENTRY("%p %p %p %p", cs, diam_ans, rad_fw, cli);
+	CHECK_PARAMS(cs);
+	
+	CHECK_FCT( fd_msg_sess_get(fd_g_config->cnf_dict, *diam_ans, &sess, NULL) );
+	if (sess) {
+		CHECK_FCT( fd_sess_state_retrieve( cs->sess_hdl, sess, &st ) );
+		CHECK_FCT( fd_sess_getsid(sess, &sid, &sidlen) );
+	}
+	
+	if (!st) {
+		TRACE_DEBUG(INFO, "Received an ACA without corresponding session information, cannot translate to RADIUS");
+		return EINVAL;
+	}
+	
+	/* Free the state */
+	memcpy(&stloc, st, sizeof(struct sess_state));
+	free(st);
+	st = &stloc;
+	
+	/* Search these AVPs first */
+	CHECK_FCT( fd_msg_search_avp (*diam_ans, cs->dict.Origin_Host, &avp) );
+	CHECK_FCT( fd_msg_avp_hdr ( avp, &oh ) );
+
+	CHECK_FCT( fd_msg_search_avp (*diam_ans, cs->dict.Origin_Realm, &avp) );
+	CHECK_FCT( fd_msg_avp_hdr ( avp, &or ) );
+
+	/* Check the Diameter error code */
+	CHECK_FCT( fd_msg_search_avp (*diam_ans, cs->dict.Result_Code, &avp) );
+	ASSERT( avp ); /* otherwise the message should have been discarded a lot earlier because of ABNF */
+	CHECK_FCT( fd_msg_avp_hdr ( avp, &ahdr ) );
+	switch (ahdr->avp_value->u32) {
+		case ER_DIAMETER_SUCCESS:
+		case ER_DIAMETER_LIMITED_SUCCESS:
+			(*rad_fw)->hdr->code = RADIUS_CODE_ACCOUNTING_RESPONSE;
+			break;
+		
+		default:
+			fd_log_debug("[acct.rgwx] Received Diameter answer with error code '%d' from server '%.*s', session %.*s, not translating into Accounting-Response",
+					ahdr->avp_value->u32, 
+					(int)oh->avp_value->os.len, oh->avp_value->os.data,
+					(int)sidlen, sid);
+			CHECK_FCT( fd_msg_search_avp (*diam_ans, cs->dict.Error_Message, &avp) );
+			if (avp) {
+				CHECK_FCT( fd_msg_avp_hdr ( avp, &ahdr ) );
+				fd_log_debug("[acct.rgwx]   Error-Message content: '%.*s'",
+						(int)ahdr->avp_value->os.len, ahdr->avp_value->os.data);
+			}
+			CHECK_FCT( fd_msg_search_avp (*diam_ans, cs->dict.Error_Reporting_Host, &avp) );
+			if (avp) {
+				CHECK_FCT( fd_msg_avp_hdr ( avp, &ahdr ) );
+				fd_log_debug("[acct.rgwx]   Error-Reporting-Host: '%.*s'",
+						(int)ahdr->avp_value->os.len, ahdr->avp_value->os.data);
+			}
+			CHECK_FCT( fd_msg_search_avp (*diam_ans, cs->dict.Failed_AVP, &avp) );
+			if (avp) {
+				fd_log_debug("[acct.rgwx]   Failed-AVP was included in the message.");
+				/* Dump its content ? */
+			}
+			
+			/* Now, destroy the Diameter message, since we know it is not converted to RADIUS */
+			CHECK_FCT( fd_msg_free(*diam_ans) );
+			*diam_ans = NULL;
+
+			return -1;
+	}
+	/* Remove this Result-Code avp */
+	CHECK_FCT( fd_msg_free( avp ) );
+	
+	/* If it was a response to a STOP record, we must send an STR for this session */
+	if (st->send_str) {
+		struct msg * str = NULL;
+		struct msg_hdr * hdr = NULL;
+		DiamId_t fqdn;
+		size_t fqdn_len;
+		DiamId_t realm;
+		size_t realm_len;
+		union avp_value avp_val;
+		
+		/* Create a new STR message */
+		CHECK_FCT(  fd_msg_new ( cs->dict.Session_Termination_Request, MSGFL_ALLOC_ETEID, &str )  );
+		
+		/* Set the application-id to the auth application if available, accounting otherwise (not sure what is actually expected...) */
+		CHECK_FCT( fd_msg_hdr ( str, &hdr ) );
+		hdr->msg_appl = st->auth_appl ?: AI_ACCT;
+		
+		/* Add the Session-Id AVP as first AVP */
+		CHECK_FCT( fd_msg_avp_new (  cs->dict.Session_Id, 0, &avp ) );
+		avp_val.os.data = sid;
+		avp_val.os.len = sidlen;
+		CHECK_FCT( fd_msg_avp_setvalue ( avp, &avp_val ) );
+		CHECK_FCT( fd_msg_avp_add ( str, MSG_BRW_FIRST_CHILD, avp) );
+		CHECK_FCT( fd_sess_ref_msg(sess) );
+
+		/* Add the Destination-Realm as next AVP */
+		CHECK_FCT( fd_msg_avp_new ( cs->dict.Destination_Realm, 0, &avp ) );
+		CHECK_FCT( fd_msg_avp_setvalue ( avp, or->avp_value ) );
+		CHECK_FCT( fd_msg_avp_add ( str, MSG_BRW_LAST_CHILD, avp) );
+
+		/* Get information on the NAS */
+		CHECK_FCT( rgw_clients_get_origin(cli, &fqdn, &fqdn_len, &realm, &realm_len) );
+
+		/* Add the Origin-Host as next AVP */
+		CHECK_FCT( fd_msg_avp_new ( cs->dict.Origin_Host, 0, &avp ) );
+		memset(&avp_val, 0, sizeof(avp_val));
+		avp_val.os.data = (unsigned char *)fqdn;
+		avp_val.os.len = fqdn_len;
+		CHECK_FCT( fd_msg_avp_setvalue ( avp, &avp_val ) );
+		CHECK_FCT( fd_msg_avp_add ( str, MSG_BRW_LAST_CHILD, avp) );
+
+		/* Add the Origin-Realm as next AVP */
+		CHECK_FCT( fd_msg_avp_new ( cs->dict.Origin_Realm, 0, &avp ) );
+		memset(&avp_val, 0, sizeof(avp_val));
+		avp_val.os.data = (unsigned char *)realm;
+		avp_val.os.len = realm_len;
+		CHECK_FCT( fd_msg_avp_setvalue ( avp, &avp_val ) );
+		CHECK_FCT( fd_msg_avp_add ( str, MSG_BRW_LAST_CHILD, avp) );
+		
+		/* Auth-Application-Id -- if we did not get it from our Class attribute, we just set "0" */
+		CHECK_FCT( fd_msg_avp_new ( cs->dict.Auth_Application_Id, 0, &avp ) );
+		avp_val.u32 = st->auth_appl;
+		CHECK_FCT( fd_msg_avp_setvalue ( avp, &avp_val ) );
+		CHECK_FCT( fd_msg_avp_add ( str, MSG_BRW_LAST_CHILD, avp) );
+		
+		/* Termination-Cause */
+		CHECK_FCT( fd_msg_avp_new ( cs->dict.Termination_Cause, 0, &avp ) );
+		avp_val.u32 = st->term_cause;
+		CHECK_FCT( fd_msg_avp_setvalue ( avp, &avp_val ) );
+		CHECK_FCT( fd_msg_avp_add ( str, MSG_BRW_LAST_CHILD, avp) );
+		
+		/* Send this message */
+		CHECK_FCT( fd_msg_send ( &str, handle_sta, cs ) );
+	}
+	
+	/* 
+		No attributes should be found in
+		   Accounting-Response packets except Proxy-State and possibly Vendor-
+		   Specific.
+	*/
+
+	/* Now loop in the list of AVPs and convert those that we know how */
+	CHECK_FCT( fd_msg_browse(*diam_ans, MSG_BRW_FIRST_CHILD, &next, NULL) );
+	
+	while (next) {
+		int handled = 1;
+		avp = next;
+		CHECK_FCT( fd_msg_browse(avp, MSG_BRW_NEXT, &next, NULL) );
+		
+		CHECK_FCT( fd_msg_avp_hdr ( avp, &ahdr ) );
+		
+		if (!(ahdr->avp_flags & AVP_FLAG_VENDOR)) {
+			switch (ahdr->avp_code) {
+				/* Based on RFC4005, sec 3.10 */
+				case DIAM_ATTR_SESSION_ID:
+				case DIAM_ATTR_ORIGIN_HOST:
+				case DIAM_ATTR_ORIGIN_REALM:
+				case DIAM_ATTR_ACCOUNTING_RECORD_TYPE:
+				case DIAM_ATTR_ACCOUNTING_RECORD_NUMBER:
+				case DIAM_ATTR_ACCT_APPLICATION_ID:
+				case DIAM_ATTR_VENDOR_SPECIFIC_APPLICATION_ID:
+				case DIAM_ATTR_USER_NAME:
+				case DIAM_ATTR_ACCOUNTING_SUB_SESSION_ID:
+				case DIAM_ATTR_ACCT_SESSION_ID:
+				case DIAM_ATTR_ACCT_MULTI_SESSION_ID:
+				case DIAM_ATTR_EVENT_TIMESTAMP:
+				case DIAM_ATTR_ORIGIN_AAA_PROTOCOL:
+				case DIAM_ATTR_ORIGIN_STATE_ID:
+				case DIAM_ATTR_NAS_IDENTIFIER:
+				case DIAM_ATTR_NAS_IP_ADDRESS:
+				case DIAM_ATTR_NAS_IPV6_ADDRESS:
+				case DIAM_ATTR_NAS_PORT:
+				case DIAM_ATTR_NAS_PORT_ID:
+				case DIAM_ATTR_NAS_PORT_TYPE:
+				case DIAM_ATTR_SERVICE_TYPE:
+				case DIAM_ATTR_TERMINATION_CAUSE:
+				case DIAM_ATTR_ACCOUNTING_REALTIME_REQUIRED:
+				case DIAM_ATTR_ACCT_INTERIM_INTERVAL:
+				case DIAM_ATTR_CLASS:
+					/* We just remove these AVP, they are not expected in RADIUS client */
+					break;
+					
+				default:
+					/* Leave the AVP in the message for further treatment */
+					handled = 0;
+			}
+		} else {
+			/* Vendor-specific AVPs */
+			switch (ahdr->avp_vendor) {
+				
+				default: /* unknown vendor */
+					handled = 0;
+			}
+		}
+		
+		if (handled) {
+			CHECK_FCT( fd_msg_free( avp ) );
+		}
+	}
+	
+	/*
+	      The Authenticator field in an Accounting-Response packet is called
+	      the Response Authenticator, and contains a one-way MD5 hash
+	      calculated over a stream of octets consisting of the Accounting-
+	      Response Code, Identifier, Length, the Request Authenticator field
+	      from the Accounting-Request packet being replied to, and the
+	      response attributes if any, followed by the shared secret.  The
+	      resulting 16 octet MD5 hash value is stored in the Authenticator
+	      field of the Accounting-Response packet.
+	      
+	      -- done in radius_msg_finish_srv 
+	*/
+
+	return 0;
+}
+
+/* The exported symbol */
+struct rgw_api rgwp_descriptor = {
+	.rgwp_name       = "acct",
+	.rgwp_conf_parse = acct_conf_parse,
+	.rgwp_conf_free  = acct_conf_free,
+	.rgwp_rad_req    = acct_rad_req,
+	.rgwp_diam_ans   = acct_diam_ans
+};	
diff --git a/extensions/app_radgw/rgwx_auth.c b/extensions/app_radgw/rgwx_auth.c
new file mode 100644
index 0000000..f78b97e
--- /dev/null
+++ b/extensions/app_radgw/rgwx_auth.c
@@ -0,0 +1,1961 @@
+/*********************************************************************************************************
+* Software License Agreement (BSD License)                                                               *
+* Author: Sebastien Decugis <sdecugis@freediameter.net>							 *
+*													 *
+* Copyright (c) 2013, WIDE Project and NICT								 *
+* All rights reserved.											 *
+* 													 *
+* Redistribution and use of this software in source and binary forms, with or without modification, are  *
+* permitted provided that the following conditions are met:						 *
+* 													 *
+* * Redistributions of source code must retain the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer.										 *
+*    													 *
+* * Redistributions in binary form must reproduce the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer in the documentation and/or other						 *
+*   materials provided with the distribution.								 *
+* 													 *
+* * Neither the name of the WIDE Project or NICT nor the 						 *
+*   names of its contributors may be used to endorse or 						 *
+*   promote products derived from this software without 						 *
+*   specific prior written permission of WIDE Project and 						 *
+*   NICT.												 *
+* 													 *
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED *
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
+* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR *
+* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 	 *
+* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 	 *
+* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR *
+* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF   *
+* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.								 *
+*********************************************************************************************************/
+
+/* RADIUS Access-Request messages translation plugin */
+
+#include "rgw_common.h"
+
+/* Attributes missing from radius.h */
+#define RADIUS_ATTR_CHAP_PASSWORD	3
+#define RADIUS_ATTR_ARAP_PASSWORD	70
+
+/* Other constants we use */
+#define AI_NASREQ		1	/* Diameter NASREQ */
+#define AI_EAP			5	/* Diameter EAP application */
+#define CC_AA			265	/* AAR */
+#define CC_DIAMETER_EAP		268	/* DER */
+#define ACV_ART_AUTHORIZE_AUTHENTICATE	3	/* AUTHORIZE_AUTHENTICATE */
+#define ACV_OAP_RADIUS			1	/* RADIUS */
+#define ACV_ASS_STATE_MAINTAINED	0	/* STATE_MAINTAINED */
+#define ACV_ASS_NO_STATE_MAINTAINED	1	/* NO_STATE_MAINTAINED */
+
+/* The state we keep for this plugin */
+struct rgwp_config {
+	struct {
+		struct dict_object * ARAP_Password;		/* ARAP-Password */
+		struct dict_object * ARAP_Security;		/* ARAP-Security */
+		struct dict_object * ARAP_Security_Data;	/* ARAP-Security-Data */
+		struct dict_object * Auth_Application_Id;	/* Auth-Application-Id */
+		struct dict_object * Auth_Request_Type;		/* Auth-Request-Type */
+		struct dict_object * Authorization_Lifetime;	/* Authorization-Lifetime */
+		struct dict_object * Callback_Number;		/* Callback-Number */
+		struct dict_object * Called_Station_Id;		/* Called-Station-Id */
+		struct dict_object * Calling_Station_Id;	/* Calling-Station-Id */
+		struct dict_object * CHAP_Algorithm;		/* CHAP-Algorithm */
+		struct dict_object * CHAP_Auth;			/* CHAP-Auth */
+		struct dict_object * CHAP_Challenge;		/* CHAP-Challenge */
+		struct dict_object * CHAP_Ident;		/* CHAP-Ident */
+		struct dict_object * CHAP_Response;		/* CHAP-Response */
+		struct dict_object * Destination_Host;		/* Destination-Host */
+		struct dict_object * Destination_Realm;		/* Destination-Realm */
+		struct dict_object * Connect_Info;		/* Connect-Info */
+		struct dict_object * EAP_Payload;		/* EAP-Payload */
+		struct dict_object * Error_Message;		/* Error-Message */
+		struct dict_object * Error_Reporting_Host;	/* Error-Reporting-Host */
+		struct dict_object * Failed_AVP;		/* Failed-AVP */
+		struct dict_object * Framed_Compression;	/* Framed-Compression */
+		struct dict_object * Framed_IP_Address;		/* Framed-IP-Address */
+		struct dict_object * Framed_IP_Netmask;		/* Framed-IP-Netmask */
+		struct dict_object * Framed_Interface_Id;	/* Framed-Interface-Id */
+		struct dict_object * Framed_IPv6_Prefix;	/* Framed-IPv6-Prefix */
+		struct dict_object * Framed_MTU;		/* Framed-MTU */
+		struct dict_object * Framed_Protocol;		/* Framed-Protocol */
+		struct dict_object * Login_IP_Host;		/* Login-IP-Host */
+		struct dict_object * Login_IPv6_Host;		/* Login-IPv6-Host */
+		struct dict_object * Login_LAT_Group;		/* Login-LAT-Group */
+		struct dict_object * Login_LAT_Node;		/* Login-LAT-Node */
+		struct dict_object * Login_LAT_Port;		/* Login-LAT-Port */
+		struct dict_object * Login_LAT_Service;		/* Login-LAT-Service */
+		struct dict_object * NAS_Identifier;		/* NAS-Identifier */
+		struct dict_object * NAS_IP_Address;		/* NAS-IP-Address */
+		struct dict_object * NAS_IPv6_Address;		/* NAS-IPv6-Address */
+		struct dict_object * NAS_Port;			/* NAS-Port */
+		struct dict_object * NAS_Port_Id;		/* NAS-Port-Id */
+		struct dict_object * NAS_Port_Type;		/* NAS-Port-Type */
+		struct dict_object * Origin_AAA_Protocol;	/* Origin-AAA-Protocol */
+		struct dict_object * Origin_Host;		/* Origin-Host */
+		struct dict_object * Origin_Realm;		/* Origin-Realm */
+		struct dict_object * Originating_Line_Info;	/* Originating-Line-Info */
+		struct dict_object * Port_Limit;		/* Port-Limit */
+		struct dict_object * Re_Auth_Request_Type;	/* Re-Auth-Request-Type */
+		struct dict_object * Result_Code;		/* Result-Code */
+		struct dict_object * Service_Type;		/* Service-Type */
+		struct dict_object * Session_Id;		/* Session-Id */
+		struct dict_object * Session_Timeout;		/* Session-Timeout */
+		struct dict_object * State;			/* State */
+		struct dict_object * Tunneling;			/* Tunneling */
+		struct dict_object * Tunnel_Type;		/* Tunnel-Type */
+		struct dict_object * Tunnel_Medium_Type;	/* Tunnel-Medium-Type */
+		struct dict_object * Tunnel_Client_Endpoint;	/* Tunnel-Client-Endpoint */
+		struct dict_object * Tunnel_Server_Endpoint;	/* Tunnel-Server-Endpoint */
+		struct dict_object * Tunnel_Private_Group_Id;	/* Tunnel-Private-Group-Id */
+		struct dict_object * Tunnel_Preference;		/* Tunnel-Preference */
+		struct dict_object * Tunnel_Client_Auth_Id;	/* Tunnel-Client-Auth-Id */
+		struct dict_object * Tunnel_Server_Auth_Id;	/* Tunnel-Server-Auth-Id */
+		struct dict_object * User_Name;			/* User-Name */
+		struct dict_object * User_Password;		/* User-Password */
+		
+	} dict; /* cache of the dictionary objects we use */
+	struct session_handler * sess_hdl; /* We store RADIUS request authenticator information in the session */
+	char * confstr;
+	
+	int ignore_nai;
+};
+
+struct sess_state {
+	uint8_t req_auth[16];
+};
+
+
+/* Initialize the plugin */
+static int auth_conf_parse(char * confstr, struct rgwp_config ** state)
+{
+	struct rgwp_config * new;
+	struct dict_object * app;
+	
+	TRACE_ENTRY("%p %p", confstr, state);
+	CHECK_PARAMS( state );
+	
+	CHECK_MALLOC( new = malloc(sizeof(struct rgwp_config)) );
+	memset(new, 0, sizeof(struct rgwp_config));
+	
+	CHECK_FCT( fd_sess_handler_create( &new->sess_hdl, (void *)free, NULL, NULL ) );
+	new->confstr = confstr;
+	
+	if (confstr && strstr(confstr, "nonai"))
+		new->ignore_nai = 1;
+	
+	/* Resolve all dictionary objects we use */
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "ARAP-Password", &new->dict.ARAP_Password, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "ARAP-Security", &new->dict.ARAP_Security, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "ARAP-Security-Data", &new->dict.ARAP_Security_Data, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Auth-Application-Id", &new->dict.Auth_Application_Id, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Auth-Request-Type", &new->dict.Auth_Request_Type, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Authorization-Lifetime", &new->dict.Authorization_Lifetime, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Callback-Number", &new->dict.Callback_Number, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Called-Station-Id", &new->dict.Called_Station_Id, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Calling-Station-Id", &new->dict.Calling_Station_Id, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "CHAP-Algorithm", &new->dict.CHAP_Algorithm, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "CHAP-Auth", &new->dict.CHAP_Auth, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "CHAP-Challenge", &new->dict.CHAP_Challenge, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "CHAP-Ident", &new->dict.CHAP_Ident, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "CHAP-Response", &new->dict.CHAP_Response, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Connect-Info", &new->dict.Connect_Info, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Destination-Host", &new->dict.Destination_Host, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Destination-Realm", &new->dict.Destination_Realm, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "EAP-Payload", &new->dict.EAP_Payload, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Error-Message", &new->dict.Error_Message, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Error-Reporting-Host", &new->dict.Error_Reporting_Host, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Failed-AVP", &new->dict.Failed_AVP, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Framed-Compression", &new->dict.Framed_Compression, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Framed-IP-Address", &new->dict.Framed_IP_Address, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Framed-IP-Netmask", &new->dict.Framed_IP_Netmask, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Framed-Interface-Id", &new->dict.Framed_Interface_Id, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Framed-IPv6-Prefix", &new->dict.Framed_IPv6_Prefix, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Framed-MTU", &new->dict.Framed_MTU, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Framed-Protocol", &new->dict.Framed_Protocol, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Login-IP-Host", &new->dict.Login_IP_Host, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Login-IPv6-Host", &new->dict.Login_IPv6_Host, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Login-LAT-Group", &new->dict.Login_LAT_Group, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Login-LAT-Node", &new->dict.Login_LAT_Node, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Login-LAT-Port", &new->dict.Login_LAT_Port, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Login-LAT-Service", &new->dict.Login_LAT_Service, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "NAS-Identifier", &new->dict.NAS_Identifier, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "NAS-IP-Address", &new->dict.NAS_IP_Address, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "NAS-IPv6-Address", &new->dict.NAS_IPv6_Address, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "NAS-Port", &new->dict.NAS_Port, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "NAS-Port-Id", &new->dict.NAS_Port_Id, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "NAS-Port-Type", &new->dict.NAS_Port_Type, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Origin-AAA-Protocol", &new->dict.Origin_AAA_Protocol, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Origin-Host", &new->dict.Origin_Host, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Origin-Realm", &new->dict.Origin_Realm, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Originating-Line-Info", &new->dict.Originating_Line_Info, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Port-Limit", &new->dict.Port_Limit, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Re-Auth-Request-Type", &new->dict.Re_Auth_Request_Type, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Result-Code", &new->dict.Result_Code, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Service-Type", &new->dict.Service_Type, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Session-Id", &new->dict.Session_Id, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Session-Timeout", &new->dict.Session_Timeout, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "State", &new->dict.State, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Tunneling", &new->dict.Tunneling, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Tunnel-Type", &new->dict.Tunnel_Type, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Tunnel-Medium-Type", &new->dict.Tunnel_Medium_Type, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Tunnel-Client-Endpoint", &new->dict.Tunnel_Client_Endpoint, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Tunnel-Server-Endpoint", &new->dict.Tunnel_Server_Endpoint, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Tunnel-Private-Group-Id", &new->dict.Tunnel_Private_Group_Id, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Tunnel-Preference", &new->dict.Tunnel_Preference, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Tunnel-Client-Auth-Id", &new->dict.Tunnel_Client_Auth_Id, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Tunnel-Server-Auth-Id", &new->dict.Tunnel_Server_Auth_Id, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "User-Name", &new->dict.User_Name, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "User-Password", &new->dict.User_Password, ENOENT) );
+	
+	/* This plugin provides the following Diameter authentication applications support: */
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_APPLICATION, APPLICATION_BY_NAME, "Diameter Network Access Server Application", &app, ENOENT) );
+	CHECK_FCT( fd_disp_app_support ( app, NULL, 1, 0 ) );
+
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_APPLICATION, APPLICATION_BY_NAME, "Diameter Extensible Authentication Protocol (EAP) Application", &app, ENOENT) );
+	CHECK_FCT( fd_disp_app_support ( app, NULL, 1, 0 ) );
+	
+	*state = new;
+	return 0;
+}
+
+/* deinitialize */
+static void auth_conf_free(struct rgwp_config * state)
+{
+	TRACE_ENTRY("%p", state);
+	CHECK_PARAMS_DO( state, return );
+	CHECK_FCT_DO( fd_sess_handler_destroy( &state->sess_hdl, NULL ),  );
+	free(state);
+	return;
+}
+
+/* Handle an incoming RADIUS request */
+static int auth_rad_req( struct rgwp_config * cs, struct radius_msg * rad_req, struct radius_msg ** rad_ans, struct msg ** diam_fw, struct rgw_client * cli )
+{
+	int idx;
+	int got_id = 0;
+	int got_mac = 0;
+	int got_passwd = 0;
+	int got_eap = 0;
+	int got_empty_eap = 0;
+	const char * prefix = "Diameter/";
+	size_t pref_len;
+	os0_t dh = NULL;
+	size_t dh_len = 0;
+	os0_t dr = NULL;
+	size_t dr_len = 0;
+	os0_t si = NULL;
+	size_t si_len = 0;
+	os0_t un = NULL;
+	size_t un_len = 0;
+	size_t nattr_used = 0;
+	struct avp ** avp_tun = NULL, *avp = NULL;
+	union avp_value value;
+	struct session * sess;
+	
+	TRACE_ENTRY("%p %p %p %p %p", cs, rad_req, rad_ans, diam_fw, cli);
+	CHECK_PARAMS(cs && rad_req && (rad_req->hdr->code == RADIUS_CODE_ACCESS_REQUEST) && rad_ans && diam_fw && *diam_fw);
+	
+	pref_len = strlen(prefix);
+	
+	/*
+	   Guidelines:
+	     http://tools.ietf.org/html/rfc4005#section-9.1
+	     http://tools.ietf.org/html/rfc4072#section-6.1
+
+	   When a Translation Agent receives a RADIUS message, the following
+	   steps should be taken:
+
+	      -  If a Message-Authenticator attribute is present, the value MUST
+        	 be checked but not included in the Diameter message.  If it is
+        	 incorrect, the RADIUS message should be silently discarded.
+        	 The gateway system SHOULD generate and include a Message-
+        	 Authenticator in returned RADIUS responses.
+	             -> done in rgw_msg_auth_check
+
+	      -  The transport address of the sender MUST be checked against the
+        	 NAS identifying attributes.  See the description of NAS-
+        	 Identifier and NAS-IP-Address below.
+		     -> done in rgw_clients_check_origin
+
+	      -  The Translation Agent must maintain transaction state
+        	 information relevant to the RADIUS request, such as the
+        	 Identifier field in the RADIUS header, any existing RADIUS
+        	 Proxy-State attribute, and the source IP address and port
+        	 number of the UDP packet.  These may be maintained locally in a
+        	 state table or saved in a Proxy-Info AVP group.  A Diameter
+        	 Session-Id AVP value must be created using a session state
+        	 mapping mechanism.
+		     -> Identifier, source and port are saved along with the request,
+		        and associated with the session state.
+		     -> sub_echo_drop should handle the Proxy-State attribute (conf issue)
+
+	      -  The Diameter Origin-Host and Origin-Realm AVPs MUST be created
+        	 and added by using the information from an FQDN corresponding
+        	 to the NAS-IP-Address attribute (preferred if available),
+        	 and/or to the NAS-Identifier attribute.  (Note that the RADIUS
+        	 NAS-Identifier is not required to be an FQDN.)
+		     -> done in rgw_clients_create_origin.
+
+	      -  The response MUST have an Origin-AAA-Protocol AVP added,
+        	 indicating the protocol of origin of the message.
+		     -> what "response" ??? Added to the AAR / DER in this function.
+
+	      -  The Proxy-Info group SHOULD be added, with the local server's
+        	 identity specified in the Proxy-Host AVP.  This should ensure
+        	 that the response is returned to this system.
+		     -> We don't need this, answer is always routed here anyway.
+		     
+	      For EAP:
+	      
+	      o  RADIUS EAP-Message attribute(s) are translated to a Diameter
+		 EAP-Payload AVP.  If multiple RADIUS EAP-Message attributes are
+		 present, they are concatenated and translated to a single Diameter
+		 EAP-Payload AVP.
+		     -> concatenation done by radius_msg_get_eap
+
+	      -> the remaining is specific conversion rules
+	*/
+	
+	/* Check basic information is there, and also retrieve some attribute information */
+	for (idx = 0; idx < rad_req->attr_used; idx++) {
+		struct radius_attr_hdr * attr = (struct radius_attr_hdr *)(rad_req->buf + rad_req->attr_pos[idx]);
+		uint8_t * attr_val = (uint8_t *)(attr + 1);
+		size_t attr_len = attr->length - sizeof(struct radius_attr_hdr);
+		
+		switch (attr->type) {
+			case RADIUS_ATTR_NAS_IP_ADDRESS:
+			case RADIUS_ATTR_NAS_IDENTIFIER:
+			case RADIUS_ATTR_NAS_IPV6_ADDRESS:
+				got_id = 1;
+				break;
+			case RADIUS_ATTR_MESSAGE_AUTHENTICATOR:
+				got_mac = 1;
+				break;
+			case RADIUS_ATTR_EAP_MESSAGE:
+				got_eap = 1;
+				if (attr->length == 2)
+					got_empty_eap = 1;
+				break;
+			case RADIUS_ATTR_USER_PASSWORD:
+			case RADIUS_ATTR_CHAP_PASSWORD:
+			case RADIUS_ATTR_ARAP_PASSWORD:
+				got_passwd += 1;
+				break;
+				
+			/* Is there a State attribute with prefix "Diameter/" in the message? (in that case: Diameter/Destination-Host/Destination-Realm/Session-Id) */
+			/* NOTE: RFC4005 says "Origin-Host" here, but it's not coherent with the rules for answers. Destination-Host makes more sense */
+			case RADIUS_ATTR_STATE:
+				if ((attr_len > pref_len + 5 /* for the '/'s and non empty strings */ ) 
+					&& ! memcmp(attr_val, prefix, pref_len)) {
+					int i, start;
+
+					TRACE_DEBUG(ANNOYING, "Found a State attribute with '%s' prefix (attr #%d).", prefix, idx);
+
+					/* Now parse the value and check its content is valid. Unfortunately we cannot use strchr here since strings are not \0-terminated */
+
+					i = start = pref_len;
+					dh = attr_val + i;
+					for (; (i < attr_len - 2) && (attr_val[i] != '/'); i++) /* loop */;
+					if ( i >= attr_len - 2 ) continue; /* the attribute format is not good */
+					dh_len = i - start;
+
+					start = ++i;
+					dr = attr_val + i;
+					for (; (i < attr_len - 1) && (attr_val[i] != '/'); i++) /* loop */;
+					if ( i >= attr_len - 1 ) continue; /* the attribute format is not good */
+					dr_len = i - start;
+
+					i++;
+					si = attr_val + i;
+					si_len = attr_len - i;
+
+					TRACE_DEBUG(ANNOYING, "Attribute parsed successfully: DH:'%.*s' DR:'%.*s' SI:'%.*s'.", (int)dh_len, dh, (int)dr_len, dr, (int)si_len, si);
+					/* Remove from the message */
+					for (i = idx + 1; i < rad_req->attr_used; i++)
+						rad_req->attr_pos[i - 1] = rad_req->attr_pos[i];
+					rad_req->attr_used -= 1;
+					idx--;
+				}
+				break;
+		
+			case RADIUS_ATTR_USER_NAME:
+				TRACE_DEBUG(ANNOYING, "Found a User-Name attribute: '%.*s'", (int)attr_len, attr_len ? (char *)attr_val : "");
+				un = attr_val;
+				un_len = attr_len;
+				break;
+			
+		}
+	}
+	if (!got_id) {
+		TRACE_DEBUG(INFO, "RADIUS Access-Request did not contain a NAS IP or Identifier attribute, reject.");
+		return EINVAL;
+	}
+	/* [Note 1] An Access-Request that contains either a User-Password or
+	   CHAP-Password or ARAP-Password or one or more EAP-Message attributes
+	   MUST NOT contain more than one type of those four attributes.  If it
+	   does not contain any of those four attributes, it SHOULD contain a
+	   Message-Authenticator.  If any packet type contains an EAP-Message
+	   attribute it MUST also contain a Message-Authenticator.  A RADIUS
+	   server receiving an Access-Request not containing any of those four
+	   attributes and also not containing a Message-Authenticator attribute
+	   SHOULD silently discard it.  */
+	if (((got_eap + got_passwd) > 1) || (got_eap && !got_mac) || (!got_eap && !got_passwd && !got_mac)) {
+		TRACE_DEBUG(INFO, "RADIUS Access-Request not conform to RFC3579 sec 3.3 note 1, discard.");
+		return EINVAL;
+	}
+	
+	
+	
+	/*
+	      -  If the RADIUS request contained a State attribute and the
+        	 prefix of the data is "Diameter/", the data following the
+        	 prefix contains the Diameter Origin-Host/Origin-Realm/Session-
+        	 Id.  If no such attributes are present and the RADIUS command
+        	 is an Access-Request, a new Session-Id is created.  The
+        	 Session-Id is included in the Session-Id AVP.
+	*/
+	
+	/* Add the Destination-Realm AVP */
+	CHECK_FCT( fd_msg_avp_new ( cs->dict.Destination_Realm, 0, &avp ) );
+	if (dr) {
+		value.os.data = (unsigned char *)dr;
+		value.os.len = dr_len;
+	} else {
+		int i = 0;
+		if (un && ! cs->ignore_nai) {
+			/* Is there an '@' in the user name? We don't care for decorated NAI here */
+			for (i = un_len - 2; i > 0; i--) {
+				if (un[i] == '@') {
+					i++;
+					break;
+				}
+			}
+		}
+		if (i <= 0) {
+			/* Not found in the User-Name => we use the local domain of this gateway */
+			value.os.data = (uint8_t *)fd_g_config->cnf_diamrlm;
+			value.os.len  = fd_g_config->cnf_diamrlm_len;
+		} else {
+			value.os.data = un + i;
+			value.os.len  = un_len - i;
+		}
+	}
+	CHECK_FCT( fd_msg_avp_setvalue ( avp, &value ) );
+	CHECK_FCT( fd_msg_avp_add ( *diam_fw, MSG_BRW_FIRST_CHILD, avp) );
+	
+	/* Add the Destination-Host if found */
+	if (dh) {
+		CHECK_FCT( fd_msg_avp_new ( cs->dict.Destination_Host, 0, &avp ) );
+		value.os.data = (unsigned char *)dh;
+		value.os.len = dh_len;
+		CHECK_FCT( fd_msg_avp_setvalue ( avp, &value ) );
+		CHECK_FCT( fd_msg_avp_add ( *diam_fw, MSG_BRW_FIRST_CHILD, avp) );
+	}
+	
+	/* Create the session if it is not already done */
+	{
+		os0_t sess_str = NULL;
+		size_t sess_strlen;
+		
+		if (si_len) {
+			/* We already have the Session-Id, just use it */
+			CHECK_FCT( fd_sess_fromsid_msg ( si, si_len, &sess, NULL) );
+		} else {
+			/* Create a new Session-Id string */
+			
+			DiamId_t fqdn;
+			size_t fqdnlen;
+			DiamId_t realm;
+			size_t realmlen;
+			
+			/* Get information on the RADIUS client */
+			CHECK_FCT( rgw_clients_get_origin(cli, &fqdn, &fqdnlen, &realm, &realmlen) );
+			
+			/* If we have a user name, create the new session with it */
+			if (un) {
+				int len;
+				/* If not found, create a new Session-Id. Our format is: {fqdn;hi32;lo32;username;diamid} */
+				CHECK_MALLOC( sess_str = malloc(un_len + 1 /* ';' */ + fd_g_config->cnf_diamid_len + 1 /* '\0' */) );
+				len = sprintf((char *)sess_str, "%.*s;%s", (int)un_len, un, fd_g_config->cnf_diamid);
+				CHECK_FCT( fd_sess_new(&sess, fqdn, fqdnlen, sess_str, len) );
+				free(sess_str);
+			} else {
+				/* We don't have enough information to create the Session-Id, the RADIUS message is probably invalid */
+				TRACE_DEBUG(INFO, "RADIUS Access-Request does not contain a User-Name attribute, rejecting.");
+				return EINVAL;
+			}	
+		}
+		
+		/* Now, add the Session-Id AVP at beginning of Diameter message */
+		CHECK_FCT( fd_sess_getsid(sess, &sess_str, &sess_strlen) );
+		TRACE_DEBUG(FULL, "[auth.rgwx] Translating new message for session '%s'...", sess_str);
+		
+		/* Now add this session in the message */
+		CHECK_FCT( fd_msg_avp_new ( cs->dict.Session_Id, 0, &avp ) );
+		value.os.data = sess_str;
+		value.os.len = sess_strlen;
+		CHECK_FCT( fd_msg_avp_setvalue ( avp, &value ) );
+		CHECK_FCT( fd_msg_avp_add ( *diam_fw, MSG_BRW_FIRST_CHILD, avp) );
+		CHECK_FCT( fd_msg_sess_set(*diam_fw, sess) );
+	}
+	
+	
+	/* Add the appropriate command code & Auth-Application-Id */
+	{
+		struct msg_hdr * header = NULL;
+		CHECK_FCT( fd_msg_hdr ( *diam_fw, &header ) );
+		header->msg_flags = CMD_FLAG_REQUEST | CMD_FLAG_PROXIABLE;
+		if (got_eap) {
+			header->msg_code = CC_DIAMETER_EAP;
+			header->msg_appl = AI_EAP;
+		} else {
+			header->msg_code = CC_AA;
+			header->msg_appl = AI_NASREQ;
+		}
+		
+		/* Add the Auth-Application-Id */
+		{
+			CHECK_FCT( fd_msg_avp_new ( cs->dict.Auth_Application_Id, 0, &avp ) );
+			value.i32 = header->msg_appl;
+			CHECK_FCT( fd_msg_avp_setvalue ( avp, &value ) );
+			CHECK_FCT( fd_msg_avp_add ( *diam_fw, MSG_BRW_LAST_CHILD, avp) );
+		}
+	}
+	
+	/*  	The type of request is identified through the Auth-Request-Type AVP
+		[BASE].  The recommended value for most RADIUS interoperabily
+		situations is AUTHORIZE_AUTHENTICATE. */
+	
+	/* Add Auth-Request-Type AVP */
+	{
+		CHECK_FCT( fd_msg_avp_new ( cs->dict.Auth_Request_Type, 0, &avp ) );
+		value.i32 = ACV_ART_AUTHORIZE_AUTHENTICATE;
+		CHECK_FCT( fd_msg_avp_setvalue ( avp, &value ) );
+		CHECK_FCT( fd_msg_avp_add ( *diam_fw, MSG_BRW_LAST_CHILD, avp) );
+	}
+	
+	/* Add Origin-AAA-Protocol AVP */
+	{
+		CHECK_FCT( fd_msg_avp_new ( cs->dict.Origin_AAA_Protocol, 0, &avp ) );
+		value.i32 = ACV_OAP_RADIUS;
+		CHECK_FCT( fd_msg_avp_setvalue ( avp, &value ) );
+		CHECK_FCT( fd_msg_avp_add ( *diam_fw, MSG_BRW_LAST_CHILD, avp) );
+	}
+	
+	/* Convert the EAP payload (concat RADIUS attributes) */
+	if (got_eap) {
+		CHECK_FCT( fd_msg_avp_new ( cs->dict.EAP_Payload, 0, &avp ) );
+		
+		/*    o  An empty RADIUS EAP-Message attribute (with length 2) signifies
+			 EAP-Start, and it is translated to an empty EAP-Payload AVP. */
+		if (got_empty_eap) {
+			value.os.len = 0;
+			value.os.data = (uint8_t *)"";
+		} else {
+			CHECK_MALLOC( value.os.data = radius_msg_get_eap(rad_req, &value.os.len) );
+		}
+		
+		CHECK_FCT( fd_msg_avp_setvalue ( avp, &value ) );
+		CHECK_FCT( fd_msg_avp_add ( *diam_fw, MSG_BRW_LAST_CHILD, avp) );
+	}
+	
+	/* Tunnel AVPs need some preparation */
+	/* Convert the attributes one by one */
+	for (idx = 0; idx < rad_req->attr_used; idx++) {
+		struct radius_attr_hdr * attr = (struct radius_attr_hdr *)(rad_req->buf + rad_req->attr_pos[idx]);
+
+		switch (attr->type) {
+			
+			/* This macro converts a RADIUS attribute to a Diameter AVP of type OctetString */
+			#define CONV2DIAM_STR( _dictobj_ )	\
+				CHECK_PARAMS( attr->length >= sizeof(struct radius_attr_hdr) );			\
+				/* Create the AVP with the specified dictionary model */			\
+				CHECK_FCT( fd_msg_avp_new ( cs->dict._dictobj_, 0, &avp ) );			\
+				value.os.len = attr->length - sizeof(struct radius_attr_hdr);			\
+				value.os.data = (os0_t)(attr + 1);						\
+				CHECK_FCT( fd_msg_avp_setvalue ( avp, &value ) );				\
+				/* Add the AVP in the Diameter message. */					\
+				CHECK_FCT( fd_msg_avp_add ( *diam_fw, MSG_BRW_LAST_CHILD, avp) );		\
+				
+			/* Same thing, for scalar AVPs of 32 bits */
+			#define CONV2DIAM_32B( _dictobj_ )	\
+				CHECK_PARAMS( attr->length == sizeof(struct radius_attr_hdr)+sizeof(uint32_t) );\
+				CHECK_FCT( fd_msg_avp_new ( cs->dict._dictobj_, 0, &avp ) );			\
+				{										\
+					uint8_t * v = (uint8_t *)(attr + 1);					\
+					value.u32  = (v[0] << 24)						\
+					           | (v[1] << 16)						\
+					           | (v[2] <<  8)						\
+					           |  v[3] ;							\
+				}										\
+				CHECK_FCT( fd_msg_avp_setvalue ( avp, &value ) );				\
+				CHECK_FCT( fd_msg_avp_add ( *diam_fw, MSG_BRW_LAST_CHILD, avp) );		\
+				
+			/* And the 64b version */
+			#define CONV2DIAM_64B( _dictobj_ )	\
+				CHECK_PARAMS( attr->length == sizeof(struct radius_attr_hdr)+sizeof(uint64_t) );\
+				CHECK_FCT( fd_msg_avp_new ( cs->dict._dictobj_, 0, &avp ) );			\
+				{										\
+					uint8_t * v = (uint8_t *)(attr + 1);					\
+					value.u64  = ((uint64_t)(v[0]) << 56)					\
+					           | ((uint64_t)(v[1]) << 48)					\
+					           | ((uint64_t)(v[2]) << 40)					\
+					           | ((uint64_t)(v[3]) << 32)					\
+					           | ((uint64_t)(v[4]) << 24)					\
+					           | ((uint64_t)(v[5]) << 16)					\
+					           | ((uint64_t)(v[6]) <<  8)					\
+					           |  (uint64_t)(v[7]) ;					\
+				}										\
+				CHECK_FCT( fd_msg_avp_setvalue ( avp, &value ) );				\
+				CHECK_FCT( fd_msg_avp_add ( *diam_fw, MSG_BRW_LAST_CHILD, avp) );		\
+				
+		/* RFC 2865 */	
+			/*
+			      -  The Destination-Realm AVP is created from the information found
+        			 in the RADIUS User-Name attribute.
+				 	-> done in rgw_clients_create_origin
+			*/
+			case RADIUS_ATTR_USER_NAME:
+				CONV2DIAM_STR( User_Name );
+				break;
+				
+			/*
+			      -  If the RADIUS User-Password attribute is present, the password
+        			 must be unencrypted by using the link's RADIUS shared secret.
+        			 The unencrypted value must be forwarded in a User-Password AVP
+        			 using Diameter security.
+			*/
+			case RADIUS_ATTR_USER_PASSWORD:
+				if ((attr->length - 2) % 16) {
+					TRACE_DEBUG(INFO, "Invalid length of User-Password attribute: %hhd", attr->length);
+					return EINVAL;
+				}
+				{
+					/* Decipher following this logic (refers to rfc2865#section-5.2 )
+					   b1 = MD5(S + RA)	p1 = c(1) xor b1
+					   b2 = MD5(S + c(1))   p2 = c(2) xor b2
+					   ...
+					*/
+					
+					uint8_t *ciph = (uint8_t *)(attr+1); 	/* c(i) */
+					size_t ciph_len = attr->length - 2;
+					uint8_t deciph[128];			/* pi */
+					size_t deciph_len = 0;
+					uint8_t * secret;			/* S */
+					size_t secret_len;
+					uint8_t hash[16];			/* b(i) */
+					const uint8_t *addr[2];
+					size_t len[2];
+					
+					/* Retrieve the shared secret */
+					CHECK_FCT(rgw_clients_getkey(cli, &secret, &secret_len));
+					
+					/* Initial b1 = MD5(S + RA) */
+					addr[0] = secret;
+					len[0] = secret_len;
+					addr[1] = rad_req->hdr->authenticator;
+					len[1] = 16;
+					md5_vector(2, addr, len, hash);
+					
+					/* loop */
+					while (deciph_len < ciph_len) {
+						int i;
+						/* pi = c(i) xor bi */
+						for (i = 0; i < 16; i++)
+							deciph[deciph_len + i] = ciph[deciph_len + i] ^ hash[i];
+							/* do we have to remove the padding '\0's ? */
+						
+						/* b(i+1) = MD5(S + c(i) */
+						addr[1] = ciph + deciph_len;
+						md5_vector(2, addr, len, hash);
+						
+						deciph_len += 16;
+					}
+					
+					/* Now save this value in the AVP */
+					CHECK_FCT( fd_msg_avp_new ( cs->dict.User_Password, 0, &avp ) );
+					value.os.data = &deciph[0];
+					value.os.len  = deciph_len;
+					CHECK_FCT( fd_msg_avp_setvalue ( avp, &value ) );
+					CHECK_FCT( fd_msg_avp_add ( *diam_fw, MSG_BRW_LAST_CHILD, avp) );
+				}
+				break;
+				
+
+			/*
+			      -  If the RADIUS CHAP-Password attribute is present, the Ident and
+        			 Data portion of the attribute are used to create the CHAP-Auth
+        			 grouped AVP.
+			*/
+			case RADIUS_ATTR_CHAP_PASSWORD:
+				CHECK_PARAMS( attr->length == 19 /* RFC 2865 */);
+				{
+					uint8_t * c = (uint8_t *)(attr + 1);
+					struct avp * chap_auth;
+					CHECK_FCT( fd_msg_avp_new ( cs->dict.CHAP_Auth, 0, &chap_auth ) );
+					CHECK_FCT( fd_msg_avp_add ( *diam_fw, MSG_BRW_LAST_CHILD, chap_auth) );
+
+					CHECK_FCT( fd_msg_avp_new ( cs->dict.CHAP_Algorithm, 0, &avp ) );
+					value.u32 = 5; /* The only value defined currently... */
+					CHECK_FCT( fd_msg_avp_setvalue ( avp, &value ) );
+					CHECK_FCT( fd_msg_avp_add ( chap_auth, MSG_BRW_LAST_CHILD, avp) );
+					
+					CHECK_FCT( fd_msg_avp_new ( cs->dict.CHAP_Ident, 0, &avp ) );
+					value.os.data = c;
+					value.os.len = 1;
+					CHECK_FCT( fd_msg_avp_setvalue ( avp, &value ) );
+					CHECK_FCT( fd_msg_avp_add ( chap_auth, MSG_BRW_LAST_CHILD, avp) );
+					
+					c++;
+					
+					CHECK_FCT( fd_msg_avp_new ( cs->dict.CHAP_Response, 0, &avp ) );
+					value.os.data = c;
+					value.os.len = attr->length - 3;
+					CHECK_FCT( fd_msg_avp_setvalue ( avp, &value ) );
+					CHECK_FCT( fd_msg_avp_add ( chap_auth, MSG_BRW_LAST_CHILD, avp) );
+				}
+				break;
+				
+			case RADIUS_ATTR_NAS_IP_ADDRESS:
+				CONV2DIAM_STR( NAS_IP_Address );
+				break;
+				
+			case RADIUS_ATTR_NAS_PORT:
+				CONV2DIAM_32B( NAS_Port );
+				break;
+				
+			case RADIUS_ATTR_SERVICE_TYPE:
+				CONV2DIAM_32B( Service_Type );
+				break;
+				
+			case RADIUS_ATTR_FRAMED_PROTOCOL:
+				CONV2DIAM_32B( Framed_Protocol );
+				break;
+				
+			case RADIUS_ATTR_FRAMED_IP_ADDRESS:
+				CONV2DIAM_STR( Framed_IP_Address );
+				break;
+				
+			case RADIUS_ATTR_FRAMED_IP_NETMASK:
+				CONV2DIAM_STR( Framed_IP_Netmask );
+				break;
+				
+			/* Framed-Routing never present in an Access-Request */
+			/* Filter-Id never present in an Access-Request */
+				
+			case RADIUS_ATTR_FRAMED_MTU:
+				CONV2DIAM_32B( Framed_MTU );
+				break;
+			
+			case RADIUS_ATTR_FRAMED_COMPRESSION:
+				CONV2DIAM_32B( Framed_Compression );
+				break;
+			
+			case RADIUS_ATTR_LOGIN_IP_HOST:
+				CONV2DIAM_STR( Login_IP_Host );
+				break;
+				
+			/* Login-Service never present in an Access-Request */
+			/* Login-TCP-Port never present in an Access-Request */
+			/* Reply-Message never present in an Access-Request */
+			
+			case RADIUS_ATTR_CALLBACK_NUMBER:
+				CONV2DIAM_STR( Callback_Number );
+				break;
+				
+			/* Callback-Id never present in an Access-Request */
+			/* Framed-Route never present in an Access-Request */
+			/* Framed-IPX-Network never present in an Access-Request */
+				
+			case RADIUS_ATTR_STATE:
+				CONV2DIAM_STR( State );
+				break;
+			
+			/* Class never present in an Access-Request */
+				
+			case RADIUS_ATTR_VENDOR_SPECIFIC:
+				/* RFC 4005, Section 9.6 : 
+					   Systems that don't have vendor format knowledge MAY discard such
+					   attributes without knowing a suitable translation.
+					   
+					   [conversion rule in 9.6.2]
+				 */
+				if (attr->length >= 6) {
+					uint32_t vendor_id;
+					uint8_t * c = (uint8_t *)(attr + 1);
+					
+					vendor_id = c[0] << 24 | c[1] << 16 | c[2] << 8 | c[3];
+					c += 4;
+					
+					switch (vendor_id) {
+						
+						/* For the vendors we KNOW they follow the VSA recommended format, we convert following the rules of RFC4005 (9.6.2) */
+						case RADIUS_VENDOR_ID_MICROSOFT : /* RFC 2548 */
+						/* other vendors ? */
+						{
+							size_t left;
+							struct radius_attr_vendor *vtlv;
+							
+							left = attr->length - 6;
+							vtlv = (struct radius_attr_vendor *)c;
+						
+							while ((left >= 2) && (vtlv->vendor_length <= left)) {
+								/* Search our dictionary for corresponding Vendor's AVP */
+								struct dict_avp_request req;
+								struct dict_object * avp_model = NULL;
+								memset(&req, 0, sizeof(struct dict_avp_request));
+								req.avp_vendor = vendor_id;
+								req.avp_code = vtlv->vendor_type;
+								
+								CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_CODE_AND_VENDOR, &req, &avp_model, 0) );
+								if (!avp_model) {
+									TRACE_DEBUG(FULL, "Unknown attribute (vendor 0x%x, code 0x%x) ignored.", req.avp_vendor, req.avp_code);
+								} else {
+									CHECK_FCT( fd_msg_avp_new ( avp_model, 0, &avp ) );
+									value.os.len = vtlv->vendor_length - 2;
+									value.os.data = (unsigned char *)(vtlv + 1);
+									CHECK_FCT( fd_msg_avp_setvalue ( avp, &value ) );
+									CHECK_FCT( fd_msg_avp_add ( *diam_fw, MSG_BRW_LAST_CHILD, avp) );
+								}
+								c += vtlv->vendor_length;
+								left -= vtlv->vendor_length;
+								vtlv = (struct radius_attr_vendor *)c;
+							}
+						}
+						break;
+						
+						/* Other vendors we KNOw how to convert the attributes would be added here... */
+						/* case RADIUS_VENDOR_ID_CISCO :
+							break; */
+						/* case RADIUS_VENDOR_ID_IETF : (extended RADIUS attributes)
+							break; */
+						
+						/* When we don't know, just discard the attribute... VSA are optional with regards to RADIUS anyway */
+						default:
+							/* do nothing */
+							TRACE_DEBUG(FULL, "VSA attribute from vendor %d discarded", vendor_id);
+							
+					}
+				}
+				break;
+				
+			/* Session-Timeout never present in an Access-Request */
+			/* Idle-Timeout never present in an Access-Request */
+			/* Termination-Action never present in an Access-Request */
+				
+			case RADIUS_ATTR_CALLED_STATION_ID:
+				CONV2DIAM_STR( Called_Station_Id );
+				break;
+			
+			case RADIUS_ATTR_CALLING_STATION_ID:
+				CONV2DIAM_STR( Calling_Station_Id );
+				break;
+			
+			case RADIUS_ATTR_NAS_IDENTIFIER:
+				CONV2DIAM_STR( NAS_Identifier );
+				break;
+			
+			/* Proxy-State is handled by echo_drop.rgwx plugin, we ignore it here */
+			
+			case RADIUS_ATTR_LOGIN_LAT_SERVICE:
+				CONV2DIAM_STR( Login_LAT_Service );
+				break;
+			
+			case RADIUS_ATTR_LOGIN_LAT_NODE:
+				CONV2DIAM_STR( Login_LAT_Node );
+				break;
+			
+			case RADIUS_ATTR_LOGIN_LAT_GROUP:
+				CONV2DIAM_STR( Login_LAT_Group );
+				break;
+			
+			/* Framed-AppleTalk-Link never present in an Access-Request */
+			/* Framed-AppleTalk-Network never present in an Access-Request */
+			/* Framed-AppleTalk-Zone never present in an Access-Request */
+			
+			case RADIUS_ATTR_CHAP_CHALLENGE:
+				CONV2DIAM_STR( CHAP_Challenge );
+				break;
+			
+			case RADIUS_ATTR_NAS_PORT_TYPE:
+				CONV2DIAM_32B( NAS_Port_Type );
+				break;
+			
+			case RADIUS_ATTR_PORT_LIMIT:
+				CONV2DIAM_32B( Port_Limit );
+				break;
+			
+			case RADIUS_ATTR_LOGIN_LAT_PORT:
+				CONV2DIAM_STR( Login_LAT_Port );
+				break;
+			
+			
+		/* RFC 3162 */	
+			case RADIUS_ATTR_NAS_IPV6_ADDRESS:
+				CONV2DIAM_STR( NAS_IPv6_Address );
+				break;
+				
+			case RADIUS_ATTR_FRAMED_INTERFACE_ID:
+				CONV2DIAM_64B( Framed_Interface_Id );
+				break;
+				
+			case RADIUS_ATTR_FRAMED_IPV6_PREFIX:
+				CONV2DIAM_STR( Framed_IPv6_Prefix );
+				break;
+				
+			case RADIUS_ATTR_LOGIN_IPV6_HOST:
+				CONV2DIAM_STR( Login_IPv6_Host );
+				break;
+				
+			/* Framed-IPv6-Route never present in an Access-Request */
+			/* Framed-IPv6-Pool never present in an Access-Request */
+
+
+		/* RFC 2868 */
+			/* Prepare the top-level Tunneling AVP for each tag values, as needed, and add to the Diameter message.
+				This macro is called when an AVP is added inside the group, so we will not have empty grouped AVPs */
+			#define AVP_TUN_PREPARE() {										\
+						if (avp_tun == NULL) {								\
+							CHECK_MALLOC( avp_tun = calloc(sizeof(struct avp *), 32 ) );		\
+						}										\
+						tag = *(uint8_t *)(attr + 1);							\
+						if (tag > 0x1F) tag = 0;							\
+						if (avp_tun[tag] == NULL) {							\
+							CHECK_FCT( fd_msg_avp_new ( cs->dict.Tunneling, 0, &avp_tun[tag] ) );	\
+							CHECK_FCT( fd_msg_avp_add (*diam_fw, MSG_BRW_LAST_CHILD, avp_tun[tag]));\
+						}										\
+					}
+			
+			/* Convert an attribute to an OctetString AVP and add inside the Tunneling AVP corresponding to the tag */
+			#define CONV2DIAM_TUN_STR( _dictobj_ ) {						\
+				uint8_t tag;									\
+				CHECK_PARAMS( attr->length >= 3);						\
+				AVP_TUN_PREPARE();								\
+				CHECK_FCT( fd_msg_avp_new ( cs->dict._dictobj_, 0, &avp ) );			\
+				value.os.len = attr->length - (tag ? 3 : 2);					\
+				value.os.data = ((unsigned char *)(attr + 1)) + (tag ? 1 : 0);			\
+				CHECK_FCT( fd_msg_avp_setvalue ( avp, &value ) );				\
+				CHECK_FCT( fd_msg_avp_add ( avp_tun[tag], MSG_BRW_LAST_CHILD, avp) );		\
+				}
+				
+			/* Convert an attribute to a scalar AVP and add inside the Tunneling AVP corresponding to the tag */
+			#define CONV2DIAM_TUN_24B( _dictobj_ ) {						\
+				uint8_t tag;									\
+				CHECK_PARAMS( attr->length == 6);						\
+				AVP_TUN_PREPARE();								\
+				CHECK_FCT( fd_msg_avp_new ( cs->dict._dictobj_, 0, &avp ) );			\
+				{										\
+					uint8_t * v = (uint8_t *)(attr + 1);					\
+					value.u32 = (v[1] << 16) | (v[2] <<8) | v[3] ;				\
+				}										\
+				CHECK_FCT( fd_msg_avp_setvalue ( avp, &value ) );				\
+				CHECK_FCT( fd_msg_avp_add ( avp_tun[tag], MSG_BRW_LAST_CHILD, avp) );		\
+				}
+
+			/*
+			      -  If the RADIUS message contains Tunnel information [RADTunnels],
+        			 the attributes or tagged groups should each be converted to a
+        			 Diameter Tunneling Grouped AVP set.  If the tunnel information
+        			 contains a Tunnel-Password attribute, the RADIUS encryption
+        			 must be resolved, and the password forwarded, by using Diameter
+        			 security methods.
+				    -> If the RADIUS message does not use properly the Tag info, result is unpredictable here.. 
+			*/
+			case RADIUS_ATTR_TUNNEL_TYPE:
+				CONV2DIAM_TUN_24B( Tunnel_Type );
+				break;
+			
+			case RADIUS_ATTR_TUNNEL_MEDIUM_TYPE:
+				CONV2DIAM_TUN_24B( Tunnel_Medium_Type );
+				break;
+			
+			case RADIUS_ATTR_TUNNEL_CLIENT_ENDPOINT:
+				CONV2DIAM_TUN_STR( Tunnel_Client_Endpoint );
+				break;
+			
+			case RADIUS_ATTR_TUNNEL_SERVER_ENDPOINT:
+				CONV2DIAM_TUN_STR( Tunnel_Server_Endpoint );
+				break;
+			
+			/* Tunnel-Password never present in an Access-Request */
+
+			case RADIUS_ATTR_TUNNEL_PRIVATE_GROUP_ID:
+				CONV2DIAM_TUN_STR( Tunnel_Private_Group_Id );
+				break;
+			
+			/* Tunnel-Assignment-ID never present in an Access-Request */
+			
+			case RADIUS_ATTR_TUNNEL_PREFERENCE:
+				CONV2DIAM_TUN_24B( Tunnel_Preference );
+				break;
+			
+			case RADIUS_ATTR_TUNNEL_CLIENT_AUTH_ID:
+				CONV2DIAM_TUN_STR( Tunnel_Client_Auth_Id );
+				break;
+			
+			case RADIUS_ATTR_TUNNEL_SERVER_AUTH_ID:
+				CONV2DIAM_TUN_STR( Tunnel_Server_Auth_Id );
+				break;
+			
+			
+		/* RFC 2869 */	
+			case RADIUS_ATTR_ARAP_PASSWORD:
+				CONV2DIAM_STR( ARAP_Password );
+				break;
+				
+			/* ARAP-Features never present in an Access-Request */
+			/* ARAP-Zone-Access never present in an Access-Request */
+			
+			case RADIUS_ATTR_ARAP_SECURITY:
+				CONV2DIAM_32B( ARAP_Security );
+				break;
+			
+			case RADIUS_ATTR_ARAP_SECURITY_DATA:
+				CONV2DIAM_STR( ARAP_Security_Data );
+				break;
+			
+			/* Password-Retry never present in an Access-Request */
+			/* Prompt never present in an Access-Request */
+			
+			case RADIUS_ATTR_CONNECT_INFO:
+				CONV2DIAM_STR( Connect_Info );
+				break;
+			
+			/* Configuration-Token never present in an Access-Request */
+			/* ARAP-Challenge-Response never present in an Access-Request */
+			/* Acct-Interim-Interval never present in an Access-Request */
+			
+			case RADIUS_ATTR_NAS_PORT_ID:
+				CONV2DIAM_STR( NAS_Port_Id );
+				break;
+			
+			/* Framed-Pool never present in an Access-Request */
+			
+				
+		/* RFC 2869 / 3579 */	
+			case RADIUS_ATTR_ORIGINATING_LINE_INFO:
+				CONV2DIAM_STR( Originating_Line_Info );
+				break;
+				
+			case RADIUS_ATTR_MESSAGE_AUTHENTICATOR:
+			case RADIUS_ATTR_EAP_MESSAGE:
+				/* It was already handled, just remove the attribute */
+				break;
+				
+		/* Default */		
+			default: /* unknown attribute */
+				/* We just keep the attribute in the RADIUS message */
+				rad_req->attr_pos[nattr_used++] = rad_req->attr_pos[idx];
+		}
+	}
+	
+	/* Destroy tunnel pointers (if we used it) */
+	free(avp_tun);
+	
+	/* Update the radius message to remove all handled attributes */
+	rad_req->attr_used = nattr_used;
+
+	/* Store the request identifier in the session (if provided) */
+	{
+		struct sess_state  *st;
+		CHECK_MALLOC(st = malloc(sizeof(struct sess_state)));
+		memcpy(st->req_auth, &rad_req->hdr->authenticator[0], 16);
+		
+		CHECK_FCT( fd_sess_state_store( cs->sess_hdl, sess, &st ) );
+	}
+	
+	return 0;
+}
+
+static int auth_diam_ans( struct rgwp_config * cs, struct msg ** diam_ans, struct radius_msg ** rad_fw, struct rgw_client * cli )
+{
+	struct msg_hdr * hdr;
+	struct avp *avp, *next, *avp_x, *avp_y, *aoh;
+	struct avp_hdr *ahdr, *oh;
+	uint8_t buf[254]; /* to store some attributes values (with final '\0') */
+	size_t sz;
+	int ta_set = 0;
+	int no_str = 0; /* indicate if an STR is required for this server */
+	uint8_t	tuntag = 0;
+	struct sess_state  *st;
+	int error_cause = 0;
+	struct session * sess;
+	os0_t sid = NULL;
+	size_t sidlen;
+	
+	TRACE_ENTRY("%p %p %p %p", cs, diam_ans, rad_fw, cli);
+	CHECK_PARAMS(cs && diam_ans && *diam_ans && rad_fw && *rad_fw);
+	
+	/* Retrieve the request identified which was stored in the session */
+	CHECK_FCT( fd_msg_sess_get(fd_g_config->cnf_dict, *diam_ans, &sess, NULL) );
+	if (sess) {
+		CHECK_FCT( fd_sess_state_retrieve( cs->sess_hdl, sess, &st ) );
+		CHECK_FCT( fd_sess_getsid(sess, &sid, &sidlen) );
+	} /* else ? */
+	
+	/*	
+	      -  If the Diameter Command-Code is set to AA-Answer and the
+        	 Result-Code AVP is set to DIAMETER_MULTI_ROUND_AUTH, the
+        	 gateway must send a RADIUS Access-Challenge.  This must have
+        	 the Origin-Host, Origin-Realm, and Diameter Session-Id AVPs
+        	 encapsulated in the RADIUS State attribute, with the prefix
+        	 "Diameter/", concatenated in the above order separated with "/"
+        	 characters, in UTF-8 [UTF-8].  This is necessary to ensure that
+        	 the Translation Agent receiving the subsequent RADIUS Access-
+        	 Request will have access to the Session Identifier and be able
+        	 to set the Destination-Host to the correct value.
+		 	-> done here below
+		 
+	      -  If the Command-Code is set to AA-Answer, the Diameter Session-
+        	 Id AVP is saved in a new RADIUS Class attribute whose format
+        	 consists of the string "Diameter/" followed by the Diameter
+        	 Session Identifier.  This will ensure that the subsequent
+        	 Accounting messages, which could be received by any Translation
+        	 Agent, would have access to the original Diameter Session
+        	 Identifier.
+		 	-> done here but only for Access-Accept messages (Result-Code = success)
+	 */
+	
+	/* MACROS to help in the process: convert AVP data to RADIUS attributes. */
+	/* Control large attributes:  _trunc_ = 0 => error; _trunc_ = 1 => truncate; _trunc = 2 => create several attributes */
+	#define CONV2RAD_STR( _attr_, _data_, _len_, _trunc_)	{					\
+		size_t __l = (size_t)(_len_);								\
+		size_t __off = 0;									\
+		TRACE_DEBUG(FULL, "Converting AVP to "#_attr_);						\
+		if ((_trunc_) == 0) {									\
+			CHECK_PARAMS( __l <= 253 );							\
+		}											\
+		if ((__l > 253) && (_trunc_ == 1)) {							\
+			TRACE_DEBUG(INFO, "[auth.rgwx] AVP truncated in "#_attr_);			\
+			__l = 253;									\
+		}											\
+		do {											\
+			size_t __w = (__l > 253) ? 253 : __l;						\
+			CHECK_MALLOC(radius_msg_add_attr(*rad_fw, (_attr_), (_data_) + __off, __w));	\
+			__off += __w;									\
+			__l   -= __w;									\
+		} while (__l);										\
+	}
+
+	#define CONV2RAD_32B( _attr_, _data_)	{							\
+		uint32_t __v = htonl((uint32_t)(_data_));						\
+		TRACE_DEBUG(FULL, "Converting AVP to "#_attr_);						\
+		CHECK_MALLOC(radius_msg_add_attr(*rad_fw, (_attr_), (uint8_t *)&__v, sizeof(__v)));	\
+	}
+
+	#define CONV2RAD_64B( _attr_, _data_)	{							\
+		uint64_t __v = htonll((uint64_t)(_data_));						\
+		TRACE_DEBUG(FULL, "Converting AVP to "#_attr_);						\
+		CHECK_MALLOC(radius_msg_add_attr(*rad_fw, (_attr_), (uint8_t *)&__v, sizeof(__v)));	\
+	}
+
+	/* Search the different AVPs we handle here */
+	CHECK_FCT( fd_msg_search_avp (*diam_ans, cs->dict.Origin_Host, &aoh) );
+	CHECK_FCT( fd_msg_avp_hdr ( aoh, &oh ) );
+
+	/* Check the Diameter error code */
+	CHECK_FCT( fd_msg_search_avp (*diam_ans, cs->dict.Result_Code, &avp) );
+	ASSERT( avp ); /* otherwise the message should have been discarded a lot earlier because of ABNF */
+	CHECK_FCT( fd_msg_avp_hdr ( avp, &ahdr ) );
+	switch (ahdr->avp_value->u32) {
+		case ER_DIAMETER_MULTI_ROUND_AUTH:
+			(*rad_fw)->hdr->code = RADIUS_CODE_ACCESS_CHALLENGE;
+			break;
+		case ER_DIAMETER_SUCCESS:
+		case ER_DIAMETER_LIMITED_SUCCESS:
+			(*rad_fw)->hdr->code = RADIUS_CODE_ACCESS_ACCEPT;
+			break;
+		
+		default:
+			/* Can we convert the value to a natural Error-Cause ? */
+			switch (ahdr->avp_value->u32) {
+				case ER_DIAMETER_AVP_UNSUPPORTED:
+					error_cause = 401; /* Unsupported Attribute */
+					break;
+					
+				case ER_DIAMETER_MISSING_AVP:
+					error_cause = 402; /* Missing Attribute */
+					break;
+					
+				case ER_DIAMETER_UNABLE_TO_COMPLY:
+					error_cause = 404; /* Invalid Request */
+					break;
+					
+				case ER_DIAMETER_APPLICATION_UNSUPPORTED:
+					error_cause = 405; /* Unsupported Service */
+					break;
+					
+				case ER_DIAMETER_COMMAND_UNSUPPORTED:
+					error_cause = 406; /* Unsupported Extension */
+					break;
+					
+				case ER_DIAMETER_INVALID_AVP_VALUE:
+					error_cause = 407; /* Invalid Attribute Value */
+					break;
+					
+				case ER_DIAMETER_AVP_NOT_ALLOWED:
+					error_cause = 501; /* Administratively Prohibited */
+					break;
+					
+				case ER_DIAMETER_REALM_NOT_SERVED:
+				case ER_DIAMETER_LOOP_DETECTED:
+				case ER_DIAMETER_UNKNOWN_PEER:
+				case ER_DIAMETER_UNABLE_TO_DELIVER:
+					error_cause = 502; /* Request Not Routable (Proxy) */
+					break;
+					
+				case ER_DIAMETER_UNKNOWN_SESSION_ID:
+					error_cause = 503; /* Session Context Not Found */
+					break;
+					
+				case ER_DIAMETER_TOO_BUSY:
+				case ER_DIAMETER_OUT_OF_SPACE:
+					error_cause = 506; /* Resources Unavailable */
+					break;
+					
+#if 0
+			/* remaining Diameter Result-Code & RADIUS Error-Cause */
+				case ER_DIAMETER_REDIRECT_INDICATION:
+				case ER_DIAMETER_INVALID_HDR_BITS:
+				case ER_DIAMETER_INVALID_AVP_BITS:
+				case ER_DIAMETER_AUTHENTICATION_REJECTED:
+				case ER_ELECTION_LOST:
+				case ER_DIAMETER_AUTHORIZATION_REJECTED:
+				case ER_DIAMETER_RESOURCES_EXCEEDED:
+				case ER_DIAMETER_CONTRADICTING_AVPS:
+				case ER_DIAMETER_AVP_OCCURS_TOO_MANY_TIMES
+				case ER_DIAMETER_NO_COMMON_APPLICATION:
+				case ER_DIAMETER_UNSUPPORTED_VERSION:
+				case ER_DIAMETER_INVALID_BIT_IN_HEADER:
+				case ER_DIAMETER_INVALID_AVP_LENGTH:
+				case ER_DIAMETER_INVALID_MESSAGE_LENGTH:
+				case ER_DIAMETER_INVALID_AVP_BIT_COMBO:
+				case ER_DIAMETER_NO_COMMON_SECURITY:
+					error_cause = 403; /* NAS Identification Mismatch */
+					error_cause = 504; /* Session Context Not Removable */
+					error_cause = 505; /* Other Proxy Processing Error */
+					error_cause = 507; /* Request Initiated */
+					error_cause = 508; /* Multiple Session Selection Unsupported */
+#endif /* 0 */
+			}
+			/* In any case, the following is processed: */
+			(*rad_fw)->hdr->code = RADIUS_CODE_ACCESS_REJECT;
+			fd_log_debug("[auth.rgwx] Received Diameter answer with error code '%d' from server '%.*s', session %.*s, translating into Access-Reject",
+					ahdr->avp_value->u32, 
+					(int)oh->avp_value->os.len, oh->avp_value->os.data,
+					(int)sidlen, sid);
+			CHECK_FCT( fd_msg_search_avp (*diam_ans, cs->dict.Error_Message, &avp_x) );
+			if (avp_x) {
+				CHECK_FCT( fd_msg_avp_hdr ( avp_x, &ahdr ) );
+				fd_log_debug("[auth.rgwx]   Error-Message content: '%.*s'",
+						(int)ahdr->avp_value->os.len, ahdr->avp_value->os.data);
+			}
+			CHECK_FCT( fd_msg_search_avp (*diam_ans, cs->dict.Error_Reporting_Host, &avp_x) );
+			if (avp_x) {
+				CHECK_FCT( fd_msg_avp_hdr ( avp_x, &ahdr ) );
+				fd_log_debug("[auth.rgwx]   Error-Reporting-Host: '%.*s'",
+						(int)ahdr->avp_value->os.len, ahdr->avp_value->os.data);
+			}
+			CHECK_FCT( fd_msg_search_avp (*diam_ans, cs->dict.Failed_AVP, &avp_x) );
+			if (avp_x) {
+				fd_log_debug("[auth.rgwx]   Failed-AVP was included in the message.");
+				/* Dump its content ? */
+			}
+	}
+	/* Remove this Result-Code avp */
+	CHECK_FCT( fd_msg_free( avp ) );
+	
+	/* Creation of the State or Class attribute with session information */
+	CHECK_FCT( fd_msg_search_avp (*diam_ans, cs->dict.Origin_Realm, &avp) );
+	CHECK_FCT( fd_msg_avp_hdr ( avp, &ahdr ) );
+	
+	/* Now, save the session-id and eventually server info in a STATE or CLASS attribute */
+	if ((*rad_fw)->hdr->code == RADIUS_CODE_ACCESS_CHALLENGE) {
+		if (sizeof(buf) < (sz = snprintf((char *)buf, sizeof(buf), "Diameter/%.*s/%.*s/%.*s", 
+				(int)oh->avp_value->os.len,  (char *)oh->avp_value->os.data,
+				(int)ahdr->avp_value->os.len,  (char *)ahdr->avp_value->os.data,
+				(int)sidlen, (char *)sid))) {
+			TRACE_DEBUG(INFO, "Data truncated in State attribute: %s", buf);
+		}
+		CONV2RAD_STR(RADIUS_ATTR_STATE, buf, sz, 0);
+	}
+
+	if ((*rad_fw)->hdr->code == RADIUS_CODE_ACCESS_ACCEPT) {
+		/* Add the Session-Id */
+		if (sizeof(buf) < (sz = snprintf((char *)buf, sizeof(buf), "Diameter/%.*s", 
+				(int)sidlen, sid))) {
+			TRACE_DEBUG(INFO, "Data truncated in Class attribute: %s", buf);
+		}
+		CONV2RAD_STR(RADIUS_ATTR_CLASS, buf, sz, 0);
+	}
+	
+	/* Unlink the Origin-Realm now; the others are unlinked at the end of this function */
+	CHECK_FCT( fd_msg_free( avp ) );
+	
+	CHECK_FCT( fd_msg_search_avp (*diam_ans, cs->dict.Session_Timeout, &avp) );
+	CHECK_FCT( fd_msg_search_avp (*diam_ans, cs->dict.Authorization_Lifetime, &avp_x) );
+	CHECK_FCT( fd_msg_search_avp (*diam_ans, cs->dict.Re_Auth_Request_Type, &avp_y) );
+	/*	
+	   When translating a Diameter AA-Answer (with successful result code)
+	   to RADIUS Access-Accept that contains a Session-Timeout or
+	   Authorization-Lifetime AVP, take the following steps:
+	   
+	      -  If the Diameter message contains a Session-Timeout AVP but no
+        	 Authorization-Lifetime AVP, translate it to a Session-Timeout
+        	 attribute (not a Termination-Action).
+	*/
+	if ((avp != NULL) && (avp_x == NULL)) {
+		CHECK_FCT( fd_msg_avp_hdr ( avp, &ahdr ) );
+		CONV2RAD_32B( RADIUS_ATTR_SESSION_TIMEOUT, ahdr->avp_value->u32 );
+	}
+	
+	/*	
+	      -  If the Diameter message contains an Authorization-Lifetime AVP
+        	 but no Session-Timeout AVP, translate it to a Session-Timeout
+        	 attribute and a Termination-Action set to AA-REQUEST.  (Remove
+        	 Authorization-Lifetime and Re-Auth-Request-Type.)
+	*/
+	if ((avp == NULL) && (avp_x != NULL)) {
+		CHECK_FCT( fd_msg_avp_hdr ( avp_x, &ahdr ) );
+		CONV2RAD_32B( RADIUS_ATTR_SESSION_TIMEOUT, ahdr->avp_value->u32 );
+		CONV2RAD_32B( RADIUS_ATTR_TERMINATION_ACTION, RADIUS_TERMINATION_ACTION_RADIUS_REQUEST );
+		ta_set = 1;
+	}
+	
+	/*	
+	      -  If the Diameter message has both, the Session-Timeout must be
+        	 greater than or equal to the Authorization-Lifetime (required
+        	 by [BASE]).  Translate it to a Session-Timeout value (with
+        	 value from Authorization-Lifetime AVP, the smaller one) and
+        	 with the Termination-Action set to AA-REQUEST.  (Remove the
+        	 Authorization-Lifetime and Re-Auth-Request-Type.)
+	*/
+	if ((avp != NULL) && (avp_x != NULL)) {
+		CHECK_FCT( fd_msg_avp_hdr ( avp_x, &ahdr ) );
+		CONV2RAD_32B( RADIUS_ATTR_SESSION_TIMEOUT, ahdr->avp_value->u32 );
+		CONV2RAD_32B( RADIUS_ATTR_TERMINATION_ACTION, RADIUS_TERMINATION_ACTION_RADIUS_REQUEST );
+		ta_set = 1;
+	}
+	
+	/*  -> Not too sure about Auth-Grace-Period... we'll just discard it for now */
+	
+	if (avp) {
+		CHECK_FCT( fd_msg_free( avp ) );
+	}
+	if (avp_x) {
+		CHECK_FCT( fd_msg_free( avp_x ) );
+	}
+	if (avp_y) {
+		CHECK_FCT( fd_msg_free( avp_y ) );
+	}
+	
+	
+	/*
+	      -  If a Proxy-State attribute was present in the RADIUS request,
+        	 the same attribute is added in the response.  This information
+        	 may be found in the Proxy-Info AVP group, or in a local state
+        	 table.
+		 	-> handled by sub_echo_drop
+
+	      -  If state information regarding the RADIUS request was saved in
+        	 a Proxy-Info AVP or local state table, the RADIUS Identifier
+        	 and UDP IP Address and port number are extracted and used in
+        	 issuing the RADIUS reply.
+		 	-> was saved with the full request
+	*/
+	
+	
+	/* Now loop in the list of AVPs and convert those that we know how */
+	CHECK_FCT( fd_msg_browse(*diam_ans, MSG_BRW_FIRST_CHILD, &next, NULL) );
+	
+	while (next) {
+		int handled = 1;
+		avp = next;
+		CHECK_FCT( fd_msg_browse(avp, MSG_BRW_NEXT, &next, NULL) );
+		
+		CHECK_FCT( fd_msg_avp_hdr ( avp, &ahdr ) );
+		
+		if (!(ahdr->avp_flags & AVP_FLAG_VENDOR)) {
+			switch (ahdr->avp_code) {
+		/* In case of Diameter error, include the Reply-Message attribute */
+				case DIAM_ATTR_ERROR_MESSAGE:
+					CONV2RAD_STR(RADIUS_ATTR_REPLY_MESSAGE, ahdr->avp_value->os.data, ahdr->avp_value->os.len, 2);
+					break;
+					
+				case DIAM_ATTR_ERROR_REPORTING_HOST:
+					{
+						char buf[254];
+						int bsz = snprintf(buf, sizeof(buf), "Error-Reporting-Host: %*s", (int)(ahdr->avp_value->os.len), ahdr->avp_value->os.data);
+						CONV2RAD_STR(RADIUS_ATTR_REPLY_MESSAGE, (uint8_t *)buf, bsz, 2);
+					}
+					break;
+				
+				case DIAM_ATTR_FAILED_AVP:
+					{
+						struct avp * favp;
+						CHECK_FCT( fd_msg_browse(avp, MSG_BRW_FIRST_CHILD, &favp, NULL) );
+						if (favp) {
+							char buf[254];
+							int bsz;
+							struct dict_object * favp_model;
+							
+							CHECK_FCT( fd_msg_model(favp, &favp_model) );
+							if (favp_model) {
+								struct dict_avp_data fadata;
+								CHECK_FCT( fd_dict_getval(favp_model, &fadata) );
+								bsz = snprintf(buf, sizeof(buf), "Failed-AVP: %s", fadata.avp_name);
+							} else {
+								struct avp_hdr * favp_hdr;
+								CHECK_FCT( fd_msg_avp_hdr ( favp, &favp_hdr ) );
+								bsz = snprintf(buf, sizeof(buf), "Failed-AVP: code %u, vendor %u", favp_hdr->avp_code, favp_hdr->avp_vendor);
+							}
+							CONV2RAD_STR(RADIUS_ATTR_REPLY_MESSAGE, (uint8_t *)buf, bsz, 2);
+						}
+					}
+					break;
+					
+		/* RFC 4005 (AVP in the order of the AA-Request/Answer AVP Table) */
+				case DIAM_ATTR_ACCT_INTERIM_INTERVAL:
+					CONV2RAD_32B(RADIUS_ATTR_ACCT_INTERIM_INTERVAL, ahdr->avp_value->u32);
+					break;
+					
+				case DIAM_ATTR_ARAP_CHALLENGE_RESPONSE:
+					CONV2RAD_STR(RADIUS_ATTR_ARAP_CHALLENGE_RESPONSE, ahdr->avp_value->os.data, ahdr->avp_value->os.len, 0);
+					break;
+					
+				case DIAM_ATTR_ARAP_FEATURES:
+					CONV2RAD_STR(RADIUS_ATTR_ARAP_FEATURES, ahdr->avp_value->os.data, ahdr->avp_value->os.len, 0);
+					break;
+					
+				/* ARAP-Password is not present in answers */
+					
+				case DIAM_ATTR_ARAP_SECURITY:
+					CONV2RAD_32B(RADIUS_ATTR_ARAP_SECURITY, ahdr->avp_value->u32);
+					break;
+					
+				case DIAM_ATTR_ARAP_SECURITY_DATA:
+					CONV2RAD_STR(RADIUS_ATTR_ARAP_SECURITY_DATA, ahdr->avp_value->os.data, ahdr->avp_value->os.len, 2);
+					break;
+					
+				case DIAM_ATTR_ARAP_ZONE_ACCESS:
+					CONV2RAD_32B(RADIUS_ATTR_ARAP_ZONE_ACCESS, ahdr->avp_value->u32);
+					break;
+					
+				case DIAM_ATTR_AUTH_APPLICATION_ID:
+					/* We just remove this AVP */
+					break;
+					
+				case DIAM_ATTR_AUTH_GRACE_PERIOD:
+					/* We just remove this AVP (?) */
+					break;
+				
+				case DIAM_ATTR_AUTH_REQUEST_TYPE:
+					/* We only check the value */
+					if (ahdr->avp_value->u32 != 3) {
+						fd_log_debug("[auth.rgwx] Received Diameter answer with Auth-Request-Type set to %d (%s) from server %.*s, session %.*s."
+								"  This may cause interoperability problems with RADIUS.",
+								ahdr->avp_value->u32,
+								(ahdr->avp_value->u32 == 1) ? "AUTHENTICATE_ONLY" :
+									((ahdr->avp_value->u32 == 2) ? "AUTHORIZE_ONLY" : "???"),
+								(int)oh->avp_value->os.len, oh->avp_value->os.data, 
+								(int)sidlen, sid);
+					}
+					break;
+				
+				case DIAM_ATTR_AUTH_SESSION_STATE:
+					if ((!ta_set) && (ahdr->avp_value->u32 == ACV_ASS_STATE_MAINTAINED)) {
+						CONV2RAD_32B( RADIUS_ATTR_TERMINATION_ACTION, RADIUS_TERMINATION_ACTION_RADIUS_REQUEST );
+					}
+					
+					if (ahdr->avp_value->u32 == ACV_ASS_NO_STATE_MAINTAINED) {
+						no_str = 1;
+					}
+					break;
+					
+				/* Authorization-Lifetime already handled */
+				
+				case DIAM_ATTR_CALLBACK_ID:
+					CONV2RAD_STR(RADIUS_ATTR_CALLBACK_ID, ahdr->avp_value->os.data, ahdr->avp_value->os.len, 1);
+					break;
+				
+				case DIAM_ATTR_CALLBACK_NUMBER:
+					CONV2RAD_STR(RADIUS_ATTR_CALLBACK_NUMBER, ahdr->avp_value->os.data, ahdr->avp_value->os.len, 1);
+					break;
+				
+				/* Called-Station-Id is not present in answers */
+				/* Calling-Station-Id is not present in answers */
+				/* CHAP-Auth is not present in answers */
+				/* CHAP-Challenge is not present in answers */
+					
+				case DIAM_ATTR_CLASS:
+					CONV2RAD_STR(RADIUS_ATTR_CLASS, ahdr->avp_value->os.data, ahdr->avp_value->os.len, 2);
+					break;
+				
+				case DIAM_ATTR_CONFIGURATION_TOKEN:
+					/* We might as well remove it since it's not supposed to be sent to the NAS... */
+					CONV2RAD_STR(RADIUS_ATTR_CONFIGURATION_TOKEN, ahdr->avp_value->os.data, ahdr->avp_value->os.len, 2);
+					break;
+				
+				/* Connect-Info is not present in answers */
+				
+				case DIAM_ATTR_FILTER_ID:
+					CONV2RAD_STR(RADIUS_ATTR_FILTER_ID, ahdr->avp_value->os.data, ahdr->avp_value->os.len, 2);
+					break;
+					
+				case DIAM_ATTR_FRAMED_APPLETALK_LINK:
+					CONV2RAD_32B(RADIUS_ATTR_FRAMED_APPLETALK_LINK, ahdr->avp_value->u32);
+					break;
+					
+				case DIAM_ATTR_FRAMED_APPLETALK_NETWORK:
+					CONV2RAD_32B(RADIUS_ATTR_FRAMED_APPLETALK_NETWORK, ahdr->avp_value->u32);
+					break;
+					
+				case DIAM_ATTR_FRAMED_APPLETALK_ZONE:
+					CONV2RAD_STR(RADIUS_ATTR_FRAMED_APPLETALK_ZONE, ahdr->avp_value->os.data, ahdr->avp_value->os.len, 1);
+					break;
+					
+				case DIAM_ATTR_FRAMED_COMPRESSION:
+					CONV2RAD_32B(RADIUS_ATTR_FRAMED_COMPRESSION,  ahdr->avp_value->u32);
+					break;
+					
+				case DIAM_ATTR_FRAMED_INTERFACE_ID:
+					CONV2RAD_64B(RADIUS_ATTR_FRAMED_INTERFACE_ID,  ahdr->avp_value->u64);
+					break;
+					
+				case DIAM_ATTR_FRAMED_IP_ADDRESS:
+					CONV2RAD_STR(RADIUS_ATTR_FRAMED_IP_ADDRESS,  ahdr->avp_value->os.data, ahdr->avp_value->os.len, 0);
+					break;
+					
+				case DIAM_ATTR_FRAMED_IP_NETMASK:
+					CONV2RAD_STR(RADIUS_ATTR_FRAMED_IP_NETMASK, ahdr->avp_value->os.data, ahdr->avp_value->os.len, 0);
+					break;
+					
+				case DIAM_ATTR_FRAMED_IPV6_PREFIX:
+					CONV2RAD_STR(RADIUS_ATTR_FRAMED_IPV6_PREFIX, ahdr->avp_value->os.data, ahdr->avp_value->os.len, 0);
+					break;
+					
+				case DIAM_ATTR_FRAMED_IPV6_POOL:
+					CONV2RAD_STR(RADIUS_ATTR_FRAMED_IPV6_POOL, ahdr->avp_value->os.data, ahdr->avp_value->os.len, 1);
+					break;
+					
+				case DIAM_ATTR_FRAMED_IPV6_ROUTE:
+					CONV2RAD_STR(RADIUS_ATTR_FRAMED_IPV6_ROUTE, ahdr->avp_value->os.data, ahdr->avp_value->os.len, 1);
+					break;
+					
+				case DIAM_ATTR_FRAMED_IPX_NETWORK:
+					CONV2RAD_32B(RADIUS_ATTR_FRAMED_IPX_NETWORK, ahdr->avp_value->u32);
+					break;
+					
+				case DIAM_ATTR_FRAMED_MTU:
+					CONV2RAD_32B(RADIUS_ATTR_FRAMED_MTU, ahdr->avp_value->u32);
+					break;
+					
+				case DIAM_ATTR_FRAMED_POOL:
+					CONV2RAD_STR(RADIUS_ATTR_FRAMED_POOL, ahdr->avp_value->os.data, ahdr->avp_value->os.len, 1);
+					break;
+					
+				case DIAM_ATTR_FRAMED_PROTOCOL:
+					CONV2RAD_32B(RADIUS_ATTR_FRAMED_PROTOCOL, ahdr->avp_value->u32);
+					break;
+					
+				case DIAM_ATTR_FRAMED_ROUTE:
+					CONV2RAD_STR(RADIUS_ATTR_FRAMED_ROUTE, ahdr->avp_value->os.data, ahdr->avp_value->os.len, 1);
+					break;
+					
+				case DIAM_ATTR_FRAMED_ROUTING:
+					CONV2RAD_32B(RADIUS_ATTR_FRAMED_ROUTING, ahdr->avp_value->u32);
+					break;
+					
+				case DIAM_ATTR_IDLE_TIMEOUT:
+					CONV2RAD_32B(RADIUS_ATTR_IDLE_TIMEOUT, ahdr->avp_value->u32);
+					break;
+					
+				case DIAM_ATTR_LOGIN_IP_HOST:
+					CONV2RAD_STR(RADIUS_ATTR_LOGIN_IP_HOST, ahdr->avp_value->os.data, ahdr->avp_value->os.len, 0);
+					break;
+					
+				case DIAM_ATTR_LOGIN_IPV6_HOST:
+					CONV2RAD_STR(RADIUS_ATTR_LOGIN_IPV6_HOST, ahdr->avp_value->os.data, ahdr->avp_value->os.len, 0);
+					break;
+					
+				case DIAM_ATTR_LOGIN_LAT_GROUP:
+					CONV2RAD_STR(RADIUS_ATTR_LOGIN_LAT_GROUP, ahdr->avp_value->os.data, ahdr->avp_value->os.len, 1);
+					break;
+					
+				case DIAM_ATTR_LOGIN_LAT_NODE:
+					CONV2RAD_STR(RADIUS_ATTR_LOGIN_LAT_NODE, ahdr->avp_value->os.data, ahdr->avp_value->os.len, 1);
+					break;
+					
+				case DIAM_ATTR_LOGIN_LAT_PORT:
+					CONV2RAD_STR(RADIUS_ATTR_LOGIN_LAT_PORT, ahdr->avp_value->os.data, ahdr->avp_value->os.len, 1);
+					break;
+					
+				case DIAM_ATTR_LOGIN_LAT_SERVICE:
+					CONV2RAD_STR(RADIUS_ATTR_LOGIN_LAT_SERVICE, ahdr->avp_value->os.data, ahdr->avp_value->os.len, 1);
+					break;
+					
+				case DIAM_ATTR_LOGIN_SERVICE:
+					CONV2RAD_32B(RADIUS_ATTR_LOGIN_SERVICE, ahdr->avp_value->u32);
+					break;
+					
+				case DIAM_ATTR_LOGIN_TCP_PORT:
+					CONV2RAD_32B(RADIUS_ATTR_LOGIN_TCP_PORT, ahdr->avp_value->u32);
+					break;
+					
+			/*
+			      -							        If the
+        			 Multi-Round-Time-Out AVP is present, the value of the AVP MUST
+        			 be inserted in the RADIUS Session-Timeout AVP.
+
+			      o  As described in [NASREQ], if the Result-Code AVP set to
+				 DIAMETER_MULTI_ROUND_AUTH and the Multi-Round-Time-Out AVP is
+				 present, it is translated to the RADIUS Session-Timeout attribute.
+			*/
+				case DIAM_ATTR_MULTI_ROUND_TIMEOUT:
+					CONV2RAD_32B(RADIUS_ATTR_SESSION_TIMEOUT, ahdr->avp_value->u32);
+					break;
+					
+				case DIAM_ATTR_NAS_FILTER_RULE:
+					/* This is not translatable to RADIUS */
+					fd_log_debug("[auth.rgwx] Received Diameter answer with non-translatable NAS-Filter-Rule AVP from '%.*s' (session: '%.*s'), ignoring.",
+							(int)oh->avp_value->os.len, oh->avp_value->os.data,
+							(int)sidlen, sid);
+					handled = 0;
+					break;
+					
+				/* NAS-Identifier is not present in answers */
+				/* NAS-IP-Address is not present in answers */
+				/* NAS-IPv6-Address is not present in answers */
+				/* NAS-Port is not present in answers */
+				/* NAS-Port-Id is not present in answers */
+				/* NAS-Port-Type is not present in answers */
+				
+				case DIAM_ATTR_ORIGIN_AAA_PROTOCOL:
+					/* We just remove this AVP */
+					break;
+					
+				/* Originating-Line-Info is not present in answers */
+				
+				case DIAM_ATTR_PASSWORD_RETRY:
+					CONV2RAD_32B(RADIUS_ATTR_PASSWORD_RETRY, ahdr->avp_value->u32);
+					break;
+				
+				case DIAM_ATTR_PORT_LIMIT:
+					CONV2RAD_32B(RADIUS_ATTR_PORT_LIMIT, ahdr->avp_value->u32);
+					break;
+				
+				case DIAM_ATTR_PROMPT:
+					CONV2RAD_32B(RADIUS_ATTR_PROMPT, ahdr->avp_value->u32);
+					break;
+					
+				case DIAM_ATTR_QOS_FILTER_RULE:
+					/* This is not translatable to RADIUS */
+					fd_log_debug("[auth.rgwx] Received Diameter answer with non-translatable QoS-Filter-Rule AVP from '%.*s' (session: '%.*s'), ignoring.",
+							(int)oh->avp_value->os.len, oh->avp_value->os.data,
+							(int)sidlen, sid);
+					handled = 0;
+					break;
+					
+				/* Re-Auth-Request-Type already handled */
+				
+				case DIAM_ATTR_REPLY_MESSAGE:
+					CONV2RAD_STR(RADIUS_ATTR_REPLY_MESSAGE, ahdr->avp_value->os.data, ahdr->avp_value->os.len, 2);
+					break;
+					
+				case DIAM_ATTR_SERVICE_TYPE:
+					CONV2RAD_32B(RADIUS_ATTR_SERVICE_TYPE, ahdr->avp_value->u32);
+					break;
+				
+				case DIAM_ATTR_STATE:
+					CONV2RAD_STR(RADIUS_ATTR_STATE, ahdr->avp_value->os.data, ahdr->avp_value->os.len, 2);
+					break;
+					
+				case DIAM_ATTR_TUNNELING:
+					{
+#define CONV2RAD_TUN_STR( _attr_, _data_, _len_, _trunc_)	{				\
+	size_t __l = (size_t)(_len_);								\
+	size_t __w = (__l > 252) ? 252 : __l;							\
+	size_t __off = 0;									\
+	if ((_trunc_) == 0) {									\
+		CHECK_PARAMS( __l <= 252 );							\
+	}											\
+	if ((__l > 252) && (_trunc_ == 1)) {							\
+		TRACE_DEBUG(FULL, "Attribute truncated!");					\
+		__l = 252;									\
+	}											\
+	buf[0] = tuntag;									\
+	memcpy(&buf[1], (_data_), __w);								\
+	CHECK_MALLOC(radius_msg_add_attr(*rad_fw, (_attr_), &buf[0], __w + 1));			\
+	while (__l -= __w) {									\
+		__off += __w;									\
+		__w = (__l > 253) ? 253 : __l;							\
+		CHECK_MALLOC(radius_msg_add_attr(*rad_fw, (_attr_), (_data_) + __off, __w));	\
+	}											\
+}
+
+#define CONV2RAD_TUN_32B( _attr_, _data_)	{						\
+	uint32_t __v = htonl((uint32_t)(_data_) | (tuntag << 24));				\
+	CHECK_MALLOC(radius_msg_add_attr(*rad_fw, (_attr_), (uint8_t *)&__v, sizeof(__v)));	\
+}
+						struct avp *inavp, *innext;
+						tuntag++;
+						CHECK_FCT( fd_msg_browse(avp, MSG_BRW_FIRST_CHILD, &innext, NULL) );
+						while (innext) {
+							inavp = innext;
+							CHECK_FCT( fd_msg_browse(inavp, MSG_BRW_NEXT, &innext, NULL) );
+							CHECK_FCT( fd_msg_avp_hdr ( inavp, &ahdr ) );
+							
+							if ( ! (ahdr->avp_flags & AVP_FLAG_VENDOR)) {
+								switch (ahdr->avp_code) {
+									case DIAM_ATTR_TUNNEL_TYPE:
+										CONV2RAD_TUN_32B( RADIUS_ATTR_TUNNEL_TYPE, ahdr->avp_value->u32);
+										break;
+										
+									case DIAM_ATTR_TUNNEL_MEDIUM_TYPE:
+										CONV2RAD_TUN_32B( RADIUS_ATTR_TUNNEL_MEDIUM_TYPE, ahdr->avp_value->u32);
+										break;
+										
+									case DIAM_ATTR_TUNNEL_CLIENT_ENDPOINT:
+										CONV2RAD_TUN_STR(RADIUS_ATTR_TUNNEL_CLIENT_ENDPOINT, ahdr->avp_value->os.data, ahdr->avp_value->os.len, 1);
+										break;
+										
+									case DIAM_ATTR_TUNNEL_SERVER_ENDPOINT:
+										CONV2RAD_TUN_STR(RADIUS_ATTR_TUNNEL_SERVER_ENDPOINT, ahdr->avp_value->os.data, ahdr->avp_value->os.len, 1);
+										break;
+										
+									case DIAM_ATTR_TUNNEL_PREFERENCE:
+										CONV2RAD_TUN_32B( RADIUS_ATTR_TUNNEL_PREFERENCE, ahdr->avp_value->u32);
+										break;
+										
+									case DIAM_ATTR_TUNNEL_CLIENT_AUTH_ID:
+										CONV2RAD_TUN_STR(RADIUS_ATTR_TUNNEL_CLIENT_AUTH_ID, ahdr->avp_value->os.data, ahdr->avp_value->os.len, 1);
+										break;
+										
+									case DIAM_ATTR_TUNNEL_SERVER_AUTH_ID:
+										CONV2RAD_TUN_STR(RADIUS_ATTR_TUNNEL_SERVER_AUTH_ID, ahdr->avp_value->os.data, ahdr->avp_value->os.len, 1);
+										break;
+										
+									case DIAM_ATTR_TUNNEL_ASSIGNMENT_ID:
+										CONV2RAD_TUN_STR(RADIUS_ATTR_TUNNEL_ASSIGNMENT_ID, ahdr->avp_value->os.data, ahdr->avp_value->os.len, 1);
+										break;
+										
+									case DIAM_ATTR_TUNNEL_PASSWORD:
+										{
+											/* This AVP must be encoded for RADIUS (similar to radius_msg_add_attr_user_password)
+											    0                   1                   2                   3
+											    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+											   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+											   |     Type      |    Length     |     Tag       |   Salt
+											   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+											      Salt (cont)  |   String ...
+											   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+											*/
+											size_t pos;
+											int i;
+											uint8_t * secret;	/* S */
+											size_t secret_len;
+											uint8_t hash[16];	/* b(i) */
+											const uint8_t *addr[3];
+											size_t len[3];
+											
+											/* We need the request authenticator */
+											CHECK_PARAMS(st);
+
+											/* Retrieve the shared secret */
+											CHECK_FCT(rgw_clients_getkey(cli, &secret, &secret_len));
+											
+											/* Beginning of the buffer */
+											buf[0] = tuntag;
+											buf[1] = (uint8_t)(lrand48()); /* A (hi bits) */
+											buf[2] = (uint8_t)(lrand48()); /* A (low bits) */
+											
+											/* The plain text string P */
+											CHECK_PARAMS(ahdr->avp_value->os.len < 240);
+											buf[3] = ahdr->avp_value->os.len;
+											memcpy(&buf[4], ahdr->avp_value->os.data, ahdr->avp_value->os.len);
+											memset(&buf[4 + ahdr->avp_value->os.len], 0, sizeof(buf) - 4 - ahdr->avp_value->os.len);
+											
+											/* Initial b1 = MD5(S + R + A) */
+											addr[0] = secret;
+											len[0] = secret_len;
+											addr[1] = st->req_auth;
+											len[1] = 16;
+											addr[2] = &buf[1];
+											len[2] = 2;
+											md5_vector(3, addr, len, hash);
+											
+											/* Initial c(1) = p(1) xor b(1) */
+											for (i = 0; i < 16; i++) {
+												buf[i + 3] ^= hash[i];
+											}
+											pos = 16;
+											
+											/* loop */
+											while (pos < ahdr->avp_value->os.len + 1) {
+												addr[0] = secret;
+												len[0] = secret_len;
+												addr[1] = &buf[pos - 13];
+												len[1] = 16;
+												/* b(i) = MD5( S + c(i-1) */
+												md5_vector(2, addr, len, hash);
+												
+												/* c(i) = p(i) xor b(i) */
+												for (i = 0; i < 16; i++)
+													buf[pos + i + 3] ^= hash[i];
+
+												pos += 16;
+											}
+											
+											CONV2RAD_STR(RADIUS_ATTR_TUNNEL_PASSWORD, &buf[0], pos + 3, 0);
+										}
+										break;
+										
+									case DIAM_ATTR_TUNNEL_PRIVATE_GROUP_ID:
+										CONV2RAD_TUN_STR(RADIUS_ATTR_TUNNEL_PRIVATE_GROUP_ID, ahdr->avp_value->os.data, ahdr->avp_value->os.len, 1);
+										break;
+									
+									default:
+										TRACE_DEBUG(FULL, "Ignored unknown AVP inside Tunneling AVP (%d)", ahdr->avp_code);
+								}
+							} else {
+								TRACE_DEBUG(FULL, "Ignored unknown Vendor AVP inside Tunneling AVP (%d, %d)", ahdr->avp_vendor, ahdr->avp_code);
+							}
+						}
+					}
+					break;
+					
+				case DIAM_ATTR_USER_NAME:
+					CONV2RAD_STR(RADIUS_ATTR_USER_NAME, ahdr->avp_value->os.data, ahdr->avp_value->os.len, 1);
+					break;
+				
+				/* User-Password never present in answers */
+					
+		/* RFC 4072 (AVP in the order of the EAP Command AVP Table) */
+			/*
+			      o  Diameter Accounting-EAP-Auth-Method AVPs, if present, are
+				 discarded.
+			*/
+				case DIAM_ATTR_ACCOUNTING_EAP_AUTH_METHOD:
+					break;
+					
+			/*
+			      o  Diameter EAP-Master-Session-Key AVP can be translated to the
+				 vendor-specific RADIUS MS-MPPE-Recv-Key and MS-MPPE-Send-Key
+				 attributes [RFC2548].  The first up to 32 octets of the key is
+				 stored into MS-MPPE-Recv-Key, and the next up to 32 octets (if
+				 present) are stored into MS-MPPE-Send-Key.  The encryption of this
+				 attribute is described in [RFC2548].
+			*/
+				case DIAM_ATTR_EAP_MASTER_SESSION_KEY:
+					{
+						uint8_t * secret;	/* S */
+						size_t secret_len;
+						size_t recv_len, send_len;
+
+						/* We need the request authenticator */
+						CHECK_PARAMS(st);
+
+						/* Retrieve the shared secret */
+						CHECK_FCT(rgw_clients_getkey(cli, &secret, &secret_len));
+						
+						if (ahdr->avp_value->os.len != 64) {
+							TRACE_DEBUG(INFO, "Received EAP-Master-Session-Key attribute with length %zd != 64.", ahdr->avp_value->os.len)
+						}
+						
+						CHECK_PARAMS(ahdr->avp_value->os.len <= 64);
+						recv_len = ahdr->avp_value->os.len >= 32 ? 32 : ahdr->avp_value->os.len;
+						send_len = ahdr->avp_value->os.len - recv_len;
+						
+						if ( ! radius_msg_add_mppe_keys(*rad_fw, st->req_auth, secret, secret_len, 
+								ahdr->avp_value->os.data + recv_len, send_len,
+								ahdr->avp_value->os.data, recv_len) ) {
+							TRACE_DEBUG(INFO, "Error while converting EAP-Master-Session-Key to RADIUS message");
+							return ENOMEM;
+						}
+					}
+					break;
+				
+				case DIAM_ATTR_EAP_KEY_NAME:
+					CONV2RAD_STR(RADIUS_ATTR_EAP_KEY_NAME, ahdr->avp_value->os.data, ahdr->avp_value->os.len, 1);
+					break;
+				
+			/*
+			      o  Diameter EAP-Payload AVP is translated to RADIUS EAP-Message
+				 attribute(s).  If necessary, the value is split into multiple
+				 RADIUS EAP-Message attributes.
+			*/
+				case DIAM_ATTR_EAP_PAYLOAD:
+					if ( ! radius_msg_add_eap(*rad_fw, ahdr->avp_value->os.data, ahdr->avp_value->os.len) ) {
+						TRACE_DEBUG(INFO, "Error while converting EAP payload to RADIUS message");
+						return ENOMEM;
+					}
+					break;
+					
+			/*
+			      o  Diameter EAP-Reissued-Payload AVP is translated to a message that
+				 contains RADIUS EAP-Message attribute(s), and a RADIUS Error-Cause
+				 attribute [RFC3576] with value 202 (decimal), "Invalid EAP Packet
+				 (Ignored)" [RFC3579].
+			*/
+				case DIAM_ATTR_EAP_REISSUED_PAYLOAD:
+					if ( ! radius_msg_add_eap(*rad_fw, ahdr->avp_value->os.data, ahdr->avp_value->os.len) ) {
+						TRACE_DEBUG(INFO, "Error while converting EAP reissued payload to RADIUS message");
+						return ENOMEM;
+					}
+					
+					error_cause = 202; /* Invalid EAP Packet */
+					break;
+			
+				default:
+					/* Leave the AVP in the message for further treatment */
+					handled = 0;
+			}
+		} else {
+			/* Vendor-specific AVPs */
+			switch (ahdr->avp_vendor) {
+				
+				default: /* unknown vendor */
+					handled = 0;
+			}
+		}
+		
+		if (handled) {
+			CHECK_FCT( fd_msg_free( avp ) );
+		}
+	}
+	
+	CHECK_FCT( fd_msg_free( aoh ) );
+	free(st);
+	
+	if (error_cause) {
+		if ( ! radius_msg_add_attr_int32(*rad_fw, RADIUS_ATTR_ERROR_CAUSE, error_cause) ) {
+			TRACE_DEBUG(INFO, "Error while adding Error-Cause attribute in RADIUS message");
+			return ENOMEM;
+		}
+	}
+
+	if ((*rad_fw)->hdr->code == RADIUS_CODE_ACCESS_ACCEPT) {
+		/* Add the auth-application-id required for STR, or 0 if no STR is required */
+		CHECK_FCT( fd_msg_hdr( *diam_ans, &hdr ) );
+		if (sizeof(buf) < (sz = snprintf((char *)buf, sizeof(buf), CLASS_AAI_PREFIX "%u", 
+				no_str ? 0 : hdr->msg_appl))) {
+			TRACE_DEBUG(INFO, "Data truncated in Class attribute: %s", buf);
+		}
+		CONV2RAD_STR(RADIUS_ATTR_CLASS, buf, sz, 0);
+	}
+	
+	return 0;
+}
+
+/* The exported symbol */
+struct rgw_api rgwp_descriptor = {
+	.rgwp_name       = "auth",
+	.rgwp_conf_parse = auth_conf_parse,
+	.rgwp_conf_free  = auth_conf_free,
+	.rgwp_rad_req    = auth_rad_req,
+	.rgwp_diam_ans   = auth_diam_ans
+};	
diff --git a/extensions/app_radgw/rgwx_debug.c b/extensions/app_radgw/rgwx_debug.c
new file mode 100644
index 0000000..282b028
--- /dev/null
+++ b/extensions/app_radgw/rgwx_debug.c
@@ -0,0 +1,143 @@
+/*********************************************************************************************************
+* Software License Agreement (BSD License)                                                               *
+* Author: Sebastien Decugis <sdecugis@freediameter.net>							 *
+*													 *
+* Copyright (c) 2013, WIDE Project and NICT								 *
+* All rights reserved.											 *
+* 													 *
+* Redistribution and use of this software in source and binary forms, with or without modification, are  *
+* permitted provided that the following conditions are met:						 *
+* 													 *
+* * Redistributions of source code must retain the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer.										 *
+*    													 *
+* * Redistributions in binary form must reproduce the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer in the documentation and/or other						 *
+*   materials provided with the distribution.								 *
+* 													 *
+* * Neither the name of the WIDE Project or NICT nor the 						 *
+*   names of its contributors may be used to endorse or 						 *
+*   promote products derived from this software without 						 *
+*   specific prior written permission of WIDE Project and 						 *
+*   NICT.												 *
+* 													 *
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED *
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
+* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR *
+* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 	 *
+* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 	 *
+* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR *
+* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF   *
+* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.								 *
+*********************************************************************************************************/
+
+/* Debug plugin for app_radgw */
+
+#include "rgw_common.h"
+
+/* Store the configuration string in the state */
+static int debug_conf_parse ( char * conf_file, struct rgwp_config ** state )
+{
+	TRACE_ENTRY("%p %p", conf_file, state);
+	CHECK_PARAMS(state);
+	
+	*state = (void *)conf_file;
+	
+	return 0;
+}
+
+
+/* Function to display the content of a RADIUS message (more friendly way than radius_msg_dump) */
+static void debug_dump_radius(struct radius_msg *msg)
+{
+	unsigned char *auth;
+	size_t i;
+	
+	auth =  &(msg->hdr->authenticator[0]);
+	fd_log_debug(" id  : 0x%02hhx, code: %hhd (%s)", msg->hdr->identifier, msg->hdr->code, rgw_msg_code_str(msg->hdr->code));
+	fd_log_debug(" auth: %02hhx %02hhx %02hhx %02hhx  %02hhx %02hhx %02hhx %02hhx",
+			auth[0], auth[1], auth[2], auth[3], 
+			auth[4], auth[5], auth[6], auth[7]);
+	fd_log_debug("       %02hhx %02hhx %02hhx %02hhx  %02hhx %02hhx %02hhx %02hhx",
+			auth[8],  auth[9],  auth[10], auth[11], 
+			auth[12], auth[13], auth[14], auth[15]);
+	for (i = 0; i < msg->attr_used; i++) {
+		struct radius_attr_hdr *attr = (struct radius_attr_hdr *)(msg->buf + msg->attr_pos[i]);
+		fd_log_debug("  - len:%3hhu, type:0x%02hhx (%s)", attr->length, attr->type, rgw_msg_attrtype_str(attr->type));
+		/* If we need to dump the value, it's better to call directly radius_msg_dump instead... */
+	}
+}
+
+/* Function called when a new RADIUS message is being converted to Diameter */
+static int debug_rad_req( struct rgwp_config * cs, struct radius_msg * rad_req, struct radius_msg ** rad_ans, struct msg ** diam_fw, struct rgw_client * cli )
+{
+	TRACE_ENTRY("%p %p %p %p %p", cs, rad_req, rad_ans, diam_fw, cli);
+	
+	fd_log_debug("------------- RADIUS/Diameter Request Debug%s%s%s -------------", cs ? " [" : "", cs ? (char *)cs : "", cs ? "]" : "");
+	
+	if (!rad_req) {
+		fd_log_debug(" RADIUS request: NULL pointer");
+	} else {
+		fd_log_debug(" RADIUS request (%p) DUMP:", rad_req);
+		debug_dump_radius(rad_req);
+	}
+	
+	if (!rad_ans || ! *rad_ans) {
+		fd_log_debug(" RADIUS answer: NULL pointer");
+	} else {
+		fd_log_debug(" RADIUS answer (%p) DUMP:", *rad_ans);
+		debug_dump_radius(*rad_ans);
+	}
+	
+	if (!diam_fw || ! *diam_fw) {
+		fd_log_debug(" Diameter message: NULL pointer");
+	} else {
+		char * buf = NULL; size_t buflen;
+		CHECK_MALLOC( fd_msg_dump_treeview(&buf, &buflen, NULL, *diam_fw, NULL, 0, 1) );
+		fd_log_debug(" Diameter message (%p) DUMP: %s", *diam_fw, buf);
+		free(buf);
+	}
+	
+	fd_log_debug("===========  Debug%s%s%s complete =============", cs ? " [" : "", cs ? (char *)cs : "", cs ? "]" : "");
+	
+	return 0;
+}
+
+/* This one, when Diameter answer is converted to RADIUS */
+static int debug_diam_ans( struct rgwp_config * cs, struct msg ** diam_ans, struct radius_msg ** rad_fw, struct rgw_client * cli )
+{
+	TRACE_ENTRY("%p %p %p %p", cs, diam_ans, rad_fw, cli);
+
+	fd_log_debug("------------- RADIUS/Diameter Answer Debug%s%s%s -------------", cs ? " [" : "", cs ? (char *)cs : "", cs ? "]" : "");
+	
+	if (!diam_ans || ! *diam_ans) {
+		fd_log_debug(" Diameter message: NULL pointer");
+	} else {
+		char * buf = NULL; size_t buflen;
+		CHECK_MALLOC( fd_msg_dump_treeview(&buf, &buflen, NULL, *diam_ans, NULL, 0, 1) );
+		fd_log_debug(" Diameter message (%p) DUMP: %s", *diam_ans, buf);
+		free(buf);
+	}
+	
+	if (!rad_fw || ! *rad_fw) {
+		fd_log_debug(" RADIUS answer: NULL pointer");
+	} else {
+		fd_log_debug(" RADIUS answer (%p) DUMP:", *rad_fw);
+		debug_dump_radius(*rad_fw);
+	}
+	
+	fd_log_debug("===========  Debug%s%s%s complete =============", cs ? " [" : "", cs ? (char *)cs : "", cs ? "]" : "");
+	return 0;
+}
+
+
+/* The exported symbol */
+struct rgw_api rgwp_descriptor = {
+	.rgwp_name       = "debug",
+	.rgwp_conf_parse = debug_conf_parse,
+	.rgwp_conf_free  = NULL,
+	.rgwp_rad_req    = debug_rad_req,
+	.rgwp_diam_ans   = debug_diam_ans
+};	
diff --git a/extensions/app_radgw/rgwx_echodrop.c b/extensions/app_radgw/rgwx_echodrop.c
new file mode 100644
index 0000000..c8f4333
--- /dev/null
+++ b/extensions/app_radgw/rgwx_echodrop.c
@@ -0,0 +1,309 @@
+/*********************************************************************************************************
+* Software License Agreement (BSD License)                                                               *
+* Author: Sebastien Decugis <sdecugis@freediameter.net>							 *
+*													 *
+* Copyright (c) 2013, WIDE Project and NICT								 *
+* All rights reserved.											 *
+* 													 *
+* Redistribution and use of this software in source and binary forms, with or without modification, are  *
+* permitted provided that the following conditions are met:						 *
+* 													 *
+* * Redistributions of source code must retain the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer.										 *
+*    													 *
+* * Redistributions in binary form must reproduce the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer in the documentation and/or other						 *
+*   materials provided with the distribution.								 *
+* 													 *
+* * Neither the name of the WIDE Project or NICT nor the 						 *
+*   names of its contributors may be used to endorse or 						 *
+*   promote products derived from this software without 						 *
+*   specific prior written permission of WIDE Project and 						 *
+*   NICT.												 *
+* 													 *
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED *
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
+* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR *
+* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 	 *
+* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 	 *
+* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR *
+* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF   *
+* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.								 *
+*********************************************************************************************************/
+
+/* See rgwx_echodrop.h for details */
+
+#include "rgwx_echodrop.h"
+
+struct sess_state {
+	struct fd_list sentinel;
+};
+
+/* If a session is destroyed, empty the list of ed_saved_attribute */
+static void state_delete(struct sess_state * arg, os0_t sid, void * opaque) {
+	while (!FD_IS_LIST_EMPTY(&arg->sentinel)) {
+		struct ed_saved_attribute * esa = (struct ed_saved_attribute *)(arg->sentinel.next);
+		fd_list_unlink(&esa->chain);
+		free(esa);
+	}
+	free(arg);
+}
+
+static DECLARE_FD_DUMP_PROTOTYPE(ed_session_state_dump, struct sess_state * st)
+{
+	struct fd_list * li;
+	CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "[rgwx sess_state](@%p):\n", st), return NULL);	
+	for (li = st->sentinel.next; li != &st->sentinel; li = li->next) {
+		struct ed_saved_attribute * esa = (struct ed_saved_attribute *)(li);
+		CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "[rgwx sess_state {esa}] t:%2hhx l:%2hhx d:", esa->attr.type, esa->attr.length), return NULL);
+		CHECK_MALLOC_DO( fd_dump_extend_hexdump(FD_DUMP_STD_PARAMS, (&esa->attr.length) + 1, esa->attr.length - 2, 0,0), return NULL);
+		CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "\n"), return NULL);
+	}
+	return *buf;
+}
+
+/* Initialize the plugin and parse the configuration. */
+static int ed_conf_parse(char * conffile, struct rgwp_config ** state)
+{
+	struct rgwp_config * new;
+	
+	TRACE_ENTRY("%p %p", conffile, state);
+	CHECK_PARAMS( state );
+	CHECK_PARAMS_DO( conffile, { fd_log_debug("[echodrop.rgwx] The configuration file is not optional for this plugin."); return EINVAL; } );
+	
+	CHECK_MALLOC( new = malloc(sizeof(struct rgwp_config)) );
+	memset(new, 0, sizeof(struct rgwp_config));
+	
+	/* Initialize the list of attributes to handle */
+	fd_list_init(&new->attributes, NULL);
+	
+	/* Create the session handler */
+	CHECK_FCT( fd_sess_handler_create( &new->sess_hdl, state_delete, ed_session_state_dump, NULL ) );
+	
+	/* Parse the configuration file */
+	CHECK_FCT( ed_conffile_parse(conffile, new) );
+	
+	if (TRACE_BOOL(FULL)) {
+		TRACE_DEBUG(INFO, "Echo/Drop plugin configuration ('%s'):", conffile);
+		struct fd_list * li;
+		
+		for (li = new->attributes.next; li != &new->attributes; li = li->next) {
+			struct ed_conf_attribute * eca = (struct ed_conf_attribute *)li;
+			char * act = (eca->action == ACT_ECHO) ? "ECHO" : "DROP";
+			if (eca->ext) {
+				fd_log_debug("  %s Code: %hhu, Vendor: %u, Ext-Type: %hu", act, eca->code, eca->vendor_id, eca->extype);
+				continue;
+			}
+			if (eca->tlv) {
+				fd_log_debug("  %s Code: %hhu, Vendor: %u, Type: %hhu", act, eca->code, eca->vendor_id, eca->type);
+				continue;
+			}
+			if (eca->vsa) {
+				fd_log_debug("  %s Code: %hhu, Vendor: %u", act, eca->code, eca->vendor_id);
+				continue;
+			}
+			fd_log_debug("  %s Code: %hhu", act, eca->code);
+		}
+	}
+	
+	/* OK, we are done */
+	*state = new;
+	return 0;
+}
+
+/* Destroy the state */
+static void ed_conf_free(struct rgwp_config * state)
+{
+	TRACE_ENTRY("%p", state);
+	CHECK_PARAMS_DO( state, return );
+	CHECK_FCT_DO( fd_sess_handler_destroy( &state->sess_hdl, NULL ),  );
+	while (! FD_IS_LIST_EMPTY(&state->attributes) ) {
+		struct fd_list * li = state->attributes.next;
+		fd_list_unlink(li);
+		free(li);
+	}
+	free(state);
+	return;
+}
+
+
+/* Handle attributes from a RADIUS request as specified in the configuration */
+static int ed_rad_req( struct rgwp_config * cs, struct radius_msg * rad_req, struct radius_msg ** rad_ans, struct msg ** diam_fw, struct rgw_client * cli )
+{
+	size_t nattr_used = 0;
+	int idx;
+	struct fd_list echo_list = FD_LIST_INITIALIZER(echo_list);
+	struct fd_list *li;
+	
+	TRACE_ENTRY("%p %p %p %p %p", cs, rad_req, rad_ans, diam_fw, cli);
+	CHECK_PARAMS(cs && rad_req);
+	
+	/* For each attribute in the original message */
+	for (idx = 0; idx < rad_req->attr_used; idx++) {
+		int action = 0;
+		struct radius_attr_hdr * attr = (struct radius_attr_hdr *)(rad_req->buf + rad_req->attr_pos[idx]);
+		
+		/* Look if we have a matching attribute in our configuration */
+		for (li = cs->attributes.next; li != &cs->attributes; li = li->next) {
+			struct ed_conf_attribute * eca = (struct ed_conf_attribute *)li;
+			uint32_t vid;
+			unsigned char * ptr;
+			
+			if (eca->code < attr->type)
+				continue;
+			if (eca->code > attr->type)
+				break;
+			
+			/* the code matches one in our configuration, check additional data if needed */
+			
+			if (! eca->vsa) {
+				action = eca->action;
+				break;
+			}
+			
+			if (attr->length < 8)
+				continue;
+			
+			ptr = (unsigned char *)(attr + 1);
+			/* since attr is not aligned, we may not access *(attr+1) directly */
+			memcpy(&vid, ptr, sizeof(uint32_t));
+			
+			if (eca->vendor_id < ntohl(vid))
+				continue;
+			if (eca->vendor_id > ntohl(vid))
+				break;
+			
+			/* The vendor matches our configured line... */
+			
+			if ( ! eca->tlv && ! eca->ext ) {
+				action = eca->action;
+				break;
+			}
+			
+			if (attr->length < 10)
+				continue;
+			
+			if (eca->tlv) {
+				struct radius_attr_vendor * tl = (struct radius_attr_vendor *)(ptr + sizeof(uint32_t));
+				if (tl->vendor_type == eca->type) {
+					action = eca->action;
+					break;
+				}
+				continue;
+			}
+			
+			if (eca->ext) {
+				/* To be done */
+				fd_log_debug("Extended attributes are not implemented yet!");
+				ASSERT(0);
+				continue;
+			}
+		}
+		
+		switch (action) {
+			case ACT_DROP:
+				TRACE_DEBUG(FULL, "Dropping attribute with code %hhd", attr->type);
+				break;
+				
+			case ACT_ECHO:
+				{
+					struct ed_saved_attribute * esa = NULL;
+					TRACE_DEBUG(FULL, "Saving attribute with code %hhd", attr->type);
+					CHECK_MALLOC( esa = malloc(sizeof(struct ed_saved_attribute) + attr->length - sizeof(struct radius_attr_hdr)) );
+					fd_list_init(&esa->chain, NULL);
+					memcpy(&esa->attr, attr, attr->length);
+					fd_list_insert_before(&echo_list, &esa->chain);
+				}
+				break;
+			
+			default: /* Attribute was not specified in the configuration */
+				/* We just keep the attribute in the RADIUS message */
+				rad_req->attr_pos[nattr_used++] = rad_req->attr_pos[idx];
+		}
+	}
+	rad_req->attr_used = nattr_used;
+	
+	/* Save the echoed values in the session, if any */
+	if (!FD_IS_LIST_EMPTY(&echo_list)) {
+		struct session * sess;
+		struct sess_state * st;
+		
+		CHECK_FCT( fd_msg_sess_get(fd_g_config->cnf_dict, *diam_fw, &sess, NULL) );
+
+		CHECK_PARAMS_DO(sess,
+			{
+				fd_log_debug(	"[echodrop.rgwx] The extension is configured to echo some attributes from this message, but no session object has been created for it (yet)."
+						" Please check your configuration file and include a session-generating extension BEFORE calling echodrop.rgwx to echo attributes."
+						" Please use debug.rgwx to retrieve more information." );
+				return EINVAL;
+			} );
+		
+		/* Move the values in a dynamically allocated list */
+		CHECK_MALLOC( st = malloc(sizeof(struct sess_state)) );
+		fd_list_init(&st->sentinel, NULL);
+		fd_list_move_end(&st->sentinel, &echo_list);
+		
+		/* Save the list in the session */
+		CHECK_FCT( fd_sess_state_store( cs->sess_hdl, sess, &st ) );
+	}
+	
+	return 0;
+}
+
+/* Process an answer: add the ECHO attributes back, if any */
+static int ed_diam_ans( struct rgwp_config * cs, struct msg ** diam_ans, struct radius_msg ** rad_fw, struct rgw_client * cli )
+{
+	struct session * sess;
+	struct sess_state * st;
+	
+	TRACE_ENTRY("%p %p %p %p", cs, diam_ans, rad_fw, cli);
+	CHECK_PARAMS(cs);
+	
+	CHECK_FCT( fd_msg_sess_get(fd_g_config->cnf_dict, *diam_ans, &sess, NULL) );
+	
+	/* If there is no session associated, just give up */
+	if (! sess ) {
+		TRACE_DEBUG(FULL, "No session associated with the message, nothing to do here...");
+		return 0;
+	}
+	
+	/* Now try and retrieve any data from the session */
+	CHECK_FCT( fd_sess_state_retrieve( cs->sess_hdl, sess, &st ) );
+	if (st == NULL) {
+		/* No attribute saved in the session, just return */
+		return 0;
+	}
+	
+	/* From this point on, we have a list of attributes to add to the radius message */
+	
+	CHECK_PARAMS( rad_fw && *rad_fw);
+	
+	while (! FD_IS_LIST_EMPTY(&st->sentinel) ) {
+		struct ed_saved_attribute * esa = (struct ed_saved_attribute *)(st->sentinel.next);
+		
+		fd_list_unlink(&esa->chain);
+		
+		TRACE_DEBUG(FULL, "Echo attribute in the RADIUS answer: type %hhu, len: %hhu", esa->attr.type, esa->attr.length);
+		
+		/* Add this attribute in the RADIUS message */
+		CHECK_MALLOC( radius_msg_add_attr(*rad_fw, esa->attr.type, (unsigned char *)(esa + 1), esa->attr.length - sizeof(struct radius_attr_hdr)) );
+		
+		free(esa);
+	}
+	free(st);
+
+	return 0;
+}
+
+
+
+/* The exported symbol */
+struct rgw_api rgwp_descriptor = {
+	.rgwp_name       = "echo/drop",
+	.rgwp_conf_parse = ed_conf_parse,
+	.rgwp_conf_free  = ed_conf_free,
+	.rgwp_rad_req    = ed_rad_req,
+	.rgwp_diam_ans   = ed_diam_ans
+};	
diff --git a/extensions/app_radgw/rgwx_echodrop.h b/extensions/app_radgw/rgwx_echodrop.h
new file mode 100644
index 0000000..db84fbd
--- /dev/null
+++ b/extensions/app_radgw/rgwx_echodrop.h
@@ -0,0 +1,84 @@
+/*********************************************************************************************************
+* Software License Agreement (BSD License)                                                               *
+* Author: Sebastien Decugis <sdecugis@freediameter.net>							 *
+*													 *
+* Copyright (c) 2011, WIDE Project and NICT								 *
+* All rights reserved.											 *
+* 													 *
+* Redistribution and use of this software in source and binary forms, with or without modification, are  *
+* permitted provided that the following conditions are met:						 *
+* 													 *
+* * Redistributions of source code must retain the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer.										 *
+*    													 *
+* * Redistributions in binary form must reproduce the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer in the documentation and/or other						 *
+*   materials provided with the distribution.								 *
+* 													 *
+* * Neither the name of the WIDE Project or NICT nor the 						 *
+*   names of its contributors may be used to endorse or 						 *
+*   promote products derived from this software without 						 *
+*   specific prior written permission of WIDE Project and 						 *
+*   NICT.												 *
+* 													 *
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED *
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
+* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR *
+* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 	 *
+* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 	 *
+* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR *
+* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF   *
+* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.								 *
+*********************************************************************************************************/
+
+/*  RADIUS translation plugin, to handle specific RADIUS attributes by either caching them and 
+adding them to a corresponding RADIUS reply, or just dropping the attributes (no conversion to Diameter) */
+/* This extension is a kind of swiss army-knife for interoperability, must be used with care. 
+  All attribute behaviors are specified through the configuration file of the extension
+ */
+
+#include "rgw_common.h"
+
+/* Action associated with an attribute */
+#define ACT_ECHO 1
+#define ACT_DROP 2
+
+/* Result of configuration parsing */
+struct rgwp_config {
+	/* list of attributes and associated actions */
+	struct fd_list attributes;
+	
+	/* Handler to store the echo'ed attributes values */
+	struct session_handler * sess_hdl;
+};
+
+/* An item of the attribute list */
+struct ed_conf_attribute {
+	struct fd_list 	chain;	/* link in the list */
+	
+	struct {
+		unsigned	action 	:2;	/* ACT_ECHO or ACT_DROP */
+		unsigned	vsa	:1;	/* Interpret as Vendor-Specific, and match the vendor id in addition to the code */
+		unsigned	tlv	:1;	/* Interpret as Vendor-Specific with TLV format, and match the type also */
+		unsigned	ext	:1;	/* Interpret as radius extended attribute, and match the ext-type also */
+	};
+	
+	uint32_t	vendor_id; /* vendor id to match when vsa = 1 */
+	uint16_t	extype; /* Ext-Type value to match if ext = 1 */
+	uint8_t		type; /* Type value to match if tlv = 1; */
+	
+	uint8_t		code; /* The attribute code, the list is ordered by this value */
+};
+
+/* For ECHO items, we save a list of these in the session */
+struct ed_saved_attribute {
+	struct fd_list		chain;
+	struct radius_attr_hdr  attr; /* copy of the attribute */
+	/* The data of the attribute follows ... */
+};
+
+
+/* The yacc parser */
+int ed_conffile_parse(char * conffile, struct rgwp_config *cs);
diff --git a/extensions/app_radgw/rgwx_echodrop.l b/extensions/app_radgw/rgwx_echodrop.l
new file mode 100644
index 0000000..aab2841
--- /dev/null
+++ b/extensions/app_radgw/rgwx_echodrop.l
@@ -0,0 +1,99 @@
+/*********************************************************************************************************
+* Software License Agreement (BSD License)                                                               *
+* Author: Sebastien Decugis <sdecugis@freediameter.net>							 *
+*													 *
+* Copyright (c) 2013, WIDE Project and NICT								 *
+* All rights reserved.											 *
+* 													 *
+* Redistribution and use of this software in source and binary forms, with or without modification, are  *
+* permitted provided that the following conditions are met:						 *
+* 													 *
+* * Redistributions of source code must retain the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer.										 *
+*    													 *
+* * Redistributions in binary form must reproduce the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer in the documentation and/or other						 *
+*   materials provided with the distribution.								 *
+* 													 *
+* * Neither the name of the WIDE Project or NICT nor the 						 *
+*   names of its contributors may be used to endorse or 						 *
+*   promote products derived from this software without 						 *
+*   specific prior written permission of WIDE Project and 						 *
+*   NICT.												 *
+* 													 *
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED *
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
+* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR *
+* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 	 *
+* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 	 *
+* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR *
+* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF   *
+* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.								 *
+*********************************************************************************************************/
+
+/* Tokenizer for echo/drop plugin */
+
+%{
+#include "rgwx_echodrop.h"
+#include "rgwx_echodrop.tab.h"
+
+/* Update the column information */
+#define YY_USER_ACTION { 						\
+	yylloc->first_column = yylloc->last_column + 1; 		\
+	yylloc->last_column = yylloc->first_column + yyleng - 1;	\
+}
+
+/* %option noinput ? */
+#define YY_NO_INPUT
+%}
+
+%option bison-bridge bison-locations
+%option noyywrap
+%option nounput
+
+%%
+
+<*>\n			{ 
+				/* Update the line count */
+				yylloc->first_line++; 
+				yylloc->last_line++; 
+				yylloc->last_column=0; 
+			} 
+
+<*>([[:space:]]{-}[\n])+	; /* Eat all spaces, not new lines */
+<*>#.*$			; /* Eat all comments */
+
+[[:digit:]]+		{
+				/* Match an integer (not hexa) */
+				int ret = sscanf(yytext, "%d", &yylval->integer);
+				if (ret != 1) {
+					/* No matching: an error occurred */
+					fd_log_debug("[echodrop.rgwx] Unable to convert the value '%s' to a valid number: %s", yytext, strerror(errno));
+					return LEX_ERROR; /* trig an error in yacc parser */
+					/* Maybe we could REJECT instead of failing here? */
+				}
+				return INTEGER;
+			}
+				
+(?i:"echo")		{ return TOK_ECHO; 		}
+(?i:"drop")		{ return TOK_DROP; 		}
+(?i:"code")		{ return TOK_CODE; 		}
+(?i:"vendor")		{ return TOK_VENDOR; 		}
+(?i:"tlv")		{ return TOK_TLV; 		}
+(?i:"ext")		{ return TOK_EXT; 		}
+
+	/* Valid single characters for yyparse */
+<*>[;]			{ return yytext[0]; }
+
+
+	/* Unrecognized token */
+<*>[[:alnum:]]+		|	/* This rule is only useful to print a complete token in error messages */
+	/* Unrecognized character */
+<*>.			{ 
+				fd_log_debug("[echodrop.rgwx] Unrecognized text on line %d col %d: '%s'.", yylloc->first_line, yylloc->first_column, yytext);
+			 	return LEX_ERROR; 
+			}
+
+%%
diff --git a/extensions/app_radgw/rgwx_echodrop.y b/extensions/app_radgw/rgwx_echodrop.y
new file mode 100644
index 0000000..fccaf06
--- /dev/null
+++ b/extensions/app_radgw/rgwx_echodrop.y
@@ -0,0 +1,255 @@
+/*********************************************************************************************************
+* Software License Agreement (BSD License)                                                               *
+* Author: Sebastien Decugis <sdecugis@freediameter.net>							 *
+*													 *
+* Copyright (c) 2013, WIDE Project and NICT								 *
+* All rights reserved.											 *
+* 													 *
+* Redistribution and use of this software in source and binary forms, with or without modification, are  *
+* permitted provided that the following conditions are met:						 *
+* 													 *
+* * Redistributions of source code must retain the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer.										 *
+*    													 *
+* * Redistributions in binary form must reproduce the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer in the documentation and/or other						 *
+*   materials provided with the distribution.								 *
+* 													 *
+* * Neither the name of the WIDE Project or NICT nor the 						 *
+*   names of its contributors may be used to endorse or 						 *
+*   promote products derived from this software without 						 *
+*   specific prior written permission of WIDE Project and 						 *
+*   NICT.												 *
+* 													 *
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED *
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
+* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR *
+* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 	 *
+* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 	 *
+* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR *
+* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF   *
+* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.								 *
+*********************************************************************************************************/
+
+/* Yacc parser for echo/drop plugin. 
+See doc/echodrop.rgwx.conf.sample for description of the parsed format. */
+
+
+/* For development only : */
+%debug 
+%error-verbose
+
+/* The parser receives the configuration file filename and the conf structure as parameter */
+%parse-param {char * conffile}
+%parse-param {struct rgwp_config *cs}
+
+/* Keep track of location */
+%locations 
+%pure-parser
+
+%{
+#include "rgwx_echodrop.h"
+#include "rgwx_echodrop.tab.h"	/* bison is not smart enough to define the YYLTYPE before including this code, so... */
+
+
+/* Forward declaration */
+int yyparse(char * conffile, struct rgwp_config *cs);
+
+/* The Lex parser prototype */
+int rgwx_echodroplex(YYSTYPE *lvalp, YYLTYPE *llocp);
+
+
+/* Parse the configuration file */
+int ed_conffile_parse(char * conffile, struct rgwp_config *cs)
+{
+	extern FILE * rgwx_echodropin;
+	int ret;
+	
+	rgwx_echodropin = fopen(conffile, "r");
+	if ((rgwx_echodropin == NULL) && (*conffile != '/')) { /* We received a relative path, try adding DEFAULT_CONF_PATH prefix */
+		char * fullpath;
+		CHECK_MALLOC( fullpath = malloc( strlen(conffile) + strlen(DEFAULT_CONF_PATH) + 2 ) );
+		sprintf( fullpath, DEFAULT_CONF_PATH "/%s", conffile );
+		rgwx_echodropin = fopen(fullpath, "r");
+		free(fullpath);
+	}
+	if (rgwx_echodropin == NULL) {
+		ret = errno;
+		fd_log_debug("[echodrop.rgwx] Unable to open plugin configuration file %s for reading: %s", conffile, strerror(ret));
+		return ret;
+	}
+
+	ret = rgwx_echodropparse(conffile, cs);
+
+	fclose(rgwx_echodropin);
+
+	if (ret != 0) {
+		return EINVAL;
+	}
+	
+	return 0;
+}
+
+/* Function to report the errors */
+void yyerror (YYLTYPE *ploc, char * conffile, struct rgwp_config *cs, char const *s)
+{
+	if (ploc->first_line != ploc->last_line)
+		fd_log_debug("%s:%d.%d-%d.%d : %s", conffile, ploc->first_line, ploc->first_column, ploc->last_line, ploc->last_column, s);
+	else if (ploc->first_column != ploc->last_column)
+		fd_log_debug("%s:%d.%d-%d : %s", conffile, ploc->first_line, ploc->first_column, ploc->last_column, s);
+	else
+		fd_log_debug("%s:%d.%d : %s", conffile, ploc->first_line, ploc->first_column, s);
+}
+
+static struct {
+	struct {
+		unsigned vendor :1;
+		unsigned tlv :1;
+		unsigned ext :1;
+	};
+	uint8_t		type;
+	uint16_t	extype;
+	uint32_t	vendor_id;
+} attrinfo;
+
+
+%}
+
+/* Values returned by lex for tokens */
+%union {
+	unsigned	integer;	/* Value  */
+}
+
+/* typed data */
+%token <integer> INTEGER
+%type  <integer> action
+
+/* simple tokens */
+%token		TOK_ECHO
+%token		TOK_DROP
+%token		TOK_CODE
+%token		TOK_VENDOR
+%token		TOK_TLV
+%token		TOK_EXT
+
+/* In case of error in the lexical analysis */
+%token 		LEX_ERROR
+
+
+/* -------------------------------------- */
+%%
+
+	/* The grammar definition */
+conffile:		/* empty grammar is OK */
+			| conffile attrdef
+			;
+
+	/* An attribute line */				
+attrdef:		{
+				memset(&attrinfo, 0, sizeof(attrinfo));
+			}
+			action TOK_CODE INTEGER vendordef ';'
+			{
+				struct ed_conf_attribute * new;
+				struct fd_list * li;
+
+				if ($4 >= 256) {
+					yyerror (&yylloc, conffile, cs, "Too big value for attribute CODE");
+					YYERROR;
+				}
+				
+				/* Create a new list item */
+				CHECK_MALLOC_DO( new = malloc(sizeof(struct ed_conf_attribute)), 
+					{
+						yyerror (&yylloc, conffile, cs, "Memory allocation error");
+						YYERROR;
+					} );
+				memset(new, 0, sizeof(struct ed_conf_attribute));
+				
+				fd_list_init(&new->chain, NULL);
+				
+				new->action = $2;
+				new->vsa = attrinfo.vendor;
+				new->tlv = attrinfo.tlv;
+				new->ext = attrinfo.ext;
+				
+				if (new->vsa)
+					new->vendor_id = attrinfo.vendor_id;
+				if (new->tlv)
+					new->type = attrinfo.type;
+				if (new->ext)
+					new->extype = attrinfo.extype;
+				
+				new->code = $4;
+				
+				/* Now place this attribute in the list */
+				for (li = cs->attributes.next; li != &cs->attributes; li = li->next) {
+					struct ed_conf_attribute *eca = (struct ed_conf_attribute *)li;
+					/* Order first by attribute code */
+					if (eca->code > new->code)
+						break;
+					if (eca->code < new->code)
+						continue;
+					
+					/* Then by VSA flag */
+					if (! new->vsa)
+						break;
+					if (! eca->vsa)
+						continue;
+					
+					/* Then by vendor value */
+					if (eca->vendor_id >= new->vendor_id)
+						break;
+				}
+				
+				fd_list_insert_before(li, &new->chain);
+			}
+			;
+	
+	/* What to do with the specified attribute */
+action:			TOK_ECHO
+			{
+				$$ = ACT_ECHO;
+			}
+			|
+			TOK_DROP
+			{
+				$$ = ACT_DROP;
+			}
+			;
+
+	/* Vendor specifics, if any */
+vendordef:		/* empty OK */
+			| TOK_VENDOR INTEGER specif
+			{
+				attrinfo.vendor_id = $2;
+				attrinfo.vendor = 1;
+			}
+			;
+			
+	/* Any additional specification ? */
+specif:			/* empty OK */
+			| TOK_TLV INTEGER
+			{
+				if ($2 >= (1 << 8)) {
+					yyerror (&yylloc, conffile, cs, "Too big value for TLV type");
+					YYERROR;
+				}
+				attrinfo.type = $2;
+				attrinfo.tlv = 1;
+			}
+			| TOK_EXT INTEGER
+			{
+				if ($2 >= (1 << 16)) {
+					yyerror (&yylloc, conffile, cs, "Too big value for Ext-Type");
+					YYERROR;
+				}
+				attrinfo.extype = $2;
+				attrinfo.ext = 1;
+				yyerror (&yylloc, conffile, cs, "The EXT option is not supported in this version.");
+				YYERROR;
+			}
+			;	
+
diff --git a/extensions/app_radgw/rgwx_sample.c b/extensions/app_radgw/rgwx_sample.c
new file mode 100644
index 0000000..4e2cd03
--- /dev/null
+++ b/extensions/app_radgw/rgwx_sample.c
@@ -0,0 +1,97 @@
+/*********************************************************************************************************
+* Software License Agreement (BSD License)                                                               *
+* Author: Sebastien Decugis <sdecugis@freediameter.net>							 *
+*													 *
+* Copyright (c) 2013, WIDE Project and NICT								 *
+* All rights reserved.											 *
+* 													 *
+* Redistribution and use of this software in source and binary forms, with or without modification, are  *
+* permitted provided that the following conditions are met:						 *
+* 													 *
+* * Redistributions of source code must retain the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer.										 *
+*    													 *
+* * Redistributions in binary form must reproduce the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer in the documentation and/or other						 *
+*   materials provided with the distribution.								 *
+* 													 *
+* * Neither the name of the WIDE Project or NICT nor the 						 *
+*   names of its contributors may be used to endorse or 						 *
+*   promote products derived from this software without 						 *
+*   specific prior written permission of WIDE Project and 						 *
+*   NICT.												 *
+* 													 *
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED *
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
+* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR *
+* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 	 *
+* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 	 *
+* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR *
+* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF   *
+* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.								 *
+*********************************************************************************************************/
+
+/* Sample radius/diameter gateway plugin, for developers to see the structure of a plugin. */
+
+#include "rgw_common.h"
+
+/* The state of this extension */
+struct rgwp_config {
+	/* In a real extension, we would store the parsed configuration file, and the states of the extension */
+	int init;
+	
+	/* If needed to store information between sent Diameter request and received answer, the session is probably the best place.
+	  See rgwx_echodrop for an example. */
+};
+
+/* The function called at plugin initialization */
+static int sample_conf_parse ( char * conf_file, struct rgwp_config ** state )
+{
+	TRACE_ENTRY("%p %p", conf_file, state);
+	CHECK_PARAMS(state);
+	
+	CHECK_MALLOC( *state = malloc(sizeof(struct rgwp_config)) );
+	
+	(*state)->init = 1;
+	
+	return 0;
+}
+
+/* This function is called when the plugin is unloaded, to cleanup all the states */
+static void sample_conf_free(struct rgwp_config * state)
+{
+	TRACE_ENTRY("%p", state);
+	CHECK_PARAMS_DO( state, );
+	free(state);
+	return;
+}
+
+/* This function is called on incoming RADIUS messages. It should handle (some) RADIUS data and store into the Diameter message. */
+static int sample_rad_req( struct rgwp_config * cs, struct radius_msg * rad_req, struct radius_msg ** rad_ans, struct msg ** diam_fw, struct rgw_client * cli )
+{
+	TRACE_ENTRY("%p %p %p %p %p", cs, rad_req, rad_ans, diam_fw, cli);
+	CHECK_PARAMS(cs);
+	TRACE_DEBUG(INFO, "RADIUS/Diameter Sample plugin received a new RADIUS message.");
+	return 0;
+}
+
+/* This function is called when a Diameter answer is coming back. It should remove the AVPs and add the attributes in the RADIUS message. */
+static int sample_diam_ans( struct rgwp_config * cs, struct msg ** diam_ans, struct radius_msg ** rad_fw, struct rgw_client * cli )
+{
+	TRACE_ENTRY("%p %p %p %p", cs, diam_ans, rad_fw, cli);
+	CHECK_PARAMS(cs);
+	TRACE_DEBUG(INFO, "RADIUS/Diameter Sample plugin received a new Diameter answer.");
+	return 0;
+}
+
+
+/* Finally, we declare the structure that will be loaded by main RADIUS/Diameter gateway extension */
+struct rgw_api rgwp_descriptor = {
+	.rgwp_name       = "sample",
+	.rgwp_conf_parse = sample_conf_parse,
+	.rgwp_conf_free  = sample_conf_free,
+	.rgwp_rad_req    = sample_rad_req,
+	.rgwp_diam_ans   = sample_diam_ans
+};	
diff --git a/extensions/app_radgw/rgwx_sip.c b/extensions/app_radgw/rgwx_sip.c
new file mode 100644
index 0000000..b4fd91e
--- /dev/null
+++ b/extensions/app_radgw/rgwx_sip.c
@@ -0,0 +1,855 @@
+/*********************************************************************************************************
+* Software License Agreement (BSD License)                                                               *
+* Author: Alexandre Westfahl <awestfahl@freediameter.net>						 *
+*													 *												 *
+* Copyright (c) 2013, WIDE Project and NICT								 *
+* Copyright (c) 2010, Alexandre Westfahl, Teraoka Laboratory (Keio University), and the WIDE Project. 	 *		
+*													 *
+* All rights reserved.											 *
+* Based on rgwx_auth plugin (Sebastien Decugis <sdecugis@freediameter.net>)					 *
+* 													 *
+* Redistribution and use of this software in source and binary forms, with or without modification, are  *
+* permitted provided that the following conditions are met:						 *
+* 													 *
+* * Redistributions of source code must retain the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer.										 *
+*    													 *
+* * Redistributions in binary form must reproduce the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer in the documentation and/or other						 *
+*   materials provided with the distribution.								 *
+* 													 *
+* * Neither the name of the Teraoka Laboratory nor the 							 *
+*   names of its contributors may be used to endorse or 						 *
+*   promote products derived from this software without 						 *
+*   specific prior written permission of Teraoka Laboratory 						 *
+*   													 *
+* 													 *
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED *
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
+* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR *
+* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 	 *
+* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 	 *
+* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR *
+* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF   *
+* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.								 *
+*********************************************************************************************************/
+
+
+/* RADIUS Access-Request messages translation plugin */
+
+#include "rgw_common.h"
+#include <string.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h> 
+
+/* Other constants we use */
+#define AI_SIP				6	/* Diameter SIP application */
+#define CC_MULTIMEDIA_AUTH_REQUEST	286	/* MAR */
+#define CC_MULTIMEDIA_AUTH_ANSWER	286	/* MAA */
+#define ACV_ASS_STATE_MAINTAINED	0	/* STATE_MAINTAINED */
+#define ACV_ASS_NO_STATE_MAINTAINED	1	/* NO_STATE_MAINTAINED */
+#define ER_DIAMETER_SUCCESS_AUTH_SENT_SERVER_NOT_STORED	2008
+#define ER_DIAMETER_SUCCESS_SERVER_NAME_NOT_STORED	2006
+
+
+
+/* This macro converts a RADIUS attribute to a Diameter AVP of type OctetString */
+#define CONV2DIAM_STR( _dictobj_ )	\
+	CHECK_PARAMS( attr->length >= sizeof(struct radius_attr_hdr) );			\
+	/* Create the AVP with the specified dictionary model */			\
+	CHECK_FCT( fd_msg_avp_new ( cs->dict._dictobj_, 0, &avp ) );			\
+	value.os.len = attr->length - sizeof(struct radius_attr_hdr);			\
+	value.os.data = (os0_t)(attr + 1);						\
+	CHECK_FCT( fd_msg_avp_setvalue ( avp, &value ) );				\
+	/* Add the AVP in the Diameter message. */					\
+	CHECK_FCT( fd_msg_avp_add ( *diam_fw, MSG_BRW_LAST_CHILD, avp) );		\
+
+#define CONV2DIAM_STR_AUTH( _dictobj_ )	\
+	CHECK_PARAMS( attr->length >= sizeof(struct radius_attr_hdr) );			\
+	/* Create the AVP with the specified dictionary model */			\
+	CHECK_FCT( fd_msg_avp_new ( cs->dict._dictobj_, 0, &avp ) );			\
+	value.os.len = attr->length - sizeof(struct radius_attr_hdr);			\
+	value.os.data = (os0_t)(attr + 1);						\
+	CHECK_FCT( fd_msg_avp_setvalue ( avp, &value ) );				\
+	/* Add the AVP in the Diameter message. */					\
+	CHECK_FCT( fd_msg_avp_add ( auth, MSG_BRW_LAST_CHILD, avp) );			\
+		
+/* Same thing, for scalar AVPs of 32 bits */
+#define CONV2DIAM_32B( _dictobj_ )	\
+	CHECK_PARAMS( attr->length == sizeof(struct radius_attr_hdr)+sizeof(uint32_t) );\
+	CHECK_FCT( fd_msg_avp_new ( cs->dict._dictobj_, 0, &avp ) );			\
+	{										\
+		uint8_t * v = (uint8_t *)(attr + 1);					\
+		value.u32  = (v[0] << 24)						\
+			   | (v[1] << 16)						\
+			   | (v[2] <<  8)						\
+			   |  v[3] ;							\
+	}										\
+	CHECK_FCT( fd_msg_avp_setvalue ( avp, &value ) );				\
+	CHECK_FCT( fd_msg_avp_add ( *diam_fw, MSG_BRW_LAST_CHILD, avp) );		\
+				
+				
+				
+				
+				
+/* The state we keep for this plugin */
+struct rgwp_config {
+	struct {
+		struct dict_object * Session_Id;		
+		struct dict_object * Auth_Application_Id;	
+		struct dict_object * Auth_Session_State;	
+		struct dict_object * Origin_Host;		
+		struct dict_object * Origin_Realm;		
+		struct dict_object * Destination_Realm;		
+		struct dict_object * SIP_AOR;			
+		struct dict_object * SIP_Method;			
+		struct dict_object * Destination_Host;		
+		struct dict_object * User_Name;			
+		struct dict_object * SIP_Server_URI;		
+		struct dict_object * SIP_Number_Auth_Items;	
+		struct dict_object * SIP_Authorization;	
+		struct dict_object * SIP_Authentication_Scheme;	
+		struct dict_object * SIP_Authentication_Info;	
+		struct dict_object * SIP_Auth_Data_Item;	
+		struct dict_object * Proxy_Info;		
+		struct dict_object * Route_Record;		
+		struct dict_object * Service_Type;		
+		struct dict_object * Result_Code;		
+		struct dict_object * Digest_URI;		
+		struct dict_object * Digest_Nonce;
+		struct dict_object * Digest_CNonce;
+		struct dict_object * Digest_Nonce_Count;				
+		struct dict_object * Digest_Realm;		
+		struct dict_object * Digest_Response;
+		struct dict_object * Digest_Method;
+		struct dict_object * Digest_Response_Auth;		
+		struct dict_object * Digest_Username;
+		struct dict_object * Digest_Algorithm;	
+		struct dict_object * Digest_QOP;
+
+		
+		
+	} dict; /* cache of the dictionary objects we use */
+	char * confstr;
+	//Chained list of nonce
+	struct fd_list listnonce;
+	//This will be used to lock access to chained list
+	pthread_mutex_t nonce_mutex; 
+};
+
+typedef struct noncechain noncechain;
+struct noncechain
+{
+	struct fd_list chain;
+    os0_t sid;
+    size_t sidlen;
+    os0_t nonce;
+    size_t noncelen;
+    
+};
+
+static int nonce_add_element(os0_t nonce, size_t noncelen, os0_t sid, size_t sidlen, struct rgwp_config * state)
+{
+	CHECK_PARAMS(nonce && state && sid && sidlen && noncelen);
+	
+	noncechain *newelt;
+	CHECK_MALLOC(newelt=malloc(sizeof(noncechain)));
+	
+	CHECK_MALLOC(newelt->nonce= os0dup(nonce, noncelen));
+	newelt->noncelen=noncelen;
+	
+	CHECK_MALLOC(newelt->sid=os0dup(sid, sidlen));
+	newelt->sidlen=sidlen;
+	
+	fd_list_init(&newelt->chain,NULL);
+	
+	CHECK_POSIX(pthread_mutex_lock(&state->nonce_mutex));
+	fd_list_insert_before(&state->listnonce,&newelt->chain);
+	CHECK_POSIX(pthread_mutex_unlock(&state->nonce_mutex));
+	
+	return 0;
+}
+/*
+static void nonce_del_element(char * nonce, struct rgwp_config *state)
+{
+	struct fd_list * li;
+	
+	CHECK_PARAMS_DO(nonce && state, return);
+	
+	for(li=state->listnonce.next;li!=&state->listnonce;li=li->next)
+	{
+		noncechain *temp=(noncechain *)li;
+		
+		if(strcmp(temp->nonce,nonce)==0)
+		{
+			fd_list_unlink (li);
+			free(temp->sid);
+			free(temp->nonce);
+			free(temp);
+			break;
+		}
+	}
+}
+*/
+//Retrieve sid from nonce
+static os0_t nonce_get_sid(os0_t nonce, size_t noncelen, size_t * sidlen, struct rgwp_config *state)
+{
+	struct fd_list * li;
+	os0_t sid=NULL;
+	
+	CHECK_PARAMS_DO(nonce && state && noncelen && sidlen, return NULL);
+	*sidlen=0;
+	
+	// **Start mutex
+	CHECK_POSIX_DO(pthread_mutex_lock(&state->nonce_mutex),); 
+	for(li=state->listnonce.next;li!=&state->listnonce;li=li->next)
+	{
+		noncechain *temp=(noncechain *)li;
+		
+		if (!fd_os_cmp(temp->nonce, temp->noncelen, nonce, noncelen))
+		{
+			fd_list_unlink (li);
+			sid=temp->sid;
+			*sidlen=temp->sidlen;
+			free(temp->nonce);
+			free(temp);
+			break;
+		}
+		
+	}
+	CHECK_POSIX_DO(pthread_mutex_unlock(&state->nonce_mutex),); 
+	// ***Stop mutex
+	return sid;
+}
+
+static void nonce_deletelistnonce(struct rgwp_config *state)
+{
+	// **Start mutex
+	CHECK_POSIX_DO(pthread_mutex_lock(&state->nonce_mutex),); 
+	while(!(FD_IS_LIST_EMPTY(&state->listnonce)) )
+	{
+		noncechain *temp=(noncechain *)state->listnonce.next;
+		
+		fd_list_unlink (&temp->chain);
+		free(temp->sid);
+		free(temp->nonce);
+		free(temp);
+		
+	}
+	CHECK_POSIX_DO(pthread_mutex_unlock(&state->nonce_mutex),); 
+	// ***Stop mutex
+}
+
+/* Initialize the plugin */
+static int sip_conf_parse(char * conffile, struct rgwp_config ** state)
+{
+	struct rgwp_config * new;
+	struct dict_object * app;
+	
+	
+	TRACE_ENTRY("%p %p", conffile, state);
+	CHECK_PARAMS( state );
+	
+	CHECK_MALLOC( new = malloc(sizeof(struct rgwp_config)) );
+	memset(new, 0, sizeof(struct rgwp_config));
+	
+	new->confstr = conffile;
+	
+	/* Resolve all dictionary objects we use */
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Session-Id", &new->dict.Session_Id, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Auth-Application-Id", &new->dict.Auth_Application_Id, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Auth-Session-State", &new->dict.Auth_Session_State, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Origin-Host", &new->dict.Origin_Host, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Origin-Realm", &new->dict.Origin_Realm, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Destination-Realm", &new->dict.Destination_Realm, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "SIP-AOR", &new->dict.SIP_AOR, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "SIP-Method", &new->dict.SIP_Method, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Destination-Host", &new->dict.Destination_Host, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "User-Name", &new->dict.User_Name, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "SIP-Server-URI", &new->dict.SIP_Server_URI, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "SIP-Number-Auth-Items", &new->dict.SIP_Number_Auth_Items, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "SIP-Authorization", &new->dict.SIP_Authorization, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "SIP-Auth-Data-Item", &new->dict.SIP_Auth_Data_Item, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "SIP-Authentication-Scheme", &new->dict.SIP_Authentication_Scheme, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "SIP-Authentication-Info", &new->dict.SIP_Authentication_Info, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Proxy-Info", &new->dict.Proxy_Info, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Route-Record", &new->dict.Route_Record, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Result-Code", &new->dict.Result_Code, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Digest-URI", &new->dict.Digest_URI, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Digest-Nonce", &new->dict.Digest_Nonce, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Digest-Method", &new->dict.Digest_Method, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Digest-CNonce", &new->dict.Digest_CNonce, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Digest-Nonce-Count", &new->dict.Digest_Nonce_Count, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Digest-Realm", &new->dict.Digest_Realm, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Digest-Response", &new->dict.Digest_Response, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Digest-Response-Auth", &new->dict.Digest_Response_Auth, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Digest-Username", &new->dict.Digest_Username, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Digest-Algorithm", &new->dict.Digest_Algorithm, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Digest-QoP", &new->dict.Digest_QOP, ENOENT) );
+
+
+	
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_APPLICATION, APPLICATION_BY_NAME, "Diameter Session Initiation Protocol (SIP) Application", &app, ENOENT) );
+	CHECK_FCT( fd_disp_app_support ( app, NULL, 1, 0 ) );
+	
+	//chained list
+	fd_list_init(&new->listnonce,NULL);
+	CHECK_POSIX(pthread_mutex_init(&new->nonce_mutex,NULL));
+	
+	*state = new;
+	return 0;
+}
+
+/* deinitialize */
+static void sip_conf_free(struct rgwp_config * state)
+{
+	TRACE_ENTRY("%p", state);
+	CHECK_PARAMS_DO( state, return );
+	
+	nonce_deletelistnonce(state);
+	CHECK_POSIX_DO(pthread_mutex_destroy(&state->nonce_mutex), /*continue*/);
+	
+	free(state);
+	return;
+}
+
+/* Handle an incoming RADIUS request */
+static int sip_rad_req( struct rgwp_config * cs, struct radius_msg * rad_req, struct radius_msg ** rad_ans, struct msg ** diam_fw, struct rgw_client * cli )
+{
+	int idx;
+	int got_AOR = 0;
+	int got_Dusername = 0;
+	int got_Drealm = 0;
+	int got_Duri = 0;
+	int got_Dmethod = 0;
+	int got_Dnonce = 0;
+	int got_Dresponse = 0;
+	int got_Dalgorithm = 0;
+	os0_t sid = NULL;
+	size_t sidlen;
+	os0_t un=NULL;
+	size_t  un_len;
+	size_t nattr_used = 0;
+	struct avp *auth_data=NULL, *auth=NULL, *avp = NULL;
+	union avp_value value;
+	struct session * sess;
+	
+	TRACE_ENTRY("%p %p %p %p %p", cs, rad_req, rad_ans, diam_fw, cli);
+	
+	CHECK_PARAMS(rad_req && (rad_req->hdr->code == RADIUS_CODE_ACCESS_REQUEST) && rad_ans && diam_fw && *diam_fw);
+	
+	/*
+	   RFC5090 RADIUS Extension Digest Application
+	*/
+	CHECK_FCT( fd_msg_sess_get(fd_g_config->cnf_dict, *diam_fw, &sess, NULL) );
+	if (sess != NULL) {
+		TRACE_DEBUG(INFO,"INTERNAL ERROR: We are not supposed to receive a session in radSIP plugin.");
+		return EINVAL;		
+	}
+	
+	/* Check basic information is there */
+	for (idx = 0; idx < rad_req->attr_used; idx++) {
+		struct radius_attr_hdr * attr = (struct radius_attr_hdr *)(rad_req->buf + rad_req->attr_pos[idx]);
+		
+		
+		switch (attr->type) {
+			
+			case RADIUS_ATTR_USER_NAME:
+				if (attr->length>sizeof(struct radius_attr_hdr)) 
+				{
+					TRACE_DEBUG(ANNOYING, "Found a User-Name attribute: '%.*s'", (int)(attr->length- sizeof(struct radius_attr_hdr)), (char *)(attr+1));
+					un = (os0_t)(attr + 1);
+					un_len =attr->length - sizeof(struct radius_attr_hdr);
+				}
+			break;
+			case RADIUS_ATTR_DIGEST_USERNAME:
+				got_Dusername = 1;
+			break;
+			case RADIUS_ATTR_DIGEST_REALM:
+				got_Drealm = 1;
+			break;
+			case RADIUS_ATTR_DIGEST_URI:
+				got_Duri = 1;
+			break;
+			case RADIUS_ATTR_DIGEST_METHOD:
+				got_Dmethod = 1;
+			break;
+			// case RADIUS_ATTR_DIGEST_QOP:
+			// 	got_Dqop = 1;
+			// break;
+			// case RADIUS_ATTR_DIGEST_NONCE_COUNT:
+			// 	got_Dnonce_count = 1;
+			// break;
+			case RADIUS_ATTR_DIGEST_NONCE:
+				got_Dnonce = 1;
+				
+				sid=nonce_get_sid((os0_t)(attr+1), attr->length - sizeof(struct radius_attr_hdr), &sidlen, cs);
+				if(!sid)
+				{
+					TRACE_DEBUG(INFO,"We haven't found the session.'");
+					return EINVAL;
+				}
+				CHECK_FCT(fd_sess_fromsid_msg (sid, sidlen, &sess, NULL));
+				free(sid);
+							
+				
+			break;
+			// case RADIUS_ATTR_DIGEST_CNONCE:
+			// 	got_Dcnonce = 1;
+			// break;
+			case RADIUS_ATTR_DIGEST_RESPONSE:
+				got_Dresponse = 1;
+			break;			
+			case RADIUS_ATTR_DIGEST_ALGORITHM:
+				got_Dalgorithm = 1;
+			break;
+			case RADIUS_ATTR_SIP_AOR:
+				got_AOR = 1;
+			break;
+		}
+	}
+	if(!un)
+	{
+		TRACE_DEBUG(INFO,"No Username in request");
+		return EINVAL;
+	}
+
+	/* Create the session if it is not already done */
+	if (!sess) {
+		
+		DiamId_t fqdn;
+		size_t fqdn_len;
+		DiamId_t realm;
+		size_t realm_len;
+		
+		/* Get information on the RADIUS client */
+		CHECK_FCT( rgw_clients_get_origin(cli, &fqdn, &fqdn_len, &realm, &realm_len) );
+		
+		/* Create a new Session-Id. The format is: {fqdn;hi32;lo32;username;diamid} */
+		CHECK_MALLOC( sid = malloc(un_len + 1 /* ';' */ + fd_g_config->cnf_diamid_len + 1 /* '\0' */) );
+		sidlen = sprintf((char *)sid, "%.*s;%s", (int)un_len, un, fd_g_config->cnf_diamid);
+		CHECK_FCT( fd_sess_new(&sess, fqdn, fqdn_len, sid, sidlen) );
+		free(sid);
+	}
+	
+	/* Now, add the Session-Id AVP at beginning of Diameter message */
+	CHECK_FCT( fd_msg_avp_new ( cs->dict.Session_Id, 0, &avp ) );
+	value.os.data = sid;
+	value.os.len = sidlen;
+	CHECK_FCT( fd_msg_avp_setvalue ( avp, &value ) );
+	CHECK_FCT( fd_msg_avp_add ( *diam_fw, MSG_BRW_FIRST_CHILD, avp) );
+	
+	TRACE_DEBUG(FULL, "[sip.rgwx] Translating new message for session '%s'...", sid);
+	
+	/* Now add this session in the message */
+	CHECK_FCT( fd_msg_sess_set(*diam_fw, sess) );
+		
+	/* Add the Destination-Realm AVP */
+	CHECK_FCT( fd_msg_avp_new ( cs->dict.Destination_Realm, 0, &avp ) );
+	
+	int i = 0;
+	
+	/* Is there an '@' in the user name? We don't care for decorated NAI here */
+	for (i = un_len - 2; i > 0; i--) {
+		if (un[i] == '@') {
+			i++;
+			break;
+		}
+	}
+
+	if (i == 0) {
+		/* Not found in the User-Name => we use the local domain of this gateway */
+		value.os.data = (os0_t)fd_g_config->cnf_diamrlm;
+		value.os.len  = fd_g_config->cnf_diamrlm_len;
+	} else {
+		value.os.data = un + i;
+		value.os.len  = un_len - i;
+	}
+	
+	CHECK_FCT( fd_msg_avp_setvalue ( avp, &value ) );
+	CHECK_FCT( fd_msg_avp_add ( *diam_fw, MSG_BRW_LAST_CHILD, avp) );
+	
+	/*
+	If the RADIUS Access-Request message does not
+	contain any Digest-* attribute, then the RADIUS client does not want
+	to apply HTTP Digest authentication, in which case, actions at the
+	gateway are outside the scope of this document.
+	*/
+	
+	if(!(got_Dmethod && got_Duri))
+	{
+		TRACE_DEBUG(INFO,"No Digest attributes in request, we drop it...");
+		return 1;
+	}
+
+	/* Add the appropriate command code & Auth-Application-Id */
+	{
+		struct msg_hdr * header = NULL;
+		CHECK_FCT( fd_msg_hdr ( *diam_fw, &header ) );
+		header->msg_flags = CMD_FLAG_REQUEST | CMD_FLAG_PROXIABLE;
+		header->msg_code = CC_MULTIMEDIA_AUTH_REQUEST;
+		header->msg_appl = AI_SIP;
+	
+	
+		/* Add the Auth-Application-Id */
+		{
+			CHECK_FCT( fd_msg_avp_new ( cs->dict.Auth_Application_Id, 0, &avp ) );
+			value.i32 = header->msg_appl;
+			CHECK_FCT( fd_msg_avp_setvalue ( avp, &value ) );
+			CHECK_FCT( fd_msg_avp_add ( *diam_fw, MSG_BRW_LAST_CHILD, avp) );
+		}
+	}
+	/*Add Auth_Session_State  AVP */
+	{
+		CHECK_FCT( fd_msg_avp_new ( cs->dict.Auth_Session_State, 0, &avp ) );
+		value.i32 = ACV_ASS_NO_STATE_MAINTAINED;
+		CHECK_FCT( fd_msg_avp_setvalue ( avp, &value ) );
+		CHECK_FCT( fd_msg_avp_add ( *diam_fw, MSG_BRW_LAST_CHILD, avp) );
+	}
+
+	
+	/*Add SIP_Number_Auth_Items  AVP */
+	{
+		CHECK_FCT( fd_msg_avp_new ( cs->dict.SIP_Number_Auth_Items, 0, &avp ) );
+		value.i32 = 1; //We just treat one auth per request in gateway
+		CHECK_FCT( fd_msg_avp_setvalue ( avp, &value ) );
+		CHECK_FCT( fd_msg_avp_add ( *diam_fw, MSG_BRW_LAST_CHILD, avp) );
+	}
+
+	/* Add SIP_Auth_Data_Item AVP */
+	{
+		CHECK_FCT( fd_msg_avp_new ( cs->dict.SIP_Auth_Data_Item, 0, &auth_data ) );
+	}
+	/* Add SIP_Authentication_Scheme AVP */
+	{
+		CHECK_FCT( fd_msg_avp_new ( cs->dict.SIP_Authentication_Scheme, 0, &avp ) );
+		value.i32=0; //There is only Digest Auth in RFC for now
+		CHECK_FCT( fd_msg_avp_setvalue ( avp, &value ) );
+		CHECK_FCT( fd_msg_avp_add ( auth_data, MSG_BRW_LAST_CHILD, avp) );
+	
+	}
+
+	
+	/* Add SIP_Authorization AVP */
+	{
+		CHECK_FCT( fd_msg_avp_new ( cs->dict.SIP_Authorization, 0, &auth ) );
+		CHECK_FCT( fd_msg_avp_add ( auth_data, MSG_BRW_LAST_CHILD, auth) );
+	}
+
+	for (idx = 0; idx < rad_req->attr_used; idx++) 
+	{
+		struct radius_attr_hdr * attr = (struct radius_attr_hdr *)(rad_req->buf + rad_req->attr_pos[idx]);
+		
+		switch (attr->type) {
+
+			case RADIUS_ATTR_USER_NAME:
+			CONV2DIAM_STR( User_Name );
+			
+			if(!got_Dusername)
+			{
+				CONV2DIAM_STR_AUTH(Digest_Username);
+				got_Dusername=1;
+			}
+			
+			break;
+
+			case RADIUS_ATTR_DIGEST_URI:
+			
+			CONV2DIAM_STR_AUTH(Digest_URI);
+			
+			//All of these attributes are required by Diameter but not defined in RFC5090 so we provide FAKE values (only in first exchange)
+			if(!got_AOR)
+			{
+				CONV2DIAM_STR( SIP_AOR );
+				got_AOR=1;
+			}
+			/*
+			We must provide a fake nonce because of RFC4740 problem
+			TODO: remove when RFC is updated
+			==START of FAKE
+			*/
+			if(!got_Dresponse)
+			{
+				CONV2DIAM_STR_AUTH(Digest_Response);
+				got_Dresponse=1;
+			}
+			/*
+			==END of FAKE
+			*/
+			if(!got_Drealm)
+			{
+				//We extract Realm from Digest_URI
+				DiamId_t realm=NULL;
+				size_t realm_len = 0;
+				os0_t temp;
+				
+				temp = (os0_t)(attr + 1);
+				
+				for (i=attr->length - sizeof(struct radius_attr_hdr) - 1; i>=0; i--) {
+					if (temp[i] == '@') {
+						realm = (DiamId_t)temp + i + 1;
+						CHECK_FCT_DO( fd_os_validate_DiameterIdentity(&realm, &realm_len, 1),
+							realm = NULL );
+						break;
+					}
+				}
+			
+				if(realm!=NULL)
+				{
+					CHECK_FCT( fd_msg_avp_new ( cs->dict.Digest_Realm, 0, &avp ) );
+					value.os.data=(os0_t)realm;
+					value.os.len=realm_len;
+					CHECK_FCT( fd_msg_avp_setvalue ( avp, &value ) );
+					CHECK_FCT( fd_msg_avp_add ( auth, MSG_BRW_LAST_CHILD, avp) );
+					
+					//We add SIP-Server-URI AVP because SIP server is registrar (through gateway)
+					CHECK_FCT( fd_msg_avp_new ( cs->dict.SIP_Server_URI, 0, &avp ) );
+					value.os.data=(os0_t)realm;
+					value.os.len=realm_len;
+					CHECK_FCT( fd_msg_avp_setvalue ( avp, &value ) );
+					CHECK_FCT( fd_msg_avp_add ( *diam_fw, MSG_BRW_LAST_CHILD, avp) );
+					
+					free(realm);
+				}
+				else
+				{
+					TRACE_DEBUG(INFO, "Can't extract domain from URI, droping request...");
+					return 1;
+				}	
+				got_Drealm=1;
+			}
+			break;
+
+			case RADIUS_ATTR_DIGEST_METHOD:
+			CONV2DIAM_STR(SIP_Method);
+			CONV2DIAM_STR_AUTH(Digest_Method);
+			break;
+			case RADIUS_ATTR_DIGEST_REALM:
+			CONV2DIAM_STR_AUTH(Digest_Realm);
+			
+			//We add SIP-Server-URI AVP because SIP server is registrar (through gateway)
+			CHECK_FCT( fd_msg_avp_new ( cs->dict.SIP_Server_URI, 0, &avp ) );
+			os0_t temp;
+			#define SIP_PREFIX	"sip:"
+			size_t temp_len = attr->length - sizeof(struct radius_attr_hdr) + CONSTSTRLEN(SIP_PREFIX) + 1;
+			CHECK_MALLOC( temp = malloc(temp_len) );
+			temp_len = snprintf((char *)temp, temp_len, SIP_PREFIX "%.*s", (int)(attr->length - sizeof(struct radius_attr_hdr)), (char *)(attr + 1));
+			
+			value.os.data=temp;
+			value.os.len=temp_len;
+			
+			free(temp);
+			
+			CHECK_FCT( fd_msg_avp_setvalue ( avp, &value ) );
+			CHECK_FCT( fd_msg_avp_add ( *diam_fw, MSG_BRW_LAST_CHILD, avp) );
+			break;
+			
+			case RADIUS_ATTR_DIGEST_USERNAME:
+			CONV2DIAM_STR_AUTH(Digest_Username);
+			break;
+				
+			case RADIUS_ATTR_DIGEST_QOP:
+			CONV2DIAM_STR_AUTH( Digest_QOP );
+			break;
+			case RADIUS_ATTR_DIGEST_ALGORITHM:		
+			CONV2DIAM_STR_AUTH( Digest_Algorithm );
+			break;
+			case RADIUS_ATTR_DIGEST_CNONCE:
+			CONV2DIAM_STR_AUTH( Digest_CNonce );
+			break;
+			case RADIUS_ATTR_DIGEST_NONCE:
+				CONV2DIAM_STR_AUTH( Digest_Nonce );
+			break;
+			case RADIUS_ATTR_DIGEST_NONCE_COUNT:
+			CONV2DIAM_STR_AUTH( Digest_Nonce_Count );
+			break;
+			case RADIUS_ATTR_DIGEST_RESPONSE:
+			CONV2DIAM_STR_AUTH( Digest_Response );
+			break;
+			case RADIUS_ATTR_SIP_AOR:
+			CONV2DIAM_STR( SIP_AOR );
+			break;
+				
+			default:
+			if(!got_Dalgorithm)
+			{
+				//[Note 3] If Digest-Algorithm is missing, 'MD5' is assumed.
+				#define DIGEST_ALGO_MD5	"MD5"
+										
+				CHECK_FCT( fd_msg_avp_new ( cs->dict.Digest_Algorithm, 0, &avp ) );			
+										
+				value.os.data = (os0_t)DIGEST_ALGO_MD5;
+				value.os.len = CONSTSTRLEN(DIGEST_ALGO_MD5) - 1;
+				CHECK_FCT( fd_msg_avp_setvalue ( avp, &value ) );					
+				CHECK_FCT( fd_msg_avp_add ( auth, MSG_BRW_LAST_CHILD, avp) );	
+				got_Dalgorithm=1;	
+			}
+			
+			if(!got_Dnonce)
+			{
+				//We give a fake nonce because it will be calculated at the server.
+				CHECK_FCT( fd_msg_avp_new ( cs->dict.Digest_Nonce, 0, &avp ) );
+				value.os.data=(unsigned char *)"nonce";
+				value.os.len=strlen((const char *)value.os.data);
+				CHECK_FCT( fd_msg_avp_setvalue ( avp, &value ) );
+				CHECK_FCT( fd_msg_avp_add ( auth, MSG_BRW_LAST_CHILD, avp) );	
+				got_Dnonce=1;
+			}
+			break;
+	
+		}
+	}
+
+	
+	CHECK_FCT( fd_msg_avp_add ( *diam_fw, MSG_BRW_LAST_CHILD, auth_data) );
+	
+	/* Update the radius message to remove all handled attributes */
+	rad_req->attr_used = nattr_used;
+
+	//fd_msg_dump_walk(1,*diam_fw);
+	
+	
+	return 0;
+}
+
+static int sip_diam_ans( struct rgwp_config * cs, struct msg ** diam_ans, struct radius_msg ** rad_fw, struct rgw_client * cli )
+{
+	
+	
+	struct avp *avp, *next;
+	struct avp_hdr *ahdr;
+	//char buf[254]; /* to store some attributes values (with final '\0') */
+	struct session * sess;
+	os0_t sid = NULL;
+	size_t sidlen;
+	
+	TRACE_ENTRY("%p %p %p %p", cs, diam_ans, rad_fw, cli);
+	CHECK_PARAMS(cs && diam_ans && *diam_ans && rad_fw && *rad_fw);
+	
+	
+	/* MACROS to help in the process: convert AVP data to RADIUS attributes. */
+	/* Control large attributes:  _trunc_ = 0 => error; _trunc_ = 1 => truncate; _trunc = 2 => create several attributes */
+	#define CONV2RAD_STR( _attr_, _data_, _len_, _trunc_)	{					\
+		size_t __l = (size_t)(_len_);								\
+		size_t __off = 0;									\
+		TRACE_DEBUG(FULL, "Converting AVP to "#_attr_);						\
+		if ((_trunc_) == 0) {									\
+			CHECK_PARAMS( __l <= 253 );							\
+		}											\
+		if ((__l > 253) && (_trunc_ == 1)) {							\
+			TRACE_DEBUG(INFO, "[authSIP.rgwx] AVP truncated in "#_attr_);			\
+			__l = 253;									\
+		}											\
+		do {											\
+			size_t __w = (__l > 253) ? 253 : __l;						\
+			CHECK_MALLOC(radius_msg_add_attr(*rad_fw, (_attr_), (_data_) + __off, __w));	\
+			__off += __w;									\
+			__l   -= __w;									\
+		} while (__l);										\
+	}
+
+	#define CONV2RAD_32B( _attr_, _data_)	{							\
+		uint32_t __v = htonl((uint32_t)(_data_));						\
+		TRACE_DEBUG(FULL, "Converting AVP to "#_attr_);						\
+		CHECK_MALLOC(radius_msg_add_attr(*rad_fw, (_attr_), (uint8_t *)&__v, sizeof(__v)));	\
+	}
+
+	/* Search the different AVPs we handle here */
+	CHECK_FCT( fd_msg_sess_get(fd_g_config->cnf_dict, *diam_ans, &sess, NULL) );
+	if (sess) {
+		CHECK_FCT( fd_sess_getsid(sess, &sid, &sidlen) );
+	}
+
+
+	/* Check the Diameter error code */
+	CHECK_FCT( fd_msg_search_avp (*diam_ans, cs->dict.Result_Code, &avp) );
+	ASSERT( avp ); /* otherwise the message should have been discarded a lot earlier because of ABNF */
+	CHECK_FCT( fd_msg_avp_hdr ( avp, &ahdr ) );
+	switch (ahdr->avp_value->u32) {
+		case ER_DIAMETER_MULTI_ROUND_AUTH:
+		case ER_DIAMETER_SUCCESS_AUTH_SENT_SERVER_NOT_STORED:		
+			(*rad_fw)->hdr->code = RADIUS_CODE_ACCESS_CHALLENGE;
+			//struct timespec nowts;
+			//CHECK_SYS(clock_gettime(CLOCK_REALTIME, &nowts));
+			//nowts.tv_sec+=600;
+			//CHECK_FCT(fd_sess_settimeout(session, &nowts ));
+			break;
+		case ER_DIAMETER_SUCCESS_SERVER_NAME_NOT_STORED:
+		case ER_DIAMETER_SUCCESS:
+			(*rad_fw)->hdr->code = RADIUS_CODE_ACCESS_ACCEPT;
+			// in_success=1;
+			break;
+		
+		default:
+			(*rad_fw)->hdr->code = RADIUS_CODE_ACCESS_REJECT;
+			fd_log_debug("[sip.rgwx] Received Diameter answer with error code '%d', session %.*s, translating into Access-Reject",
+					ahdr->avp_value->u32, (int)sidlen, sid);
+			return 0;
+	}
+	/* Remove this Result-Code avp */
+	CHECK_FCT( fd_msg_free( avp ) );
+	
+	/* Now loop in the list of AVPs and convert those that we know how */
+	CHECK_FCT( fd_msg_browse(*diam_ans, MSG_BRW_FIRST_CHILD, &next, NULL) );
+	
+	while (next) {
+		int handled = 1;
+		avp = next;
+		CHECK_FCT( fd_msg_browse(avp, MSG_BRW_WALK, &next, NULL) );
+		
+		CHECK_FCT( fd_msg_avp_hdr ( avp, &ahdr ) );
+		
+		if (!(ahdr->avp_flags & AVP_FLAG_VENDOR)) {
+			switch (ahdr->avp_code) {
+				
+				
+				case DIAM_ATTR_DIGEST_NONCE:
+					CONV2RAD_STR(DIAM_ATTR_DIGEST_NONCE, ahdr->avp_value->os.data, ahdr->avp_value->os.len, 0);
+					nonce_add_element(ahdr->avp_value->os.data, ahdr->avp_value->os.len, sid, sidlen, cs);
+					break;
+				case DIAM_ATTR_DIGEST_REALM:
+					CONV2RAD_STR(DIAM_ATTR_DIGEST_REALM, ahdr->avp_value->os.data, ahdr->avp_value->os.len, 1);
+					break;
+				case DIAM_ATTR_DIGEST_QOP:
+					CONV2RAD_STR(DIAM_ATTR_DIGEST_QOP, ahdr->avp_value->os.data, ahdr->avp_value->os.len, 1);
+					break;
+				case DIAM_ATTR_DIGEST_ALGORITHM:
+					CONV2RAD_STR(DIAM_ATTR_DIGEST_ALGORITHM, ahdr->avp_value->os.data, ahdr->avp_value->os.len, 1);
+					break;		
+				case DIAM_ATTR_DIGEST_RESPONSE_AUTH:
+					CONV2RAD_STR(DIAM_ATTR_DIGEST_RESPONSE_AUTH, ahdr->avp_value->os.data, ahdr->avp_value->os.len, 0);
+					break;
+				default:
+					handled=0;
+					break;
+			}
+		} 
+		else 
+		{
+			/* Vendor-specific AVPs */
+			switch (ahdr->avp_vendor) {
+				
+				default: /* unknown vendor */
+					handled = 0;
+			}
+		}
+		if (handled) {
+			CHECK_FCT( fd_msg_free( avp ) );
+		}
+	}
+	
+	return 0;
+}
+
+/* The exported symbol */
+struct rgw_api rgwp_descriptor = {
+	.rgwp_name       = "sip",
+	.rgwp_conf_parse = sip_conf_parse,
+	.rgwp_conf_free  = sip_conf_free,
+	.rgwp_rad_req    = sip_rad_req,
+	.rgwp_diam_ans   = sip_diam_ans
+};	
+
diff --git a/extensions/app_redirect/CMakeLists.txt b/extensions/app_redirect/CMakeLists.txt
new file mode 100644
index 0000000..3b61915
--- /dev/null
+++ b/extensions/app_redirect/CMakeLists.txt
@@ -0,0 +1,42 @@
+# The app_redirect extension
+PROJECT("Configurable Redirects server extension" C)
+
+# Check if REG_STARTEND is provided on the host
+SET(CHECK_REG_STARTEND_SOURCE_CODE "
+	#include <unistd.h>
+	#include <regex.h>
+	int main() {
+	   return regexec(NULL, NULL, 0, NULL, REG_STARTEND);
+	}
+	")
+CHECK_C_SOURCE_COMPILES("${CHECK_REG_STARTEND_SOURCE_CODE}" HAVE_REG_STARTEND)
+# Generate the host.h file
+CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/ard-host.h.in ${CMAKE_CURRENT_BINARY_DIR}/ard-host.h)
+
+# Parser files
+BISON_FILE(ard_conf.y)
+FLEX_FILE(ard_conf.l)
+SET_SOURCE_FILES_PROPERTIES(lex.ard_conf.c ard_conf.tab.c PROPERTIES COMPILE_FLAGS "-I ${CMAKE_CURRENT_SOURCE_DIR}")
+
+# List of source files
+SET( APP_REDIR_SRC
+	app_redir.c
+	app_redir.h
+	lex.ard_conf.c
+	ard_conf.tab.c
+	ard_conf.tab.h
+	ard_rules.c
+)
+
+INCLUDE_DIRECTORIES(${CMAKE_CURRENT_BINARY_DIR})
+
+# Compile these files as a freeDiameter extension
+FD_ADD_EXTENSION(app_redirect ${APP_REDIR_SRC})
+
+
+####
+## INSTALL section ##
+
+INSTALL(TARGETS app_redirect
+	LIBRARY DESTINATION ${INSTALL_EXTENSIONS_SUFFIX}
+	COMPONENT freeDiameter-app_redirect)
diff --git a/extensions/app_redirect/app_redir.c b/extensions/app_redirect/app_redir.c
new file mode 100644
index 0000000..d199687
--- /dev/null
+++ b/extensions/app_redirect/app_redir.c
@@ -0,0 +1,100 @@
+/*********************************************************************************************************
+* Software License Agreement (BSD License)                                                               *
+* Author: Sebastien Decugis <sdecugis@freediameter.net>							 *
+*													 *
+* Copyright (c) 2011, WIDE Project and NICT								 *
+* All rights reserved.											 *
+* 													 *
+* Redistribution and use of this software in source and binary forms, with or without modification, are  *
+* permitted provided that the following conditions are met:						 *
+* 													 *
+* * Redistributions of source code must retain the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer.										 *
+*    													 *
+* * Redistributions in binary form must reproduce the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer in the documentation and/or other						 *
+*   materials provided with the distribution.								 *
+* 													 *
+* * Neither the name of the WIDE Project or NICT nor the 						 *
+*   names of its contributors may be used to endorse or 						 *
+*   promote products derived from this software without 						 *
+*   specific prior written permission of WIDE Project and 						 *
+*   NICT.												 *
+* 													 *
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED *
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
+* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR *
+* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 	 *
+* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 	 *
+* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR *
+* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF   *
+* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.								 *
+*********************************************************************************************************/
+
+/* 
+ * Configurable routing of messages for freeDiameter.
+ */
+
+#include "app_redir.h"
+
+static struct fd_rt_fwd_hdl * ard_fwd_cb = NULL;
+
+/* entry point */
+static int ard_entry(char * conffile)
+{
+	TRACE_ENTRY("%p", conffile);
+	
+	/* Parse the configuration file */
+	CHECK_FCT( ard_conf_handle(conffile) );
+	
+	/* Resolve the dictionary objects we use */
+	CHECK_FCT( fd_dict_search ( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Redirect-Host", &avp_Redirect_Host, ENOENT ));
+	CHECK_FCT( fd_dict_search ( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Redirect-Host-Usage", &avp_Redirect_Host_Usage, ENOENT ));
+	CHECK_FCT( fd_dict_search ( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Redirect-Max-Cache-Time", &avp_Redirect_Max_Cache_Time, ENOENT ));
+	
+	/* Register the proxy callback */
+	CHECK_FCT( fd_rt_fwd_register(ard_rule_apply, NULL, RT_FWD_REQ, &ard_fwd_cb) );
+	
+	/* We're done */
+	return 0;
+}
+
+/* Unload */
+void fd_ext_fini(void)
+{
+	TRACE_ENTRY();
+	
+	/* Unregister the proxy callback */
+	if (ard_fwd_cb) {
+		CHECK_FCT_DO( fd_rt_fwd_unregister(ard_fwd_cb, NULL), );
+	}
+	
+	/* Destroy all rules */
+	while (!FD_IS_LIST_EMPTY(&ard_conf->rules)) {
+		struct ard_rule * r = ard_conf->rules.next->o;
+		fd_list_unlink(&r->chain);
+		while (!FD_IS_LIST_EMPTY(&r->criteria)) {
+			struct ard_criteria * c = r->criteria.next->o;
+			fd_list_unlink(&c->chain);
+			if (c->is_regex) {
+				regfree(&c->preg);
+			}
+			free(c->s);
+			free(c);
+		}
+		while (!FD_IS_LIST_EMPTY(&r->targets)) {
+			struct ard_target * t = r->targets.next->o;
+			fd_list_unlink(&t->chain);
+			free(t->s);
+			free(t);
+		}
+		free(r);
+	}
+	
+	/* Done */
+	return ;
+}
+
+EXTENSION_ENTRY("app_redirect", ard_entry);
diff --git a/extensions/app_redirect/app_redir.h b/extensions/app_redirect/app_redir.h
new file mode 100644
index 0000000..732c33d
--- /dev/null
+++ b/extensions/app_redirect/app_redir.h
@@ -0,0 +1,121 @@
+/*********************************************************************************************************
+* Software License Agreement (BSD License)                                                               *
+* Author: Sebastien Decugis <sdecugis@freediameter.net>							 *
+*													 *
+* Copyright (c) 2011, WIDE Project and NICT								 *
+* All rights reserved.											 *
+* 													 *
+* Redistribution and use of this software in source and binary forms, with or without modification, are  *
+* permitted provided that the following conditions are met:						 *
+* 													 *
+* * Redistributions of source code must retain the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer.										 *
+*    													 *
+* * Redistributions in binary form must reproduce the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer in the documentation and/or other						 *
+*   materials provided with the distribution.								 *
+* 													 *
+* * Neither the name of the WIDE Project or NICT nor the 						 *
+*   names of its contributors may be used to endorse or 						 *
+*   promote products derived from this software without 						 *
+*   specific prior written permission of WIDE Project and 						 *
+*   NICT.												 *
+* 													 *
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED *
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
+* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR *
+* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 	 *
+* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 	 *
+* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR *
+* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF   *
+* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.								 *
+*********************************************************************************************************/
+
+/* Header file for the app_redirect extension. 
+ *
+ *  See the app_redirect.conf.sample file for the format of the configuration file.
+ */
+ 
+/* FreeDiameter's common include file */
+#include <freeDiameter/extension.h>
+
+/* Host configuration for this specific extension */
+#include <ard-host.h>
+#include <regex.h>
+
+/* Extension's configuration */
+struct ard_config {
+	uint32_t	default_rct; /* redirect-cache-time to use unless overwritten by a rule */
+	struct fd_list  rules;	     /* the list of rules in the order they appear in the conf file. */
+};
+extern struct ard_config * ard_conf; /* initialized in ard_conf.y */
+
+/* The types of redirects (from Redirect-Host-Usage AVP value) */
+enum redir_h_u {
+	DONT_CACHE = 0,
+	ALL_SESSION,
+	ALL_REALM,
+	REALM_AND_APPLICATION,
+	ALL_APPLICATION,
+	ALL_HOST,
+	ALL_USER
+};
+#define H_U_MAX	ALL_USER
+
+/* A rule */
+struct ard_rule {
+	struct fd_list	chain; /* link in configuration */
+	
+	enum redir_h_u 	type; /* What kind of rule is this? */
+	uint32_t	rct;  /* overwrite default_rct is not 0 */
+	
+	struct fd_list  criteria; /* list of criteria to match. The rule is applied if all criteria match */
+	
+	struct fd_list  targets;  /* list of Redirect-Host values to send. */
+};
+
+/* What kind of criteria exist */
+enum rule_criteria { /* note: the order of the values reflects the complexity of matching -- it should be kept this way */
+	APP_ID,
+	FROM_ID,
+	FROM_REALM,
+	AVP_INT,
+	AVP_STR
+};
+
+/* A criteria in the list */
+struct ard_criteria {
+	struct fd_list  chain; /* link in ard_rule->criteria */
+	enum rule_criteria type; /* What is this rule */
+	
+	/* the data that must be matched -- everything is not used by all criteria types */
+	char * s;
+	size_t sl;
+	int is_regex;
+	regex_t  preg;
+	uint32_t i;
+	struct dict_avp_data avp_info;
+};
+
+/* A target entry in the ard_rule->targets list */
+struct ard_target {
+	struct fd_list chain;
+	os0_t  s; /* must be freed afterwards */
+	size_t l;
+};
+
+/* The AVPs we use */
+extern struct dict_object * avp_Redirect_Host;
+extern struct dict_object * avp_Redirect_Host_Usage;
+extern struct dict_object * avp_Redirect_Max_Cache_Time;
+
+/* Parse the configuration file */
+int ard_conf_handle(char * conffile);
+
+/* Dump a rule (debug) */
+void ard_rule_dump(struct ard_rule * r);
+
+/* Check if a rule applies, and if found, create the reply */
+int ard_rule_apply(void * cbdata, struct msg ** msg);
diff --git a/extensions/app_redirect/ard-host.h.in b/extensions/app_redirect/ard-host.h.in
new file mode 100644
index 0000000..34e05a5
--- /dev/null
+++ b/extensions/app_redirect/ard-host.h.in
@@ -0,0 +1,42 @@
+/*********************************************************************************************************
+* Software License Agreement (BSD License)                                                               *
+* Author: Sebastien Decugis <sdecugis@freediameter.net>							 *
+*													 *
+* Copyright (c) 2011, WIDE Project and NICT								 *
+* All rights reserved.											 *
+* 													 *
+* Redistribution and use of this software in source and binary forms, with or without modification, are  *
+* permitted provided that the following conditions are met:						 *
+* 													 *
+* * Redistributions of source code must retain the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer.										 *
+*    													 *
+* * Redistributions in binary form must reproduce the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer in the documentation and/or other						 *
+*   materials provided with the distribution.								 *
+* 													 *
+* * Neither the name of the WIDE Project or NICT nor the 						 *
+*   names of its contributors may be used to endorse or 						 *
+*   promote products derived from this software without 						 *
+*   specific prior written permission of WIDE Project and 						 *
+*   NICT.												 *
+* 													 *
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED *
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
+* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR *
+* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 	 *
+* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 	 *
+* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR *
+* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF   *
+* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.								 *
+*********************************************************************************************************/
+
+/* Configuration from compile-time */
+#ifndef RTD_IS_CONFIG
+#define RTD_IS_CONFIG
+
+#cmakedefine HAVE_REG_STARTEND
+
+#endif /* RTD_IS_CONFIG */
diff --git a/extensions/app_redirect/ard_conf.l b/extensions/app_redirect/ard_conf.l
new file mode 100644
index 0000000..0c39949
--- /dev/null
+++ b/extensions/app_redirect/ard_conf.l
@@ -0,0 +1,140 @@
+/*********************************************************************************************************
+* Software License Agreement (BSD License)                                                               *
+* Author: Sebastien Decugis <sdecugis@freediameter.net>							 *
+*													 *
+* Copyright (c) 2013, WIDE Project and NICT								 *
+* All rights reserved.											 *
+* 													 *
+* Redistribution and use of this software in source and binary forms, with or without modification, are  *
+* permitted provided that the following conditions are met:						 *
+* 													 *
+* * Redistributions of source code must retain the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer.										 *
+*    													 *
+* * Redistributions in binary form must reproduce the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer in the documentation and/or other						 *
+*   materials provided with the distribution.								 *
+* 													 *
+* * Neither the name of the WIDE Project or NICT nor the 						 *
+*   names of its contributors may be used to endorse or 						 *
+*   promote products derived from this software without 						 *
+*   specific prior written permission of WIDE Project and 						 *
+*   NICT.												 *
+* 													 *
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED *
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
+* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR *
+* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 	 *
+* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 	 *
+* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR *
+* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF   *
+* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.								 *
+*********************************************************************************************************/
+
+/* Tokenizer
+ *
+ */
+
+%{
+#include "app_redir.h"
+/* Include yacc tokens definitions */
+#include "ard_conf.tab.h"
+
+/* Update the column information */
+#define YY_USER_ACTION { 						\
+	yylloc->first_column = yylloc->last_column + 1; 		\
+	yylloc->last_column = yylloc->first_column + yyleng - 1;	\
+}
+
+/* Avoid warning with newer flex */
+#define YY_NO_INPUT
+
+%}
+
+qstring		\"[^\"\n]*\"
+
+
+%option bison-bridge bison-locations
+%option noyywrap
+%option nounput
+
+%%
+
+	/* Update the line count */
+\n			{
+				yylloc->first_line++; 
+				yylloc->last_line++; 
+				yylloc->last_column=0; 
+			}
+	 
+	/* Eat all spaces but not new lines */
+([[:space:]]{-}[\n])+	;
+	/* Eat all comments */
+#.*$			;
+
+	/* Recognize any integer */
+[[:digit:]]+		{
+				/* Convert this to an u32 value */
+				int ret=0;
+				ret = sscanf(yytext, "%u", &yylval->u32);
+				if (ret != 1) {
+					/* No matching: an error occurred */
+					fd_log_debug("Unable to convert the value '%s' to a valid number: %s", yytext, strerror(errno));
+					return TOK_LEX_ERROR; /* trig an error in yacc parser */
+					/* Maybe we could REJECT instead of failing here? */
+				}
+				return TOK_U32VAL;
+			}
+			
+	/* Recognize bracketed quoted strings */
+[[]{qstring}[]] 	{
+				/* Match a quoted string containing a regex */
+				CHECK_MALLOC_DO( yylval->tstring.str = strdup(yytext+2), 
+				{
+					TRACE_DEBUG(INFO, "Unable to copy the string '%s': %s", yytext, strerror(errno));
+					return TOK_LEX_ERROR; /* trig an error in yacc parser */
+				} );
+				yylval->tstring.str[strlen(yytext) - 4] = '\0';
+				yylval->tstring.regex = 1;
+				return TOK_TSTRING;
+			}
+			
+	/* Recognize quoted strings (since it comes after the previous rule, the string should not be quoted) */
+{qstring}		{
+				/* Match a quoted string. */
+				CHECK_MALLOC_DO( yylval->tstring.str = strdup(yytext+1), 
+				{
+					TRACE_DEBUG(INFO, "Unable to copy the string '%s': %s", yytext, strerror(errno));
+					return TOK_LEX_ERROR; /* trig an error in yacc parser */
+				} );
+				yylval->tstring.str[strlen(yytext) - 2] = '\0';
+				yylval->tstring.regex = 0;
+				return TOK_TSTRING;
+			}
+	
+	/* The key words */	
+(?i:"default_redirect_cache_time")	{ return TOK_DEFAULT_RCT;		}
+(?i:"to")	 			{ return TOK_TO;			}
+(?i:"DONT_CACHE")	 		{ return TOK_DONT_CACHE;		}
+(?i:"ALL_SESSION")	 		{ return TOK_ALL_SESSION;		}
+(?i:"ALL_REALM")	 		{ return TOK_ALL_REALM;			}
+(?i:"REALM_AND_APPLICATION")	 	{ return TOK_REALM_AND_APPLICATION;	}
+(?i:"ALL_APPLICATION")	 		{ return TOK_ALL_APPLICATION;		}
+(?i:"ALL_HOST")	 			{ return TOK_ALL_HOST;			}
+(?i:"ALL_USER")	 			{ return TOK_ALL_USER;			}
+(?i:"from.id")	 			{ return TOK_FROM_ID;			}
+(?i:"from.realm")	 		{ return TOK_FROM_REALM;		}
+(?i:"app")	 			{ return TOK_APP;			}
+			
+	/* Valid single characters for yyparse */
+[:=;]		{ return yytext[0]; }
+
+	/* Unrecognized sequence, if it did not match any previous pattern */
+[^[:space:]\":=;\n]+	{ 
+				fd_log_debug("Unrecognized text on line %d col %d: '%s'.", yylloc->first_line, yylloc->first_column, yytext);
+			 	return TOK_LEX_ERROR; 
+			}
+
+%%
diff --git a/extensions/app_redirect/ard_conf.y b/extensions/app_redirect/ard_conf.y
new file mode 100644
index 0000000..14a1280
--- /dev/null
+++ b/extensions/app_redirect/ard_conf.y
@@ -0,0 +1,451 @@
+/*********************************************************************************************************
+* Software License Agreement (BSD License)                                                               *
+* Author: Sebastien Decugis <sdecugis@freediameter.net>							 *
+*													 *
+* Copyright (c) 2013, WIDE Project and NICT								 *
+* All rights reserved.											 *
+* 													 *
+* Redistribution and use of this software in source and binary forms, with or without modification, are  *
+* permitted provided that the following conditions are met:						 *
+* 													 *
+* * Redistributions of source code must retain the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer.										 *
+*    													 *
+* * Redistributions in binary form must reproduce the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer in the documentation and/or other						 *
+*   materials provided with the distribution.								 *
+* 													 *
+* * Neither the name of the WIDE Project or NICT nor the 						 *
+*   names of its contributors may be used to endorse or 						 *
+*   promote products derived from this software without 						 *
+*   specific prior written permission of WIDE Project and 						 *
+*   NICT.												 *
+* 													 *
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED *
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
+* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR *
+* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 	 *
+* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 	 *
+* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR *
+* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF   *
+* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.								 *
+*********************************************************************************************************/
+
+/* Yacc extension's configuration parser.
+ * See doc/app_redirect.conf.sample for configuration file format
+ */
+
+/* For development only : */
+%debug 
+%error-verbose
+
+/* The parser receives the configuration file filename as parameter */
+%parse-param {char * conffile}
+
+/* Keep track of location */
+%locations 
+%pure-parser
+
+%{
+#include "app_redir.h"
+#include "ard_conf.tab.h"	/* bison is not smart enough to define the YYLTYPE before including this code, so... */
+
+/* Forward declaration */
+int yyparse(char * conffile);
+
+static int rules_added = 0;
+
+/* We initialize statically the config */
+static struct ard_config local_conf = { .default_rct = 86400, .rules = FD_LIST_INITIALIZER(local_conf.rules) };
+struct ard_config * ard_conf = &local_conf;
+
+/* We use these lists in the rules parsing */
+static struct fd_list temp_list_criteria = FD_LIST_INITIALIZER(temp_list_criteria);
+static struct fd_list temp_list_target = FD_LIST_INITIALIZER(temp_list_target);
+
+/* Local variable */
+static struct ard_criteria * c;
+
+/* Dump the configuration */
+static void ard_conf_dump()
+{
+	struct fd_list * li;
+	if (!TRACE_BOOL(FULL))
+		return;
+		
+	fd_log_debug("app_redirect: configuration dump:");
+	fd_log_debug("   default_redirect_cache_time : %u sec", ard_conf->default_rct);
+	for (li = ard_conf->rules.next; li != &ard_conf->rules; li = li->next) {
+		ard_rule_dump(li->o);
+	}
+	fd_log_debug("app_redirect: end of configuration dump");
+}
+
+/* Parse the configuration file */
+int ard_conf_handle(char * conffile)
+{
+	extern FILE * ard_confin;
+	int ret;
+	
+	TRACE_ENTRY("%p", conffile);
+	
+	TRACE_DEBUG (FULL, "Parsing configuration file: %s...", conffile);
+	
+	ard_confin = fopen(conffile, "r");
+	if (ard_confin == NULL) {
+		ret = errno;
+		TRACE_DEBUG(INFO, "Unable to open extension configuration file %s for reading: %s", conffile, strerror(ret));
+		return ret;
+	}
+
+	ret = yyparse(conffile);
+
+	fclose(ard_confin);
+
+	if (ret != 0) {
+		TRACE_DEBUG (INFO, "Unable to parse the configuration file.");
+		return EINVAL;
+	} else {
+		TRACE_DEBUG(FULL, "Added %d Redirect RULES successfully.", rules_added);
+		ard_conf_dump();
+	}
+	
+	return 0;
+}
+
+/* The Lex parser prototype */
+int ard_conflex(YYSTYPE *lvalp, YYLTYPE *llocp);
+
+/* Function to report the errors */
+void yyerror (YYLTYPE *ploc, char * conffile, char const *s)
+{
+	TRACE_DEBUG(INFO, "Error in configuration parsing");
+	
+	if (ploc->first_line != ploc->last_line) {
+		TRACE_DEBUG (INFO, "%s:%d.%d-%d.%d : %s", conffile, ploc->first_line, ploc->first_column, ploc->last_line, ploc->last_column, s);
+	} else if (ploc->first_column != ploc->last_column) {
+		TRACE_DEBUG (INFO, "%s:%d.%d-%d : %s", conffile, ploc->first_line, ploc->first_column, ploc->last_column, s);
+	} else {
+		TRACE_DEBUG (INFO, "%s:%d.%d : %s", conffile, ploc->first_line, ploc->first_column, s);
+	}
+}
+
+/* Compile a regular expression pattern */
+static int compile_regex( regex_t  * preg, char * str )
+{
+	int err;
+	
+	/* Compile the regular expression */
+	err = regcomp(preg, str, REG_EXTENDED | REG_NOSUB);
+	if (err != 0) {
+		char * buf;
+		size_t bl;
+		
+		/* Error while compiling the regex */
+		TRACE_DEBUG(INFO, "Error while compiling the regular expression '%s':", str);
+		
+		/* Get the error message size */
+		bl = regerror(err, preg, NULL, 0);
+		
+		/* Alloc the buffer for error message */
+		CHECK_MALLOC( buf = malloc(bl) );
+		
+		/* Get the error message content */
+		regerror(err, preg, buf, bl);
+		TRACE_DEBUG(INFO, "\t%s", buf);
+		
+		/* Free the buffer, return the error */
+		free(buf);
+		return EINVAL;
+	}
+
+	return 0;
+}
+
+
+%}
+
+/* Values returned by lex for token */
+%union {
+	/* returned by lex */
+	uint32_t	 u32;	/* Store integer values */
+	struct {
+		char * str;
+		int regex; /* true or false */
+	}	 tstring;	/* typed string */
+}
+
+/* In case of error in the lexical analysis */
+%token 		TOK_LEX_ERROR
+
+/* A string (malloc'd in lex parser; it must be freed after use):*/
+%token <tstring> TOK_TSTRING
+
+/* An integer value */
+%token <u32> 	TOK_U32VAL
+
+%type <u32>	rule_type
+%type <u32>	rule_duration
+
+/* Tokens */
+%token 		TOK_DEFAULT_RCT
+
+%token 		TOK_TO
+
+%token 		TOK_DONT_CACHE
+%token 		TOK_ALL_SESSION
+%token 		TOK_ALL_REALM
+%token 		TOK_REALM_AND_APPLICATION
+%token 		TOK_ALL_APPLICATION
+%token 		TOK_ALL_HOST
+%token 		TOK_ALL_USER
+
+%token 		TOK_FROM_ID
+%token 		TOK_FROM_REALM
+
+%token 		TOK_APP
+
+
+
+
+
+/* -------------------------------------- */
+%%
+
+	/* The grammar definition */
+conffile:		/* empty grammar is OK */
+			| conffile def_rct
+			| conffile rule
+			;
+			
+	/* Overwrite default cache time value */
+def_rct:		TOK_DEFAULT_RCT '=' TOK_U32VAL ';'
+			{
+				ard_conf->default_rct = $3;
+			}
+			;
+			
+	/* a RULE entry */
+rule:			rule_type rule_duration ':' criteria_list TOK_TO target_list ';'
+			{
+				struct ard_rule * r;
+				/* Create the new rule with data in file */
+				CHECK_MALLOC_DO( r = malloc(sizeof(struct ard_rule)),
+					{
+						yyerror (&yylloc, conffile, "Error while allocating new memory...");
+						YYERROR;
+					} );
+				memset(r, 0, sizeof(struct ard_rule));
+				fd_list_init(&r->chain, r);
+				r->type = $1;
+				r->rct = $2;
+				fd_list_init(&r->criteria, NULL);
+				fd_list_move_end(&r->criteria, &temp_list_criteria);
+				fd_list_init(&r->targets, NULL);
+				fd_list_move_end(&r->targets, &temp_list_target);
+				
+				/* Add the new rule in config */
+				fd_list_insert_before(&ard_conf->rules, &r->chain);
+				rules_added++;
+			}
+			;
+
+rule_type:		TOK_DONT_CACHE
+			{
+				$$ = DONT_CACHE;
+			}
+			| TOK_ALL_SESSION
+			{
+				$$ = ALL_SESSION;
+			}
+			| TOK_ALL_REALM
+			{
+				$$ = ALL_REALM;
+			}
+			| TOK_REALM_AND_APPLICATION
+			{
+				$$ = REALM_AND_APPLICATION;
+			}
+			| TOK_ALL_APPLICATION
+			{
+				$$ = ALL_APPLICATION;
+			}
+			| TOK_ALL_HOST
+			{
+				$$ = ALL_HOST;
+			}
+			| TOK_ALL_USER
+			{
+				$$ = ALL_USER;
+			}
+			;
+			
+rule_duration:		/* empty */
+			{
+				$$ = 0;
+			}
+			|
+			TOK_U32VAL
+			{
+				$$ = $1;
+			}
+			;
+
+criteria_list:		/* empty is OK */
+			| criteria_list criteria_item;
+			;
+
+criteria_item:		{
+				/* Create the new criteria */
+				CHECK_MALLOC_DO( c = malloc(sizeof(struct ard_criteria)),
+					{
+						yyerror (&yylloc, conffile, "Error while allocating new memory...");
+						YYERROR;
+					} );
+				memset(c, 0, sizeof(struct ard_criteria));
+				fd_list_init(&c->chain, c);
+			}
+			criteria_item_inside
+			{
+				struct fd_list * li;
+				/* If there is a string, save its length */
+				if (c->s)
+					c->sl = strlen(c->s);
+				/* If the criteria contains a regex, parse it */
+				if (c->is_regex) {
+					CHECK_FCT_DO( compile_regex( &c->preg, c->s ),
+						{
+							yyerror (&yylloc, conffile, "Error parsing a regular expression...");
+							YYERROR;
+						} );
+				}
+				
+				/* Now link this new criteria in the list. Order by criteria type to accelerate the search */
+				for (li = temp_list_criteria.next; li != &temp_list_criteria; li = li->next) {
+					struct ard_criteria * nc = li->o;
+					if (nc->type >= c->type)
+						break;
+				}
+				fd_list_insert_before(li, &c->chain);
+			}
+			;
+
+criteria_item_inside:	TOK_FROM_ID '=' TOK_TSTRING
+			{
+				c->type = FROM_ID;
+				c->s = $3.str;
+				c->is_regex = $3.regex;
+			}
+			|
+			TOK_FROM_REALM '=' TOK_TSTRING
+			{
+				c->type = FROM_REALM;
+				c->s = $3.str;
+				c->is_regex = $3.regex;
+			}
+			|
+			TOK_APP '=' TOK_U32VAL
+			{
+				c->type = APP_ID;
+				c->i = $3;
+			}
+			|
+			TOK_TSTRING '=' TOK_U32VAL
+			{
+				struct dict_object * avp = NULL;
+				if ($1.regex) {
+					yyerror(&yylloc, conffile, "Error: the AVP name cannot be specified as regular expression");
+					YYERROR;
+				}
+				CHECK_FCT_DO( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME_ALL_VENDORS, $1.str, &avp, ENOENT ),
+					{
+						TRACE_DEBUG(INFO, "Error while searching for AVP '%s'. Did you load the relevant dictionary extensions?", $1.str);
+						yyerror(&yylloc, conffile, "Unable to resolve specified AVP name.");
+						YYERROR;
+					}  );
+				CHECK_FCT_DO( fd_dict_getval(avp, &c->avp_info),
+					{
+						TRACE_DEBUG(INFO, "Error while retrieving the description for AVP '%s'", $1.str);
+						yyerror(&yylloc, conffile, "Unable to retrieve specified AVP's data.");
+						YYERROR;
+					}  );
+				if (c->avp_info.avp_basetype != AVP_TYPE_UNSIGNED32) {
+					TRACE_DEBUG(INFO, "The AVP '%s' is not of type UNSIGNED32, matching is not supported (yet)", $1.str);
+					yyerror(&yylloc, conffile, "Invalid AVP for this operation.");
+					YYERROR;
+				}
+				
+				c->type = AVP_INT;
+				c->i = $3;
+			}
+			|
+			TOK_TSTRING '=' TOK_TSTRING
+			{
+				struct dict_object * avp = NULL;
+				if ($1.regex) {
+					yyerror(&yylloc, conffile, "Error: the AVP name cannot be specified as regular expression");
+					YYERROR;
+				}
+				CHECK_FCT_DO( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME_ALL_VENDORS, $1.str, &avp, ENOENT ),
+					{
+						TRACE_DEBUG(INFO, "Error while searching for AVP '%s'. Did you load the relevant dictionary extensions?", $1.str);
+						yyerror(&yylloc, conffile, "Unable to resolve specified AVP name.");
+						YYERROR;
+					}  );
+				CHECK_FCT_DO( fd_dict_getval(avp, &c->avp_info),
+					{
+						TRACE_DEBUG(INFO, "Error while retrieving the description for AVP '%s'", $1.str);
+						yyerror(&yylloc, conffile, "Unable to retrieve specified AVP's data.");
+						YYERROR;
+					}  );
+				if (c->avp_info.avp_basetype != AVP_TYPE_OCTETSTRING) {
+					TRACE_DEBUG(INFO, "The AVP '%s' is not of type OCTETSTRING, matching is not supported (yet)", $1.str);
+					yyerror(&yylloc, conffile, "Invalid AVP for this operation.");
+					YYERROR;
+				}
+				
+				c->type = AVP_STR;
+				c->s = $3.str;
+				c->is_regex = $3.regex;
+			}
+			;
+
+target_list:		/* This list cannot be empty */
+			target_item
+			| target_list target_item
+			;
+
+target_item:		TOK_TSTRING
+			{
+				struct ard_target * t;
+				
+				if ($1.regex) {
+					yyerror(&yylloc, conffile, "Regular expressions are not allowed in Redirect-Host specification.");
+					YYERROR;
+				}
+				
+				/* Check if the format is valid */
+				CHECK_FCT_DO( fd_os_parse_DiameterURI((uint8_t *)$1.str, strlen($1.str), NULL, NULL, NULL, NULL, NULL, NULL),
+					{
+						TRACE_DEBUG(INFO, "Error while parsing DiameterURI '%s'", $1.str);
+						yyerror(&yylloc, conffile, "Specified DiameterURI is invalid.");
+						YYERROR;
+					}  );
+				
+				/* Ok. we create the new target */
+				CHECK_MALLOC_DO( t = malloc(sizeof(struct ard_target)),
+					{
+						yyerror (&yylloc, conffile, "Error while allocating new memory...");
+						YYERROR;
+					} );
+				memset(t, 0, sizeof(struct ard_target));
+				fd_list_init(&t->chain, t);
+				
+				t->s = (os0_t) $1.str;
+				t->l = strlen($1.str);
+				
+				fd_list_insert_before(&temp_list_target, &t->chain);
+			}
+			;
diff --git a/extensions/app_redirect/ard_rules.c b/extensions/app_redirect/ard_rules.c
new file mode 100644
index 0000000..c7a3861
--- /dev/null
+++ b/extensions/app_redirect/ard_rules.c
@@ -0,0 +1,298 @@
+/*********************************************************************************************************
+* Software License Agreement (BSD License)                                                               *
+* Author: Sebastien Decugis <sdecugis@freediameter.net>							 *
+*													 *
+* Copyright (c) 2013, WIDE Project and NICT								 *
+* All rights reserved.											 *
+* 													 *
+* Redistribution and use of this software in source and binary forms, with or without modification, are  *
+* permitted provided that the following conditions are met:						 *
+* 													 *
+* * Redistributions of source code must retain the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer.										 *
+*    													 *
+* * Redistributions in binary form must reproduce the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer in the documentation and/or other						 *
+*   materials provided with the distribution.								 *
+* 													 *
+* * Neither the name of the WIDE Project or NICT nor the 						 *
+*   names of its contributors may be used to endorse or 						 *
+*   promote products derived from this software without 						 *
+*   specific prior written permission of WIDE Project and 						 *
+*   NICT.												 *
+* 													 *
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED *
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
+* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR *
+* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 	 *
+* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 	 *
+* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR *
+* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF   *
+* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.								 *
+*********************************************************************************************************/
+
+#include "app_redir.h"
+
+static const char * redir_type_str[] = {
+	"DONT_CACHE",
+	"ALL_SESSION",
+	"ALL_REALM",
+	"REALM_AND_APPLICATION",
+	"ALL_APPLICATION",
+	"ALL_HOST",
+	"ALL_USER"
+};
+
+struct dict_object * avp_Redirect_Host = NULL;
+struct dict_object * avp_Redirect_Host_Usage = NULL;
+struct dict_object * avp_Redirect_Max_Cache_Time = NULL;
+	
+
+void ard_rule_dump(struct ard_rule * r)
+{
+	struct fd_list * li;
+	fd_log_debug("   rule @%p: %s, %us", r, redir_type_str[r->type], r->rct);
+	for (li = r->criteria.next; li != &r->criteria; li = li->next) {
+		struct ard_criteria * c = li->o;
+		switch (c->type) {
+			case FROM_ID:
+				fd_log_debug("      Criteria: received from peer %s'%s'", c->is_regex?"REGEX":"", c->s);
+				break;
+			case FROM_REALM:
+				fd_log_debug("      Criteria: received from realm %s'%s'", c->is_regex?"REGEX":"", c->s);
+				break;
+			case APP_ID:
+				fd_log_debug("      Criteria: application id is %u", c->i);
+				break;
+			case AVP_INT:
+				fd_log_debug("      Criteria: contains '%s' AVP with value '%d'", c->avp_info.avp_name, c->i);
+				break;
+			case AVP_STR:
+				fd_log_debug("      Criteria: contains '%s' AVP with value %s'%s'", c->avp_info.avp_name, c->is_regex?"REGEX":"", c->s);
+				break;
+		
+			default:
+				fd_log_debug("      Criteria: invalid (%d)!", c->type);
+		}
+	}
+	for (li = r->targets.next; li != &r->targets; li = li->next) {
+		struct ard_target * t = li->o;
+		fd_log_debug("      Redirect to: '%s'", t->s);
+	}
+}
+
+/* Tells if the string in s (is0term or not) matches the string in the criteria (regex or not) */
+static int str_match(struct ard_criteria * c, uint8_t *s, size_t l, int is0term, int * match)
+{
+	TRACE_ENTRY("%p %p %zd %d %p", c, s, l, is0term, match);
+	
+	*match = 0;
+	
+	if (c->is_regex == 0) {
+		if ( ! fd_os_almostcasesrch(c->s, c->sl, s, l, NULL) )
+			*match = 1;
+	} else {
+		int err;
+#ifdef HAVE_REG_STARTEND
+		regmatch_t pmatch[1];
+		memset(pmatch, 0, sizeof(pmatch));
+		pmatch[0].rm_so = 0;
+		pmatch[0].rm_eo = l;
+		err = regexec(&c->preg, (char *)s, 0, pmatch, REG_STARTEND);
+#else /* HAVE_REG_STARTEND */
+		if (!is0term) {
+			/* We have to create a copy of the string in this case */
+			char *mystrcpy;
+			CHECK_MALLOC( mystrcpy = (char *)os0dup(s, l) );
+			err = regexec(&c->preg, mystrcpy, 0, NULL, 0);
+			free(mystrcpy);
+		} else {
+			err = regexec(&c->preg, (char *)s, 0, NULL, 0);
+		}
+#endif /* HAVE_REG_STARTEND */
+		
+		/* Now check the result */
+		if (err == 0) {
+			/* We have a match */
+			*match = 1;
+		} else if (err != REG_NOMATCH) {
+			/* An error occurred */
+			char * buf;
+			size_t bl;
+
+			/* Error while compiling the regex */
+			TRACE_DEBUG(INFO, "Error while executing the regular expression '%s':", c->s);
+
+			/* Get the error message size */
+			bl = regerror(err, &c->preg, NULL, 0);
+
+			/* Alloc the buffer for error message */
+			CHECK_MALLOC( buf = malloc(bl) );
+
+			/* Get the error message content */
+			regerror(err, &c->preg, buf, bl);
+			TRACE_DEBUG(INFO, "\t%s", buf);
+
+			/* Free the buffer, return the error */
+			free(buf);
+			return (err == REG_ESPACE) ? ENOMEM : EINVAL;
+		}
+	}
+	return 0;
+}
+
+/* Search the first matching rule in the config */
+static int find_rule(struct msg * msg, struct ard_rule ** found)
+{
+	struct fd_list * li;
+	struct msg_hdr * mhdr = NULL;
+	struct peer_hdr * phdr = NULL;
+	
+	ASSERT(msg && found);
+	*found = NULL;
+	
+	/* Get the message's header */
+	CHECK_FCT( fd_msg_hdr(msg, &mhdr) );
+	
+	/* Get the message's origin */
+	{
+		DiamId_t id;
+		size_t len;
+		CHECK_FCT( fd_msg_source_get(msg, &id, &len) );
+		CHECK_FCT( fd_peer_getbyid(id, len, 0, &phdr) );
+	}
+	
+	/* Now for each rule check if all criteria match */
+	for (li = ard_conf->rules.next; li != &ard_conf->rules; li = li->next) {
+		struct fd_list * lic;
+		struct ard_rule * r = li->o;
+		int is_match = 1;
+		
+		for (lic = r->criteria.next; is_match && (lic != &r->criteria); lic = lic->next) {
+			struct ard_criteria * c = lic->o;
+			
+			/* Does this criteria match ? */
+			switch (c->type) {
+				case APP_ID:
+					if (c->i != mhdr->msg_appl)
+						is_match = 0;
+					break;
+					
+				case FROM_ID:
+					CHECK_FCT( str_match(c, (uint8_t *)phdr->info.pi_diamid, phdr->info.pi_diamidlen, 1, &is_match) );
+					break;
+				
+				case FROM_REALM:
+					if (phdr->info.runtime.pir_realm) {
+						CHECK_FCT( str_match(c, (uint8_t *)phdr->info.runtime.pir_realm, phdr->info.runtime.pir_realmlen, 1, &is_match) );
+					} else {
+						/* since we don't have the realm it was received from, assume it does not match */
+						TRACE_DEBUG(INFO, "Missing realm info for peer '%s', skipping rule %p", phdr->info.pi_diamid, r);
+						is_match = 0;
+					}
+					break;
+				
+				case AVP_INT:
+				case AVP_STR:
+					/* We have to search the whole message for the matching AVP */
+					{
+						is_match = 0;
+						struct avp * avp = NULL;
+						CHECK_FCT(  fd_msg_browse(msg, MSG_BRW_FIRST_CHILD, &avp, NULL)  );
+						while (avp && !is_match) {
+							struct avp_hdr * ahdr = NULL;
+							CHECK_FCT( fd_msg_avp_hdr(avp, &ahdr) );
+
+							if ( (ahdr->avp_code == c->avp_info.avp_code)
+							  && (ahdr->avp_vendor == c->avp_info.avp_vendor) )  /* always 0 if no V flag */
+							{
+								/* dict-parse this AVP to ensure it has a value */
+								CHECK_FCT( fd_msg_parse_dict( avp, fd_g_config->cnf_dict, NULL ) );
+
+								/* Now check if the value matches our criteria */
+								if (c->type == AVP_INT) {
+									if (ahdr->avp_value->u32 == c->i)
+										is_match = 1;
+								} else {
+									/* it is AVP_STR */
+									CHECK_FCT( str_match(c, ahdr->avp_value->os.data, ahdr->avp_value->os.len, 0, &is_match) );
+								}
+
+								if (is_match)
+									break;
+							}
+
+							/* go to next */
+							CHECK_FCT( fd_msg_browse(avp, MSG_BRW_NEXT, &avp, NULL) );
+						}
+
+					}
+				
+					break;
+			
+			}
+		}
+		
+		if (is_match) {
+			/* We found the first rule that matches for this message */
+			*found = r;
+			break;
+		}
+	}
+	
+	return 0;
+}
+
+/* The forward callback */
+int ard_rule_apply(void * cbdata, struct msg ** msg)
+{
+	struct ard_rule * rule = NULL;
+	
+	TRACE_ENTRY("%p %p", cbdata, msg);
+	CHECK_PARAMS(msg && *msg);
+	
+	/* First, check if we have a rule that applies to this message */
+	CHECK_FCT( find_rule(*msg, &rule) );
+	
+	if (rule) {
+		struct avp * avp;
+		union avp_value val;
+		struct fd_list * li;
+		
+		/* We have to reply a Redirect message in this case */
+		CHECK_FCT( fd_msg_new_answer_from_req(fd_g_config->cnf_dict, msg, MSGFL_ANSW_ERROR) );
+		
+		CHECK_FCT( fd_msg_rescode_set( *msg, "DIAMETER_REDIRECT_INDICATION", NULL, NULL, 1 ) );
+		
+		/* Now add the Redirect-* AVPs */
+		CHECK_FCT( fd_msg_avp_new( avp_Redirect_Host_Usage, 0, &avp ) );
+		val.u32 = rule->type;
+		CHECK_FCT( fd_msg_avp_setvalue( avp, &val ) );
+		CHECK_FCT( fd_msg_avp_add( *msg, MSG_BRW_LAST_CHILD, avp ) );
+		
+		if (rule->type) {
+			CHECK_FCT( fd_msg_avp_new( avp_Redirect_Max_Cache_Time, 0, &avp ) );
+			val.u32 = rule->rct ?: ard_conf->default_rct;
+			CHECK_FCT( fd_msg_avp_setvalue( avp, &val ) );
+			CHECK_FCT( fd_msg_avp_add( *msg, MSG_BRW_LAST_CHILD, avp ) );
+		}
+		
+		for (li = rule->targets.next; li != &rule->targets; li = li->next) {
+			struct ard_target * t = li->o;
+			
+			CHECK_FCT( fd_msg_avp_new( avp_Redirect_Host, 0, &avp ) );
+			val.os.data = t->s;
+			val.os.len  = t->l;
+			CHECK_FCT( fd_msg_avp_setvalue( avp, &val ) );
+			CHECK_FCT( fd_msg_avp_add( *msg, MSG_BRW_LAST_CHILD, avp ) );
+		}
+		
+		/* Send this answer */
+		CHECK_FCT( fd_msg_send( msg, NULL, NULL) );
+	}
+	
+	return 0;
+}
+
diff --git a/extensions/app_sip/CMakeLists.txt b/extensions/app_sip/CMakeLists.txt
new file mode 100644
index 0000000..8bd89d1
--- /dev/null
+++ b/extensions/app_sip/CMakeLists.txt
@@ -0,0 +1,47 @@
+# The app_sip extension
+PROJECT("Diameter SIP Application (RFC4740)" C)
+
+FIND_PACKAGE(MySQL REQUIRED)
+INCLUDE_DIRECTORIES(${MySQL_INCLUDE_DIR}) 
+
+# Parser files
+BISON_FILE(app_sip.y)
+FLEX_FILE(app_sip.l)
+SET_SOURCE_FILES_PROPERTIES(lex.app_sip.c app_sip.tab.c PROPERTIES COMPILE_FLAGS "-I ${CMAKE_CURRENT_SOURCE_DIR}")
+
+# List of source files
+SET( DIAM_SIP_SRC
+	lex.app_sip.c
+	app_sip.tab.c
+	app_sip.tab.h
+	app_sip.c
+	app_sip.h
+	libapp_sip.c
+	md5.c
+	multimediaauth.c
+	registrationtermination.c
+	userauthorization.c
+	pushprofile.c
+	serverassignment.c
+	locationinfo.c
+	locationinfosl.c
+)
+
+# Compile as a module
+FD_ADD_EXTENSION(app_sip ${DIAM_SIP_SRC})
+
+TARGET_LINK_LIBRARIES(app_sip ${MySQL_LIBRARIES})
+
+SUBDIRS(tools)
+
+####
+## INSTALL section ##
+
+INSTALL(TARGETS app_sip
+	LIBRARY DESTINATION ${INSTALL_EXTENSIONS_SUFFIX}
+	COMPONENT freeDiameter-sip-server)
+
+INSTALL(FILES README TODO
+	DESTINATION /usr/share/doc/freeDiameter-sip-server
+	CONFIGURATIONS DebianPackage 
+	COMPONENT freeDiameter-sip-server)
diff --git a/extensions/app_sip/README b/extensions/app_sip/README
new file mode 100644
index 0000000..fbc5536
--- /dev/null
+++ b/extensions/app_sip/README
@@ -0,0 +1,39 @@
+/*********************************************************************************************************
+* Software License Agreement (BSD License)                                                               *
+* Author: Alexandre Westfahl <awestfahl@freediameter.net>						 *
+*													 *
+* Copyright (c) 2010, Alexandre Westfahl, Teraoka Laboratory (Keio University), and the WIDE Project. 	 *		
+*													 *
+* All rights reserved.											 *
+* 													 *
+* Redistribution and use of this software in source and binary forms, with or without modification, are  *
+* permitted provided that the following conditions are met:						 *
+* 													 *
+* * Redistributions of source code must retain the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer.										 *
+*    													 *
+* * Redistributions in binary form must reproduce the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer in the documentation and/or other						 *
+*   materials provided with the distribution.								 *
+* 													 *
+* * Neither the name of the Teraoka Laboratory nor the 							 *
+*   names of its contributors may be used to endorse or 						 *
+*   promote products derived from this software without 						 *
+*   specific prior written permission of Teraoka Laboratory 						 *
+*   													 *
+* 													 *
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED *
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
+* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR *
+* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 	 *
+* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 	 *
+* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR *
+* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF   *
+* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.								 *
+*********************************************************************************************************/
+
+
+Diameter-SIP Application will be fully compliant with RFC4740 (server part). However, there is still some work to do so it should be considered as experimental for now.
+
diff --git a/extensions/app_sip/TODO b/extensions/app_sip/TODO
new file mode 100644
index 0000000..661face
--- /dev/null
+++ b/extensions/app_sip/TODO
@@ -0,0 +1,57 @@
+/*********************************************************************************************************
+* Software License Agreement (BSD License)                                                               *
+* Author: Alexandre Westfahl <awestfahl@freediameter.net>						 *
+*													 *
+* Copyright (c) 2010, Alexandre Westfahl, Teraoka Laboratory (Keio University), and the WIDE Project. 	 *		
+*													 *
+* All rights reserved.											 *
+* 													 *
+* Redistribution and use of this software in source and binary forms, with or without modification, are  *
+* permitted provided that the following conditions are met:						 *
+* 													 *
+* * Redistributions of source code must retain the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer.										 *
+*    													 *
+* * Redistributions in binary form must reproduce the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer in the documentation and/or other						 *
+*   materials provided with the distribution.								 *
+* 													 *
+* * Neither the name of the Teraoka Laboratory nor the 							 *
+*   names of its contributors may be used to endorse or 						 *
+*   promote products derived from this software without 						 *
+*   specific prior written permission of Teraoka Laboratory 						 *
+*   													 *
+* 													 *
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED *
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
+* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR *
+* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 	 *
+* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 	 *
+* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR *
+* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF   *
+* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.								 *
+*********************************************************************************************************/
+
+Diameter-SIP implementation is still under development. 
+
+TODO List
+* add in malloc the size of char
+* when getting results from mysql, check lenght
+* sort capabilities in LIR/LIA
+* make functions for database access in MAR/MAA
+* order diamsip.h because it's becoming a mess ^^
+* replace password in MAR/MAA and libdiamsip from table to malloc char!
+* display errors of mysql
+* check that all user data inserted in requests are purified
+* add accounting server uri in database and diamsip
+* add mutex on mysql writing
+* check multithreading of mysql!
+* get destination host in database for RTR and PPR
+
+
+
+
+
+
diff --git a/extensions/app_sip/app_sip.c b/extensions/app_sip/app_sip.c
new file mode 100644
index 0000000..dfabdcc
--- /dev/null
+++ b/extensions/app_sip/app_sip.c
@@ -0,0 +1,252 @@
+/*********************************************************************************************************
+* Software License Agreement (BSD License)                                                               *
+* Author: Alexandre Westfahl <awestfahl@freediameter.net>						 *
+*													 *
+* Copyright (c) 2010, Alexandre Westfahl, Teraoka Laboratory (Keio University), and the WIDE Project. 	 *		
+*													 *
+* All rights reserved.											 *
+* 													 *
+* Redistribution and use of this software in source and binary forms, with or without modification, are  *
+* permitted provided that the following conditions are met:						 *
+* 													 *
+* * Redistributions of source code must retain the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer.										 *
+*    													 *
+* * Redistributions in binary form must reproduce the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer in the documentation and/or other						 *
+*   materials provided with the distribution.								 *
+* 													 *
+* * Neither the name of the Teraoka Laboratory nor the 							 *
+*   names of its contributors may be used to endorse or 						 *
+*   promote products derived from this software without 						 *
+*   specific prior written permission of Teraoka Laboratory 						 *
+*   													 *
+* 													 *
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED *
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
+* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR *
+* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 	 *
+* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 	 *
+* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR *
+* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF   *
+* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.								 *
+*********************************************************************************************************/
+#include "app_sip.h"
+
+//Diameter-SIP server
+struct disp_hdl * app_sip_MAR_hdl=NULL;
+struct disp_hdl * app_sip_LIR_hdl=NULL;
+struct disp_hdl * app_sip_UAR_hdl=NULL;
+struct disp_hdl * app_sip_SAR_hdl=NULL;
+struct disp_hdl * app_sip_PPA_hdl=NULL;
+struct disp_hdl * app_sip_RTA_hdl=NULL;
+
+//Suscriber Locator
+struct disp_hdl * app_sip_SL_LIR_hdl=NULL;
+
+
+
+struct disp_hdl * app_sip_default_hdl=NULL;
+struct session_handler * ds_sess_hdl;
+
+//configuration stucture
+struct as_conf * as_conf=NULL;
+static struct as_conf app_sip_conf;
+
+//dictionary of SIP
+struct app_sip_dict sip_dict;
+
+int app_sip_default_cb( struct msg ** msg, struct avp * avp, struct session * sess, void * opaque, enum disp_action * act)
+{
+	TRACE_ENTRY("%p %p %p %p %p", msg, avp, sess, opaque, act);
+	
+	return 0;
+}
+
+void dump_config()
+{
+	TRACE_DEBUG(FULL,"***Configuration of Diameter-SIP extension***");
+	TRACE_DEBUG(FULL,"# mode: *%d*",as_conf->mode);
+	TRACE_DEBUG(FULL,"# datasource: *%d*",as_conf->datasource);
+	TRACE_DEBUG(FULL,"# mysql_login: *%s*",as_conf->mysql_login);
+	TRACE_DEBUG(FULL,"# mysql_password: *%s*",as_conf->mysql_password);
+	TRACE_DEBUG(FULL,"# mysql_database: *%s*",as_conf->mysql_database);
+	TRACE_DEBUG(FULL,"# mysql_server: *%s*",as_conf->mysql_server);
+	TRACE_DEBUG(FULL,"# mysql_port: *%d*",as_conf->mysql_port);
+	TRACE_DEBUG(FULL,"# mysql_port: *%s*",as_conf->mysql_prefix);
+	TRACE_DEBUG(FULL,"***End of Diameter-SIP configuration extension***");
+}
+
+static int as_conf_init(void)
+{
+	as_conf=&app_sip_conf;
+	//memset(app_sip_conf, 0, sizeof(struct as_conf));
+	
+
+	return 0;
+}
+
+/* entry point */
+int as_entry(char * conffile)
+{
+	TRACE_ENTRY("%p", conffile);
+	
+	struct dict_object * app=NULL;
+	struct disp_when data;
+	pthread_t rtr_thread, ppr_thread;
+	
+	/* Initialize configuration */
+	CHECK_FCT( as_conf_init() );
+	
+	
+	//We parse the configuration file
+	if (conffile != NULL) {
+		CHECK_FCT( as_conf_handle(conffile) );
+	}
+	else
+	{
+		TRACE_DEBUG(INFO, "We need a configuration file for Diameter-SIP extension. See doc/ for an example.");
+	}
+	
+	//TODO: replace by configuration file!!
+	strcpy(as_conf->mysql_prefix,"as_");
+	
+	//We can dump the configuration extracted from app_sip.conf
+	//dump_config();
+	
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_APPLICATION, APPLICATION_BY_NAME, "Diameter Session Initiation Protocol (SIP) Application", &app, ENOENT) );
+	CHECK_FCT( fd_disp_app_support ( app, NULL, 1, 0 ) );
+	
+	
+	
+	//We set useful AVPs 
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Auth-Session-State", &sip_dict.Auth_Session_State, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Auth-Application-Id", &sip_dict.Auth_Application_Id, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Destination-Host", &sip_dict.Destination_Host, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Destination-Realm", &sip_dict.Destination_Realm, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Session-Id", &sip_dict.Session_Id, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Redirect-Host", &sip_dict.Redirect_Host, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Redirect-Host-Usage", &sip_dict.Redirect_Host_Usage, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "SIP-Auth-Data-Item", &sip_dict.SIP_Auth_Data_Item, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "SIP-Authorization", &sip_dict.SIP_Authorization, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "SIP-Authenticate", &sip_dict.SIP_Authenticate, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "SIP-Number-Auth-Items", &sip_dict.SIP_Number_Auth_Items, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "SIP-Authentication-Scheme", &sip_dict.SIP_Authentication_Scheme, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "SIP-Authentication-Info", &sip_dict.SIP_Authentication_Info, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "SIP-Server-URI", &sip_dict.SIP_Server_URI, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "SIP-Server-Capabilities", &sip_dict.SIP_Server_Capabilities, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "SIP-Mandatory-Capability", &sip_dict.SIP_Mandatory_Capability, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "SIP-Optional-Capability", &sip_dict.SIP_Optional_Capability, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "SIP-Method", &sip_dict.SIP_Method, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "SIP-AOR", &sip_dict.SIP_AOR, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "SIP-Deregistration-Reason", &sip_dict.SIP_Deregistration_Reason, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "SIP-Reason-Code", &sip_dict.SIP_Reason_Code, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "SIP-Reason-Info", &sip_dict.SIP_Reason_Info, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "SIP-Accounting-Information", &sip_dict.SIP_Accounting_Information, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "SIP-Accounting-Server-URI", &sip_dict.SIP_Accounting_Server_URI, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "SIP-Credit-Control-Server-URI", &sip_dict.SIP_Credit_Control_Server_URI, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "SIP-Server-Assignment-Type", &sip_dict.SIP_Server_Assignment_Type, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "SIP-Item-Number", &sip_dict.SIP_Item_Number, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "SIP-User-Authorization-Type", &sip_dict.SIP_User_Authorization_Type, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "SIP-Supported-User-Data-Type", &sip_dict.SIP_Supported_User_Data_Type, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "SIP-User-Data", &sip_dict.SIP_User_Data, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "SIP-User-Data-Type", &sip_dict.SIP_User_Data_Type, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "SIP-User-Data-Contents", &sip_dict.SIP_User_Data_Contents, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "SIP-User-Data-Already-Available", &sip_dict.SIP_User_Data_Already_Available, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "SIP-Visited-Network-Id", &sip_dict.SIP_Visited_Network_Id, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Digest-Realm", &sip_dict.Digest_Realm, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Digest-URI", &sip_dict.Digest_URI, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Digest-Nonce", &sip_dict.Digest_Nonce, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Digest-CNonce", &sip_dict.Digest_CNonce, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Digest-Method", &sip_dict.Digest_Method, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Digest-Nonce-Count", &sip_dict.Digest_Nonce_Count, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Digest-Realm", &sip_dict.Digest_Realm, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Digest-Response", &sip_dict.Digest_Response, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Digest-Response-Auth", &sip_dict.Digest_Response_Auth, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Digest-Username", &sip_dict.Digest_Username, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Digest-Algorithm", &sip_dict.Digest_Algorithm, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Digest-QoP", &sip_dict.Digest_QOP, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "User-Name", &sip_dict.User_Name, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Digest-HA1", &sip_dict.Digest_HA1, ENOENT) );
+	
+	
+	//Register Application
+	memset(&data, 0, sizeof(data));
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_APPLICATION, APPLICATION_BY_NAME, "Diameter Session Initiation Protocol (SIP) Application", &data.app, ENOENT) );
+	
+	if(as_conf->mode==1)
+	{
+	  // **Command Codes
+	  //MAR
+	  CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_COMMAND, CMD_BY_NAME, "Multimedia-Auth-Request", &data.command, ENOENT) );
+	  CHECK_FCT( fd_disp_register( app_sip_MAR_cb, DISP_HOW_CC, &data, NULL, &app_sip_MAR_hdl ) );
+	  //RTA
+	  CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_COMMAND, CMD_BY_NAME, "Registration-Termination-Answer", &data.command, ENOENT) );
+	  CHECK_FCT( fd_disp_register( app_sip_RTA_cb, DISP_HOW_CC, &data, NULL, &app_sip_RTA_hdl ) );
+	  //PPA
+	  CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_COMMAND, CMD_BY_NAME, "Push-Profile-Answer", &data.command, ENOENT) );
+	  CHECK_FCT( fd_disp_register( app_sip_PPA_cb, DISP_HOW_CC, &data, NULL, &app_sip_PPA_hdl ) );
+	  //LIR
+	  CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_COMMAND, CMD_BY_NAME, "Location-Info-Request", &data.command, ENOENT) );
+	  CHECK_FCT( fd_disp_register( app_sip_LIR_cb, DISP_HOW_CC, &data, NULL, &app_sip_LIR_hdl ) );
+	  //UAR
+	  CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_COMMAND, CMD_BY_NAME, "User-Authorization-Request", &data.command, ENOENT) );
+	  CHECK_FCT( fd_disp_register( app_sip_UAR_cb, DISP_HOW_CC, &data, NULL, &app_sip_UAR_hdl ) );
+	  //SAR
+	  CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_COMMAND, CMD_BY_NAME, "Server-Assignment-Request", &data.command, ENOENT) );
+	  CHECK_FCT( fd_disp_register( app_sip_SAR_cb, DISP_HOW_CC, &data, NULL, &app_sip_SAR_hdl ) );
+	}
+	if(as_conf->mode==2)
+	{
+	  //LIR
+	  CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_COMMAND, CMD_BY_NAME, "Location-Info-Request", &data.command, ENOENT) );
+	  CHECK_FCT( fd_disp_register( app_sip_SL_LIR_cb, DISP_HOW_CC, &data, NULL, &app_sip_SL_LIR_hdl ) );
+	}
+	//Callback for unexpected messages
+	CHECK_FCT( fd_disp_register( app_sip_default_cb, DISP_HOW_APPID, &data, NULL, &app_sip_default_hdl ) );
+	
+	
+	//We start database connection
+	if(start_mysql_connection())
+		return EINVAL;
+	
+	CHECK_FCT(fd_sess_handler_create(&ds_sess_hdl, (void *)free, NULL, NULL));
+	
+	//Creation of thread for Registration Termination	
+	if(pthread_create(&rtr_thread, NULL,rtr_socket, NULL))
+	{
+		TRACE_DEBUG(INFO,"Creation of thread failed, abort!");
+		return EINVAL;
+	}
+	//Creation of thread for Push Profile	
+	if(pthread_create(&ppr_thread, NULL,ppr_socket, NULL))
+	{
+		TRACE_DEBUG(INFO,"Creation of thread failed, abort!");
+		return EINVAL;
+	}
+	
+	
+	return 0;
+}
+
+//Cleanup callback
+void fd_ext_fini(void)
+{
+	//TODO:unregister other callbacks
+	
+	(void) fd_disp_unregister(&app_sip_MAR_hdl, NULL);
+	CHECK_FCT_DO( fd_sess_handler_destroy(&ds_sess_hdl, NULL),return);
+	
+	
+	//We close database connection
+	close_mysql_connection();
+	
+
+	
+	TRACE_ENTRY();
+	return ;
+}
+
+EXTENSION_ENTRY("app_sip", as_entry, "dict_sip");
diff --git a/extensions/app_sip/app_sip.h b/extensions/app_sip/app_sip.h
new file mode 100644
index 0000000..a6532b7
--- /dev/null
+++ b/extensions/app_sip/app_sip.h
@@ -0,0 +1,266 @@
+/*********************************************************************************************************
+* Software License Agreement (BSD License)                                                               *
+* Author: Alexandre Westfahl <awestfahl@freesipserver.net>						 *
+*													 *
+* Copyright (c) 2010, Alexandre Westfahl, Teraoka Laboratory (Keio University), and the WIDE Project. 	 *		
+*													 *
+* All rights reserved.											 *
+* 													 *
+* Redistribution and use of this software in source and binary forms, with or without modification, are  *
+* permitted provided that the following conditions are met:						 *
+* 													 *
+* * Redistributions of source code must retain the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer.										 *
+*    													 *
+* * Redistributions in binary form must reproduce the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer in the documentation and/or other						 *
+*   materials provided with the distribution.								 *
+* 													 *
+* * Neither the name of the Teraoka Laboratory nor the 							 *
+*   names of its contributors may be used to endorse or 						 *
+*   promote products derived from this software without 						 *
+*   specific prior written permission of Teraoka Laboratory 						 *
+*   													 *
+* 													 *
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED *
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
+* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR *
+* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 	 *
+* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 	 *
+* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR *
+* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF   *
+* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.								 *
+*********************************************************************************************************/
+#include <freeDiameter/extension.h>
+#include <sys/time.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <stdio.h>
+GCC_DIAG_OFF("-Wdeprecated-declarations")
+#include <gcrypt.h>
+GCC_DIAG_ON("-Wdeprecated-declarations")
+#include <string.h>
+#include <mysql.h>
+#include "md5.h"
+
+
+#define NONCE_SIZE 16
+#define DIGEST_LEN 16
+
+
+/* Mode for the extension */
+#define MODE_DSSERVER	0x1
+#define	MODE_SL	0x2
+
+//Redirect_Host_Usage
+#define ALL_USER	6
+
+/* The module configuration */
+struct as_conf {
+	int		mode;		/* default MODE_DSSERVER | MODE_SL */
+	enum {ASMYSQL} datasource; 
+	char * mysql_login;
+	char * mysql_password;
+	char * mysql_database;
+	char * mysql_server;
+	char mysql_prefix[10]; //default: as_
+	uint16_t  mysql_port; //if 0, default port will be used
+	uint16_t rtr_port;
+	uint16_t ppr_port;
+};
+extern struct as_conf * as_conf;
+
+/* Parse the configuration file */
+int as_conf_handle(char * conffile);
+
+
+extern MYSQL *conn;
+
+
+
+void calc_md5(char *buffer, char * data);
+void clear_digest(uint8_t * digest, char * readable_digest, int digestlength);
+struct avp_hdr * walk_digest(struct avp *avp, int avp_code);
+
+
+//MySQL part
+int start_mysql_connection();
+void request_mysql(char *query);
+void close_mysql_connection();
+int get_sipserver_uri(const unsigned char *sip_aor, const size_t sipaorlen, unsigned char ** sipserver_uri, size_t *sipserverurilen);
+int exist_username(const unsigned char *sip_aor, const size_t sipaorlen);
+int get_sipserver_cap(const unsigned char *sip_aor, const size_t sipaorlen, struct avp **capabilities);
+int get_password(const unsigned char *username, const size_t usernamelen, char *password);
+int check_sipaor(const unsigned char  *username, const size_t usernamelen, const char * sip_aor,const size_t sipaorlen);
+int add_user_datatype(const unsigned char  *sip_aor, const size_t sipaorlen,struct msg *message);
+int set_pending_flag(const unsigned char  *username, const size_t usernamelen);
+int clear_pending_flag(const unsigned char  *username, const size_t usernamelen);
+int set_real_sipserver_uri(const unsigned char  *username, const size_t usernamelen, const unsigned char *sipserver_uri,const size_t sipserverurilen);
+int set_sipserver_uri(const unsigned char  *username, const size_t usernamelen, const unsigned char *sipserver_uri,const size_t sipserverurilen);
+//int get_sipserver_uri(const unsigned char *sip_aor, const size_t sipaorlen, unsigned char ** sipserver_uri, size_t *sipserverurilen);
+int allow_roaming(const unsigned char  *username, const size_t usernamelen, const char * network,const size_t networklen);
+int get_diameter_uri(const unsigned char *sip_aor, const size_t sipaorlen, char ** diameter_uri, size_t *diameterurilen);
+//count functions
+int count_avp(struct msg * message, int code, int vendor);
+
+
+void DigestCalcHA1(char * pszAlg,char * pszUserName,char * pszRealm,char * pszPassword,char * pszNonce,char * pszCNonce,HASHHEX SessionKey);
+void DigestCalcResponse(HASHHEX HA1,char * pszNonce,char * pszNonceCount,char * pszCNonce,char * pszQop,char * pszMethod,char * pszDigestUri,HASHHEX HEntity,HASHHEX Response);
+void DigestCalcResponseAuth(HASHHEX HA1,char * pszNonce,char * pszNonceCount,char * pszCNonce,char * pszQop,char * pszMethod,char * pszDigestUri,HASHHEX HEntity,HASHHEX Response);
+
+int fd_avp_search_avp ( struct avp * groupedavp, struct dict_object * what, struct avp ** avp );
+
+//thread procedure
+void *rtr_socket(void *);
+void *ppr_socket(void *);
+
+struct rtrsipaor
+{
+	char username[200];
+	char sip_aor1[200];
+	char sip_aor2[200];
+	char sip_aor3[200];
+	char strreason[200];
+	char desthost[200];
+	int reason;
+};
+struct pprsipaor
+{
+	char username[200];
+	char datatype1[255];
+	char datatype2[255];
+	char datatype3[255];
+	int accounting;
+};
+
+int app_sip_RTR_cb(struct rtrsipaor *structure);
+int app_sip_PPR_cb(struct pprsipaor *structure);
+
+
+int ds_entry();
+void fd_ext_fini(void);
+int app_sip_default_cb( struct msg ** msg, struct avp * avp, struct session * sess, void * opaque, enum disp_action * act);
+int app_sip_MAR_cb( struct msg ** msg, struct avp * avp, struct session * sess, void * opaque, enum disp_action * act);
+int app_sip_RTA_cb( struct msg ** msg, struct avp * avp, struct session * sess, void * opaque, enum disp_action * act);
+int app_sip_PPA_cb( struct msg ** msg, struct avp * avp, struct session * sess, void * opaque, enum disp_action * act);
+int app_sip_LIR_cb( struct msg ** msg, struct avp * avp, struct session * sess, void * opaque, enum disp_action * act);
+int app_sip_UAR_cb( struct msg ** msg, struct avp * avp, struct session * sess, void * opaque, enum disp_action * act);
+int app_sip_SAR_cb( struct msg ** msg, struct avp * avp, struct session * sess, void * opaque, enum disp_action * act);
+
+//Suscriber Locator
+int app_sip_SL_LIR_cb( struct msg ** msg, struct avp * paramavp, struct session * sess, void * opaque, enum disp_action * act);
+//int app_sip_SL_SAR_cb( struct msg ** msg, struct avp * paramavp, struct session * sess, void * opaque, enum disp_action * act);
+
+#define SQL_GETPASSWORD "SELECT `password` FROM ds_users WHERE `username` ='%s'"
+#define SQL_GETPASSWORD_LEN sizeof(SQL_GETPASSWORD)-2
+
+//username by SIP-AOR
+#define SQL_GETUSERNAME  "SELECT `username` FROM ds_users, ds_sip_aor WHERE `sip_aor` ='%s' AND `ds_sip_aor`.`id_user` = `ds_users`.`id_user`"
+#define SQL_GETUSERNAME_LEN sizeof(SQL_GETUSERNAME)-2
+
+//sip server uri by username
+#define SQL_GETSIPURI  "SELECT `sip_server_uri` FROM ds_users WHERE `username` ='%s'"
+#define SQL_GETSIPURI_LEN sizeof(SQL_GETSIPURI)-2
+
+//sip server uri by SIP-AOR
+#define SQL_GETSIPSERURI  "SELECT `ds_sip_aor`.`sip_server_uri` FROM ds_users, ds_sip_aor WHERE `sip_aor` ='%s' AND `ds_sip_aor`.`id_user` = `ds_users`.`id_user`"
+#define SQL_GETSIPSERURI_LEN sizeof(SQL_GETSIPSERURI)-2
+
+//sip capabilities for a SIP-AOR
+#define SQL_GETSIPSERCAP  "SELECT `compulsory`,`id_service` FROM ds_user_services, ds_sip_aor WHERE `sip_aor` ='%s' AND `ds_sip_aor`.`id_user` = `ds_user_services`.`id_user`"
+#define SQL_GETSIPSERCAP_LEN sizeof(SQL_GETSIPSERCAP)-2
+
+//user data for a user data supported
+#define SQL_GETSIPDATA  "SELECT `label_type`,`data` FROM ds_sip_aor, ds_user_data, ds_data_types WHERE `sip_aor` ='%s' AND `ds_sip_aor`.`id_sip_aor` = `ds_user_data`.`id_sip_aor` AND `ds_data_types`.`id_data_type`=`ds_user_data`.`id_data_type`"
+#define SQL_GETSIPDATA_LEN sizeof(SQL_GETSIPDATA)-2
+
+#define SQL_GETDIAMURI "SELECT `sipserver_uri` FROM ds_sip_aor_map WHERE `sip_aor` ='%s'"
+#define SQL_GETDIAMURI_LEN sizeof(SQL_GETDIAMURI)-2
+
+//networks for this user
+#define SQL_GETUSERNET "SELECT `label_network` FROM ds_users, ds_user_networks, ds_networks WHERE `ds_users`.`username` ='%s' AND `ds_user_networks`.`id_user` = `ds_users`.`id_user` AND `ds_user_networks`.`id_network` = `ds_networks`.`id_network`"
+#define SQL_GETUSERNET_LEN sizeof(SQL_GETUSERNET)-2
+
+#define SQL_SETSIPURI "UPDATE ds_users SET `temp_sip_server_uri`='%s' WHERE `username` ='%s'"
+#define SQL_SETSIPURI_LEN sizeof(SQL_SETSIPURI)-4
+
+//TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO 
+#define SQL_RMSIPURI "UPDATE ds_users SET `temp_sip_server_uri`='', `sip_server_uri`='' WHERE `id_user` ='%s'"
+#define SQL_RMSIPURI_LEN sizeof(SQL_RMSIPURI)-2
+//TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO 
+
+#define SQL_SETREALSIPURI "UPDATE ds_users SET `sip_server_uri`='%s' WHERE `username` ='%s'"
+#define SQL_SETREALSIPURI_LEN sizeof(SQL_SETREALSIPURI)-4
+
+#define SQL_SETFLAG "UPDATE ds_users SET `authentication_pending`=1 WHERE `username` ='%s'"
+#define SQL_SETFLAG_LEN sizeof(SQL_SETFLAG)-2
+
+#define SQL_CLEARFLAG "UPDATE ds_users SET `authentication_pending`=0, `registrated`=1 WHERE `username` ='%s'"
+#define SQL_CLEARFLAG_LEN sizeof(SQL_CLEARFLAG)-2
+
+#define SQL_GETSIPAOR "SELECT `sip_aor` FROM `ds_sip_aor`, `ds_users` WHERE `ds_sip_aor`.`id_user` = `ds_users`.`id_user` AND `ds_users`.`username` = '%s'"
+#define SQL_GETSIPAOR_LEN sizeof(SQL_GETSIPAOR)-2
+
+//#define SQL_CLEARFLAG "UPDATE ds_users SET `authentication_pending`=0 WHERE `username` ='%s'"
+//#define SQL_CLEARFLAG_LEN 67
+
+extern struct session_handler * ds_sess_hdl;
+
+//AVP code
+#define CODE_SIP_USER_DATA_TYPE	388
+#define CODE_SIP_AOR	122
+
+//Storage for some useful AVPs
+struct app_sip_dict{
+	struct dict_object * Auth_Session_State;
+	struct dict_object * Auth_Application_Id;
+	struct dict_object * Destination_Host;
+	struct dict_object * Destination_Realm;
+	struct dict_object * User_Name;
+	struct dict_object * Session_Id;
+	struct dict_object * Redirect_Host;
+	struct dict_object * Redirect_Host_Usage;
+	struct dict_object * SIP_Auth_Data_Item;
+	struct dict_object * SIP_Accounting_Information;
+	struct dict_object * SIP_Accounting_Server_URI;
+	struct dict_object * SIP_Credit_Control_Server_URI;
+	struct dict_object * SIP_Server_Assignment_Type;
+	struct dict_object * SIP_Item_Number;
+	struct dict_object * SIP_User_Authorization_Type;
+	struct dict_object * SIP_Supported_User_Data_Type;
+	struct dict_object * SIP_User_Data;
+	struct dict_object * SIP_User_Data_Type;
+	struct dict_object * SIP_User_Data_Contents;
+	struct dict_object * SIP_User_Data_Already_Available;
+	struct dict_object * SIP_Visited_Network_Id;
+	struct dict_object * SIP_Authorization;
+	struct dict_object * SIP_Authenticate;
+	struct dict_object * SIP_Number_Auth_Items;	
+	struct dict_object * SIP_Authentication_Scheme;
+	struct dict_object * SIP_Authentication_Info;	
+	struct dict_object * SIP_Server_URI;
+	struct dict_object * SIP_Server_Capabilities;
+	struct dict_object * SIP_Mandatory_Capability;
+	struct dict_object * SIP_Optional_Capability;
+	struct dict_object * SIP_Method;
+	struct dict_object * SIP_AOR;
+	struct dict_object * SIP_Deregistration_Reason;
+	struct dict_object * SIP_Reason_Code;
+	struct dict_object * SIP_Reason_Info;
+	struct dict_object * Digest_URI;		
+	struct dict_object * Digest_Nonce;
+	struct dict_object * Digest_Nonce_Count;
+	struct dict_object * Digest_CNonce;		
+	struct dict_object * Digest_Realm;		
+	struct dict_object * Digest_Response;	
+	struct dict_object * Digest_Response_Auth;	
+	struct dict_object * Digest_Username;	
+	struct dict_object * Digest_Method;
+	struct dict_object * Digest_QOP;	
+	struct dict_object * Digest_Algorithm;
+	struct dict_object * Digest_HA1;
+};
+
+extern  struct app_sip_dict  sip_dict;
diff --git a/extensions/app_sip/app_sip.l b/extensions/app_sip/app_sip.l
new file mode 100644
index 0000000..f8e9044
--- /dev/null
+++ b/extensions/app_sip/app_sip.l
@@ -0,0 +1,162 @@
+/*********************************************************************************************************
+* Software License Agreement (BSD License)                                                               *
+* Author: Alexandre Westfahl <awestfahl@freediameter.net>						 *
+*													 *
+* Copyright (c) 2010, Alexandre Westfahl, Teraoka Laboratory (Keio University), and the WIDE Project. 	 *		
+*													 *
+* All rights reserved.											 *
+* Based on ta_conf.l (Sebastien Decugis <sdecugis@freediameter.net>)					 *
+* 													 *
+* Redistribution and use of this software in source and binary forms, with or without modification, are  *
+* permitted provided that the following conditions are met:						 *
+* 													 *
+* * Redistributions of source code must retain the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer.										 *
+*    													 *
+* * Redistributions in binary form must reproduce the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer in the documentation and/or other						 *
+*   materials provided with the distribution.								 *
+* 													 *
+* * Neither the name of the Teraoka Laboratory nor the 							 *
+*   names of its contributors may be used to endorse or 						 *
+*   promote products derived from this software without 						 *
+*   specific prior written permission of Teraoka Laboratory 						 *
+*   													 *
+* 													 *
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED *
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
+* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR *
+* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 	 *
+* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 	 *
+* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR *
+* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF   *
+* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.								 *
+*********************************************************************************************************/
+
+
+
+%{
+#include "app_sip.h"
+/* Include yacc tokens definitions */
+#include "app_sip.tab.h"
+
+/* Update the column information */
+#define YY_USER_ACTION { 						\
+	yylloc->first_column = yylloc->last_column + 1; 		\
+	yylloc->last_column = yylloc->first_column + yyleng - 1;	\
+}
+
+/* Avoid warning with newer flex */
+#define YY_NO_INPUT
+
+%}
+
+%option bison-bridge bison-locations
+%option noyywrap
+%option nounput
+
+%%
+
+	/* Update the line count */
+\n			{
+				yylloc->first_line++; 
+				yylloc->last_line++; 
+				yylloc->last_column=0; 
+			}
+	 
+	/* Eat all spaces but not new lines */
+([[:space:]]{-}[\n])+	;
+	/* Eat all comments */
+#.*$			;
+
+	/* Recognize any integer */
+[-]?[[:digit:]]+		{
+				/* Convert this to an integer value */
+				int ret=0;
+				ret = sscanf(yytext, "%i", &yylval->integer);
+				if (ret != 1) {
+					/* No matching: an error occurred */
+					fd_log_debug("Unable to convert the value '%s' to a valid number: %s", yytext, strerror(errno));
+					return LEX_ERROR; /* trig an error in yacc parser */
+					/* Maybe we could REJECT instead of failing here? */
+				}
+				return INTEGER;
+			}
+
+	/* Recognize quoted strings -- we do not support escaped \" in the string currently. */
+\"[^\"]+\"		{
+				/* Match a quoted string. Let's be very permissive. */
+				yylval->string = strdup(yytext+1);
+				if (!yylval->string) {
+					fd_log_debug("Unable to copy the string '%s': %s", yytext, strerror(errno));
+					TRACE_DEBUG(INFO, "strdup failed");
+					return LEX_ERROR; /* trig an error in yacc parser */
+				}
+				yylval->string[strlen(yytext) - 2] = '\0';
+				return QSTRING;
+			}
+
+
+
+	/* Recognize the tokens */	
+(?i:"mysql_login")	{
+				return ASMYSQL_LOGIN;
+			}
+
+(?i:"mysql_password")		{
+				return ASMYSQL_PASSWORD;
+			}
+
+(?i:"mysql_database")		{
+				return ASMYSQL_DATABASE;
+			}
+
+(?i:"mysql_server")		{
+				return ASMYSQL_SERVER;
+			}
+
+(?i:"mysql_port")		{
+				return ASMYSQL_PORT;
+			}
+(?i:"rtr_port")		{
+				return RTR_PORT;
+			}
+(?i:"ppr_port")		{
+				return PPR_PORT;
+			}
+(?i:"mode")		{
+				return MODE;
+			}
+
+(?i:"datasource")		{
+				return DATASOURCE;
+			}
+			
+(?i:"mysql")		{
+				yylval->integer = ASMYSQL;
+				return INTEGER;
+			}
+(?i:"dsserver")		{
+				yylval->integer = MODE_DSSERVER;
+				return INTEGER;
+			}
+
+(?i:"sl")	{
+				yylval->integer = MODE_SL;
+				return INTEGER;
+			}
+
+
+			
+	/* Valid single characters for yyparse */
+[=;]			{ return yytext[0]; }
+
+	/* Unrecognized sequence, if it did not match any previous pattern */
+[^[:space:]"*=>;\n]+	{ 
+				fd_log_debug("Unrecognized text on line %d col %d: '%s'.", yylloc->first_line, yylloc->first_column, yytext);
+			 	return LEX_ERROR; 
+			}
+
+%%
diff --git a/extensions/app_sip/app_sip.y b/extensions/app_sip/app_sip.y
new file mode 100644
index 0000000..6c288a4
--- /dev/null
+++ b/extensions/app_sip/app_sip.y
@@ -0,0 +1,208 @@
+/*********************************************************************************************************
+* Software License Agreement (BSD License)                                                               *
+* Author: Alexandre Westfahl <awestfahl@freediameter.net>						 *
+*													 *
+* Copyright (c) 2010, Alexandre Westfahl, Teraoka Laboratory (Keio University), and the WIDE Project. 	 *		
+*													 *
+* All rights reserved.											 *
+* Based on ta_conf.y  (Sebastien Decugis <sdecugis@freediameter.net>)					 *
+* 													 *
+* Redistribution and use of this software in source and binary forms, with or without modification, are  *
+* permitted provided that the following conditions are met:						 *
+* 													 *
+* * Redistributions of source code must retain the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer.										 *
+*    													 *
+* * Redistributions in binary form must reproduce the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer in the documentation and/or other						 *
+*   materials provided with the distribution.								 *
+* 													 *
+* * Neither the name of the Teraoka Laboratory nor the 							 *
+*   names of its contributors may be used to endorse or 						 *
+*   promote products derived from this software without 						 *
+*   specific prior written permission of Teraoka Laboratory 						 *
+*   													 *
+* 													 *
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED *
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
+* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR *
+* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 	 *
+* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 	 *
+* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR *
+* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF   *
+* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.								 *
+*********************************************************************************************************/
+
+
+
+/* For development only : */
+%debug 
+%error-verbose
+
+/* The parser receives the configuration file filename as parameter */
+%parse-param {char * conffile}
+
+/* Keep track of location */
+%locations 
+%pure-parser
+
+%{
+#include "app_sip.h"
+#include "app_sip.tab.h"	/* bison is not smart enough to define the YYLTYPE before including this code, so... */
+
+#include <string.h>
+#include <errno.h>
+
+/* Forward declaration */
+int yyparse(char * conffile);
+
+/* Parse the configuration file */
+int as_conf_handle(char * conffile)
+{
+	extern FILE * app_sipin;
+	int ret;
+	
+	TRACE_ENTRY("%p", conffile);
+	
+	TRACE_DEBUG (FULL, "Parsing configuration file: %s...", conffile);
+	
+	app_sipin = fopen(conffile, "r");
+	if (app_sipin == NULL) {
+		ret = errno;
+		fd_log_debug("Unable to open extension configuration file %s for reading: %s", conffile, strerror(ret));
+		TRACE_DEBUG (INFO, "Error occurred, message logged -- configuration file.");
+		return ret;
+	}
+
+	ret = yyparse(conffile);
+
+	fclose(app_sipin);
+
+	if (ret != 0) {
+		TRACE_DEBUG (INFO, "Unable to parse the configuration file.");
+		return EINVAL;
+	}
+	
+	return 0;
+}
+
+/* The Lex parser prototype */
+int app_siplex(YYSTYPE *lvalp, YYLTYPE *llocp);
+
+/* Function to report the errors */
+void yyerror (YYLTYPE *ploc, char * conffile, char const *s)
+{
+	TRACE_DEBUG(INFO, "Error in configuration parsing");
+	
+	if (ploc->first_line != ploc->last_line)
+		fd_log_debug("%s:%d.%d-%d.%d : %s", conffile, ploc->first_line, ploc->first_column, ploc->last_line, ploc->last_column, s);
+	else if (ploc->first_column != ploc->last_column)
+		fd_log_debug("%s:%d.%d-%d : %s", conffile, ploc->first_line, ploc->first_column, ploc->last_column, s);
+	else
+		fd_log_debug("%s:%d.%d : %s", conffile, ploc->first_line, ploc->first_column, s);
+}
+
+%}
+
+/* Values returned by lex for token */
+%union {
+	char 		*string;	/* The string is allocated by strdup in lex.*/
+	int		 integer;		/* Store integer values */
+}
+
+/* In case of error in the lexical analysis */
+%token 		LEX_ERROR
+
+/* Key words */
+%token 		MODE
+%token 		DATASOURCE
+%token 		ASMYSQL_LOGIN
+%token 		ASMYSQL_PASSWORD
+%token 		ASMYSQL_DATABASE
+%token 		ASMYSQL_SERVER
+%token 		ASMYSQL_PORT
+%token 		RTR_PORT
+%token 		PPR_PORT
+
+/* Tokens and types for routing table definition */
+/* A (de)quoted string (malloc'd in lex parser; it must be freed after use) */
+%token <string>	QSTRING
+
+/* An integer value */
+%token <integer> INTEGER
+
+
+
+/* -------------------------------------- */
+%%
+
+	/* The grammar definition */
+conffile:		/* empty grammar is OK */
+			| conffile mode
+			| conffile datasource
+			| conffile mysql_login
+			| conffile mysql_password
+			| conffile mysql_database
+			| conffile mysql_server
+			| conffile mysql_port
+			| conffile rtr_port
+			| conffile ppr_port
+			;
+
+mode:			MODE '=' INTEGER ';'
+			{
+				as_conf->mode = $3;
+			}
+			;
+
+datasource:			DATASOURCE '=' INTEGER ';'
+			{
+				as_conf->datasource = $3;
+			}
+			;
+
+mysql_login:			ASMYSQL_LOGIN '=' QSTRING ';'
+			{
+				free(as_conf->mysql_login);
+				as_conf->mysql_login = $3;
+			}
+			;
+
+mysql_password:			ASMYSQL_PASSWORD '=' QSTRING ';'
+			{
+				free(as_conf->mysql_password);
+				as_conf->mysql_password = $3;
+			}
+			;
+
+mysql_database:			ASMYSQL_DATABASE '=' QSTRING ';'
+			{
+				free(as_conf->mysql_database);
+				as_conf->mysql_database = $3;
+			}
+			;
+
+mysql_server:		ASMYSQL_SERVER '=' QSTRING ';'
+			{
+				free(as_conf->mysql_server);
+				as_conf->mysql_server = $3;
+			}
+			;
+
+mysql_port:		ASMYSQL_PORT '=' INTEGER ';'
+			{
+				as_conf->mysql_port = (uint16_t)$3;
+			}
+			;
+rtr_port:		RTR_PORT '=' INTEGER ';'
+			{
+				as_conf->rtr_port = (uint16_t)$3;
+			}
+			;
+ppr_port:		PPR_PORT '=' INTEGER ';'
+			{
+				as_conf->ppr_port = (uint16_t)$3;
+			}
+			;
diff --git a/extensions/app_sip/libapp_sip.c b/extensions/app_sip/libapp_sip.c
new file mode 100644
index 0000000..6442ff4
--- /dev/null
+++ b/extensions/app_sip/libapp_sip.c
@@ -0,0 +1,1078 @@
+/*********************************************************************************************************
+* Software License Agreement (BSD License)                                                               *
+* Author: Alexandre Westfahl <awestfahl@freediameter.net>						 *
+*													 *
+* Copyright (c) 2010, Alexandre Westfahl, Teraoka Laboratory (Keio University), and the WIDE Project. 	 *		
+*													 *
+* All rights reserved.											 *
+* 													 *
+* Redistribution and use of this software in source and binary forms, with or without modification, are  *
+* permitted provided that the following conditions are met:						 *
+* 													 *
+* * Redistributions of source code must retain the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer.										 *
+*    													 *
+* * Redistributions in binary form must reproduce the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer in the documentation and/or other						 *
+*   materials provided with the distribution.								 *
+* 													 *
+* * Neither the name of the Teraoka Laboratory nor the 							 *
+*   names of its contributors may be used to endorse or 						 *
+*   promote products derived from this software without 						 *
+*   specific prior written permission of Teraoka Laboratory 						 *
+*   													 *
+* 													 *
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED *
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
+* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR *
+* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 	 *
+* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 	 *
+* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR *
+* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF   *
+* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.								 *
+*********************************************************************************************************/
+//#include <mysql.h>
+#include "app_sip.h"
+
+MYSQL *conn;
+
+void clear_digest(uint8_t * digest, char * readable_digest, int digestlength)
+{
+	int i=0;
+	for(i=0;i<digestlength * 2;i++)
+		sprintf(&readable_digest[2 * i], "%2.2hhx", digest[i]);
+	readable_digest[2 * digestlength]='\0';
+	
+	return;
+}
+
+// You must create a table like this "char  clearDigest[DIGEST_LEN*2+1];"
+void calc_md5(char *clearDigest, char * data)
+{
+	gcry_md_hd_t md5;
+	uint8_t * binDigest=NULL;
+	
+	CHECK_MALLOC_DO(binDigest=malloc(DIGEST_LEN),return);
+	
+	gcry_md_open(&md5,GCRY_MD_MD5, 0); 
+	gcry_md_write(md5, (char *)data, sizeof(data));
+	memcpy(binDigest, gcry_md_read(md5,  GCRY_MD_MD5),gcry_md_get_algo_dlen(GCRY_MD_MD5));
+	gcry_md_close(md5);
+	
+	clear_digest(binDigest, clearDigest, DIGEST_LEN);
+	free(binDigest);
+	return;
+}
+
+
+/* Search a given AVP model in an AVP (extracted from libfreediameter/message.c ) */
+int fd_avp_search_avp ( struct avp * groupedavp, struct dict_object * what, struct avp ** avp )
+{
+	struct avp * nextavp;
+	struct avp_hdr * nextavphdr;
+	struct dict_avp_data 	dictdata;
+	
+	
+	TRACE_ENTRY("%p %p %p", groupedavp, what, avp);
+	
+	CHECK_FCT(  fd_dict_getval(what, &dictdata)  );
+	
+	// Loop only in the group AVP 
+	CHECK_FCT(  fd_msg_browse(groupedavp, MSG_BRW_FIRST_CHILD, (void *)&nextavp, NULL)  );
+	CHECK_FCT( fd_msg_avp_hdr( nextavp, &nextavphdr )  );
+	
+	while (nextavphdr) {
+		
+		if ( (nextavphdr->avp_code   == dictdata.avp_code) && (nextavphdr->avp_vendor == dictdata.avp_vendor) ) // always 0 if no Vendor flag
+		{
+			break;
+		}
+		
+		// Otherwise move to next AVP in the grouped AVP 
+		CHECK_FCT( fd_msg_browse(nextavp, MSG_BRW_NEXT, (void *)&nextavp, NULL) );
+		
+		if(nextavp!=NULL)
+		{
+			CHECK_FCT( fd_msg_avp_hdr( nextavp, &nextavphdr )  );
+		}
+		else
+			nextavphdr=NULL;
+	}
+	if (avp)
+		*avp = nextavp;
+	
+	if (avp && nextavp) {
+		struct dictionary * dict;
+		CHECK_FCT( fd_dict_getdict( what, &dict) );
+		CHECK_FCT_DO( fd_msg_parse_dict( nextavp, dict, NULL ),  );
+	}
+	
+	if (avp || nextavp)
+		return 0;
+	else
+		return ENOENT;
+}
+struct avp_hdr *walk_digest(struct avp *avp, int avp_code)
+{
+	struct avp_hdr *temphdr=NULL;
+	CHECK_FCT_DO(fd_msg_browse ( avp, MSG_BRW_WALK, &avp, NULL),return NULL);
+	
+	while(avp!=NULL)
+	{
+		
+		CHECK_FCT_DO( fd_msg_avp_hdr( avp,&temphdr ),return NULL);
+
+		if(temphdr->avp_code==avp_code)
+		{
+			//We found the AVP so we set avp to NULL to exit the loop
+			avp=NULL;
+			return temphdr;
+			
+		}
+		else if(temphdr->avp_code==380)//SIP-Authorization AVP
+		{
+			//We didn't found the AVP but we finished browsing the Authentication AVP
+			avp=NULL;
+			temphdr=NULL;
+			
+			return temphdr;
+		}
+		else
+		{
+			CHECK_FCT_DO(fd_msg_browse ( avp, MSG_BRW_WALK, &avp, NULL),return NULL);
+			temphdr=NULL;
+			
+		}
+	}
+	
+	return temphdr;
+}
+
+int start_mysql_connection()
+{
+	conn = mysql_init(NULL);
+	
+	mysql_options(conn, MYSQL_OPT_RECONNECT, "true");
+	
+	if (!mysql_real_connect(conn, as_conf->mysql_server,as_conf->mysql_login, as_conf->mysql_password, as_conf->mysql_database, as_conf->mysql_port, NULL, 0)) 
+	{//TODO: display error from mysql
+		TRACE_DEBUG(INFO,"Unable to connect to database (%s) with login:%s",as_conf->mysql_database,as_conf->mysql_login);
+		return 1;
+	}
+	return 0;
+	
+}
+
+
+void request_mysql(char *query)
+{
+	//We check if the connection is still up
+	mysql_ping(conn);
+	
+	if (mysql_query(conn, query)) 
+	{
+		TRACE_DEBUG(INFO,"Query %s failed", query);
+		
+	}
+	
+}
+
+void close_mysql_connection()
+{
+	mysql_close(conn);
+	
+}
+
+//If password is null, we just verify this user exist
+//We don't need the password length because it is a table'
+int get_password(const unsigned char *username, const size_t usernamelen, char *password)
+{
+	CHECK_PARAMS(username && usernamelen);
+	
+	int not_found=2;
+	size_t querylen, usernamepurelen;
+	char *query, *username_pure;
+	
+	switch(as_conf->datasource)
+	{
+		//MySQL
+		case ASMYSQL:
+			//We allocate the double size of username because at worst it can be all quotes
+			username_pure=malloc(usernamelen*2+1);
+			//We purify username not to have forbidden characters
+			usernamepurelen=mysql_real_escape_string(conn, username_pure, (const char *)username, usernamelen);
+			
+			//We copy username in query
+			querylen=SQL_GETPASSWORD_LEN + usernamepurelen;
+			query = malloc(querylen+2);
+			snprintf(query, querylen+1, SQL_GETPASSWORD, username_pure);
+			
+			MYSQL_RES *res;
+			MYSQL_ROW row;
+			
+			//We make the query	
+			request_mysql(query);
+			res=mysql_use_result(conn);
+			if(res==NULL)
+			{
+				if(password!=NULL)
+					password[0]='\0';
+				free(query);
+				return 2;
+			}
+			
+			
+			
+			while ((row = mysql_fetch_row(res)) != NULL)
+			{
+				if(strlen(row[0])>0)
+				{
+					if(password!=NULL)
+						strcpy(password,row[0]);
+					
+					not_found=0;
+					break;
+				}
+			}
+			mysql_free_result(res);
+			free(query);
+		break;
+	}
+	return not_found;
+}
+
+int check_sipaor(const unsigned char  *username, const size_t usernamelen, const char * sip_aor,const size_t sipaorlen)
+{
+	CHECK_PARAMS(username && usernamelen && sip_aor && sipaorlen);
+	
+	int not_found=2;
+	size_t querylen, usernamepurelen;
+	char *query, *username_pure;
+	
+	switch(as_conf->datasource)
+	{
+		//MySQL
+		case ASMYSQL:
+			//We allocate the double size of username because at worst it can be all quotes
+			username_pure=malloc(usernamelen*2+1);
+			//We purify username not to have forbidden characters
+			usernamepurelen=mysql_real_escape_string(conn, username_pure, (const char *)username, usernamelen);
+	
+			//We get the list of AOR owned by this user
+			querylen=SQL_GETSIPAOR_LEN + usernamepurelen;
+			query = malloc(querylen+2);
+			snprintf(query, querylen+1, SQL_GETSIPAOR, username_pure);
+			
+			MYSQL_RES *res;
+			MYSQL_ROW row;
+			
+			//We make the query
+			request_mysql(query);
+			res=mysql_use_result(conn);
+			if(res==NULL)
+			{
+				free(query);
+				return 2;
+			}
+			
+			
+			not_found=1;
+			while ((row = mysql_fetch_row(res)) != NULL)
+			{
+				if(strncmp((const char *)sip_aor,row[0],sipaorlen)==0)
+				{
+					not_found=0;
+					break;
+				}
+			}
+			mysql_free_result(res);
+			free(query);
+		break;
+	}
+	return not_found;
+}
+
+int get_diameter_uri(const unsigned char *sip_aor, const size_t sipaorlen, char ** diameter_uri, size_t *diameterurilen)
+{
+	CHECK_PARAMS(sip_aor && sipaorlen);
+
+	size_t querylen, sipaorpurelen;
+	char *query, *sipaor_pure;
+	int not_found=2;
+
+
+
+
+	//a sip aor must begin by "sip:" or "sips:" so it must at least be longer than 4 chars
+	if(sipaorlen<5)
+		return 2;
+
+	//NOTE: each method has to purify sip_aor itself. You must remove quotes or special chars for security
+	switch(as_conf->datasource)
+	{
+		//MySQL
+		case ASMYSQL:
+
+			querylen=SQL_GETDIAMURI_LEN + sipaorlen;
+
+			
+			//We allocate the double size of SIP-URI because at worst it can be all quotes
+			CHECK_MALLOC(sipaor_pure=malloc(sipaorlen*2+1));
+			//We purify SIP-URI not to have forbidden characters
+			sipaorpurelen=mysql_real_escape_string(conn, sipaor_pure, (const char *)sip_aor, sipaorlen);
+			
+			
+			query = malloc(querylen+sipaorpurelen+ 2);
+			snprintf(query, querylen+1, SQL_GETDIAMURI, sipaor_pure);
+			
+			MYSQL_RES *res;
+			MYSQL_ROW row;
+			
+
+			//We make the query	
+			request_mysql(query);
+			res=mysql_use_result(conn);
+			if(res==NULL)
+			{
+				//We couldn't make the request
+				diameter_uri=NULL;
+				return 2;
+			}
+			
+			while ((row = mysql_fetch_row(res)) != NULL)
+			{
+				*diameterurilen=strlen(row[0]);
+				if(*diameterurilen>0)
+				{
+					CHECK_MALLOC(*diameter_uri=malloc(*diameterurilen+1));
+					strcpy(*diameter_uri,row[0]);
+					not_found=0;
+					break;
+				}
+			}
+			mysql_free_result(res);
+			free(query);
+			free(sipaor_pure);
+		break;
+      
+    default:
+      
+      //We must never go here, if so, we must stop diameter_sip
+      diameter_uri=NULL;
+      return 2;
+      
+      break;
+  }
+  
+  //0 if it was found
+  return not_found;
+  
+}
+
+
+int exist_username(const unsigned char *sip_aor, const size_t sipaorlen)
+{
+	CHECK_PARAMS(sip_aor && sipaorlen);
+	
+	size_t querylen, sipaorpurelen;
+	char *query, *sipaor_pure;
+	int not_found=1;
+	
+	//a sip aor must begin by "sip:" or "sips:" so it must at least be longer than 4 chars
+	if(sipaorlen<5)
+		return 2;
+	
+	//NOTE: each method has to purify sip_aor itself. You must remove quotes or special chars for security
+	
+	switch(as_conf->datasource)
+	{
+		//MySQL
+		case ASMYSQL:
+			
+			querylen=SQL_GETUSERNAME_LEN + sipaorlen;
+			
+			
+			//We allocate the double size of SIP-URI because at worst it can be all quotes
+			CHECK_MALLOC(sipaor_pure=malloc(sipaorlen*2+1));
+			//We purify SIP-URI not to have forbidden characters
+			sipaorpurelen=mysql_real_escape_string(conn, sipaor_pure, (const char *)sip_aor, sipaorlen);
+			
+			
+			query = malloc(querylen+sipaorpurelen+ 2);
+			snprintf(query, querylen+1, SQL_GETUSERNAME, sipaor_pure);
+			
+			MYSQL_RES *res;
+			MYSQL_ROW row;
+			
+			
+			//We make the query	
+			request_mysql(query);
+			res=mysql_use_result(conn);
+			if(res==NULL)
+			{
+				//We couldn't make the request
+				return 2;
+			}
+			
+			while ((row = mysql_fetch_row(res)) != NULL)
+			{
+				if(strlen(row[0])>0)
+				{
+					not_found=0;
+					break;
+				}
+			}
+			mysql_free_result(res);
+			free(query);
+			free(sipaor_pure);
+			break;
+			
+		default:
+			
+			//We must never go here, if so, we must stop diameter_sip
+			TRACE_DEBUG(INFO,"FATAL ERROR: the datasource is unknown, please check your config file!");
+			return 2;
+			
+			break;
+	}
+	
+	//0 if it was found
+	return not_found;
+	
+}
+
+//We check if this user can go in the given network
+int allow_roaming(const unsigned char  *username, const size_t usernamelen, const char * network,const size_t networklen)
+{
+	CHECK_PARAMS(username && usernamelen && network && networklen);
+	
+	int not_found=2;
+	size_t querylen, usernamepurelen;
+	char *query, *username_pure;
+	
+	switch(as_conf->datasource)
+	{
+		//MySQL
+		case ASMYSQL:
+			//We allocate the double size of username because at worst it can be all quotes
+			username_pure=malloc(usernamelen*2+1);
+			//We purify username not to have forbidden characters
+			usernamepurelen=mysql_real_escape_string(conn, username_pure, (const char *)username, usernamelen);
+			
+			//We get the list of AOR owned by this user
+			querylen=SQL_GETUSERNET_LEN + usernamepurelen;
+			query = malloc(querylen+2);
+			snprintf(query, querylen+1, SQL_GETUSERNET, username_pure);
+			
+			
+			MYSQL_RES *res;
+			MYSQL_ROW row;
+			
+			
+			//We make the query
+			request_mysql(query);
+			res=mysql_use_result(conn);
+			if(res==NULL)
+			{
+				free(query);
+				return 2;
+			}
+			
+			
+			not_found=1;
+			while ((row = mysql_fetch_row(res)) != NULL)
+			{
+				if(strncmp((const char *)network,row[0],networklen)==0)
+				{
+					not_found=0;
+					break;
+				}
+			}
+			mysql_free_result(res);
+			free(query);
+			break;
+	}
+	return not_found;
+}
+
+//SIP-Server-Capabilities for the SIP-AOR
+int get_sipserver_cap(const unsigned char *sip_aor, const size_t sipaorlen, struct avp **capabilities)
+{
+	CHECK_PARAMS(sip_aor && sipaorlen && capabilities);
+	
+	size_t querylen, sipaorpurelen;
+	char *query, *sipaor_pure;
+	int not_found=2;
+	union avp_value value;
+	struct avp *avp;
+	
+	//a sip aor must begin by "sip:" or "sips:" so it must at least be longer than 4 chars
+	if(sipaorlen<5)
+		return 2;
+	
+	//NOTE: each method has to purify sip_aor itself. You must remove quotes or special chars for security
+	switch(as_conf->datasource)
+	{
+		//MySQL
+		case ASMYSQL:
+			
+			querylen=SQL_GETSIPSERCAP_LEN + sipaorlen;
+			
+			
+			//We allocate the double size of SIP-URI because at worst it can be all quotes
+			CHECK_MALLOC(sipaor_pure=malloc(sipaorlen*2+1));
+			//We purify SIP-URI not to have forbidden characters
+			sipaorpurelen=mysql_real_escape_string(conn, sipaor_pure, (const char *)sip_aor, sipaorlen);
+			
+			
+			query = malloc(querylen+sipaorpurelen+ 2);
+			snprintf(query, querylen+1, SQL_GETSIPSERCAP, sipaor_pure);
+			
+			MYSQL_RES *res;
+			MYSQL_ROW row;
+			
+			//We make the query	
+			request_mysql(query);
+			res=mysql_use_result(conn);
+			if(res==NULL)
+			{
+				//We couldn't make the request
+				return 2;
+			}
+			not_found=1;
+			while ((row = mysql_fetch_row(res)) != NULL)
+			{
+				if(atoi(row[0])==1)
+				{//mandatory
+					CHECK_FCT( fd_msg_avp_new ( sip_dict.SIP_Mandatory_Capability, 0, &avp ) );
+					value.i32=(uint32_t)atoi(row[1]);
+					CHECK_FCT( fd_msg_avp_setvalue ( avp, &value ) );
+					CHECK_FCT( fd_msg_avp_add ( *capabilities, MSG_BRW_LAST_CHILD, avp) );
+					
+				}
+				else
+				{//optional
+					CHECK_FCT( fd_msg_avp_new ( sip_dict.SIP_Optional_Capability, 0, &avp ) );
+					value.i32=(uint32_t)atoi(row[1]);
+					CHECK_FCT( fd_msg_avp_setvalue ( avp, &value ) );
+					CHECK_FCT( fd_msg_avp_add ( *capabilities, MSG_BRW_LAST_CHILD, avp) );
+				}
+				not_found=0;
+			}
+			
+			mysql_free_result(res);
+			free(query);
+			free(sipaor_pure);
+			break;
+			
+		default:
+			
+			//We must never go here, if so, we must stop diameter_sip
+			TRACE_DEBUG(INFO,"FATAL ERROR: the datasource is unknown, please check your config file!");
+			return 2;
+			
+			break;
+	}
+	
+	//0 if it was found
+	return not_found;
+	
+}
+
+
+//We retrieve datatype
+int add_user_datatype(const unsigned char  *sip_aor, const size_t sipaorlen,struct msg *message)
+{
+	CHECK_PARAMS(sip_aor && sipaorlen && message );
+	
+	size_t querylen, sipaorpurelen;
+	char *query, *sipaor_pure;
+	int not_found=2;
+	union avp_value value;
+	struct avp *avp, *rootavp;
+	unsigned long *length;
+	
+	//a sip aor must begin by "sip:" or "sips:" so it must at least be longer than 4 chars
+	if(sipaorlen<5)
+		return 2;
+	
+	//NOTE: each method has to purify sip_aor itself. You must remove quotes or special chars for security
+	switch(as_conf->datasource)
+	{
+		//MySQL
+		case ASMYSQL:
+			
+			querylen=SQL_GETSIPDATA_LEN + sipaorlen;
+			
+			
+			//We allocate the double size of SIP-URI because at worst it can be all quotes
+			CHECK_MALLOC(sipaor_pure=malloc(sipaorlen*2+1));
+			//We purify SIP-URI not to have forbidden characters
+			sipaorpurelen=mysql_real_escape_string(conn, sipaor_pure, (const char *)sip_aor, sipaorlen);
+			
+			
+			query = malloc(querylen+sipaorpurelen+ 2);
+			snprintf(query, querylen+1, SQL_GETSIPDATA, sipaor_pure);
+			
+			MYSQL_RES *res;
+			MYSQL_ROW row;
+			
+			//We make the query	
+			request_mysql(query);
+			res=mysql_use_result(conn);
+			if(res==NULL)
+			{
+				//We couldn't make the request
+				return 2;
+			}
+			not_found=1;
+			while ((row = mysql_fetch_row(res)) != NULL)
+			{
+				length=mysql_fetch_lengths(res);
+				
+				if(strlen(row[0])>1)
+				{
+					CHECK_FCT( fd_msg_avp_new ( sip_dict.SIP_User_Data, 0, &rootavp ) );
+					
+					CHECK_FCT( fd_msg_avp_new ( sip_dict.SIP_User_Data_Type, 0, &avp ) );
+					CHECK_MALLOC(value.os.data=malloc(length[0]*sizeof(unsigned char)));
+					strncpy((char *)value.os.data,(char *)row[0],length[0]);
+					value.os.len=(size_t)length[0];
+					CHECK_FCT( fd_msg_avp_setvalue ( avp, &value ) );
+					CHECK_FCT( fd_msg_avp_add ( rootavp, MSG_BRW_LAST_CHILD, avp) );
+					
+					
+					
+					CHECK_FCT( fd_msg_avp_new ( sip_dict.SIP_User_Data_Contents, 0, &avp ) );
+					CHECK_MALLOC(value.os.data=malloc(length[1]*sizeof(unsigned char)));
+					memcpy(value.os.data,row[1],length[1]);
+					value.os.len=(size_t)length[1];
+					CHECK_FCT( fd_msg_avp_setvalue ( avp, &value ) );
+					CHECK_FCT( fd_msg_avp_add ( rootavp, MSG_BRW_LAST_CHILD, avp) );
+					
+					//We add SIP_User_Data to message
+					CHECK_FCT( fd_msg_avp_add ( message, MSG_BRW_LAST_CHILD, rootavp) );
+					not_found=0;
+				}
+				
+			}
+			
+			mysql_free_result(res);
+			free(query);
+			free(sipaor_pure);
+			break;
+			
+			default:
+				
+				//We must never go here, if so, we must stop diameter_sip
+				TRACE_DEBUG(INFO,"FATAL ERROR: the datasource is unknown, please check your config file!");
+				return 2;
+				
+				break;
+	}
+	
+	//0 if it was found
+	return not_found;
+	
+	
+	
+}
+
+int set_pending_flag(const unsigned char  *username, const size_t usernamelen)
+{
+	CHECK_PARAMS(username && usernamelen);
+	
+	
+	size_t querylen, usernamepurelen;
+	char *query, *username_pure;
+	
+	switch(as_conf->datasource)
+	{
+		//MySQL
+		case ASMYSQL:
+			//We allocate the double size of username because at worst it can be all quotes
+			username_pure=malloc(usernamelen*2+1);
+			//We purify username not to have forbidden characters
+			usernamepurelen=mysql_real_escape_string(conn, username_pure, (const char *)username, usernamelen);
+			
+			
+			
+			//We clear the flag "authentication pending"
+			querylen=SQL_SETFLAG_LEN + usernamepurelen;
+			query = malloc(querylen+2);
+			snprintf(query, querylen+1, SQL_SETFLAG, username_pure);
+			
+			if (mysql_query(conn, query)) 
+			{
+				TRACE_DEBUG(INFO,"Query %s failed", query);
+				free(query);
+				return 2;
+			}
+			
+			free(query);
+			break;
+	}	
+	return 0;
+}
+int clear_pending_flag(const unsigned char  *username, const size_t usernamelen)
+{
+	CHECK_PARAMS(username && usernamelen);
+	
+	
+	size_t querylen, usernamepurelen;
+	char *query, *username_pure;
+	
+	switch(as_conf->datasource)
+	{
+		//MySQL
+		case ASMYSQL:
+			//We allocate the double size of username because at worst it can be all quotes
+			username_pure=malloc(usernamelen*2+1);
+			//We purify username not to have forbidden characters
+			usernamepurelen=mysql_real_escape_string(conn, username_pure, (const char *)username, usernamelen);
+			
+			
+			
+			//We clear the flag "authentication pending"
+			querylen=SQL_CLEARFLAG_LEN + usernamepurelen;
+			query = malloc(querylen+2);
+			snprintf(query, querylen+1, SQL_CLEARFLAG, username_pure);
+			
+			if (mysql_query(conn, query)) 
+			{
+				TRACE_DEBUG(INFO,"Query %s failed", query);
+				free(query);
+				return 2;
+			}
+			
+			free(query);
+		break;
+	}	
+	return 0;
+}
+
+
+
+int set_sipserver_uri(const unsigned char  *username, const size_t usernamelen, const unsigned char *sipserver_uri,const size_t sipserverurilen)
+{
+	CHECK_PARAMS(username && usernamelen && sipserver_uri && sipserverurilen);
+	
+	
+	size_t querylen, usernamepurelen, sipserveruripurelen;
+	char *query, *username_pure, *sipserveruri_pure;
+	
+	switch(as_conf->datasource)
+	{
+		//MySQL
+		case ASMYSQL:
+			//We allocate the double size of username because at worst it can be all quotes
+			username_pure=malloc(usernamelen*2+1);
+			//We purify username not to have forbidden characters
+			usernamepurelen=mysql_real_escape_string(conn, username_pure, (const char *)username, usernamelen);
+			
+			//We allocate the double size of username because at worst it can be all quotes
+			sipserveruri_pure=malloc(sipserverurilen*2+1);
+			//We purify username not to have forbidden characters
+			sipserveruripurelen=mysql_real_escape_string(conn, sipserveruri_pure, (const char *)sipserver_uri, sipserverurilen);
+			
+			//We clear the flag "authentication pending"
+			querylen=SQL_SETSIPURI_LEN + usernamepurelen + sipserveruripurelen;
+			query = malloc(querylen+2);
+			snprintf(query, querylen+1, SQL_SETSIPURI, sipserveruri_pure,username_pure);
+			
+			if (mysql_query(conn, query)) 
+			{
+				TRACE_DEBUG(INFO,"Query %s failed", query);
+				free(query);
+				return 2;
+			}
+			
+			free(query);
+			break;
+	}	
+	return 0;
+}
+int remove_sipserver_uri(const unsigned char *sipserver_uri,const size_t sipserverurilen)
+{
+	CHECK_PARAMS(sipserver_uri && sipserverurilen);
+	
+
+	size_t querylen, sipserveruripurelen;
+	char *query, *sipserveruri_pure;
+	
+	switch(as_conf->datasource)
+	{
+		//MySQL
+		case ASMYSQL:
+			//We allocate the double size of username because at worst it can be all quotes
+			sipserveruri_pure=malloc(sipserverurilen*2+1);
+			//We purify username not to have forbidden characters
+			sipserveruripurelen=mysql_real_escape_string(conn, sipserveruri_pure, (const char *)sipserver_uri, sipserverurilen);
+			
+			//We clear the flag "authentication pending"
+			querylen=SQL_RMSIPURI_LEN + sipserveruripurelen;
+			query = malloc(querylen+2);
+			snprintf(query, querylen+1, SQL_RMSIPURI, sipserveruri_pure);
+			
+			if (mysql_query(conn, query)) 
+			{
+				TRACE_DEBUG(INFO,"Query %s failed", query);
+				free(query);
+				return 2;
+			}
+			
+			free(query);
+			break;
+	}	
+	return 0;
+}
+int set_real_sipserver_uri(const unsigned char  *username, const size_t usernamelen, const unsigned char *sipserver_uri,const size_t sipserverurilen)
+{
+	CHECK_PARAMS(username && usernamelen && sipserver_uri && sipserverurilen);
+	
+	
+	size_t querylen, usernamepurelen, sipserveruripurelen;
+	char *query, *username_pure, *sipserveruri_pure;
+	
+	switch(as_conf->datasource)
+	{
+		//MySQL
+		case ASMYSQL:
+			//We allocate the double size of username because at worst it can be all quotes
+			username_pure=malloc(usernamelen*2+1);
+			//We purify username not to have forbidden characters
+			usernamepurelen=mysql_real_escape_string(conn, username_pure, (const char *)username, usernamelen);
+			
+			//We allocate the double size of username because at worst it can be all quotes
+			sipserveruri_pure=malloc(sipserverurilen*2+1);
+			//We purify username not to have forbidden characters
+			sipserveruripurelen=mysql_real_escape_string(conn, sipserveruri_pure, (const char *)sipserver_uri, sipserverurilen);
+			
+			//We clear the flag "authentication pending"
+			querylen=SQL_SETREALSIPURI_LEN + usernamepurelen + sipserveruripurelen;
+			query = malloc(querylen+2);
+			snprintf(query, querylen+1, SQL_SETREALSIPURI, sipserveruri_pure,username_pure);
+			
+			if (mysql_query(conn, query)) 
+			{
+				TRACE_DEBUG(INFO,"Query %s failed", query);
+				free(query);
+				return 2;
+			}
+			
+			free(query);
+			break;
+	}	
+	return 0;
+}
+
+int get_sipserver_uri(const unsigned char *sip_aor, const size_t sipaorlen, unsigned char ** sipserver_uri, size_t *sipserverurilen)
+{
+	CHECK_PARAMS(sip_aor && sipaorlen && sipserver_uri && sipserverurilen );
+	
+	size_t querylen, sipaorpurelen;
+	char *query, *sipaor_pure;
+	int not_found=2;
+	
+	
+	
+	
+	//a sip aor must begin by "sip:" or "sips:" so it must at least be longer than 4 chars
+	if(sipaorlen<5)
+		return 2;
+	
+	//NOTE: each method has to purify sip_aor itself. You must remove quotes or special chars for security
+	
+	switch(as_conf->datasource)
+	{
+		//MySQL
+		case ASMYSQL:
+			
+			querylen=SQL_GETSIPSERURI_LEN + sipaorlen;
+			
+			//We allocate the double size of SIP-URI because at worst it can be all quotes
+			CHECK_MALLOC(sipaor_pure=malloc(sipaorlen*2+1));
+			//We purify SIP-URI not to have forbidden characters
+			sipaorpurelen=mysql_real_escape_string(conn, sipaor_pure, (const char *)sip_aor, sipaorlen);
+			
+			
+			query = malloc(querylen+sipaorpurelen+ 2);
+			snprintf(query, querylen+1, SQL_GETSIPSERURI, sipaor_pure);
+			
+			MYSQL_RES *res;
+			MYSQL_ROW row;
+			
+			//We make the query	
+			request_mysql(query);
+			res=mysql_use_result(conn);
+			if(res==NULL)
+			{
+				//We couldn't make the request
+				sipserver_uri=NULL;
+				return 2;
+			}
+			
+			not_found=1;
+			while ((row = mysql_fetch_row(res)) != NULL)
+			{
+				*sipserverurilen=strlen(row[0]);
+				if(*sipserverurilen>4)
+				{
+					CHECK_MALLOC(*sipserver_uri=malloc(*sipserverurilen+1));
+					strcpy((char *)*sipserver_uri,row[0]);
+					not_found=0;
+					break;
+				}
+			}
+			mysql_free_result(res);
+			free(query);
+			free(sipaor_pure);
+			break;
+			
+		default:
+			
+			//We must never go here, if so, we must stop diameter_sip
+			TRACE_DEBUG(INFO,"FATAL ERROR: the datasource is unknown, please check your config file!");
+			sipserver_uri=NULL;
+			return 2;
+			
+			break;
+	}
+	
+	//0 if it was found
+	return not_found;
+	
+}
+
+
+int count_avp(struct msg * message, int code, int vendor)
+{
+	CHECK_PARAMS(message);
+	
+	struct avp_hdr *temphdr;
+	struct avp *avp;
+	int counter=0;
+	
+	CHECK_FCT(fd_msg_browse (message, MSG_BRW_WALK, &avp, NULL));
+	
+	while(avp!=NULL)
+	{
+		
+		CHECK_FCT( fd_msg_avp_hdr( avp,&temphdr ));
+		
+		if(temphdr->avp_code==code && temphdr->avp_vendor==vendor)
+		{
+			counter++;
+		}
+		
+		CHECK_FCT(fd_msg_browse (avp, MSG_BRW_WALK, &avp, NULL));
+	}
+	return counter;
+}
+/* 
+void nonce_add_element(char * nonce)
+{
+	noncechain *newelt=malloc(sizeof(noncechain));
+	
+	newelt->nonce=nonce;
+	
+	newelt->timestamp=(int)time(NULL);
+	newelt->next=NULL;
+	
+	if(listnonce==NULL)
+	{
+		listnonce=newelt;
+	}
+	else
+	{
+		noncechain* temp=listnonce;
+		
+		while(temp->next != NULL)
+		{
+			if(temp->timestamp < ((int)time(NULL)-300))
+			{
+				listnonce=temp->next;
+				free(temp);
+				temp=listnonce;
+			}
+			temp = temp->next;
+		}
+		temp->next = newelt;
+	}
+	
+}
+void nonce_del_element(char * nonce)
+{
+	if(listnonce!=NULL)
+	{
+		noncechain *temp=listnonce, *tempbefore=NULL;
+		
+		if(listnonce->next==NULL && strcmp(listnonce->nonce,nonce)==0)
+		{
+			free(listnonce);
+			listnonce=NULL;
+			return;
+		}
+		while(temp->next != NULL)
+		{
+			if(strcmp(temp->nonce,nonce)==0)
+			{
+				if(tempbefore==NULL)
+				{
+					listnonce=temp->next;
+					free(temp);
+					return;
+				}
+				tempbefore->next=temp->next;
+				free(temp);
+				break;
+			}
+			tempbefore=temp;
+			temp = temp->next;
+		}
+		
+	}
+	
+}
+int nonce_check_element(char * nonce)
+{
+	if(listnonce==NULL)
+	{
+		//Not found
+		return 0;
+	}
+	else
+	{
+		noncechain* temp=listnonce;
+		
+		while(temp->next != NULL)
+		{
+			if(strcmp(temp->nonce,nonce)==0)
+				return 1;
+			else
+				temp = temp->next;
+		}
+	}
+	return 0;
+}
+
+void nonce_deletelistnonce()
+{
+	if(listnonce !=NULL)
+	{
+		noncechain* temp=listnonce;
+	
+		while(listnonce->next != NULL)
+		{
+			temp = listnonce->next;
+		
+			free(listnonce);
+		
+			listnonce=temp;
+		}
+		free(listnonce);
+	}
+}
+*/
diff --git a/extensions/app_sip/locationinfo.c b/extensions/app_sip/locationinfo.c
new file mode 100644
index 0000000..e2c372a
--- /dev/null
+++ b/extensions/app_sip/locationinfo.c
@@ -0,0 +1,208 @@
+/*********************************************************************************************************
+* Software License Agreement (BSD License)                                                               *
+* Author: Alexandre Westfahl <awestfahl@freediameter.net>						 *
+*													 *
+* Copyright (c) 2010, Alexandre Westfahl, Teraoka Laboratory (Keio University), and the WIDE Project. 	 *		
+*													 *
+* All rights reserved.											 *
+* 													 *
+* Redistribution and use of this software in source and binary forms, with or without modification, are  *
+* permitted provided that the following conditions are met:						 *
+* 													 *
+* * Redistributions of source code must retain the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer.										 *
+*    													 *
+* * Redistributions in binary form must reproduce the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer in the documentation and/or other						 *
+*   materials provided with the distribution.								 *
+* 													 *
+* * Neither the name of the Teraoka Laboratory nor the 							 *
+*   names of its contributors may be used to endorse or 						 *
+*   promote products derived from this software without 						 *
+*   specific prior written permission of Teraoka Laboratory 						 *
+*   													 *
+* 													 *
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED *
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
+* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR *
+* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 	 *
+* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 	 *
+* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR *
+* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF   *
+* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.								 *
+*********************************************************************************************************/
+#include "app_sip.h"
+
+
+int app_sip_LIR_cb( struct msg ** msg, struct avp * paramavp, struct session * sess, void * opaque, enum disp_action * act)
+{
+	TRACE_ENTRY("%p %p %p %p", msg, paramavp, sess, act);
+	
+	struct msg *ans, *qry;
+	struct avp *avp, *groupedavp;
+	struct avp_hdr *avphdr;
+	union avp_value value;
+	int ret=0;
+	
+	//Result_Code to return in the answer
+	char result[55];
+	
+	if (msg == NULL)
+		return EINVAL;
+
+	
+	// Create answer header 
+	qry = *msg;
+	CHECK_FCT( fd_msg_new_answer_from_req ( fd_g_config->cnf_dict, msg, 0 ) );
+	ans = *msg;
+	
+	//Add the Auth-Application-Id 
+	{
+		CHECK_FCT( fd_msg_avp_new ( sip_dict.Auth_Application_Id, 0, &avp ) );
+		value.i32 = 6;
+		CHECK_FCT( fd_msg_avp_setvalue ( avp, &value ) );
+		CHECK_FCT( fd_msg_avp_add ( ans, MSG_BRW_LAST_CHILD, avp) );
+	}
+	// Add the Auth-Session-State AVP 
+	{
+		
+		CHECK_FCT( fd_msg_search_avp ( qry, sip_dict.Auth_Session_State, &avp) );
+		CHECK_FCT( fd_msg_avp_hdr( avp, &avphdr )  );
+		
+		CHECK_FCT( fd_msg_avp_new ( sip_dict.Auth_Session_State, 0, &avp ) );
+		CHECK_FCT( fd_msg_avp_setvalue( avp, avphdr->avp_value ) );
+		CHECK_FCT( fd_msg_avp_add( ans, MSG_BRW_LAST_CHILD, avp ) );
+	}
+	
+	
+	//Add a SIP_Server_URI
+	{
+		CHECK_FCT( fd_msg_search_avp ( qry, sip_dict.SIP_AOR, &avp) );
+		CHECK_FCT( fd_msg_avp_hdr( avp, &avphdr )  );
+		
+		
+		
+		
+		
+		ret=exist_username(avphdr->avp_value->os.data, avphdr->avp_value->os.len);
+		
+		
+		if(ret==2)
+		{//error
+			/*
+			If the Diameter server cannot process the Diameter LIR command, e.g.,
+			due to a database error, the Diameter server MUST set the Result-Code
+			AVP value to DIAMETER_UNABLE_TO_COMPLY and return it in a Diameter
+			LIA message.
+			*/
+			strcpy(result,"DIAMETER_UNABLE_TO_COMPLY");
+			goto out;
+		}
+		else if(ret==1)
+		{//not found
+			/*
+			One of the errors that the Diameter server may find is that the
+			SIP-AOR AVP value is not a valid user in the realm.  In such cases,
+			the Diameter server MUST set the Result-Code AVP value to
+			DIAMETER_ERROR_USER_UNKNOWN and return it in a Diameter LIA message.
+			
+			*/
+			strcpy(result,"DIAMETER_ERROR_USER_UNKNOWN");
+			goto out;
+		}
+		
+		//If we arrive here, the user is known
+		size_t sipserverurilen;
+		unsigned char * sipserver_uri=NULL;
+		
+		ret=get_sipserver_uri(avphdr->avp_value->os.data, avphdr->avp_value->os.len, &sipserver_uri, &sipserverurilen);
+		
+		
+		if(ret==0)
+		{//found
+			if(sipserver_uri==NULL)
+			{
+				//There is a problem because we must get a Diameter_URI here
+				strcpy(result,"DIAMETER_UNABLE_TO_COMPLY");
+				goto out;
+			}
+			else
+			{
+				CHECK_FCT( fd_msg_avp_new ( sip_dict.SIP_Server_URI, 0, &avp ) );
+				value.os.data=(unsigned char *)sipserver_uri;
+				value.os.len=sipserverurilen;
+				CHECK_FCT( fd_msg_avp_setvalue ( avp, &value ) );
+				CHECK_FCT( fd_msg_avp_add ( ans, MSG_BRW_LAST_CHILD, avp) );
+				
+				strcpy(result,"DIAMETER_SUCCESS");
+			}
+		}
+		else if(ret==1)
+		{//not found
+			//We don't know this SIP_AOR in SL, that means 
+			strcpy(result,"DIAMETER_ERROR_USER_UNKNOWN");
+			goto out;
+		}
+		else
+		{// returned 2, impossible to make request
+			//We couldn't make the request, we must stop process!
+			strcpy(result,"DIAMETER_UNABLE_TO_COMPLY");
+			goto out;
+		}
+		
+		//Adding SIP-Server-Capabilities
+		CHECK_FCT( fd_msg_avp_new ( sip_dict.SIP_Server_Capabilities, 0, &groupedavp ) );
+		//We add mandatory and optional capabilities
+		ret=get_sipserver_cap(avphdr->avp_value->os.data, avphdr->avp_value->os.len, &groupedavp);
+		
+		
+		if(ret==0)
+		{//found
+		if(sipserver_uri==NULL)
+		{
+			//There is a problem because we must get a Diameter_URI here
+			strcpy(result,"DIAMETER_UNABLE_TO_COMPLY");
+			CHECK_FCT( fd_msg_free( groupedavp ) );
+			goto out;
+		}
+		else
+		{
+			
+			CHECK_FCT( fd_msg_avp_add ( ans, MSG_BRW_LAST_CHILD, groupedavp) );
+			
+			strcpy(result,"DIAMETER_SUCCESS");
+		}
+		}
+		else if(ret==1)
+		{//not found
+			//We don't know this SIP_AOR in SL, that means 
+			strcpy(result,"DIAMETER_ERROR_IDENTITY_NOT_REGISTERED");
+			CHECK_FCT( fd_msg_free( groupedavp ) );
+			goto out;
+		}
+		else
+		{// returned 2, impossible to make request
+			//We couldn't make the request, we must stop process!
+			strcpy(result,"DIAMETER_UNABLE_TO_COMPLY");
+			CHECK_FCT( fd_msg_free( groupedavp ) );
+			goto out;
+		}
+		
+		
+		
+	}
+	
+	
+	
+	
+out:
+	CHECK_FCT( fd_msg_rescode_set( ans, result, NULL, NULL, 1 ) );
+	
+	CHECK_FCT( fd_msg_send( msg, NULL, NULL ));
+	
+	
+	
+	return 0;
+}
diff --git a/extensions/app_sip/locationinfosl.c b/extensions/app_sip/locationinfosl.c
new file mode 100644
index 0000000..f28beef
--- /dev/null
+++ b/extensions/app_sip/locationinfosl.c
@@ -0,0 +1,144 @@
+/*********************************************************************************************************
+* Software License Agreement (BSD License)                                                               *
+* Author: Alexandre Westfahl <awestfahl@freediameter.net>						 *
+*													 *
+* Copyright (c) 2010, Alexandre Westfahl, Teraoka Laboratory (Keio University), and the WIDE Project. 	 *		
+*													 *
+* All rights reserved.											 *
+* 													 *
+* Redistribution and use of this software in source and binary forms, with or without modification, are  *
+* permitted provided that the following conditions are met:						 *
+* 													 *
+* * Redistributions of source code must retain the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer.										 *
+*    													 *
+* * Redistributions in binary form must reproduce the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer in the documentation and/or other						 *
+*   materials provided with the distribution.								 *
+* 													 *
+* * Neither the name of the Teraoka Laboratory nor the 							 *
+*   names of its contributors may be used to endorse or 						 *
+*   promote products derived from this software without 						 *
+*   specific prior written permission of Teraoka Laboratory 						 *
+*   													 *
+* 													 *
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED *
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
+* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR *
+* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 	 *
+* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 	 *
+* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR *
+* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF   *
+* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.								 *
+*********************************************************************************************************/
+#include "app_sip.h"
+
+//This callback is specific to SUSCRIBER LOCATOR. We must look for the "serving" SIP server
+int app_sip_SL_LIR_cb( struct msg ** msg, struct avp * paramavp, struct session * sess, void * opaque, enum disp_action * act)
+{
+	TRACE_ENTRY("%p %p %p %p", msg, paramavp, sess, act);
+	
+	struct msg *ans, *qry;
+	struct avp *avp;
+	struct avp_hdr *avphdr;
+	union avp_value value;
+	
+	//Result_Code to return in the answer
+	char result[55];
+	int ret=0;
+	
+	
+	if (msg == NULL)
+		return EINVAL;
+
+	
+	
+	// Create answer header 
+	qry = *msg;
+	CHECK_FCT( fd_msg_new_answer_from_req ( fd_g_config->cnf_dict, msg, 0 ) );
+	ans = *msg;
+	
+	
+	//Add the Auth-Application-Id 
+	{
+		CHECK_FCT( fd_msg_avp_new ( sip_dict.Auth_Application_Id, 0, &avp ) );
+		value.i32 = 6;
+		CHECK_FCT( fd_msg_avp_setvalue ( avp, &value ) );
+		CHECK_FCT( fd_msg_avp_add ( ans, MSG_BRW_LAST_CHILD, avp) );
+	}
+	
+	// Add the Auth-Session-State AVP 
+	{
+		
+		CHECK_FCT( fd_msg_search_avp ( qry, sip_dict.Auth_Session_State, &avp) );
+		CHECK_FCT( fd_msg_avp_hdr( avp, &avphdr )  );
+		
+		CHECK_FCT( fd_msg_avp_new ( sip_dict.Auth_Session_State, 0, &avp ) );
+		CHECK_FCT( fd_msg_avp_setvalue( avp, avphdr->avp_value ) );
+		CHECK_FCT( fd_msg_avp_add( ans, MSG_BRW_LAST_CHILD, avp ) );
+	}
+	
+	
+	// Add the Redirect Host AVP 
+	{
+		CHECK_FCT( fd_msg_search_avp ( qry, sip_dict.SIP_AOR, &avp) );
+		CHECK_FCT( fd_msg_avp_hdr( avp, &avphdr )  );
+		size_t diameterurilen;
+		char * diameter_uri=NULL;
+		
+		
+		
+		ret=get_diameter_uri(avphdr->avp_value->os.data, avphdr->avp_value->os.len, &diameter_uri, &diameterurilen);
+		
+		//found
+		if(ret==0)
+		{
+		  if(diameter_uri==NULL)
+		  {
+			  //There is a problem because we must get a Diameter_URI here
+			  strcpy(result,"DIAMETER_UNABLE_TO_COMPLY");
+			  goto out;
+		  }
+		  else
+		  {
+		    CHECK_FCT( fd_msg_avp_new ( sip_dict.Redirect_Host, 0, &avp ) );
+		    value.os.data=(unsigned char *)diameter_uri;
+		    value.os.len=diameterurilen;
+		    CHECK_FCT( fd_msg_avp_setvalue( avp, &value ) );
+		    CHECK_FCT( fd_msg_avp_add( ans, MSG_BRW_LAST_CHILD, avp ) );
+		    
+		    CHECK_FCT( fd_msg_avp_new ( sip_dict.Redirect_Host_Usage, 0, &avp ) );
+		    value.i32=ALL_USER; //All the request about the same user must be sent to this server
+		    CHECK_FCT( fd_msg_avp_setvalue( avp, &value ) );
+		    CHECK_FCT( fd_msg_avp_add( ans, MSG_BRW_LAST_CHILD, avp ) );
+		    strcpy(result,"DIAMETER_SUCCESS");
+		  }
+		}
+		else if(ret==1)
+		{//not found
+			//We don't know this SIP_AOR in SL
+			strcpy(result,"DIAMETER_ERROR_USER_UNKNOWN");
+			goto out;
+		}
+		else
+		{// returned 2, impossible to make request
+			//We couldn't make the request, we must stop process!
+			strcpy(result,"DIAMETER_UNABLE_TO_COMPLY");
+			goto out;
+		}
+	}
+	
+	
+out:
+	CHECK_FCT( fd_msg_rescode_set( ans, result, NULL, NULL, 1 ) );
+	
+	
+	
+	CHECK_FCT( fd_msg_send( msg, NULL, NULL ));
+	
+	
+	
+	return 0;
+}
diff --git a/extensions/app_sip/md5.c b/extensions/app_sip/md5.c
new file mode 100644
index 0000000..4079bda
--- /dev/null
+++ b/extensions/app_sip/md5.c
@@ -0,0 +1,421 @@
+/*********************************************************************************/
+/* freeDiameter author note:
+ *  The content from this file comes directly from the hostap project.
+ * It is redistributed under the terms of the BSD license, as allowed
+ * by the original copyright reproduced below.
+ *  In addition to this notice, only the #include directives have been modified.
+ */
+
+/*********************************************************************************/
+#include"app_sip.h"
+ 
+/*
+ * MD5 hash implementation and interface functions
+ * Copyright (c) 2003-2005, Jouni Malinen <j@w1.fi>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Alternatively, this software may be distributed under the terms of BSD
+ * license.
+ *
+ * See README and COPYING for more details.
+ */
+void CvtHex(
+    IN HASH Bin,
+    OUT HASHHEX Hex
+    )
+{
+    unsigned short i;
+    unsigned char j;
+
+    for (i = 0; i < HASHLEN; i++) {
+        j = (Bin[i] >> 4) & 0xf;
+        if (j <= 9)
+            Hex[i*2] = (j + '0');
+         else
+            Hex[i*2] = (j + 'a' - 10);
+        j = Bin[i] & 0xf;
+        if (j <= 9)
+            Hex[i*2+1] = (j + '0');
+         else
+            Hex[i*2+1] = (j + 'a' - 10);
+    }
+    Hex[HASHHEXLEN] = '\0';
+}
+
+// calculate H(A1) as per spec 
+void DigestCalcHA1(char * pszAlg,char * pszUserName,char * pszRealm,char * pszPassword,char * pszNonce,char * pszCNonce,HASHHEX SessionKey)
+{
+      MD5_CTX Md5Ctx;
+      HASH HA1;
+
+      MD5Init(&Md5Ctx);
+      MD5Update(&Md5Ctx, (const unsigned char *)pszUserName, strlen(pszUserName));
+      MD5Update(&Md5Ctx, (const unsigned char *)":", 1);
+      MD5Update(&Md5Ctx, (const unsigned char *)pszRealm, strlen(pszRealm));
+      MD5Update(&Md5Ctx, (const unsigned char *)":", 1);
+      MD5Update(&Md5Ctx, (const unsigned char *)pszPassword, strlen(pszPassword));
+      MD5Final((unsigned char *)HA1, &Md5Ctx);
+      if (strcmp(pszAlg, "md5-sess") == 0) {	
+		MD5Init(&Md5Ctx);
+		MD5Update(&Md5Ctx, (const unsigned char *)HA1, HASHLEN);
+		MD5Update(&Md5Ctx, (const unsigned char *)":", 1);
+		MD5Update(&Md5Ctx, (const unsigned char *)pszNonce, strlen(pszNonce));
+		MD5Update(&Md5Ctx, (const unsigned char *)":", 1);
+		MD5Update(&Md5Ctx, (const unsigned char *)pszCNonce, strlen(pszCNonce));
+		MD5Final((unsigned char *)HA1, &Md5Ctx);
+      }
+      CvtHex(HA1, SessionKey);
+}
+
+// calculate request-digest as  SIP Digest spec RFC5090
+void DigestCalcResponse(HASHHEX HA1,char * pszNonce,char * pszNonceCount,char * pszCNonce,char * pszQop,char * pszMethod,char * pszDigestUri,HASHHEX HEntity,HASHHEX Response)
+{
+      MD5_CTX Md5Ctx;
+      HASH HA2;
+      HASH RespHash;
+       HASHHEX HA2Hex;
+
+      // calculate H(A2)
+      MD5Init(&Md5Ctx);
+      MD5Update(&Md5Ctx, (const unsigned char *)pszMethod, strlen(pszMethod));
+      MD5Update(&Md5Ctx, (const unsigned char *)":", 1);
+      MD5Update(&Md5Ctx, (const unsigned char *)pszDigestUri, strlen(pszDigestUri));
+      if (strcmp(pszQop, "auth-int") == 0) {
+            MD5Update(&Md5Ctx, (const unsigned char *)":", 1);
+            MD5Update(&Md5Ctx, (const unsigned char *)HEntity, HASHHEXLEN);
+      }
+      MD5Final((unsigned char *)HA2, &Md5Ctx);
+       CvtHex(HA2, HA2Hex);
+       
+      // calculate response
+      MD5Init(&Md5Ctx);
+      MD5Update(&Md5Ctx, (const unsigned char *)HA1, HASHHEXLEN);
+      MD5Update(&Md5Ctx, (const unsigned char *)":", 1);
+      MD5Update(&Md5Ctx,(const unsigned char *) pszNonce, strlen(pszNonce));
+      MD5Update(&Md5Ctx, (const unsigned char *)":", 1);
+      if (*pszQop) {
+          MD5Update(&Md5Ctx, (const unsigned char *)pszNonceCount, strlen(pszNonceCount));
+          MD5Update(&Md5Ctx, (const unsigned char *)":", 1);
+          MD5Update(&Md5Ctx, (const unsigned char *)pszCNonce, strlen(pszCNonce));
+          MD5Update(&Md5Ctx, (const unsigned char *)":", 1);
+          MD5Update(&Md5Ctx, (const unsigned char *)pszQop, strlen(pszQop));
+          MD5Update(&Md5Ctx, (const unsigned char *)":", 1);
+      }
+      MD5Update(&Md5Ctx, (const unsigned char *)HA2Hex, HASHHEXLEN);
+      MD5Final((unsigned char *)RespHash, &Md5Ctx);
+      CvtHex(RespHash, Response);
+}
+// calculate Digest_response_Auth as per SIP Digest spec RFC5090
+void DigestCalcResponseAuth(HASHHEX HA1,char * pszNonce,char * pszNonceCount,char * pszCNonce,char * pszQop,char * pszMethod,char * pszDigestUri,HASHHEX HEntity,HASHHEX Response)
+{
+      MD5_CTX Md5Ctx;
+      HASH HA2;
+      HASH RespHash;
+       HASHHEX HA2Hex;
+
+      // calculate H(A2)
+      MD5Init(&Md5Ctx);
+      MD5Update(&Md5Ctx, (const unsigned char *)":", 1);
+      MD5Update(&Md5Ctx, (const unsigned char *)pszDigestUri, strlen(pszDigestUri));
+      if (strcmp(pszQop, "auth-int") == 0) {
+            MD5Update(&Md5Ctx, (const unsigned char *)":", 1);
+            MD5Update(&Md5Ctx, (const unsigned char *)HEntity, HASHHEXLEN);
+      }
+      MD5Final((unsigned char *)HA2, &Md5Ctx);
+       CvtHex(HA2, HA2Hex);
+       
+      // calculate response
+      MD5Init(&Md5Ctx);
+      MD5Update(&Md5Ctx, (const unsigned char *)HA1, HASHHEXLEN);
+      MD5Update(&Md5Ctx, (const unsigned char *)":", 1);
+      MD5Update(&Md5Ctx, (const unsigned char *)pszNonce, strlen(pszNonce));
+      MD5Update(&Md5Ctx, (const unsigned char *)":", 1);
+      if (*pszQop) {
+          MD5Update(&Md5Ctx, (const unsigned char *)pszNonceCount, strlen(pszNonceCount));
+          MD5Update(&Md5Ctx, (const unsigned char *)":", 1);
+          MD5Update(&Md5Ctx, (const unsigned char *)pszCNonce, strlen(pszCNonce));
+          MD5Update(&Md5Ctx, (const unsigned char *)":", 1);
+          MD5Update(&Md5Ctx, (const unsigned char *)pszQop, strlen(pszQop));
+          MD5Update(&Md5Ctx, (const unsigned char *)":", 1);
+      }
+      MD5Update(&Md5Ctx, (const unsigned char *)HA2Hex, HASHHEXLEN);
+      MD5Final((unsigned char *)RespHash, &Md5Ctx);
+      CvtHex(RespHash, Response);
+}
+
+
+
+
+
+static void MD5Transform(u32 buf[4], u32 const in[16]);
+
+
+
+
+/**
+ * md5_vector - MD5 hash for data vector
+ * @num_elem: Number of elements in the data vector
+ * @addr: Pointers to the data areas
+ * @len: Lengths of the data blocks
+ * @mac: Buffer for the hash
+ */
+void md5_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac)
+{
+	MD5_CTX ctx;
+	size_t i;
+
+	MD5Init(&ctx);
+	for (i = 0; i < num_elem; i++)
+		MD5Update(&ctx, addr[i], len[i]);
+	MD5Final(mac, &ctx);
+}
+
+
+/* ===== start - public domain MD5 implementation ===== */
+/*
+ * This code implements the MD5 message-digest algorithm.
+ * The algorithm is due to Ron Rivest.  This code was
+ * written by Colin Plumb in 1993, no copyright is claimed.
+ * This code is in the public domain; do with it what you wish.
+ *
+ * Equivalent code is available from RSA Data Security, Inc.
+ * This code has been tested against that, and is equivalent,
+ * except that you don't need to include two pages of legalese
+ * with every copy.
+ *
+ * To compute the message digest of a chunk of bytes, declare an
+ * MD5Context structure, pass it to MD5Init, call MD5Update as
+ * needed on buffers full of bytes, and then call MD5Final, which
+ * will fill a supplied 16-byte array with the digest.
+ */
+
+#ifndef WORDS_BIGENDIAN
+#define byteReverse(buf, len)	/* Nothing */
+#else
+/*
+ * Note: this code is harmless on little-endian machines.
+ */
+static void byteReverse(unsigned char *buf, unsigned longs)
+{
+    u32 t;
+    do {
+	t = (u32) ((unsigned) buf[3] << 8 | buf[2]) << 16 |
+	    ((unsigned) buf[1] << 8 | buf[0]);
+	*(u32 *) buf = t;
+	buf += 4;
+    } while (--longs);
+}
+#endif
+
+/*
+ * Start MD5 accumulation.  Set bit count to 0 and buffer to mysterious
+ * initialization constants.
+ */
+void MD5Init(struct MD5Context *ctx)
+{
+    ctx->buf[0] = 0x67452301;
+    ctx->buf[1] = 0xefcdab89;
+    ctx->buf[2] = 0x98badcfe;
+    ctx->buf[3] = 0x10325476;
+
+    ctx->bits[0] = 0;
+    ctx->bits[1] = 0;
+}
+
+/*
+ * Update context to reflect the concatenation of another buffer full
+ * of bytes.
+ */
+void MD5Update(struct MD5Context *ctx, unsigned char const *buf, unsigned len)
+{
+    u32 t;
+
+    /* Update bitcount */
+
+    t = ctx->bits[0];
+    if ((ctx->bits[0] = t + ((u32) len << 3)) < t)
+	ctx->bits[1]++;		/* Carry from low to high */
+    ctx->bits[1] += len >> 29;
+
+    t = (t >> 3) & 0x3f;	/* Bytes already in shsInfo->data */
+
+    /* Handle any leading odd-sized chunks */
+
+    if (t) {
+	unsigned char *p = (unsigned char *) ctx->in + t;
+
+	t = 64 - t;
+	if (len < t) {
+	    os_memcpy(p, buf, len);
+	    return;
+	}
+	os_memcpy(p, buf, t);
+	byteReverse(ctx->in, 16);
+	MD5Transform(ctx->buf, (u32 *) ctx->in);
+	buf += t;
+	len -= t;
+    }
+    /* Process data in 64-byte chunks */
+
+    while (len >= 64) {
+	os_memcpy(ctx->in, buf, 64);
+	byteReverse(ctx->in, 16);
+	MD5Transform(ctx->buf, (u32 *) ctx->in);
+	buf += 64;
+	len -= 64;
+    }
+
+    /* Handle any remaining bytes of data. */
+
+    os_memcpy(ctx->in, buf, len);
+}
+
+/*
+ * Final wrapup - pad to 64-byte boundary with the bit pattern
+ * 1 0* (64-bit count of bits processed, MSB-first)
+ */
+void MD5Final(unsigned char digest[16], struct MD5Context *ctx)
+{
+    unsigned count;
+    unsigned char *p;
+
+    /* Compute number of bytes mod 64 */
+    count = (ctx->bits[0] >> 3) & 0x3F;
+
+    /* Set the first char of padding to 0x80.  This is safe since there is
+       always at least one byte free */
+    p = ctx->in + count;
+    *p++ = 0x80;
+
+    /* Bytes of padding needed to make 64 bytes */
+    count = 64 - 1 - count;
+
+    /* Pad out to 56 mod 64 */
+    if (count < 8) {
+	/* Two lots of padding:  Pad the first block to 64 bytes */
+	os_memset(p, 0, count);
+	byteReverse(ctx->in, 16);
+	MD5Transform(ctx->buf, (u32 *) ctx->in);
+
+	/* Now fill the next block with 56 bytes */
+	os_memset(ctx->in, 0, 56);
+    } else {
+	/* Pad block to 56 bytes */
+	os_memset(p, 0, count - 8);
+    }
+    byteReverse(ctx->in, 14);
+
+    /* Append length in bits and transform */
+    ((u32 *) ctx->in)[14] = ctx->bits[0];
+    ((u32 *) ctx->in)[15] = ctx->bits[1];
+
+    MD5Transform(ctx->buf, (u32 *) ctx->in);
+    byteReverse((unsigned char *) ctx->buf, 4);
+    os_memcpy(digest, ctx->buf, 16);
+    os_memset(ctx, 0, sizeof(*ctx));	/* In case it's sensitive */
+}
+
+/* The four core functions - F1 is optimized somewhat */
+
+/* #define F1(x, y, z) (x & y | ~x & z) */
+#define F1(x, y, z) (z ^ (x & (y ^ z)))
+#define F2(x, y, z) F1(z, x, y)
+#define F3(x, y, z) (x ^ y ^ z)
+#define F4(x, y, z) (y ^ (x | ~z))
+
+/* This is the central step in the MD5 algorithm. */
+#define MD5STEP(f, w, x, y, z, data, s) \
+	( w += f(x, y, z) + data,  w = w<<s | w>>(32-s),  w += x )
+
+/*
+ * The core of the MD5 algorithm, this alters an existing MD5 hash to
+ * reflect the addition of 16 longwords of new data.  MD5Update blocks
+ * the data and converts bytes into longwords for this routine.
+ */
+static void MD5Transform(u32 buf[4], u32 const in[16])
+{
+    register u32 a, b, c, d;
+
+    a = buf[0];
+    b = buf[1];
+    c = buf[2];
+    d = buf[3];
+
+    MD5STEP(F1, a, b, c, d, in[0] + 0xd76aa478, 7);
+    MD5STEP(F1, d, a, b, c, in[1] + 0xe8c7b756, 12);
+    MD5STEP(F1, c, d, a, b, in[2] + 0x242070db, 17);
+    MD5STEP(F1, b, c, d, a, in[3] + 0xc1bdceee, 22);
+    MD5STEP(F1, a, b, c, d, in[4] + 0xf57c0faf, 7);
+    MD5STEP(F1, d, a, b, c, in[5] + 0x4787c62a, 12);
+    MD5STEP(F1, c, d, a, b, in[6] + 0xa8304613, 17);
+    MD5STEP(F1, b, c, d, a, in[7] + 0xfd469501, 22);
+    MD5STEP(F1, a, b, c, d, in[8] + 0x698098d8, 7);
+    MD5STEP(F1, d, a, b, c, in[9] + 0x8b44f7af, 12);
+    MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1, 17);
+    MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7be, 22);
+    MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122, 7);
+    MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193, 12);
+    MD5STEP(F1, c, d, a, b, in[14] + 0xa679438e, 17);
+    MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821, 22);
+
+    MD5STEP(F2, a, b, c, d, in[1] + 0xf61e2562, 5);
+    MD5STEP(F2, d, a, b, c, in[6] + 0xc040b340, 9);
+    MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51, 14);
+    MD5STEP(F2, b, c, d, a, in[0] + 0xe9b6c7aa, 20);
+    MD5STEP(F2, a, b, c, d, in[5] + 0xd62f105d, 5);
+    MD5STEP(F2, d, a, b, c, in[10] + 0x02441453, 9);
+    MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681, 14);
+    MD5STEP(F2, b, c, d, a, in[4] + 0xe7d3fbc8, 20);
+    MD5STEP(F2, a, b, c, d, in[9] + 0x21e1cde6, 5);
+    MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6, 9);
+    MD5STEP(F2, c, d, a, b, in[3] + 0xf4d50d87, 14);
+    MD5STEP(F2, b, c, d, a, in[8] + 0x455a14ed, 20);
+    MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905, 5);
+    MD5STEP(F2, d, a, b, c, in[2] + 0xfcefa3f8, 9);
+    MD5STEP(F2, c, d, a, b, in[7] + 0x676f02d9, 14);
+    MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20);
+
+    MD5STEP(F3, a, b, c, d, in[5] + 0xfffa3942, 4);
+    MD5STEP(F3, d, a, b, c, in[8] + 0x8771f681, 11);
+    MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122, 16);
+    MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380c, 23);
+    MD5STEP(F3, a, b, c, d, in[1] + 0xa4beea44, 4);
+    MD5STEP(F3, d, a, b, c, in[4] + 0x4bdecfa9, 11);
+    MD5STEP(F3, c, d, a, b, in[7] + 0xf6bb4b60, 16);
+    MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70, 23);
+    MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6, 4);
+    MD5STEP(F3, d, a, b, c, in[0] + 0xeaa127fa, 11);
+    MD5STEP(F3, c, d, a, b, in[3] + 0xd4ef3085, 16);
+    MD5STEP(F3, b, c, d, a, in[6] + 0x04881d05, 23);
+    MD5STEP(F3, a, b, c, d, in[9] + 0xd9d4d039, 4);
+    MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5, 11);
+    MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16);
+    MD5STEP(F3, b, c, d, a, in[2] + 0xc4ac5665, 23);
+
+    MD5STEP(F4, a, b, c, d, in[0] + 0xf4292244, 6);
+    MD5STEP(F4, d, a, b, c, in[7] + 0x432aff97, 10);
+    MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7, 15);
+    MD5STEP(F4, b, c, d, a, in[5] + 0xfc93a039, 21);
+    MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3, 6);
+    MD5STEP(F4, d, a, b, c, in[3] + 0x8f0ccc92, 10);
+    MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47d, 15);
+    MD5STEP(F4, b, c, d, a, in[1] + 0x85845dd1, 21);
+    MD5STEP(F4, a, b, c, d, in[8] + 0x6fa87e4f, 6);
+    MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10);
+    MD5STEP(F4, c, d, a, b, in[6] + 0xa3014314, 15);
+    MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1, 21);
+    MD5STEP(F4, a, b, c, d, in[4] + 0xf7537e82, 6);
+    MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235, 10);
+    MD5STEP(F4, c, d, a, b, in[2] + 0x2ad7d2bb, 15);
+    MD5STEP(F4, b, c, d, a, in[9] + 0xeb86d391, 21);
+
+    buf[0] += a;
+    buf[1] += b;
+    buf[2] += c;
+    buf[3] += d;
+}
+/* ===== end - public domain MD5 implementation ===== */
+
diff --git a/extensions/app_sip/md5.h b/extensions/app_sip/md5.h
new file mode 100644
index 0000000..fc55872
--- /dev/null
+++ b/extensions/app_sip/md5.h
@@ -0,0 +1,59 @@
+/*********************************************************************************/
+/* freeDiameter author note:
+ *  The content from this file comes directly from the hostap project.
+ * It is redistributed under the terms of the BSD license, as allowed
+ * by the original copyright reproduced below.
+ *  The file has not been modified, except for this notice.
+ */
+/*********************************************************************************/
+
+/*
+ * MD5 hash implementation and interface functions
+ * Copyright (c) 2003-2005, Jouni Malinen <j@w1.fi>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Alternatively, this software may be distributed under the terms of BSD
+ * license.
+ *
+ * See README and COPYING for more details.
+ */
+
+#ifndef MD5_H
+#define MD5_H
+
+#define MD5_MAC_LEN 16
+
+typedef uint64_t u64;
+typedef uint32_t u32;
+typedef uint16_t u16;
+typedef uint8_t u8;
+typedef int64_t s64;
+typedef int32_t s32;
+typedef int16_t s16;
+typedef int8_t s8;
+
+#define HASHLEN 16
+typedef char HASH[HASHLEN];
+#define HASHHEXLEN 32
+typedef char HASHHEX[HASHHEXLEN+1];
+#define IN
+#define OUT
+
+struct MD5Context {
+	u32 buf[4];
+	u32 bits[2];
+	u8 in[64];
+};
+typedef struct MD5Context MD5_CTX;
+#define os_memcpy(d, s, n) memcpy((d), (s), (n))
+#define os_memset(s, c, n) memset(s, c, n)
+
+
+void MD5Init(struct MD5Context *ctx);
+void MD5Update(struct MD5Context *ctx, unsigned char const *buf, unsigned len);
+void MD5Final(unsigned char digest[16], struct MD5Context *ctx);
+
+#endif /* MD5_H */
diff --git a/extensions/app_sip/multimediaauth.c b/extensions/app_sip/multimediaauth.c
new file mode 100644
index 0000000..12c1bcb
--- /dev/null
+++ b/extensions/app_sip/multimediaauth.c
@@ -0,0 +1,762 @@
+/*********************************************************************************************************
+* Software License Agreement (BSD License)                                                               *
+* Author: Alexandre Westfahl <awestfahl@freediameter.net>						 *
+*													 *
+* Copyright (c) 2010, Alexandre Westfahl, Teraoka Laboratory (Keio University), and the WIDE Project. 	 *		
+*													 *
+* All rights reserved.											 *
+* 													 *
+* Redistribution and use of this software in source and binary forms, with or without modification, are  *
+* permitted provided that the following conditions are met:						 *
+* 													 *
+* * Redistributions of source code must retain the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer.										 *
+*    													 *
+* * Redistributions in binary form must reproduce the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer in the documentation and/or other						 *
+*   materials provided with the distribution.								 *
+* 													 *
+* * Neither the name of the Teraoka Laboratory nor the 							 *
+*   names of its contributors may be used to endorse or 						 *
+*   promote products derived from this software without 						 *
+*   specific prior written permission of Teraoka Laboratory 						 *
+*   													 *
+* 													 *
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED *
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
+* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR *
+* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 	 *
+* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 	 *
+* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR *
+* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF   *
+* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.								 *
+*********************************************************************************************************/
+#include "app_sip.h"
+
+struct sess_state
+{
+	char *nonce;
+};
+
+
+int app_sip_MAR_cb( struct msg ** msg, struct avp * paramavp, struct session * sess, void * opaque, enum disp_action * act)
+{
+	struct msg *ans, *qry;
+	struct avp *avp, *a2, *authdataitem;
+	//struct msg_hdr * header = NULL;
+	struct avp_hdr * avphdr=NULL, *avpheader=NULL, *avpheader_auth=NULL,*digestheader=NULL;
+	union avp_value val;
+	int found_cnonce=0;
+	struct avp * tempavp=NULL,*sipAuthentication=NULL,*sipAuthenticate=NULL;
+	char * result;
+	char password[51];
+	int idx=0, number_of_auth_items=0,i=0, ret=0;
+	//Flags and variables for Database
+	int sipurinotstored=0, authenticationpending=0; 
+	size_t querylen=0, usernamelen=0;
+	char *query=NULL;
+	unsigned char *username=NULL;
+	
+	//The nonce we will store and retrieve in session
+	struct sess_state *storednonce=NULL;
+	
+	
+	TRACE_ENTRY("%p %p %p %p", msg, paramavp, sess, act);
+	
+	if (msg == NULL)
+		return EINVAL;
+
+	
+	/* Create answer header */
+	qry = *msg;
+	CHECK_FCT( fd_msg_new_answer_from_req ( fd_g_config->cnf_dict, msg, 0 ) );
+	ans = *msg;
+	
+
+
+	/* Add the appropriate command code & Auth-Application-Id 
+	{
+		
+		CHECK_FCT( fd_msg_hdr ( *msg, &header ) );
+		header->msg_flags = CMD_FLAG_PROXIABLE;
+		header->msg_code = 286;
+		header->msg_appl = 6;
+		
+		
+		// Add the Auth-Application-Id 
+		{
+			CHECK_FCT( fd_msg_avp_new ( sip_dict.Auth_Application_Id, 0, &avp ) );
+			ASSERT(avp);
+			val.i32 = header->msg_appl;
+			CHECK_FCT( fd_msg_avp_setvalue ( avp, &val ) );
+			CHECK_FCT( fd_msg_avp_add ( ans, MSG_BRW_LAST_CHILD, avp) );
+		}
+	}*/
+	
+	
+	/* Add the Auth-Session-State AVP */
+	{
+		
+		CHECK_FCT( fd_msg_search_avp ( qry, sip_dict.Auth_Session_State, &avp) );
+		CHECK_FCT( fd_msg_avp_hdr( avp, &avphdr )  );
+		
+		CHECK_FCT( fd_msg_avp_new ( sip_dict.Auth_Session_State, 0, &avp ) );
+		CHECK_FCT( fd_msg_avp_setvalue( avp, avphdr->avp_value ) );
+		CHECK_FCT( fd_msg_avp_add( ans, MSG_BRW_LAST_CHILD, avp ) );
+	}
+
+	
+	
+	/* Check if method is REGISTER then User-Name must be present */
+	{
+		
+		CHECK_FCT( fd_msg_search_avp ( qry, sip_dict.SIP_Method, &avp) );
+		CHECK_FCT( fd_msg_avp_hdr( avp, &avpheader ));
+		
+
+		char *method=NULL;
+		
+		CHECK_FCT( fd_msg_search_avp ( qry, sip_dict.User_Name, &avp) );
+		if(avp!=NULL)
+		{
+			
+			int not_found=1;
+			MYSQL_RES *res=NULL;
+			MYSQL_ROW row;
+			
+			CHECK_FCT( fd_msg_avp_hdr( avp, &avphdr )  );
+			
+			
+			
+			
+			if((strncmp((const char *)avpheader->avp_value->os.data,"REGISTER",avpheader->avp_value->os.len)==0))
+			{
+				not_found=1;
+				
+				//TODO TODO TODO TODO TODO TODO TODO: maybe doesn't work!!'
+				ret=get_password(avphdr->avp_value->os.data, avphdr->avp_value->os.len, (char *)&password);
+				
+				if(ret>1)
+				{
+					//We couldn't make the request
+					result="DIAMETER_UNABLE_TO_COMPLY";
+					goto out;
+				}
+				not_found=ret;
+				
+				if(not_found)
+				{
+					TRACE_DEBUG(FULL,"The user %s doesn't exist!",username);
+					result="DIAMETER_ERROR_USER_UNKNOWN";
+					free(username);	
+					goto out;
+				}
+			
+			
+				//We allocate the double size of username because at worst it can be all quotes
+				username=malloc(avphdr->avp_value->os.len*2+1);
+				//We purify username not to have forbidden characters
+				usernamelen=mysql_real_escape_string(conn, (char *)username, (const char *)avphdr->avp_value->os.data, avphdr->avp_value->os.len);
+				
+				//Now that we know the user exist, we get the list of AOR owned by this user
+				querylen=SQL_GETSIPAOR_LEN + usernamelen;
+				query = malloc(querylen+2);
+				snprintf(query, querylen+1, SQL_GETSIPAOR, username);
+			
+				//We make the query
+				request_mysql(query);
+				res=mysql_use_result(conn);
+				if(res==NULL)
+				{
+					//We couldn't make the request
+					result="DIAMETER_UNABLE_TO_COMPLY";
+					goto out;
+				}
+			
+				//We retrieve the SIP-AOR from AVP to check if the user can us it
+				CHECK_FCT( fd_msg_search_avp ( qry, sip_dict.SIP_AOR, &avp) );
+				CHECK_FCT( fd_msg_avp_hdr( avp, &avphdr )  );
+			
+				not_found=1;
+				while ((row = mysql_fetch_row(res)) != NULL)
+				{
+					if(strncmp((const char *)avphdr->avp_value->os.data,row[0],avphdr->avp_value->os.len)==0)
+					{
+						not_found=0;
+						break;
+					}
+				}
+				mysql_free_result(res);
+				free(query);
+      				
+				if(not_found)
+				{
+					TRACE_DEBUG(FULL,"The user %s can't use this SIP-AOR!",username);
+					result="DIAMETER_ERROR_IDENTITIES_DONT_MATCH";
+					free(username);	
+					goto out;
+				}
+				
+			}
+
+			CHECK_FCT( fd_msg_search_avp ( qry, sip_dict.SIP_Server_URI, &avp) );
+			CHECK_FCT( fd_msg_avp_hdr( avp, &avphdr ));
+			
+			if(avphdr!=NULL)
+			{
+				unsigned char *sipuri=NULL;
+				int sipurilen=0;
+
+				//We allocate the double size of SIP-URI because at worst it can be all quotes
+				CHECK_MALLOC(sipuri=malloc(avphdr->avp_value->os.len*2+1));
+				//We purify SIP-URI not to have forbidden characters
+				sipurilen=mysql_real_escape_string(conn, (char *)sipuri, (const char *)avphdr->avp_value->os.data, avphdr->avp_value->os.len);
+				
+				
+				//We get the SIP-URI assignated to the user
+				querylen=SQL_GETSIPURI_LEN + usernamelen;
+				CHECK_MALLOC(query = malloc(querylen+2));
+				snprintf(query, querylen+1, SQL_GETSIPURI, username);
+
+				//We make the query
+				request_mysql(query);
+				res=mysql_use_result(conn);
+				if(res==NULL)
+				{
+					//We couldn't make the request
+					result="DIAMETER_UNABLE_TO_COMPLY";
+					goto out;
+				}
+				not_found=1;
+				while ((row = mysql_fetch_row(res)) != NULL)
+				{
+					if(strncmp((const char *)avphdr->avp_value->os.data,row[0],avphdr->avp_value->os.len)==0)
+					{
+						not_found=0;
+						break;
+					}
+				}
+				mysql_free_result(res);
+				free(query);
+
+				if(not_found)
+				{
+					//Temporary
+					set_sipserver_uri(username, usernamelen, sipuri,sipurilen);
+					
+					
+					set_pending_flag(username, usernamelen);
+					
+					
+					authenticationpending=1;
+				}
+				free(sipuri);
+				
+			}
+			else
+				sipurinotstored=1;
+
+		}
+		else
+		{
+			result="DIAMETER_USER_NAME_REQUIRED";
+			goto out;
+		}
+
+			
+		free(method);
+
+	}
+
+	
+	//TODO: remove loop for authdataitem because RFC say only one (wait for answer from Garcia)
+	// How many Auth Data Items?
+	CHECK_FCT( fd_msg_search_avp ( qry, sip_dict.SIP_Number_Auth_Items, &avp) );
+	CHECK_FCT( fd_msg_avp_hdr( avp, &avpheader )  );
+	
+	
+	if(avp!=NULL)
+	{
+		CHECK_FCT(fd_msg_search_avp ( qry, sip_dict.SIP_Auth_Data_Item, &avp));
+		CHECK_FCT( fd_msg_avp_hdr( avp, &avphdr )  );
+		
+		if(avp!=NULL)
+		{
+			//First is Authentication Scheme
+			CHECK_FCT(fd_msg_browse ( avp, MSG_BRW_FIRST_CHILD, &avp, NULL) );
+			CHECK_FCT( fd_msg_avp_hdr( avp, &avphdr )  );
+			
+			//Digest-Authentication?
+			if(avphdr->avp_value->i32==0)
+			{
+				
+				for(idx=0;idx<avpheader->avp_value->i32;idx++)
+				{
+					//We look for SIP Auth items
+					CHECK_FCT(fd_msg_browse ( avp, MSG_BRW_WALK, &avp, NULL) );
+					
+					if(avp!=NULL)
+					{
+						
+						CHECK_FCT( fd_msg_avp_hdr( avp,&avphdr ));
+		
+						if(avphdr->avp_code==380) //We only create Auth-Data-Item to answer Auth-Data-Item
+						{
+							/* Add the Auth-Data-Item AVP */
+							CHECK_FCT( fd_msg_avp_new ( sip_dict.SIP_Auth_Data_Item, 0, &authdataitem ) );
+					
+							/* Add the Authentication Scheme AVP */
+							{
+								CHECK_FCT( fd_msg_avp_new ( sip_dict.SIP_Authentication_Scheme, 0, &a2 ) );
+								val.i32=0; //We only know Digest Authentication
+								CHECK_FCT( fd_msg_avp_setvalue( a2, &val ) );
+								CHECK_FCT( fd_msg_avp_add( authdataitem, MSG_BRW_LAST_CHILD, a2 ) );
+							}
+							
+							//We need to know if there is a Cnonce attribute (only in the second MAR request)
+							
+							//CHECK_FCT(fd_msg_browse ( avp, MSG_BRW_WALK, &avp, NULL) );
+							
+							
+							CHECK_FCT(fd_avp_search_avp (avp, sip_dict.Digest_CNonce, &a2 ));
+							
+							if(a2!=NULL)
+								found_cnonce=1;
+							else
+								found_cnonce=0;
+								
+							if(!found_cnonce)
+							{
+								/*
+								We are in the case of first access request so we need to challenge the user.
+								*/
+								TRACE_DEBUG(FULL,"First Authorization in progress...");
+
+								/* Create a new session */ //this create a new session Id !!!
+								//CHECK_FCT_DO( fd_sess_new( &sess, fd_g_config->cnf_diamid, "diamsip", 7), goto out );
+								
+
+								/* Create the SIP-Authenticate AVP */
+								{
+									CHECK_FCT( fd_msg_avp_new ( sip_dict.SIP_Authenticate, 0, &sipAuthenticate ) );
+								}						
+
+								/* Add the Digest QOP AVP */
+								{
+									CHECK_FCT( fd_msg_avp_new ( sip_dict.Digest_QOP, 0, &a2 ) );
+									val.os.data=(unsigned char *)"auth";
+									val.os.len=strlen((const char *)val.os.data);
+									CHECK_FCT( fd_msg_avp_setvalue( a2, &val ) );
+									CHECK_FCT( fd_msg_avp_add( sipAuthenticate, MSG_BRW_LAST_CHILD, a2 ) );
+								}
+								/* Add the Digest Nonce AVP */
+								{
+									uint8_t buffer[NONCE_SIZE];
+									char nonce[NONCE_SIZE * 2 + 1];
+							
+								
+									gcry_create_nonce ((uint8_t *)buffer, sizeof(buffer));
+							
+									for(i=0;i<NONCE_SIZE;i++)
+										sprintf(&nonce[2 * i], "%2.2hhx", buffer[i]);
+								
+									CHECK_FCT( fd_msg_avp_new ( sip_dict.Digest_Nonce, 0, &a2 ) );
+									
+									
+									//We store the nonce (storednonce structure) inside the session
+									storednonce=malloc(sizeof(struct sess_state));
+									memset(storednonce,0,sizeof(struct sess_state));
+									CHECK_MALLOC(storednonce->nonce=malloc(NONCE_SIZE*2+1));
+									memcpy(storednonce->nonce,(char *)nonce,NONCE_SIZE*2+1);
+									CHECK_FCT( fd_sess_state_store ( ds_sess_hdl, sess, &storednonce ));  
+									
+									val.os.data=(unsigned char *)nonce;
+									val.os.len=NONCE_SIZE * 2;
+									
+									CHECK_FCT( fd_msg_avp_setvalue( a2, &val ) );
+									CHECK_FCT( fd_msg_avp_add( sipAuthenticate, MSG_BRW_LAST_CHILD, a2 ) );
+								}
+								/* Add the Digest Algorithm AVP */
+								{
+									CHECK_FCT( fd_msg_avp_new ( sip_dict.Digest_Algorithm, 0, &a2 ) );
+									val.os.data=(unsigned char *)"MD5";
+									val.os.len=strlen((const char *)val.os.data);
+									CHECK_FCT( fd_msg_avp_setvalue( a2, &val ) );
+									CHECK_FCT( fd_msg_avp_add( sipAuthenticate, MSG_BRW_LAST_CHILD, a2 ) );
+							
+								}
+								/* Add the Digest Realm AVP */
+								{
+									tempavp=avp;
+								
+									avpheader_auth=walk_digest(tempavp, 104);
+									if(avpheader_auth!=NULL)
+									{
+										CHECK_FCT( fd_msg_avp_new ( sip_dict.Digest_Realm, 0, &a2 ) );
+										CHECK_FCT( fd_msg_avp_setvalue( a2, avpheader_auth->avp_value ) );
+										CHECK_FCT( fd_msg_avp_add( sipAuthenticate, MSG_BRW_LAST_CHILD, a2 ) );
+								
+									}
+								}
+						
+						
+								//We add SIP Authenticate to Auth Data Item
+								CHECK_FCT( fd_msg_avp_add( authdataitem, MSG_BRW_LAST_CHILD, sipAuthenticate ) );
+								//We add Auth Data Item to Answer
+								CHECK_FCT( fd_msg_avp_add( ans, MSG_BRW_LAST_CHILD, authdataitem ) );
+						
+								number_of_auth_items++;
+								if(sipurinotstored)
+									result="DIAMETER_SUCCESS_AUTH_SENT_SERVER_NOT_STORED";
+								else
+									result="DIAMETER_MULTI_ROUND_AUTH";
+								found_cnonce=0;
+							}
+							else
+							{
+								/*
+								We are in the case of access request after challenge so we need to check credentials.
+								*/
+								TRACE_DEBUG(FULL,"Authentication after challenge");
+								
+								/* Search the session, retrieve its data */
+								{
+									//int new=0;
+									
+									//TRACE_DEBUG(FULL,"new: *%d*",new);
+									//ASSERT( new == 0 );
+									CHECK_FCT( fd_sess_state_retrieve( ds_sess_hdl, sess, &storednonce ));
+									if(storednonce ==NULL)
+									{
+										result="DIAMETER_UNABLE_TO_COMPLY";
+												
+										if(username!=NULL)
+											free(username);
+										goto out;
+									}
+								}
+								
+								/* Create the SIP-Authentication-Info AVP */
+								{
+									CHECK_FCT( fd_msg_avp_new ( sip_dict.SIP_Authentication_Info, 0, &sipAuthentication ) );
+								}
+								
+								
+							
+								/* Add the Digest response Auth AVP */
+								{
+									//uint8_t bufferresp[DIGEST_LEN];
+									//char response[DIGEST_LEN*2+1];
+									
+									
+									//We extract all the data we need
+									tempavp=avp;
+									
+									char * digest_username=NULL, *digest_uri=NULL, *digest_response=NULL, *digest_realm=NULL, *digest_nonce=NULL, *digest_method=NULL, *digest_qop=NULL, *digest_algorithm=NULL, *digest_cnonce=NULL, *digest_noncecount=NULL;
+									
+									
+									CHECK_FCT(fd_avp_search_avp (avp, sip_dict.Digest_Nonce, &a2 ));
+									if(a2!=NULL)
+									{
+										CHECK_FCT( fd_msg_avp_hdr( a2, &digestheader )  );
+										if(digestheader!=NULL)
+										{
+											
+											digest_nonce = malloc(digestheader->avp_value->os.len + 1);
+											memcpy(digest_nonce, digestheader->avp_value->os.data,
+											digestheader->avp_value->os.len);
+											digest_nonce[digestheader->avp_value->os.len]='\0';
+											TRACE_DEBUG(FULL,"Element:*%s*",digest_nonce);	
+											TRACE_DEBUG(FULL,"Stored Nonce:*%s*",storednonce->nonce);
+											
+											if(strcmp(digest_nonce,storednonce->nonce)!=0)
+											{
+												free(digest_nonce);
+												free(storednonce->nonce);
+												free(storednonce);
+												result="DIAMETER_UNABLE_TO_COMPLY";
+												
+												if(username!=NULL)
+													free(username);
+												goto out;
+											}
+											
+										}
+											
+									}
+									CHECK_FCT(fd_avp_search_avp (avp, sip_dict.Digest_Response, &a2 ));
+									if(a2!=NULL)
+									{
+										CHECK_FCT( fd_msg_avp_hdr( a2, &digestheader )  );
+										if(digestheader!=NULL)
+										{
+											digest_response = malloc(digestheader->avp_value->os.len + 1);
+											memcpy(digest_response, digestheader->avp_value->os.data,
+											digestheader->avp_value->os.len);
+											digest_response[digestheader->avp_value->os.len]='\0';
+											TRACE_DEBUG(FULL,"Element:*%s*",digest_response);	
+										}
+										
+									}
+									CHECK_FCT(fd_avp_search_avp (avp, sip_dict.Digest_Realm, &a2 ));
+									if(a2!=NULL)
+									{
+										CHECK_FCT( fd_msg_avp_hdr( a2, &digestheader )  );
+										if(digestheader!=NULL)
+										{
+											digest_realm = malloc(digestheader->avp_value->os.len + 1);
+											memcpy(digest_realm, digestheader->avp_value->os.data,
+											digestheader->avp_value->os.len);
+											digest_realm[digestheader->avp_value->os.len]='\0';
+											TRACE_DEBUG(FULL,"Element:*%s*",digest_realm);	
+										}
+									}
+									
+									CHECK_FCT(fd_avp_search_avp (avp, sip_dict.Digest_Method, &a2 ));
+									if(a2!=NULL)
+									{
+										CHECK_FCT( fd_msg_avp_hdr( a2, &digestheader )  );
+										if(digestheader!=NULL)
+										{
+											digest_method = malloc(digestheader->avp_value->os.len + 1);
+											memcpy(digest_method, digestheader->avp_value->os.data,
+											digestheader->avp_value->os.len);
+											digest_method[digestheader->avp_value->os.len]='\0';
+											TRACE_DEBUG(FULL,"Element:*%s*",digest_method);	
+										}
+									}
+									else
+										digest_method="";
+									
+									CHECK_FCT(fd_avp_search_avp (avp, sip_dict.Digest_URI, &a2 ));
+									if(a2!=NULL)
+									{
+										CHECK_FCT( fd_msg_avp_hdr( a2, &digestheader )  );
+										if(digestheader!=NULL)
+										{
+											digest_uri = malloc(digestheader->avp_value->os.len + 1);
+											memcpy(digest_uri, digestheader->avp_value->os.data,
+											digestheader->avp_value->os.len);
+											digest_uri[digestheader->avp_value->os.len]='\0';
+											TRACE_DEBUG(FULL,"Element:*%s*",digest_uri);	
+										}
+									}
+									
+									CHECK_FCT(fd_avp_search_avp (avp, sip_dict.Digest_QOP, &a2 ));
+									if(a2!=NULL)
+									{
+										CHECK_FCT( fd_msg_avp_hdr( a2, &digestheader )  );
+										if(digestheader!=NULL)
+										{
+											digest_qop = malloc(digestheader->avp_value->os.len + 1);
+											memcpy(digest_qop, digestheader->avp_value->os.data,
+											digestheader->avp_value->os.len);
+											digest_qop[digestheader->avp_value->os.len]='\0';
+											TRACE_DEBUG(FULL,"Element:*%s*",digest_qop);	
+										}
+									}
+									else
+										digest_qop=NULL;
+									CHECK_FCT(fd_avp_search_avp (avp, sip_dict.Digest_Algorithm, &a2 ));
+									if(a2!=NULL)
+									{
+										CHECK_FCT( fd_msg_avp_hdr( a2, &digestheader )  );
+										if(digestheader!=NULL)
+										{
+											digest_algorithm = malloc(digestheader->avp_value->os.len + 1);
+											memcpy(digest_algorithm, digestheader->avp_value->os.data,
+											digestheader->avp_value->os.len);
+											digest_algorithm[digestheader->avp_value->os.len]='\0';
+											TRACE_DEBUG(FULL,"Element:*%s*",digest_algorithm);	
+										}
+									}
+									else
+										digest_algorithm=NULL;
+									CHECK_FCT(fd_avp_search_avp (avp, sip_dict.Digest_CNonce, &a2 ));
+									if(a2!=NULL)
+									{
+										CHECK_FCT( fd_msg_avp_hdr( a2, &digestheader )  );
+										if(digestheader!=NULL)
+										{
+											digest_cnonce = malloc(digestheader->avp_value->os.len + 1);
+											memcpy(digest_cnonce, digestheader->avp_value->os.data,
+											digestheader->avp_value->os.len);
+											digest_cnonce[digestheader->avp_value->os.len]='\0';
+											TRACE_DEBUG(FULL,"Element:*%s*",digest_cnonce);	
+										}
+									}
+									else
+										digest_cnonce="";
+									CHECK_FCT(fd_avp_search_avp (avp, sip_dict.Digest_Nonce_Count, &a2 ));
+									if(a2!=NULL)
+									{
+										CHECK_FCT( fd_msg_avp_hdr( a2, &digestheader )  );
+										if(digestheader!=NULL)
+										{
+											digest_noncecount = malloc(digestheader->avp_value->os.len + 1);
+											memcpy(digest_noncecount, digestheader->avp_value->os.data,
+											digestheader->avp_value->os.len);
+											digest_noncecount[digestheader->avp_value->os.len]='\0';
+											TRACE_DEBUG(FULL,"Element:*%s*",digest_noncecount);	
+										}
+									}
+									else
+										digest_noncecount="";
+									CHECK_FCT(fd_avp_search_avp (avp, sip_dict.Digest_Username, &a2 ));
+									if(a2!=NULL)
+									{
+										CHECK_FCT( fd_msg_avp_hdr( a2, &digestheader )  );
+										if(digestheader!=NULL)
+										{
+											digest_username = malloc(digestheader->avp_value->os.len + 1);
+											memcpy(digest_username, digestheader->avp_value->os.data,
+											digestheader->avp_value->os.len);
+											digest_username[digestheader->avp_value->os.len]='\0';
+											TRACE_DEBUG(FULL,"Element:*%s*",digest_username);	
+										}
+									}
+									//TODO: replace by authentication function
+									
+									HASHHEX HA1;
+									HASHHEX HA2 = "";
+									HASHHEX response, responseauth;
+
+									
+									DigestCalcHA1(digest_algorithm, digest_username, digest_realm, password, digest_nonce,digest_cnonce, HA1);
+      								DigestCalcResponse(HA1, digest_nonce, digest_noncecount, digest_cnonce, digest_qop,digest_method, digest_uri, HA2, response);
+      									
+		
+									// We check that the Digest-Response is the same (UA, Diameter)
+									if(strcmp(response,digest_response)!=0)
+									{
+										TRACE_DEBUG(FULL,"Response calculated by Diameter server:%s",response);
+										TRACE_DEBUG(FULL,"Response calculated by UA:%s",digest_response);
+										TRACE_DEBUG(INFO,"Digest-Response does not match!");
+										result="DIAMETER_UNABLE_TO_COMPLY";
+										free(digest_algorithm);
+										free(digest_cnonce);
+										free(digest_nonce);
+										free(digest_noncecount);
+										free(digest_method);
+										free(digest_username);
+										free(digest_uri);
+										free(digest_qop);
+										free(digest_response);
+										free(digest_realm);
+										free(storednonce->nonce);
+										free(storednonce);
+										if(username!=NULL)
+											free(username);
+										goto out;
+										
+									}
+									//We calculate Digest_Response_Auth
+									DigestCalcResponseAuth(HA1, digest_nonce, digest_noncecount, digest_cnonce, digest_qop,digest_method, digest_uri, HA2, responseauth);
+									
+									TRACE_DEBUG(FULL,"Response calculated by Diameter server:%s",response);
+										TRACE_DEBUG(FULL,"Response calculated by UA:%s",digest_response);
+									if(strcmp(digest_qop,"auth-int")==0)
+									{
+										//Digest-HA1 MUST be used instead of Digest-Response-Auth if Digest-Qop is 'auth-int'.
+										CHECK_FCT( fd_msg_avp_new ( sip_dict.Digest_HA1, 0, &a2 ) );
+										val.os.data=(unsigned char *)HA1;
+										val.os.len=HASHHEXLEN+1;
+										CHECK_FCT( fd_msg_avp_setvalue( a2, &val ) );
+										CHECK_FCT( fd_msg_avp_add( sipAuthentication, MSG_BRW_LAST_CHILD, a2 ) );
+									}
+									else
+									{
+										//Digest-Response-Auth MUST be used instead of Digest-HA1 if Digest-Qop is 'auth'.
+										CHECK_FCT( fd_msg_avp_new ( sip_dict.Digest_Response_Auth, 0, &a2 ) );
+										val.os.data=(unsigned char *)responseauth;
+										val.os.len=DIGEST_LEN*2;
+										CHECK_FCT( fd_msg_avp_setvalue( a2, &val ) );
+										CHECK_FCT( fd_msg_avp_add( sipAuthentication, MSG_BRW_LAST_CHILD, a2 ) );
+									}
+									free(digest_algorithm);
+									free(digest_cnonce);
+									free(digest_nonce);
+									free(digest_noncecount);
+									free(digest_method);
+									free(digest_username);
+									free(digest_uri);
+									free(digest_qop);
+									free(digest_response);
+									free(digest_realm);
+									free(storednonce->nonce);
+									free(storednonce);
+								
+									number_of_auth_items++;
+								}	
+								
+								
+								//We add SIP Authentication-Info to Auth Data Item
+								CHECK_FCT( fd_msg_avp_add( authdataitem, MSG_BRW_LAST_CHILD, sipAuthentication ) );
+								//We add Auth Data Item to Answer
+								CHECK_FCT( fd_msg_avp_add( ans, MSG_BRW_LAST_CHILD, authdataitem ) );
+								
+								
+								if(username!=NULL && authenticationpending)
+								{
+									//We clear the pending flag
+									clear_pending_flag(username, usernamelen);
+								}
+								
+								if(sipurinotstored)
+									result="DIAMETER_SUCCESS_SERVER_NAME_NOT_STORED";
+								else
+									result="DIAMETER_SUCCESS";
+								found_cnonce=0;
+							}
+						}
+					}
+					else
+						TRACE_DEBUG(INFO,"No auth data items!");
+				}
+				/*Add SIP_Number_Auth_Items  AVP */
+				{
+					CHECK_FCT( fd_msg_avp_new ( sip_dict.SIP_Number_Auth_Items, 0, &avp ) );
+					val.i32 = number_of_auth_items;
+					CHECK_FCT( fd_msg_avp_setvalue ( avp, &val ) );
+					CHECK_FCT( fd_msg_avp_add ( ans, MSG_BRW_LAST_CHILD, avp) );
+				}
+				
+				
+			}
+			else
+			{
+				TRACE_DEBUG(INFO,"We only support DIGEST for now, unable to comply");
+				result="DIAMETER_ERROR_AUTH_SCHEME_NOT_SUPPORTED";
+				if(username!=NULL)
+					free(username);
+				goto out;
+			}
+		}
+	}
+	else
+	{
+		//TODO: remove this because Number_Auth_Items is not compulsory
+		TRACE_DEBUG(FULL,"Number-Auth-Items is not included.");
+		result="DIAMETER_UNABLE_TO_COMPLY";
+		if(username!=NULL)
+			free(username);
+		goto out;
+	}
+	
+	if(username!=NULL)
+		free(username);
+	
+
+out:
+	/* Set the Origin-Host, Origin-Realm, Result-Code AVPs */
+	CHECK_FCT( fd_msg_rescode_set( ans, result, NULL, NULL, 1 ) );
+	
+	
+	/* Send the answer */
+	CHECK_FCT( fd_msg_send( msg, NULL, NULL ) );
+	
+	
+	return 0;
+}
diff --git a/extensions/app_sip/pushprofile.c b/extensions/app_sip/pushprofile.c
new file mode 100644
index 0000000..e6233ed
--- /dev/null
+++ b/extensions/app_sip/pushprofile.c
@@ -0,0 +1,319 @@
+/*********************************************************************************************************
+* Software License Agreement (BSD License)                                                               *
+* Author: Alexandre Westfahl <awestfahl@freediameter.net>						 *
+*													 *
+* Copyright (c) 2010, Alexandre Westfahl, Teraoka Laboratory (Keio University), and the WIDE Project. 	 *		
+*													 *
+* All rights reserved.											 *
+* 													 *
+* Redistribution and use of this software in source and binary forms, with or without modification, are  *
+* permitted provided that the following conditions are met:						 *
+* 													 *
+* * Redistributions of source code must retain the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer.										 *
+*    													 *
+* * Redistributions in binary form must reproduce the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer in the documentation and/or other						 *
+*   materials provided with the distribution.								 *
+* 													 *
+* * Neither the name of the Teraoka Laboratory nor the 							 *
+*   names of its contributors may be used to endorse or 						 *
+*   promote products derived from this software without 						 *
+*   specific prior written permission of Teraoka Laboratory 						 *
+*   													 *
+* 													 *
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED *
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
+* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR *
+* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 	 *
+* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 	 *
+* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR *
+* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF   *
+* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.								 *
+*********************************************************************************************************/
+#include "app_sip.h"
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <unistd.h>
+typedef int SOCKET;
+typedef struct sockaddr_in SOCKADDR_IN;
+typedef struct sockaddr SOCKADDR;
+
+//Procedure which always wait for data on socket 
+void *ppr_socket(void *arg)
+{
+	
+	SOCKET sock;
+    SOCKADDR_IN sin, csin;
+    struct pprsipaor pprsip;
+    int rcvbytes=0;
+	sock = socket(AF_INET, SOCK_STREAM, 0);
+	sin.sin_addr.s_addr = inet_addr("127.0.0.1");
+    sin.sin_family = AF_INET;
+	sin.sin_port = htons(as_conf->ppr_port);
+    socklen_t sinsize = sizeof(csin);
+	int accepted=0;
+
+    
+	if(!bind(sock, (SOCKADDR*)&sin, sizeof(sin)))
+	{
+		if(listen(sock,1))
+		{
+			TRACE_DEBUG(INFO,"ERROR on listen!");
+		}
+		
+		while(1)
+		{
+			accepted=accept(sock, (struct sockaddr *)&csin,&sinsize);
+			if(accepted>-1)
+			{
+				rcvbytes=recv(accepted, &pprsip, sizeof(struct pprsipaor),0);
+				
+				if(rcvbytes>-1)
+				{
+					//We received something, we can send an PPR
+					app_sip_PPR_cb(&pprsip);
+				}
+			}
+		}
+		
+		
+	}
+	else
+		TRACE_DEBUG(INFO,"Can't create socket!");
+
+	
+	pthread_exit(NULL);
+	
+}
+//Called to send a PPR
+int app_sip_PPR_cb(struct pprsipaor *structure)
+{
+	/*
+	TRACE_ENTRY("%p", structure);
+	
+	int got_username=0;
+	int got_streason=0;
+	int num_aor=0;//How many SIP-AOR?
+	struct dict_object * rtr_model=NULL;
+	struct msg * message=NULL;
+	struct avp *groupedavp=NULL, *avp=NULL;
+	struct session *sess=NULL;
+	union avp_value value;
+	
+	//We must check that we have all needed value in structure
+	if(structure.username[0]!='\0')
+		got_username=1;
+	
+	if(structure.sip_aor1[0]!='\0')
+	{	
+		num_aor++;
+		if(structure.sip_aor2[0]!='\0')
+		{
+			num_aor++;
+			if(structure.sip_aor3[0]!='\0')
+				num_aor++;
+		}
+	}
+	
+	if(structure.strreason!='\0')
+		got_streason=1;
+	
+	
+	TRACE_DEBUG(INFO,"We have %d SIP_AOR",num_aor);
+	
+	if((got_username + num_aor)==0)
+	{
+		//We must have a least a SIP_AOR or a Username
+		TRACE_DEBUG(INFO,"Can not proceed because there is no SIP_AOR or Username");
+		return EINVAL;
+	}
+	if(structure.reason<0)
+	{
+		//We must have a least a SIP_AOR or a Username
+		TRACE_DEBUG(INFO,"Incorrect Reason-Code");
+		return EINVAL;
+	}
+	
+	if(structure.desthost[0]=='\0')
+	{
+		//We must have a least a SIP_AOR or a Username
+		TRACE_DEBUG(INFO,"No Destination_Host was provided!");
+		return EINVAL;
+	}
+	//Create the base message for an RTR
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_COMMAND, CMD_BY_NAME, "Registration-Termination-Request", &rtr_model, ENOENT) );
+	CHECK_FCT( fd_msg_new (rtr_model, 0, &message));
+	
+	// Create a new session 
+	{
+		CHECK_FCT( fd_sess_new( &sess, fd_g_config->cnf_diamid, "app_sip", 7 ));
+		char * sid;
+		CHECK_FCT( fd_sess_getsid ( sess, &sid ));
+		CHECK_FCT( fd_msg_avp_new ( sip_dict.Session_Id, 0, &avp ));
+		value.os.data = (uint8_t *)sid;
+		value.os.len  = strlen(sid);
+		CHECK_FCT( fd_msg_avp_setvalue( avp, &value ));
+		CHECK_FCT( fd_msg_avp_add( message, MSG_BRW_FIRST_CHILD, avp ));
+	}
+	
+	
+	//Auth_Session_State
+	{
+		CHECK_FCT( fd_msg_avp_new ( sip_dict.Auth_Session_State, 0, &avp ) );
+		value.i32=1;
+		CHECK_FCT( fd_msg_avp_setvalue( avp, &value ) );
+		CHECK_FCT( fd_msg_avp_add( message, MSG_BRW_LAST_CHILD, avp ) );
+	}
+	
+	//Origin_Host & Origin_Realm
+	CHECK_FCT( fd_msg_add_origin ( message, 0 ));
+	
+	//Destination_Host
+	{
+		CHECK_FCT( fd_msg_avp_new ( sip_dict.Destination_Host, 0, &avp ) );
+		value.os.data=(unsigned char *)structure.desthost;
+		value.os.len=(size_t)strlen(structure.desthost);
+		CHECK_FCT( fd_msg_avp_setvalue( avp, &value ) );
+		CHECK_FCT( fd_msg_avp_add( message, MSG_BRW_LAST_CHILD, avp ) );
+	}
+	
+	
+	//SIP Deregistration Reason (Grouped AVP)
+	{
+		CHECK_FCT( fd_msg_avp_new ( sip_dict.SIP_Deregistration_Reason, 0, &groupedavp ) );
+		
+		//Reason Code
+		CHECK_FCT( fd_msg_avp_new ( sip_dict.SIP_Reason_Code, 0, &avp ) );
+		value.i32=structure.reason;
+		CHECK_FCT( fd_msg_avp_setvalue( avp, &value ) );
+		CHECK_FCT( fd_msg_avp_add( groupedavp, MSG_BRW_LAST_CHILD, avp ) );
+		
+		if(got_streason)
+		{
+			//Reason Info
+			CHECK_FCT( fd_msg_avp_new ( sip_dict.SIP_Reason_Info, 0, &avp ) );
+			value.os.data=(unsigned char *)structure.strreason;
+			value.os.len=(size_t)strlen(structure.strreason);
+			CHECK_FCT( fd_msg_avp_setvalue( avp, &value ) );
+			CHECK_FCT( fd_msg_avp_add( groupedavp, MSG_BRW_LAST_CHILD, avp ) );
+		}
+		
+		//We add the grouped AVP to the message
+		CHECK_FCT( fd_msg_avp_add( message, MSG_BRW_LAST_CHILD, groupedavp ) );
+	}
+	
+	//Username
+	{
+		if(got_username)
+		{
+			CHECK_FCT( fd_msg_avp_new ( sip_dict.User_Name, 0, &avp ) );
+			value.os.data=(unsigned char *)structure.username;
+			value.os.len=(size_t)strlen(structure.username);
+			CHECK_FCT( fd_msg_avp_setvalue( avp, &value ) );
+			CHECK_FCT( fd_msg_avp_add( message, MSG_BRW_LAST_CHILD, avp ) );
+		}
+	}
+	
+	//SIP_AOR
+	{
+		if(num_aor>0)
+		{
+			CHECK_FCT( fd_msg_avp_new ( sip_dict.SIP_AOR, 0, &avp ) );
+			value.os.data=(unsigned char *)structure.sip_aor1;
+			value.os.len=(size_t)strlen(structure.sip_aor1);
+			CHECK_FCT( fd_msg_avp_setvalue( avp, &value ) );
+			CHECK_FCT( fd_msg_avp_add( message, MSG_BRW_LAST_CHILD, avp ) );
+			if(num_aor>1)
+			{
+				CHECK_FCT( fd_msg_avp_new ( sip_dict.SIP_AOR, 0, &avp ) );
+				value.os.data=(unsigned char *)structure.sip_aor2;
+				value.os.len=(size_t)strlen(structure.sip_aor2);
+				CHECK_FCT( fd_msg_avp_setvalue( avp, &value ) );
+				CHECK_FCT( fd_msg_avp_add( message, MSG_BRW_LAST_CHILD, avp ) );
+				if(num_aor>2)
+				{
+					CHECK_FCT( fd_msg_avp_new ( sip_dict.SIP_AOR, 0, &avp ) );
+					value.os.data=(unsigned char *)structure.sip_aor3;
+					value.os.len=(size_t)strlen(structure.sip_aor3);
+					CHECK_FCT( fd_msg_avp_setvalue( avp, &value ) );
+					CHECK_FCT( fd_msg_avp_add( message, MSG_BRW_LAST_CHILD, avp ) );
+				}
+			}
+		}
+	}
+	
+	fd_msg_dump_walk(INFO,message);
+	CHECK_FCT( fd_msg_send( &message, NULL, NULL ));
+	*/
+	return 0;
+}
+
+//Called when an PPA arrive
+int app_sip_PPA_cb( struct msg ** msg, struct avp * paramavp, struct session * sess, void * opaque, enum disp_action * act)
+{
+	//TODO: PPA reception
+/*
+	//TODO:remove unused variables
+	struct msg *ans, *qry;
+	struct avp *avp, *a2, *authdataitem;
+	struct msg_hdr * header = NULL;
+	struct avp_hdr * avphdr=NULL, *avpheader=NULL, *avpheader_auth=NULL,*digestheader=NULL;
+	union avp_value val;
+	int found_cnonce=0;
+	struct avp * tempavp=NULL,*sipAuthentication=NULL,*sipAuthenticate=NULL;
+	char * result;
+	int idx=0, idx2=0, number_of_auth_items=0,i=0;
+	//Flags and variables for Database
+	int sipurinotstored=0, authenticationpending=0, querylen=0, usernamelen=0;
+	char *query=NULL,*username=NULL;
+	
+	
+	
+	TRACE_ENTRY("%p %p %p %p", msg, avp, sess, act);
+	
+	if (msg == NULL)
+		return EINVAL;
+	
+	
+	// Create answer header 
+	qry = *msg;
+	CHECK_FCT( fd_msg_new_answer_from_req ( fd_g_config->cnf_dict, msg, 0 ) );
+	ans = *msg;	
+	
+	
+	// Add the Auth-Session-State AVP 
+	{
+		
+		CHECK_FCT( fd_msg_search_avp ( qry, sip_dict.Auth_Session_State, &avp) );
+		CHECK_FCT( fd_msg_avp_hdr( avp, &avphdr )  );
+		
+		CHECK_FCT( fd_msg_avp_new ( sip_dict.Auth_Session_State, 0, &avp ) );
+		CHECK_FCT( fd_msg_avp_setvalue( avp, avphdr->avp_value ) );
+		CHECK_FCT( fd_msg_avp_add( ans, MSG_BRW_LAST_CHILD, avp ) );
+	}
+	
+	CHECK_FCT( fd_msg_search_avp ( qry, sip_dict.SIP_Deregistration_Reason, &avp) );
+	CHECK_FCT( fd_msg_avp_hdr( avp, &avphdr )  );
+	
+	
+	
+	
+	
+	
+	
+	
+	
+	
+	
+	
+	
+	*/
+	return 0;
+	
+}
+
diff --git a/extensions/app_sip/registrationtermination.c b/extensions/app_sip/registrationtermination.c
new file mode 100644
index 0000000..9300467
--- /dev/null
+++ b/extensions/app_sip/registrationtermination.c
@@ -0,0 +1,315 @@
+/*********************************************************************************************************
+* Software License Agreement (BSD License)                                                               *
+* Author: Alexandre Westfahl <awestfahl@freediameter.net>						 *
+*													 *
+* Copyright (c) 2010, Alexandre Westfahl, Teraoka Laboratory (Keio University), and the WIDE Project. 	 *		
+*													 *
+* All rights reserved.											 *
+* 													 *
+* Redistribution and use of this software in source and binary forms, with or without modification, are  *
+* permitted provided that the following conditions are met:						 *
+* 													 *
+* * Redistributions of source code must retain the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer.										 *
+*    													 *
+* * Redistributions in binary form must reproduce the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer in the documentation and/or other						 *
+*   materials provided with the distribution.								 *
+* 													 *
+* * Neither the name of the Teraoka Laboratory nor the 							 *
+*   names of its contributors may be used to endorse or 						 *
+*   promote products derived from this software without 						 *
+*   specific prior written permission of Teraoka Laboratory 						 *
+*   													 *
+* 													 *
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED *
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
+* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR *
+* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 	 *
+* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 	 *
+* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR *
+* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF   *
+* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.								 *
+*********************************************************************************************************/
+#include "app_sip.h"
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <unistd.h>
+typedef int SOCKET;
+typedef struct sockaddr_in SOCKADDR_IN;
+typedef struct sockaddr SOCKADDR;
+
+//Procedure which always wait for data on socket 
+void *rtr_socket(void *arg)
+{
+	SOCKET sock;
+	SOCKADDR_IN sin, csin;
+	struct rtrsipaor rtrsip;
+	int rcvbytes=0;
+	sock = socket(AF_INET, SOCK_STREAM, 0);
+	sin.sin_addr.s_addr = inet_addr("127.0.0.1");
+	sin.sin_family = AF_INET;
+	sin.sin_port = htons(as_conf->rtr_port);
+	socklen_t sinsize = sizeof(csin);
+	int accepted=0;
+
+	if(!bind(sock, (SOCKADDR*)&sin, sizeof(sin)))
+	{
+		if(listen(sock,1))
+		{
+			TRACE_DEBUG(INFO,"ERROR on listen!");
+		}
+		
+		while(1)
+		{
+			accepted=accept(sock, (struct sockaddr *)&csin,&sinsize);
+			if(accepted>-1)
+			{
+				rcvbytes=recv(accepted, &rtrsip, sizeof(struct rtrsipaor),0);
+				
+				if(rcvbytes>-1)
+				{
+					//We received something, we can send an RTR
+					app_sip_RTR_cb(&rtrsip);
+				}
+			}
+		}
+	}
+	else
+		TRACE_DEBUG(INFO,"Can't create socket!");
+
+	
+	pthread_exit(NULL);
+	
+}
+//Called to send a RTR
+int app_sip_RTR_cb(struct rtrsipaor *structure)
+{
+	TRACE_ENTRY("%p", structure);
+	
+	int got_username=0;
+	int got_streason=0;
+	int num_aor=0;//How many SIP-AOR?
+	struct dict_object * rtr_model=NULL;
+	struct msg * message=NULL;
+	struct avp *groupedavp=NULL, *avp=NULL;
+	union avp_value value;
+	
+	//We must check that we have all needed value in structure
+	if(structure->username[0]!='\0')
+		got_username=1;
+	
+	if(structure->sip_aor1[0]!='\0')
+	{	
+		num_aor++;
+		if(structure->sip_aor2[0]!='\0')
+		{
+			num_aor++;
+			if(structure->sip_aor3[0]!='\0')
+				num_aor++;
+		}
+	}
+	
+	if(structure->strreason!='\0')
+		got_streason=1;
+	
+	
+	TRACE_DEBUG(FULL,"Request for %d SIP_AOR to be deregistred.",num_aor);
+	
+	if((got_username + num_aor)==0)
+	{
+		//We must have a least a SIP_AOR or a Username
+		TRACE_DEBUG(INFO,"Can not proceed because there is no SIP_AOR or Username");
+		return EINVAL;
+	}
+	if(structure->reason<0)
+	{
+		//We must have a least a SIP_AOR or a Username
+		TRACE_DEBUG(INFO,"Incorrect Reason-Code");
+		return EINVAL;
+	}
+	
+	if(structure->desthost[0]=='\0')
+	{
+		//We must have a least a SIP_AOR or a Username
+		TRACE_DEBUG(INFO,"No Destination_Host was provided!");
+		return EINVAL;
+	}
+	//Create the base message for an RTR
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_COMMAND, CMD_BY_NAME, "Registration-Termination-Request", &rtr_model, ENOENT) );
+	CHECK_FCT( fd_msg_new (rtr_model, 0, &message));
+	
+	// Create a new session 
+	{
+		#define APP_SIP_SID_OPT  "app_sip"
+		CHECK_FCT( fd_msg_new_session( message, (os0_t)APP_SIP_SID_OPT, CONSTSTRLEN(APP_SIP_SID_OPT) ) );
+	}
+	
+	//Add the Auth-Application-Id 
+	{
+		CHECK_FCT( fd_msg_avp_new ( sip_dict.Auth_Application_Id, 0, &avp ) );
+		value.i32 = 6;
+		CHECK_FCT( fd_msg_avp_setvalue ( avp, &value ) );
+		CHECK_FCT( fd_msg_avp_add ( message, MSG_BRW_LAST_CHILD, avp) );
+	}
+	
+	//Auth_Session_State
+	{
+		CHECK_FCT( fd_msg_avp_new ( sip_dict.Auth_Session_State, 0, &avp ) );
+		value.i32=1;
+		CHECK_FCT( fd_msg_avp_setvalue( avp, &value ) );
+		CHECK_FCT( fd_msg_avp_add( message, MSG_BRW_LAST_CHILD, avp ) );
+	}
+	
+	//Origin_Host & Origin_Realm
+	CHECK_FCT( fd_msg_add_origin ( message, 0 ));
+	
+	//Destination_Host
+	{
+		CHECK_FCT( fd_msg_avp_new ( sip_dict.Destination_Host, 0, &avp ) );
+		value.os.data=(unsigned char *)structure->desthost;
+		value.os.len=(size_t)strlen(structure->desthost);
+		CHECK_FCT( fd_msg_avp_setvalue( avp, &value ) );
+		CHECK_FCT( fd_msg_avp_add( message, MSG_BRW_LAST_CHILD, avp ) );
+	}
+	
+	
+	//SIP Deregistration Reason (Grouped AVP)
+	{
+		CHECK_FCT( fd_msg_avp_new ( sip_dict.SIP_Deregistration_Reason, 0, &groupedavp ) );
+		
+		//Reason Code
+		CHECK_FCT( fd_msg_avp_new ( sip_dict.SIP_Reason_Code, 0, &avp ) );
+		value.i32=structure->reason;
+		CHECK_FCT( fd_msg_avp_setvalue( avp, &value ) );
+		CHECK_FCT( fd_msg_avp_add( groupedavp, MSG_BRW_LAST_CHILD, avp ) );
+		
+		if(got_streason)
+		{
+			//Reason Info
+			CHECK_FCT( fd_msg_avp_new ( sip_dict.SIP_Reason_Info, 0, &avp ) );
+			value.os.data=(unsigned char *)structure->strreason;
+			value.os.len=(size_t)strlen(structure->strreason);
+			CHECK_FCT( fd_msg_avp_setvalue( avp, &value ) );
+			CHECK_FCT( fd_msg_avp_add( groupedavp, MSG_BRW_LAST_CHILD, avp ) );
+		}
+		
+		//We add the grouped AVP to the message
+		CHECK_FCT( fd_msg_avp_add( message, MSG_BRW_LAST_CHILD, groupedavp ) );
+	}
+	
+	//Username
+	{
+		if(got_username)
+		{
+			CHECK_FCT( fd_msg_avp_new ( sip_dict.User_Name, 0, &avp ) );
+			value.os.data=(unsigned char *)structure->username;
+			value.os.len=(size_t)strlen(structure->username);
+			CHECK_FCT( fd_msg_avp_setvalue( avp, &value ) );
+			CHECK_FCT( fd_msg_avp_add( message, MSG_BRW_LAST_CHILD, avp ) );
+		}
+	}
+	
+	//SIP_AOR
+	{
+		if(num_aor>0)
+		{
+			CHECK_FCT( fd_msg_avp_new ( sip_dict.SIP_AOR, 0, &avp ) );
+			value.os.data=(unsigned char *)structure->sip_aor1;
+			value.os.len=(size_t)strlen(structure->sip_aor1);
+			CHECK_FCT( fd_msg_avp_setvalue( avp, &value ) );
+			CHECK_FCT( fd_msg_avp_add( message, MSG_BRW_LAST_CHILD, avp ) );
+			if(num_aor>1)
+			{
+				CHECK_FCT( fd_msg_avp_new ( sip_dict.SIP_AOR, 0, &avp ) );
+				value.os.data=(unsigned char *)structure->sip_aor2;
+				value.os.len=(size_t)strlen(structure->sip_aor2);
+				CHECK_FCT( fd_msg_avp_setvalue( avp, &value ) );
+				CHECK_FCT( fd_msg_avp_add( message, MSG_BRW_LAST_CHILD, avp ) );
+				if(num_aor>2)
+				{
+					CHECK_FCT( fd_msg_avp_new ( sip_dict.SIP_AOR, 0, &avp ) );
+					value.os.data=(unsigned char *)structure->sip_aor3;
+					value.os.len=(size_t)strlen(structure->sip_aor3);
+					CHECK_FCT( fd_msg_avp_setvalue( avp, &value ) );
+					CHECK_FCT( fd_msg_avp_add( message, MSG_BRW_LAST_CHILD, avp ) );
+				}
+			}
+		}
+	}
+	
+	//TODO:remove for debug
+	//fd_msg_dump_walk(INFO,message);
+	CHECK_FCT( fd_msg_send( &message, NULL, NULL ));
+	
+	return 0;
+}
+
+//Called when an RTA arrive
+int app_sip_RTA_cb( struct msg ** msg, struct avp * paramavp, struct session * sess, void * opaque, enum disp_action * act)
+{
+	//TODO: RTA reception
+/*
+	//TODO:remove unused variables
+	struct msg *ans, *qry;
+	struct avp *avp, *a2, *authdataitem;
+	struct msg_hdr * header = NULL;
+	struct avp_hdr * avphdr=NULL, *avpheader=NULL, *avpheader_auth=NULL,*digestheader=NULL;
+	union avp_value val;
+	int found_cnonce=0;
+	struct avp * tempavp=NULL,*sipAuthentication=NULL,*sipAuthenticate=NULL;
+	char * result;
+	int idx=0, idx2=0, number_of_auth_items=0,i=0;
+	//Flags and variables for Database
+	int sipurinotstored=0, authenticationpending=0, querylen=0, usernamelen=0;
+	char *query=NULL,*username=NULL;
+	
+	
+	
+	TRACE_ENTRY("%p %p %p %p", msg, avp, sess, act);
+	
+	if (msg == NULL)
+		return EINVAL;
+	
+	
+	// Create answer header 
+	qry = *msg;
+	CHECK_FCT( fd_msg_new_answer_from_req ( fd_g_config->cnf_dict, msg, 0 ) );
+	ans = *msg;	
+	
+	
+	// Add the Auth-Session-State AVP 
+	{
+		
+		CHECK_FCT( fd_msg_search_avp ( qry, sip_dict.Auth_Session_State, &avp) );
+		CHECK_FCT( fd_msg_avp_hdr( avp, &avphdr )  );
+		
+		CHECK_FCT( fd_msg_avp_new ( sip_dict.Auth_Session_State, 0, &avp ) );
+		CHECK_FCT( fd_msg_avp_setvalue( avp, avphdr->avp_value ) );
+		CHECK_FCT( fd_msg_avp_add( ans, MSG_BRW_LAST_CHILD, avp ) );
+	}
+	
+	CHECK_FCT( fd_msg_search_avp ( qry, sip_dict.SIP_Deregistration_Reason, &avp) );
+	CHECK_FCT( fd_msg_avp_hdr( avp, &avphdr )  );
+	
+	
+	
+	
+	
+	
+	
+	
+	
+	
+	
+	
+	
+	*/
+	return 0;
+	
+}
+
diff --git a/extensions/app_sip/serverassignment.c b/extensions/app_sip/serverassignment.c
new file mode 100644
index 0000000..fa31a81
--- /dev/null
+++ b/extensions/app_sip/serverassignment.c
@@ -0,0 +1,484 @@
+/*********************************************************************************************************
+* Software License Agreement (BSD License)                                                               *
+* Author: Alexandre Westfahl <awestfahl@freediameter.net>						 *
+*													 *
+* Copyright (c) 2010, Alexandre Westfahl, Teraoka Laboratory (Keio University), and the WIDE Project. 	 *		
+*													 *
+* All rights reserved.											 *
+* 													 *
+* Redistribution and use of this software in source and binary forms, with or without modification, are  *
+* permitted provided that the following conditions are met:						 *
+* 													 *
+* * Redistributions of source code must retain the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer.										 *
+*    													 *
+* * Redistributions in binary form must reproduce the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer in the documentation and/or other						 *
+*   materials provided with the distribution.								 *
+* 													 *
+* * Neither the name of the Teraoka Laboratory nor the 							 *
+*   names of its contributors may be used to endorse or 						 *
+*   promote products derived from this software without 						 *
+*   specific prior written permission of Teraoka Laboratory 						 *
+*   													 *
+* 													 *
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED *
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
+* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR *
+* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 	 *
+* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 	 *
+* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR *
+* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF   *
+* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.								 *
+*********************************************************************************************************/
+#include "app_sip.h"
+
+
+int app_sip_SAR_cb( struct msg ** msg, struct avp * paramavp, struct session * sess, void * opaque, enum disp_action * act)
+{
+	TRACE_ENTRY("%p %p %p %p", msg, paramavp, sess, act);
+	
+	struct msg *ans, *qry;
+	struct avp *avp;
+	struct avp_hdr *avphdr, *sipaorhdr, *usernamehdr, *sipuserdataalreadyavailable;
+	union avp_value value;
+	int ret=0, assignment_type=0, got_datatype=1;
+	
+	
+	struct listdatatype
+	{
+		struct fd_list datatype;
+		char * type;
+		size_t typelen;
+	};
+	
+	//Result_Code to return in the answer
+	char result[55];
+	
+	if (msg == NULL)
+		return EINVAL;
+	
+	
+	// Create answer header 
+	qry = *msg;
+	CHECK_FCT( fd_msg_new_answer_from_req ( fd_g_config->cnf_dict, msg, 0 ) );
+	ans = *msg;
+	
+	//Add the Auth-Application-Id 
+	{
+		CHECK_FCT( fd_msg_avp_new ( sip_dict.Auth_Application_Id, 0, &avp ) );
+		value.i32 = 6;
+		CHECK_FCT( fd_msg_avp_setvalue ( avp, &value ) );
+		CHECK_FCT( fd_msg_avp_add ( ans, MSG_BRW_LAST_CHILD, avp) );
+	}
+	// Add the Auth-Session-State AVP 
+	{
+		
+		CHECK_FCT( fd_msg_search_avp ( qry, sip_dict.Auth_Session_State, &avp) );
+		CHECK_FCT( fd_msg_avp_hdr( avp, &avphdr )  );
+		
+		CHECK_FCT( fd_msg_avp_new ( sip_dict.Auth_Session_State, 0, &avp ) );
+		CHECK_FCT( fd_msg_avp_setvalue( avp, avphdr->avp_value ) );
+		CHECK_FCT( fd_msg_avp_add( ans, MSG_BRW_LAST_CHILD, avp ) );
+	}
+	//Retrieve SIP-AOR
+	{
+		CHECK_FCT( fd_msg_search_avp ( qry, sip_dict.SIP_AOR, &avp) );
+		if(avp!=NULL)
+		{
+			CHECK_FCT( fd_msg_avp_hdr( avp, &sipaorhdr )  );
+		}
+		else
+			sipaorhdr=NULL;
+		
+	}
+	
+	//We check if we have a username AVP
+	{
+		CHECK_FCT( fd_msg_search_avp ( qry, sip_dict.User_Name, &avp) );
+		if(avp!=NULL)
+		{
+			CHECK_FCT( fd_msg_avp_hdr( avp, &usernamehdr )  );
+			
+			ret=get_password(usernamehdr->avp_value->os.data, usernamehdr->avp_value->os.len, NULL);
+			
+			
+			if(ret==1)
+			{//not found
+				strcpy(result,"DIAMETER_ERROR_USER_UNKNOWN");
+				goto out;
+			}
+			else if(ret==2)
+			{//error
+				//We couldn't make the request, we must stop process!
+				strcpy(result,"DIAMETER_UNABLE_TO_COMPLY");
+				goto out;
+			}
+			else if(ret==0)
+			{//found
+				
+				if(sipaorhdr!=NULL)
+				{
+					//We must check that this user can use this SIP-AOR
+					ret=check_sipaor(usernamehdr->avp_value->os.data, usernamehdr->avp_value->os.len,(const char *) sipaorhdr->avp_value->os.data,sipaorhdr->avp_value->os.len);
+					
+					if(ret==0)
+					{
+						//The SIP-AOR and Username are ok!
+						ret=clear_pending_flag(usernamehdr->avp_value->os.data, usernamehdr->avp_value->os.len);
+						if(ret==2)
+						{
+							TRACE_DEBUG(INFO,"ERROR: We couldn't clear the flag of pending authentication.'");
+							strcpy(result,"DIAMETER_UNABLE_TO_COMPLY");
+							goto out;
+						}
+					}
+					else if(ret==1)
+					{//not found
+						strcpy(result,"DIAMETER_ERROR_IDENTITIES_DONT_MATCH");
+						goto out;
+					}
+					else
+					{//error
+						//We couldn't make the request, we must stop process!
+						strcpy(result,"DIAMETER_UNABLE_TO_COMPLY");
+						goto out;
+					}
+				}
+				else
+				{
+					TRACE_DEBUG(INFO,"ERROR: There is no SIP-AOR AVP!'");
+					strcpy(result,"DIAMETER_ERROR_IDENTITIES_DONT_MATCH");
+					goto out;
+				}
+			}
+		}
+		else
+		{
+			if(sipaorhdr!=NULL)
+			{//If we have a SIP-AOR, we want the user to check it.
+				strcpy(result,"DIAMETER_USER_NAME_REQUIRED");
+				goto out;
+			}
+			usernamehdr=NULL;
+		}
+			
+	}
+	
+	//We get the SIP_Server_Assignment_Type
+	{
+		CHECK_FCT( fd_msg_search_avp ( qry, sip_dict.SIP_Server_Assignment_Type, &avp) );
+		CHECK_FCT( fd_msg_avp_hdr( avp, &avphdr )  );
+		
+		assignment_type=avphdr->avp_value->i32;
+	}
+	
+	
+	
+	
+	
+	//We get SIP_User_Data_Already_Available AVP
+	{
+		CHECK_FCT( fd_msg_search_avp ( qry, sip_dict.SIP_User_Data_Already_Available, &avp) );
+		CHECK_FCT( fd_msg_avp_hdr( avp, &sipuserdataalreadyavailable )  );
+	}
+	
+	if(assignment_type==1 || assignment_type==2)
+	{//registration & re-registration
+		if(count_avp(qry,CODE_SIP_AOR,0)==1)
+		{
+			
+			if(sipuserdataalreadyavailable->avp_value->i32==0)
+			{//Data not available, we must provide it
+				ret=add_user_datatype(sipaorhdr->avp_value->os.data, sipaorhdr->avp_value->os.len,ans);
+				
+				if(ret==0)
+				{
+					//We found and added datatype
+					got_datatype=1;
+				}
+				else if(ret==1)
+				{
+					//No data type was found
+					got_datatype=0;
+				}
+				else
+				{//error
+				//We couldn't make the request, we must stop process!
+				strcpy(result,"DIAMETER_UNABLE_TO_COMPLY");
+				goto out;
+				}
+			}
+			strcpy(result,"DIAMETER_SUCCESS");
+			goto out;
+		}
+		else
+		{//There is more than 1 SIP-AOR AVP
+			strcpy(result,"DIAMETER_AVP_OCCURS_TOO_MANY_TIMES");
+			goto out;
+		}
+	}
+	else if(assignment_type==3)
+	{//Unregistered user
+		
+		//TODO:place user unknown here!
+		if(count_avp(qry,CODE_SIP_AOR,0)==1)
+		{
+			if(sipuserdataalreadyavailable->avp_value->i32==0)
+			{//Data not available, we must provide it
+				if(got_datatype==1)
+				{
+					ret=add_user_datatype(sipaorhdr->avp_value->os.data, sipaorhdr->avp_value->os.len,ans);
+					
+					if(ret==0)
+					{
+						//We found and added datatype
+						got_datatype=1;
+					}
+					else if(ret==1)
+					{
+						//No data type was found
+						got_datatype=0;
+					}
+					else
+					{//error
+						//We couldn't make the request, we must stop process!
+						strcpy(result,"DIAMETER_UNABLE_TO_COMPLY");
+						goto out;
+					}
+				}
+			}
+			strcpy(result,"DIAMETER_SUCCESS");
+			goto out;
+		}
+		else
+		{//There is more than 1 SIP-AOR AVP
+			strcpy(result,"DIAMETER_AVP_OCCURS_TOO_MANY_TIMES");
+			goto out;
+		}
+		
+		if(sipuserdataalreadyavailable->avp_value->i32==0)
+		{//Data not available, we must provide it
+			if(got_datatype==1)
+			{
+				ret=add_user_datatype(sipaorhdr->avp_value->os.data, sipaorhdr->avp_value->os.len,ans);
+				
+				if(ret==0)
+				{
+					//We found and added datatype
+					got_datatype=1;
+				}
+				else if(ret==1)
+				{
+					//No data type was found
+					got_datatype=0;
+				}
+				else
+				{//error
+					//We couldn't make the request, we must stop process!
+					strcpy(result,"DIAMETER_UNABLE_TO_COMPLY");
+					goto out;
+				}
+			}
+		}
+		
+		CHECK_FCT( fd_msg_search_avp ( qry, sip_dict.SIP_Server_URI, &avp) );
+		if(avp!=NULL)
+		{
+			CHECK_FCT( fd_msg_avp_hdr( avp, &avphdr ));
+			
+			set_real_sipserver_uri(usernamehdr->avp_value->os.data, usernamehdr->avp_value->os.len, avphdr->avp_value->os.data,avphdr->avp_value->os.len);
+			strcpy(result,"DIAMETER_SUCCESS");
+			goto out;
+		}
+		else
+		{
+			TRACE_DEBUG(INFO,"There is no SIP_Server_URI AVP in this Unregistered User Request!");
+			strcpy(result,"DIAMETER_UNABLE_TO_COMPLY");
+			goto out;
+		}
+	}
+	else if(assignment_type==4 || assignment_type==5 || assignment_type==11 || assignment_type==8)
+	{//Unregistered user
+		
+		if(got_datatype==1)
+		{
+			if(sipuserdataalreadyavailable->avp_value->i32==0)
+			{//Data not available, we must provide it
+				
+				ret=add_user_datatype(sipaorhdr->avp_value->os.data, sipaorhdr->avp_value->os.len,ans);
+				
+				if(ret==0)
+				{
+					//We found and added datatype
+					got_datatype=1;
+				}
+				else if(ret==1)
+				{
+					//No data type was found
+					got_datatype=0;
+				}
+				else
+				{//error
+					//We couldn't make the request, we must stop process!
+					strcpy(result,"DIAMETER_UNABLE_TO_COMPLY");
+					goto out;
+				}
+			}
+		}
+		
+		if(sipaorhdr==NULL)
+		{
+			//We don't have any SIP-AOR to unregister, this is strange!'
+			TRACE_DEBUG(INFO, "There was no SIP-AOR in this request, we can't proceed request!'");
+			strcpy(result,"DIAMETER_UNABLE_TO_COMPLY");
+			goto out;
+		}
+		else
+		{
+			//TODO: unregister SIP-Server-URI for all SIP-AOR
+		}
+		strcpy(result,"DIAMETER_SUCCESS");
+		goto out;
+	}
+	else if(assignment_type==6 || assignment_type==7)
+	{
+		
+		
+		CHECK_FCT( fd_msg_search_avp ( qry, sip_dict.SIP_Server_URI, &avp) );
+		if(avp!=NULL)
+		{
+			CHECK_FCT( fd_msg_avp_hdr( avp, &avphdr ));
+			
+			//TODO: set SIP server URI for each AOR
+			
+			//TODO: unregister all SIP-AOR provided
+			
+			//set_real_sipserver_uri(usernamehdr->avp_value->os.data, usernamehdr->avp_value->os.len, avphdr->avp_value->os.data,avphdr->avp_value->os.len);
+			strcpy(result,"DIAMETER_SUCCESS");
+			goto out;
+		}
+		else
+		{
+			
+			
+			//TODO: unregister all SIP-AOR provided
+			
+			//TODO: clear sip server uri in database for the sip-aor
+			
+			
+			TRACE_DEBUG(INFO,"There is no SIP_Server_URI AVP in this Deregistration User Request! We just unregister SIP-AOR");
+			strcpy(result,"DIAMETER_SUCCESS_SERVER_NAME_NOT_STORED");
+			goto out;
+		}
+	}
+	else if(assignment_type==0)
+	{
+		
+		
+		CHECK_FCT( fd_msg_search_avp ( qry, sip_dict.SIP_Server_URI, &avp) );
+		if(avp!=NULL)
+		{
+			unsigned char * sipserver_uri;
+			size_t sipserverurilen;
+			
+			
+			
+			
+			ret=get_sipserver_uri(sipaorhdr->avp_value->os.data, sipaorhdr->avp_value->os.len, &sipserver_uri, &sipserverurilen);
+			
+			if(ret==0)
+			{//found
+				CHECK_FCT( fd_msg_avp_hdr( avp, &avphdr ));
+				
+				
+				
+				
+				if(strncmp((char *)avphdr->avp_value->os.data,(char *)sipserver_uri,sipserverurilen))
+				{
+					if(got_datatype==1)
+					{
+						if(sipuserdataalreadyavailable->avp_value->i32==0)
+						{//Data not available, we must provide it
+							
+							ret=add_user_datatype(sipaorhdr->avp_value->os.data, sipaorhdr->avp_value->os.len,ans);
+							
+							if(ret==0)
+							{
+								//We found and added datatype
+								got_datatype=1;
+							}
+							else if(ret==1)
+							{
+								//No data type was found
+								got_datatype=0;
+							}
+							else
+							{//error
+								//We couldn't make the request, we must stop process!
+								strcpy(result,"DIAMETER_UNABLE_TO_COMPLY");
+								goto out;
+							}
+						}
+					}
+				}
+				else
+				{//error
+					TRACE_DEBUG(FULL,"SIP_Server_URI is different from the one in database");
+					strcpy(result,"DIAMETER_UNABLE_TO_COMPLY");
+					goto out;
+				}
+			}
+			else
+			{
+				TRACE_DEBUG(FULL,"SIP_Server_URI is different from the one in database");
+				strcpy(result,"DIAMETER_UNABLE_TO_COMPLY");
+				goto out;
+			}
+			
+			
+			
+			
+			
+			
+			
+			//set_real_sipserver_uri(usernamehdr->avp_value->os.data, usernamehdr->avp_value->os.len, avphdr->avp_value->os.data,avphdr->avp_value->os.len);
+			strcpy(result,"DIAMETER_SUCCESS");
+			goto out;
+		}
+		else
+		{
+			TRACE_DEBUG(INFO, "There was no SIP_Server_URI in this request, we can't proceed request!'");
+			strcpy(result,"DIAMETER_UNABLE_TO_COMPLY");
+			goto out;
+		}
+	}
+	else if(assignment_type==9 || assignment_type==10)
+	{
+		if(count_avp(qry, CODE_SIP_AOR,0)==1)
+		{
+			//TODO: remove SIP-server URI for sip_aor
+			//TODO: unregister it
+			strcpy(result,"DIAMETER_SUCCESS");
+			goto out;
+		}
+		else
+		{//There is more than 1 SIP-AOR AVP
+			strcpy(result,"DIAMETER_AVP_OCCURS_TOO_MANY_TIMES");
+			goto out;
+		}
+	}
+	out:
+	CHECK_FCT( fd_msg_rescode_set( ans, result, NULL, NULL, 1 ) );
+	
+	
+	//fd_msg_dump_walk(INFO,ans);
+	
+	CHECK_FCT( fd_msg_send( msg, NULL, NULL ));
+	
+	
+	
+	return 0;
+}
diff --git a/extensions/app_sip/tools/CMakeLists.txt b/extensions/app_sip/tools/CMakeLists.txt
new file mode 100644
index 0000000..c80ccff
--- /dev/null
+++ b/extensions/app_sip/tools/CMakeLists.txt
@@ -0,0 +1,12 @@
+# Utilities for app_sip
+PROJECT("Diameter SIP Application (RFC4740) tools" C)
+
+ADD_EXECUTABLE(freediameter-sip-rtr app_sip_rtr.c)
+ADD_EXECUTABLE(freediameter-sip-ppr app_sip_ppr.c)
+
+####
+## INSTALL section ##
+
+INSTALL(TARGETS freediameter-sip-rtr freediameter-sip-ppr
+	RUNTIME DESTINATION ${INSTALL_DAEMON_SUFFIX}
+	COMPONENT freeDiameter-sip-server)
diff --git a/extensions/app_sip/tools/app_sip_ppr.c b/extensions/app_sip/tools/app_sip_ppr.c
new file mode 100644
index 0000000..d8d8056
--- /dev/null
+++ b/extensions/app_sip/tools/app_sip_ppr.c
@@ -0,0 +1,237 @@
+/*********************************************************************************************************
+* Software License Agreement (BSD License)                                                               *
+* Author: Alexandre Westfahl <awestfahl@freediameter.net>						 *
+*													 *
+* Copyright (c) 2010, Alexandre Westfahl, Teraoka Laboratory (Keio University), and the WIDE Project. 	 *		
+*													 *
+* All rights reserved.											 *
+* 													 *
+* Redistribution and use of this software in source and binary forms, with or without modification, are  *
+* permitted provided that the following conditions are met:						 *
+* 													 *
+* * Redistributions of source code must retain the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer.										 *
+*    													 *
+* * Redistributions in binary form must reproduce the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer in the documentation and/or other						 *
+*   materials provided with the distribution.								 *
+* 													 *
+* * Neither the name of the Teraoka Laboratory nor the 							 *
+*   names of its contributors may be used to endorse or 						 *
+*   promote products derived from this software without 						 *
+*   specific prior written permission of Teraoka Laboratory 						 *
+*   													 *
+* 													 *
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED *
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
+* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR *
+* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 	 *
+* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 	 *
+* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR *
+* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF   *
+* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.								 *
+*********************************************************************************************************/
+
+
+// This file is separated from the source code because it is a separate command which will call push profile function in Diameter-SIP
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <unistd.h>
+typedef int SOCKET;
+typedef struct sockaddr_in SOCKADDR_IN;
+typedef struct sockaddr SOCKADDR;
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <errno.h>
+
+struct pprsipaor
+{
+	char username[200];
+	char datatype1[255];
+	char datatype2[255];
+	char datatype3[255];
+	int accounting;
+};
+
+int main (int argc, char **argv)
+{
+	SOCKET sock;
+    SOCKADDR_IN sin;
+    struct pprsipaor pprsip;
+    int numdatatype=0,i=0;
+    int port=667;
+	
+	sock = socket(AF_INET, SOCK_STREAM, 0);
+	sin.sin_addr.s_addr = inet_addr("127.0.0.1");
+    sin.sin_family = AF_INET;
+    
+    
+    //We initialize the structure
+    pprsip.username[0]='\0';
+    pprsip.datatype1[0]='\0';
+    pprsip.datatype2[0]='\0';
+    pprsip.datatype3[0]='\0';
+    pprsip.accounting=0;
+    
+	//Start of arguments check
+	if(argc<3)
+	{
+		fprintf(stderr,"Missing arguments! You must at least provide a username.\n");
+		return 1;
+	}
+	
+	
+	for (i=1;i<argc;i++)
+	{
+		//We must check if it is a value or the name
+		if(strncmp(argv[i],"-",1)==0)
+		{
+			if(strcmp(argv[i],"-u")==0)
+			{
+				//Username
+				if(strlen(argv[i+1])<199)
+				{
+					strcpy(pprsip.username,argv[i+1]);
+					//We must not check the value
+					i++;
+				}
+				else
+				{
+					fprintf(stderr,"Username is too long!\n");
+				}
+			}
+			else if(strcmp(argv[i],"-t")==0)
+			{//User-data types
+				i++;
+				int j=i;
+			
+				for(j=i;j<argc;j++)
+				{
+					
+					if(strncmp(argv[i],"-",1)!=0)
+					{
+						if(strlen(argv[i])>254)
+						{
+							fprintf(stderr,"User-data type is too long!\n");
+						}
+						else
+						{
+							if(numdatatype<3)
+							{
+								switch(numdatatype)
+								{
+									case 0:
+										strcpy(pprsip.datatype1,argv[i]);
+									break;
+									case 1:
+										strcpy(pprsip.datatype2,argv[i]);
+									break;
+									case 2:
+										strcpy(pprsip.datatype3,argv[i]);
+									break;
+								}
+								numdatatype++;
+							}
+							else
+							{
+								fprintf(stderr,"You can not provide more than 3 User-data type at the same time!\n");
+								break;
+							}
+						}
+						i=j+1;
+					}
+					else
+					{
+						//We have a new argument
+						i--;
+						break;
+					}
+				}
+			}
+			else if(strcmp(argv[i],"-a")==0)
+			{
+				pprsip.accounting=1;
+				
+				
+			}
+			else if(strcmp(argv[i],"-p")==0)
+			{
+				
+				if(sscanf(argv[i+1],"%d", &port)!=1)
+				{
+					fprintf(stderr,"Incorrect port number!\n");
+					return 1;
+				}
+				
+				
+				i++;
+			}
+			
+		}
+		else
+		{
+			fprintf(stderr,"Unknown argument: %s\n",argv[i]);
+			i++;
+		}
+			
+	}
+	
+	//We set the port number
+	sin.sin_port = htons(port);
+	
+	
+	//We want a username
+	if(strlen(pprsip.username)==0)
+	{
+		fprintf(stderr,"You must provide a username!\n");
+		return 1;
+	}
+	
+    
+    fprintf(stderr,"%d!\n",port);
+   
+    /*
+    //DEBUG
+    fprintf(stderr,"*%s*\n",pprsip.username);
+	fprintf(stderr,"*%s*\n",pprsip.datatype1);
+	fprintf(stderr,"*%s*\n",pprsip.datatype2);
+	fprintf(stderr,"*%s*\n",pprsip.datatype3);
+	fprintf(stderr,"*%d*\n",pprsip.accounting);
+	
+	return 0;
+	*/
+	
+	
+	//TODO: check args
+	if(!connect(sock, (SOCKADDR*)&sin, sizeof(sin)))
+    {
+       fprintf(stderr,"Connexion succeed!\n");
+        
+ 
+        if(send(sock, &pprsip, sizeof(struct pprsipaor), 0))
+			fprintf(stderr,"sent OK!\n");
+		else
+			fprintf(stderr,"not sent\n");
+        
+    }
+    else
+    {
+        fprintf(stderr,"Unable to connect\n");
+    }
+ 
+    close(sock);
+
+	return 0;
+}
+
+
+
+
+
+
diff --git a/extensions/app_sip/tools/app_sip_rtr.c b/extensions/app_sip/tools/app_sip_rtr.c
new file mode 100644
index 0000000..21c3c60
--- /dev/null
+++ b/extensions/app_sip/tools/app_sip_rtr.c
@@ -0,0 +1,303 @@
+/*********************************************************************************************************
+* Software License Agreement (BSD License)                                                               *
+* Author: Alexandre Westfahl <awestfahl@freediameter.net>						 *
+*													 *
+* Copyright (c) 2010, Alexandre Westfahl, Teraoka Laboratory (Keio University), and the WIDE Project. 	 *		
+*													 *
+* All rights reserved.											 *
+* 													 *
+* Redistribution and use of this software in source and binary forms, with or without modification, are  *
+* permitted provided that the following conditions are met:						 *
+* 													 *
+* * Redistributions of source code must retain the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer.										 *
+*    													 *
+* * Redistributions in binary form must reproduce the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer in the documentation and/or other						 *
+*   materials provided with the distribution.								 *
+* 													 *
+* * Neither the name of the Teraoka Laboratory nor the 							 *
+*   names of its contributors may be used to endorse or 						 *
+*   promote products derived from this software without 						 *
+*   specific prior written permission of Teraoka Laboratory 						 *
+*   													 *
+* 													 *
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED *
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
+* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR *
+* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 	 *
+* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 	 *
+* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR *
+* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF   *
+* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.								 *
+*********************************************************************************************************/
+
+
+// This file is separated from the source code because it is a separate command which will call registration termination function in Diameter-SIP
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <unistd.h>
+typedef int SOCKET;
+typedef struct sockaddr_in SOCKADDR_IN;
+typedef struct sockaddr SOCKADDR;
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+
+struct rtrsipaor
+{
+	char username[200];
+	char sip_aor1[200];
+	char sip_aor2[200];
+	char sip_aor3[200];
+	char strreason[200];
+	char desthost[200];
+	int reason;
+};
+
+int main (int argc, char **argv)
+{
+	SOCKET sock;
+    SOCKADDR_IN sin;
+    struct rtrsipaor rtrsip;
+    int numaor=0,i=0;
+	int port=666;
+	
+	sock = socket(AF_INET, SOCK_STREAM, 0);
+	sin.sin_addr.s_addr = inet_addr("127.0.0.1");
+    sin.sin_family = AF_INET;
+    
+    
+    //We initialize the structure
+    rtrsip.username[0]='\0';
+    rtrsip.sip_aor1[0]='\0';
+    rtrsip.sip_aor2[0]='\0';
+    rtrsip.sip_aor3[0]='\0';
+    rtrsip.strreason[0]='\0';
+    rtrsip.desthost[0]='\0';
+    rtrsip.reason=-1;
+    
+    
+	//Start of arguments check
+	if(argc<3)
+	{
+		fprintf(stderr,"Missing arguments! You must at least provide a username.\n");
+		return 1;
+	}
+	
+	
+	for (i=1;i<argc;i++)
+	{
+		//We must check if it is a value or the name
+		if(strncmp(argv[i],"-",1)==0)
+		{
+			if(strcmp(argv[i],"-u")==0)
+			{
+				//Username
+				if(strlen(argv[i+1])<199)
+				{
+					strcpy(rtrsip.username,argv[i+1]);
+					//We must not check the value
+					i++;
+				}
+				else
+				{
+					fprintf(stderr,"Username is too long!\n");
+				}
+			}
+			else if(strcmp(argv[i],"-a")==0)
+			{
+				i++;
+				int j=i;
+			
+				for(j=i;j<argc;j++)
+				{
+					
+					if(strncmp(argv[i],"-",1)!=0)
+					{
+						if(strlen(argv[i])>199)
+						{
+							fprintf(stderr,"SIP-AOR is too long!\n");
+						}
+						else if(strncmp(argv[i],"sip",3)!=0)
+						{
+							//Bad format of SIP-AOR
+							fprintf(stderr,"A SIP-AOR must start by 'sip:' or 'sips:'. Aborting...\n");
+							return 1;
+						}
+						else
+						{
+							if(numaor<3)
+							{
+								switch(numaor)
+								{
+									case 0:
+										strcpy(rtrsip.sip_aor1,argv[i]);
+									break;
+									case 1:
+										strcpy(rtrsip.sip_aor2,argv[i]);
+									break;
+									case 2:
+										strcpy(rtrsip.sip_aor3,argv[i]);
+									break;
+								}
+								numaor++;
+							}
+							else
+							{
+								fprintf(stderr,"You can not provide more than 3 SIP-AOR at the same time!\n");
+								break;
+							}
+						}
+						i=j+1;
+					}
+					else
+					{
+						//We have a new argument
+						i--;
+						break;
+					}
+				}
+			}
+			else if(strcmp(argv[i],"-r")==0)
+			{
+				
+				if(strlen(argv[i+1])>199)
+				{
+					fprintf(stderr,"Deregistration reason is too long!\n");
+				}
+				else
+				{
+					strcpy(rtrsip.strreason,argv[i+1]);
+				}
+				i++;
+			}
+			else if(strcmp(argv[i],"-h")==0)
+			{
+				//Remote SIP Server
+				if(strlen(argv[i+1])>199)
+				{
+					fprintf(stderr,"Host is too long!\n");
+				}
+				else if(strlen(argv[i+1])<5)
+				{
+					fprintf(stderr,"Host is too short!\n");
+				}
+				else
+				{
+					strcpy(rtrsip.desthost,argv[i+1]);
+				}
+				i++;
+			}
+			else if(strcmp(argv[i],"-pt")==0)
+			{
+				//Permanent Termination
+				rtrsip.reason=0;
+			}
+			else if(strcmp(argv[i],"-nssa")==0)
+			{
+				//New SIP Server Assigned
+				rtrsip.reason=1;
+			}
+			else if(strcmp(argv[i],"-ssc")==0)
+			{
+				//SIP Server Change
+				rtrsip.reason=2;
+			}
+			else if(strcmp(argv[i],"-rss")==0)
+			{
+				//Remote SIP Server
+				rtrsip.reason=3;
+			}
+			else if(strcmp(argv[i],"-p")==0)
+			{
+				
+				if(sscanf(argv[i+1],"%d", &port)!=1)
+				{
+					fprintf(stderr,"Incorrect port number!\n");
+					return 1;
+				}
+				
+				
+				i++;
+			}
+			else
+			{
+				fprintf(stderr,"Unknown argument: %s\n",argv[i]);
+			}
+		}
+		else
+		{
+			fprintf(stderr,"Unknown argument: %s\n",argv[i]);
+			i++;
+		}
+			
+	}
+	
+	//If no SIP-AOR provided, we remove all
+	if(numaor<1)
+	{
+		fprintf(stderr,"All SIP-AOR of %s will be deregistrated.\n",rtrsip.username);
+	}
+	
+	//We want a username
+	if(strlen(rtrsip.username)==0)
+	{
+		fprintf(stderr,"You must provide a username!\n");
+		return 1;
+	}
+	
+	if(rtrsip.desthost[0]=='\0')
+	{
+		fprintf(stderr,"You must provide the hostname of SIP-Server!\n");
+		return 1;
+	}
+    
+    //We set the port number
+    sin.sin_port = htons(port);
+   
+    
+    /*
+    fprintf(stderr,"*%s*\n",rtrsip.username);
+	fprintf(stderr,"*%s*\n",rtrsip.sip_aor1);
+	fprintf(stderr,"*%s*\n",rtrsip.sip_aor2);
+	fprintf(stderr,"*%s*\n",rtrsip.sip_aor3);
+	fprintf(stderr,"*%d*\n",rtrsip.reason);
+	fprintf(stderr,"*%s*\n",rtrsip.strreason);
+	
+	//return 0;
+	*/
+	
+	
+	//TODO: check args
+	if(!connect(sock, (SOCKADDR*)&sin, sizeof(sin)))
+    {
+       fprintf(stderr,"Connexion succeed!\n");
+        
+ 
+        if(send(sock, &rtrsip, sizeof(struct rtrsipaor), 0))
+			fprintf(stderr,"sent OK!\n");
+		else
+			fprintf(stderr,"not sent\n");
+        
+    }
+    else
+    {
+        fprintf(stderr,"Unable to connect\n");
+    }
+ 
+    close(sock);
+
+	return 0;
+}
+
+
+
+
+
+
diff --git a/extensions/app_sip/userauthorization.c b/extensions/app_sip/userauthorization.c
new file mode 100644
index 0000000..f87ceb6
--- /dev/null
+++ b/extensions/app_sip/userauthorization.c
@@ -0,0 +1,337 @@
+/*********************************************************************************************************
+* Software License Agreement (BSD License)                                                               *
+* Author: Alexandre Westfahl <awestfahl@freediameter.net>						 *
+*													 *
+* Copyright (c) 2010, Alexandre Westfahl, Teraoka Laboratory (Keio University), and the WIDE Project. 	 *		
+*													 *
+* All rights reserved.											 *
+* 													 *
+* Redistribution and use of this software in source and binary forms, with or without modification, are  *
+* permitted provided that the following conditions are met:						 *
+* 													 *
+* * Redistributions of source code must retain the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer.										 *
+*    													 *
+* * Redistributions in binary form must reproduce the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer in the documentation and/or other						 *
+*   materials provided with the distribution.								 *
+* 													 *
+* * Neither the name of the Teraoka Laboratory nor the 							 *
+*   names of its contributors may be used to endorse or 						 *
+*   promote products derived from this software without 						 *
+*   specific prior written permission of Teraoka Laboratory 						 *
+*   													 *
+* 													 *
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED *
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
+* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR *
+* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 	 *
+* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 	 *
+* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR *
+* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF   *
+* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.								 *
+*********************************************************************************************************/
+#include "app_sip.h"
+
+
+int app_sip_UAR_cb( struct msg ** msg, struct avp * paramavp, struct session * sess, void * opaque, enum disp_action * act)
+{
+	TRACE_ENTRY("%p %p %p %p", msg, paramavp, sess, act);
+	
+	struct msg *ans, *qry;
+	struct avp *avp, *groupedavp=NULL;
+	struct avp_hdr *avphdr, *sipaorhdr, *visitednethdr, *usernamehdr;
+	union avp_value value;
+	int ret=0, hascap=0;
+	
+	//Result_Code to return in the answer
+	char result[55];
+	
+	if (msg == NULL)
+		return EINVAL;
+
+	
+	// Create answer header 
+	qry = *msg;
+	CHECK_FCT( fd_msg_new_answer_from_req ( fd_g_config->cnf_dict, msg, 0 ) );
+	ans = *msg;
+	
+	//Add the Auth-Application-Id 
+	{
+		CHECK_FCT( fd_msg_avp_new ( sip_dict.Auth_Application_Id, 0, &avp ) );
+		value.i32 = 6;
+		CHECK_FCT( fd_msg_avp_setvalue ( avp, &value ) );
+		CHECK_FCT( fd_msg_avp_add ( ans, MSG_BRW_LAST_CHILD, avp) );
+	}
+	// Add the Auth-Session-State AVP 
+	{
+		
+		CHECK_FCT( fd_msg_search_avp ( qry, sip_dict.Auth_Session_State, &avp) );
+		CHECK_FCT( fd_msg_avp_hdr( avp, &avphdr )  );
+		
+		CHECK_FCT( fd_msg_avp_new ( sip_dict.Auth_Session_State, 0, &avp ) );
+		CHECK_FCT( fd_msg_avp_setvalue( avp, avphdr->avp_value ) );
+		CHECK_FCT( fd_msg_avp_add( ans, MSG_BRW_LAST_CHILD, avp ) );
+	}
+	
+	//Retrieve SIP-AOR
+	{
+		CHECK_FCT( fd_msg_search_avp ( qry, sip_dict.SIP_AOR, &avp) );
+		CHECK_FCT( fd_msg_avp_hdr( avp, &sipaorhdr )  );
+	}
+	
+	//We check if we have a User-Name AVP
+	{
+		CHECK_FCT( fd_msg_search_avp ( qry, sip_dict.User_Name, &avp) );
+		if(avp!=NULL)
+		{
+			CHECK_FCT( fd_msg_avp_hdr( avp, &usernamehdr )  );
+			
+			ret=get_password(usernamehdr->avp_value->os.data, usernamehdr->avp_value->os.len, NULL);
+			
+			
+			if(ret==1)
+			{//not found
+				strcpy(result,"DIAMETER_ERROR_USER_UNKNOWN");
+				goto out;
+			}
+			else if(ret==2)
+			{//error
+				//We couldn't make the request, we must stop process!
+				strcpy(result,"DIAMETER_UNABLE_TO_COMPLY");
+				goto out;
+			}
+			else if(ret==0)
+			{//found
+				
+				//We must check that this user can use this SIP-AOR
+				ret=check_sipaor(usernamehdr->avp_value->os.data, usernamehdr->avp_value->os.len, (const char *)sipaorhdr->avp_value->os.data,sipaorhdr->avp_value->os.len);
+				
+				if(ret==0)
+				{
+					//The SIP-AOR and Username are ok!
+				}
+				else if(ret==1)
+				{//not found
+					strcpy(result,"DIAMETER_ERROR_IDENTITIES_DONT_MATCH");
+					goto out;
+				}
+				else
+				{//error
+					//We couldn't make the request, we must stop process!
+					strcpy(result,"DIAMETER_UNABLE_TO_COMPLY");
+					goto out;
+				}
+			}
+		}
+	}
+	
+	//We check if we have a SIP-Visited-Network-Id AVP
+	{
+		CHECK_FCT( fd_msg_search_avp ( qry, sip_dict.SIP_Visited_Network_Id, &avp) );
+		
+		if(avp!=NULL)
+		{
+			CHECK_FCT( fd_msg_avp_hdr( avp, &visitednethdr )  );
+		}
+		else
+			visitednethdr=NULL;
+	}
+	
+	//We check if we have a SIP_User_Authorization_Type
+	{
+		int auth_type;
+		
+		CHECK_FCT( fd_msg_search_avp ( qry, sip_dict.SIP_User_Authorization_Type, &avp) );
+		
+		if(avp!=NULL)
+		{
+			CHECK_FCT( fd_msg_avp_hdr( avp, &avphdr )  );
+			auth_type=avphdr->avp_value->i32;
+			
+			if(auth_type==0 || auth_type==2)
+			{
+				if(visitednethdr!=NULL)
+				{
+					/*
+					If there is a SIP-Visited-Network-Id AVP in the Diameter UAR message,
+					and the SIP-User-Authorization-Type AVP value received in the
+					Diameter UAR message is set to REGISTRATION or REGISTRATION&
+					CAPABILITIES, then the Diameter server SHOULD verify whether the user
+					is allowed to roam into the network specified in the
+					SIP-Visited-Network-Id AVP in the Diameter UAR message.  If the user
+					is not allowed to roam into that network, the Diameter AAA server
+					MUST set the Result-Code AVP value in the Diameter UAA message to
+					DIAMETER_ERROR_ROAMING_NOT_ALLOWED.
+					*/
+					ret=allow_roaming(usernamehdr->avp_value->os.data, usernamehdr->avp_value->os.len, (const char *)visitednethdr->avp_value->os.data,visitednethdr->avp_value->os.len);
+					
+					if(ret==0)
+					{
+						//This user can come in this network
+					}
+					else if(ret==1)
+					{
+						strcpy(result,"DIAMETER_ERROR_ROAMING_NOT_ALLOWED");
+						goto out;
+					}
+					else
+					{
+						strcpy(result,"DIAMETER_UNABLE_TO_COMPLY");
+						goto out;
+					}
+					
+				}
+				/*
+				If the SIP-User-Authorization-Type AVP value received in the Diameter
+				UAR message is set to REGISTRATION or REGISTRATION&CAPABILITIES, then
+				the Diameter server SHOULD verify whether the SIP-AOR AVP value is
+				authorized to register in the Home Realm.  Where the SIP AOR is not
+				authorized to register in the Home Realm, the Diameter server MUST
+				set the Result-Code AVP to DIAMETER_AUTHORIZATION_REJECTED and send
+				it in a Diameter UAA message.
+				*/
+				ret=exist_username(sipaorhdr->avp_value->os.data, sipaorhdr->avp_value->os.len);
+				if(ret==0)
+				{
+					//The SIP_AOR exists in this realm
+				}
+				else if(ret==1)
+				{
+					strcpy(result,"DIAMETER_AUTHORIZATION_REJECTED");
+					goto out;
+				}
+				else
+				{
+					strcpy(result,"DIAMETER_UNABLE_TO_COMPLY");
+					goto out;
+				}
+			}
+		}
+		else
+			auth_type=0; //Registration only (default value if absent)
+		
+		
+		//Let's look for the SIP_Server_URI'
+		unsigned char *sipserver_uri;
+		size_t sipserverurilen;
+		
+		ret=get_sipserver_uri(sipaorhdr->avp_value->os.data, sipaorhdr->avp_value->os.len, &sipserver_uri, &sipserverurilen);
+		
+		if(ret==0)
+		{//We know a SIP Server so we must provide it
+			//We only add this AVP when we have registration or deregistration
+			if(auth_type==0 ||auth_type==1)
+			{
+				CHECK_FCT( fd_msg_avp_new ( sip_dict.SIP_Server_URI, 0, &avp ) );
+				value.os.data=sipserver_uri;
+				value.os.len=sipserverurilen;
+				CHECK_FCT( fd_msg_avp_setvalue( avp, &value ) );
+				CHECK_FCT( fd_msg_avp_add( ans, MSG_BRW_LAST_CHILD, avp ) );
+			}
+		}
+		else if(ret==1)
+		{
+			sipserver_uri=NULL;
+			sipserverurilen=0;
+			
+		}
+		else
+		{
+			strcpy(result,"DIAMETER_UNABLE_TO_COMPLY");
+			goto out;
+		}
+		
+		//If we have a REGISTRATION or REGISTRATION & CAPABILITIES
+		if(auth_type==0 ||auth_type==2)
+		{
+			//Adding SIP-Server-Capabilities
+			CHECK_FCT( fd_msg_avp_new ( sip_dict.SIP_Server_Capabilities, 0, &groupedavp ) );
+			
+			ret=get_sipserver_cap(sipaorhdr->avp_value->os.data, sipaorhdr->avp_value->os.len,&groupedavp);
+			
+			if(ret==0)
+			{
+				CHECK_FCT( fd_msg_avp_add ( ans, MSG_BRW_LAST_CHILD, groupedavp) );
+				hascap=1;
+			}
+			else if(ret==1)
+			{
+				
+				hascap=0;
+			}
+			else
+			{
+				CHECK_FCT( fd_msg_free( groupedavp ) );
+				strcpy(result,"DIAMETER_UNABLE_TO_COMPLY");
+				goto out;
+			}
+		}
+		
+		
+		
+		if(auth_type==0)
+		{//Registration
+			
+			if(sipserver_uri==NULL)
+			{
+				strcpy(result,"DIAMETER_FIRST_REGISTRATION");
+			}
+			else
+			{
+				if(hascap==1)
+				{
+					strcpy(result,"DIAMETER_SERVER_SELECTION");
+				}
+				else
+				{
+					//We free the Capabilities AVP because we didn't found any'
+					if(groupedavp!=NULL)
+						CHECK_FCT( fd_msg_free( groupedavp ) );
+					strcpy(result,"DIAMETER_SUBSEQUENT_REGISTRATION");
+				}
+			}
+		}
+		else if(auth_type==2)
+		{//Registration & Capabilities
+			//We let the groupedavp in the message even if there is no capabilities
+			
+			if(hascap==0)
+			{
+				CHECK_FCT( fd_msg_avp_add ( ans, MSG_BRW_LAST_CHILD, groupedavp) );
+			}
+			strcpy(result,"DIAMETER_SUCCESS");	
+		}
+		else if(auth_type==1)
+		{//Deregistration
+			if(sipserver_uri==NULL)
+			{
+				strcpy(result,"DIAMETER_ERROR_IDENTITY_NOT_REGISTERED");
+			}
+			else
+			{
+				strcpy(result,"DIAMETER_SUCCESS");	
+			}
+		}
+		else
+		{//We should never be here!!
+			strcpy(result,"DIAMETER_UNABLE_TO_COMPLY");
+			goto out;
+		}
+	}
+	
+	
+out:
+	CHECK_FCT( fd_msg_rescode_set( ans, result, NULL, NULL, 1 ) );
+	
+	
+	//fd_msg_dump_walk(INFO,ans);
+	
+	CHECK_FCT( fd_msg_send( msg, NULL, NULL ));
+	
+	
+	
+	return 0;
+}
diff --git a/extensions/dbg_interactive/CMakeLists.txt b/extensions/dbg_interactive/CMakeLists.txt
new file mode 100644
index 0000000..4bb3eb0
--- /dev/null
+++ b/extensions/dbg_interactive/CMakeLists.txt
@@ -0,0 +1,77 @@
+# The dbg_interactive extension
+PROJECT("Interactive debug facility based on SWIG" C)
+
+
+# This module is using Python
+SET(Python_ADDITIONAL_VERSIONS 2.7 2.6 2.5 2.4 2.3 2.2 2.1 2.0)
+FIND_PACKAGE(PythonLibs)
+INCLUDE_DIRECTORIES(${PYTHON_INCLUDE_PATH})
+
+##### 
+# Wrapper to fD in python
+FIND_PACKAGE(SWIG REQUIRED)
+INCLUDE(${SWIG_USE_FILE})
+SET(CMAKE_SWIG_FLAGS -castmode -threads)
+
+# Add the dependencies for re-swig-ing the file
+SET(SWIG_MODULE_fDpy_EXTRA_DEPS 
+	${CMAKE_BINARY_DIR}/include/freeDiameter/freeDiameter-host.h 
+	${CMAKE_SOURCE_DIR}/include/freeDiameter/libfdcore.h 
+	${CMAKE_SOURCE_DIR}/include/freeDiameter/libfdproto.h 
+	lists.i
+	dictionary.i
+	sessions.i
+	routing.i
+	messages.i
+	dispatch.i
+	queues.i
+	peers.i
+	events.i
+	endpoints.i
+	posix.i
+	hooks.i
+	)
+SET_SOURCE_FILES_PROPERTIES(dbg_interactive.i PROPERTIES SWIG_MODULE_NAME fDpy)
+
+# The following code is inspired from SWIG_ADD_MODULE, but we do only what we need
+SWIG_MODULE_INITIALIZE(fDpy python)
+SWIG_ADD_SOURCE_TO_MODULE(fDpy swig_generated_sources "dbg_interactive.i")
+	
+# In order to avoid shipping the python file that contains the shadow class definitions, 
+# we transform this file in a C-style string and compile it within our software.
+# We use for this purpose xxd tool provided with vim package.
+FIND_PROGRAM(XXD_EXECUTABLE xxd)
+# To avoid the dependency, simply compile it if not provided
+if (NOT XXD_EXECUTABLE) 
+   SET_SOURCE_FILES_PROPERTIES(helper/xxd.c PROPERTIES COMPILE_DEFINITIONS UNIX)
+   ADD_EXECUTABLE(xxd helper/xxd.c)
+   SET(XXD_EXECUTABLE xxd)
+endif (NOT XXD_EXECUTABLE) 
+# And now the magic command
+ADD_CUSTOM_COMMAND(
+    OUTPUT "fDpy-inc.c"
+    COMMAND "${XXD_EXECUTABLE}"
+    ARGS "-i"
+    "fDpy.py"
+    "fDpy-inc.c"
+    MAIN_DEPENDENCY "${swig_extra_generated_files}"
+    COMMENT "Shadow definitions") 
+
+# Ensure that the generated source files are removed
+GET_DIRECTORY_PROPERTY(swig_extra_clean_files ADDITIONAL_MAKE_CLEAN_FILES)
+SET_DIRECTORY_PROPERTIES(PROPERTIES
+        ADDITIONAL_MAKE_CLEAN_FILES "${swig_extra_clean_files};${swig_generated_sources};fDpy-inc.c")
+
+
+#####
+# Extension that embeds the python interpreter
+FD_ADD_EXTENSION(dbg_interactive dbg_interactive.c ${swig_generated_sources} fDpy-inc.c)
+TARGET_LINK_LIBRARIES(dbg_interactive ${PYTHON_LIBRARIES})
+
+
+####
+## INSTALL section ##
+
+INSTALL(TARGETS dbg_interactive
+	LIBRARY DESTINATION ${INSTALL_EXTENSIONS_SUFFIX}
+	COMPONENT freeDiameter-debug-tools)
diff --git a/extensions/dbg_interactive/dbg_interactive.c b/extensions/dbg_interactive/dbg_interactive.c
new file mode 100644
index 0000000..d1347a2
--- /dev/null
+++ b/extensions/dbg_interactive/dbg_interactive.c
@@ -0,0 +1,140 @@
+/*********************************************************************************************************
+* Software License Agreement (BSD License)                                                               *
+* Author: Sebastien Decugis <sdecugis@freediameter.net>							 *
+*													 *
+* Copyright (c) 2013, WIDE Project and NICT								 *
+* All rights reserved.											 *
+* 													 *
+* Redistribution and use of this software in source and binary forms, with or without modification, are  *
+* permitted provided that the following conditions are met:						 *
+* 													 *
+* * Redistributions of source code must retain the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer.										 *
+*    													 *
+* * Redistributions in binary form must reproduce the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer in the documentation and/or other						 *
+*   materials provided with the distribution.								 *
+* 													 *
+* * Neither the name of the WIDE Project or NICT nor the 						 *
+*   names of its contributors may be used to endorse or 						 *
+*   promote products derived from this software without 						 *
+*   specific prior written permission of WIDE Project and 						 *
+*   NICT.												 *
+* 													 *
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED *
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
+* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR *
+* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 	 *
+* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 	 *
+* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR *
+* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF   *
+* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.								 *
+*********************************************************************************************************/
+
+#include <Python.h>
+#include <freeDiameter/extension.h>
+#include <unistd.h>
+
+/* wrapper generated by SWIG */
+#if PY_VERSION_HEX >= 0x03000000
+	extern void PyInit__fDpy(void);
+	#define WRAPPER_INIT	PyInit__fDpy()
+#else /* PY_VERSION_HEX */
+	extern void init_fDpy(void);
+	#define WRAPPER_INIT	init_fDpy()
+#endif /* PY_VERSION_HEX */
+	
+/* The string created in the shadow proxy C string file */
+extern unsigned char fDpy_py[];
+extern unsigned int fDpy_py_len;
+
+/* Run an interactive interpreter in a separate thread */
+static pthread_t pyinterp = (pthread_t)NULL;
+static void * myinterp (void * arg)
+{
+	char * dum[3] = { "<dbg_interactive>", arg, NULL };
+
+	TRACE_ENTRY("%p", arg);
+	
+	fd_log_threadname ( "fDpy" );
+	
+	CHECK_FCT_DO(fd_core_waitstartcomplete(), goto end);
+	
+	if (arg) {
+		fd_log_debug("Starting python interpreter with a script file [experimental].");
+		Py_Main(2, dum);
+	} else {
+		if (!isatty(fileno(stdin)) || !isatty(fileno(stdout))) {
+			TRACE_ERROR("[dbg_interactive]: this extension requires freeDiameter to be run from a console terminal!");
+			goto end;
+		}
+		printf("Starting interactive python interpreter [experimental].\n");
+		printf("Please use Ctrl-D to exit.\n");
+		printf("Example syntax:\n");
+		printf("   >>> print cvar.fd_g_config.cnf_diamid\n");
+		printf("   '%s'\n", fd_g_config->cnf_diamid);
+		Py_Main(1, dum);
+		printf("Python interpreter has exited...\n");
+	}
+	
+end:	
+	/* Upon exit, issue the order of terminating to fD, if the interpreter was started without a file */
+	if (!arg) {
+		(void)fd_core_shutdown();
+	}
+
+	return NULL;
+}
+
+/* Register the callbacks to the daemon */
+static int di_main(char * conffile)
+{
+	char * shadow_hlp = NULL;
+	int mustfree = 0;
+	TRACE_ENTRY("%p", conffile);
+	
+	Py_InitializeEx(0);
+	
+	WRAPPER_INIT;
+	
+	/* Small hack to avoid duplicating the string, we replace the last char by a \0.
+	  It works if the python file is terminated with several \n */
+	if (   (fDpy_py[fDpy_py_len - 2] == '\n')
+	    && (fDpy_py[fDpy_py_len - 1] == '\n')) {
+		fDpy_py[fDpy_py_len - 1] = '\0';
+		shadow_hlp = (char *)&fDpy_py[0];
+	} else {
+		CHECK_MALLOC(shadow_hlp = malloc(fDpy_py_len + 1));
+		memcpy(shadow_hlp, fDpy_py, fDpy_py_len);
+		shadow_hlp[fDpy_py_len] = '\0';
+		mustfree=1;
+	}
+	
+	PyRun_SimpleString("__file__ = \"\"\n");
+	PyRun_SimpleString(shadow_hlp);
+	
+	if (mustfree)
+		free(shadow_hlp);
+		
+	CHECK_POSIX( pthread_create(&pyinterp, NULL, myinterp, conffile) );
+ 
+	return 0;
+}
+
+/* Terminate the extension */
+void fd_ext_fini(void)
+{
+	TRACE_ENTRY();
+	void * ret;
+	
+	/* Cleanup the python interpreter */
+	Py_Finalize();
+	pthread_join(pyinterp, &ret);
+	
+	return ;
+}
+
+/* Define the entry point function */
+EXTENSION_ENTRY("dbg_interactive", di_main);
diff --git a/extensions/dbg_interactive/dbg_interactive.i b/extensions/dbg_interactive/dbg_interactive.i
new file mode 100644
index 0000000..044584f
--- /dev/null
+++ b/extensions/dbg_interactive/dbg_interactive.i
@@ -0,0 +1,209 @@
+/* This interface file is processed by SWIG to create a python wrapper interface to freeDiameter framework. */
+%module fDpy
+%begin %{
+/*********************************************************************************************************
+* Software License Agreement (BSD License)                                                               *
+* Author: Sebastien Decugis <sdecugis@freediameter.net>							 *
+*													 *
+* Copyright (c) 2013, WIDE Project and NICT								 *
+* All rights reserved.											 *
+* 													 *
+* Redistribution and use of this software in source and binary forms, with or without modification, are  *
+* permitted provided that the following conditions are met:						 *
+* 													 *
+* * Redistributions of source code must retain the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer.										 *
+*    													 *
+* * Redistributions in binary form must reproduce the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer in the documentation and/or other						 *
+*   materials provided with the distribution.								 *
+* 													 *
+* * Neither the name of the WIDE Project or NICT nor the 						 *
+*   names of its contributors may be used to endorse or 						 *
+*   promote products derived from this software without 						 *
+*   specific prior written permission of WIDE Project and 						 *
+*   NICT.												 *
+* 													 *
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED *
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
+* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR *
+* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 	 *
+* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 	 *
+* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR *
+* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF   *
+* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.								 *
+*********************************************************************************************************/
+%}
+
+%{
+/* This text is included in the generated wrapper verbatim */
+#define SWIG
+#include <freeDiameter/extension.h>
+%}
+
+
+/* Include standard types & functions used in freeDiameter headers */
+%include <stdint.i>
+//%include <cdata.i>
+%include <cstring.i>
+%include <typemaps.i>
+
+
+/* Inline functions seems to give problems to SWIG -- just remove the inline definition */
+%define __inline__ 
+%enddef
+
+
+/* Make some global-variables read-only (mainly to avoid warnings) */
+%immutable fd_g_config;
+%immutable peer_state_str;
+
+#pragma SWIG nowarn=451
+
+/*****************
+ *  Exceptions  *
+*****************/
+%{
+/* This is not thread-safe etc. but it should work /most of the time/. */
+static int wrapper_errno;
+static PyObject* wrapper_errno_py;
+static const char * wrapper_error_txt; /* if NULL, use strerror(errno) */
+#define DI_ERROR(code, pycode, str) {	\
+	fd_log_debug("[dbg_interactive] ERROR: %s: %s", __PRETTY_FUNCTION__, str ? str : strerror(code)); \
+	wrapper_errno = code;		\
+	wrapper_errno_py = pycode;	\
+	wrapper_error_txt = str;	\
+}
+
+#define DI_ERROR_MALLOC	\
+	 DI_ERROR(ENOMEM, PyExc_MemoryError, NULL)
+
+%}
+
+%exception {
+	/* reset the errno */
+	wrapper_errno = 0;
+	/* Call the function  -- it will use DI_ERROR macro in case of error */
+	$action
+	/* Now, test for error */
+	if (wrapper_errno) {
+		const char * str = wrapper_error_txt ? wrapper_error_txt : strerror(wrapper_errno);
+		PyObject * exc = wrapper_errno_py;
+		if (!exc) {
+			switch (wrapper_errno) {
+				case ENOMEM: exc = PyExc_MemoryError; break;
+				case EINVAL: exc = PyExc_ValueError; break;
+				default: exc = PyExc_RuntimeError;
+			}
+		}
+		SWIG_PYTHON_THREAD_BEGIN_BLOCK;
+		PyErr_SetString(exc, str);
+		SWIG_fail;
+		SWIG_PYTHON_THREAD_END_BLOCK;
+	}
+}
+
+
+/***********************************
+ Some types & typemaps for usability 
+ ***********************************/
+
+%apply (char *STRING, size_t LENGTH) { ( char * string, size_t len ) };
+%apply (char *STRING, size_t LENGTH) { ( uint8_t * string, size_t len ) };
+
+/* Generic typemap for functions that create something */
+%typemap(in, numinputs=0,noblock=1) SWIGTYPE ** OUTPUT (void *temp = NULL) {
+	$1 = (void *)&temp;
+}
+%typemap(argout,noblock=1) SWIGTYPE ** OUTPUT {
+	%append_output(SWIG_NewPointerObj(*$1, $*1_descriptor, 0));
+}
+
+/* Case of the fd_*_dump functions */
+%typemap(in,noblock=1,numinputs=0) (char ** buf, size_t *len, size_t *offset) ($*1_ltype temp = NULL, $*2_ltype tempn = 0) {
+	$1 = &temp; $2 = &tempn; $3 = NULL;
+}
+%typemap(freearg,match="in") (char ** buf, size_t *len, size_t *offset) "";
+%typemap(argout,noblock=1,fragment="SWIG_FromCharPtr")(char ** buf, size_t *len, size_t *offset) { 
+  if (*$1) {
+    %append_output(SWIG_FromCharPtr(*$1));
+    free(*$1);					  	     
+  }					  	     
+}							     
+
+/* Typemap to return a boolean value as output parameter */
+%typemap(in, numinputs=0,noblock=1) int * BOOL_OUT (int temp) {
+	$1 = &temp;
+}
+%typemap(argout,noblock=1) int * BOOL_OUT {
+	PyObject * r;
+	if (*$1)
+		r = Py_True;
+	else
+		r = Py_False;
+	Py_XINCREF(r);
+	%append_output(r);
+}
+
+/* To allow passing callback functions defined in python */
+%typemap(in) PyObject *PyCb {
+	if (!$input || ($input == Py_None)) {
+		$1 = NULL;
+	} else {
+		if (!PyCallable_Check($input)) {
+			PyErr_SetString(PyExc_TypeError, "Need a callable object!");
+			SWIG_fail;
+		}
+		$1 = $input;
+	}
+}
+
+%{
+/* Forward declaration for the peers module */
+static void fd_add_cb(struct peer_info *peer, void *data);
+
+/* This one gives problems when included from the header file */
+void fd_log_va( int, const char *, va_list);
+void fd_log_deprecated( int level, const char *format, ... ) MARK_DEPRECATED
+{ 
+	va_list ap;
+	va_start(ap, format);
+	fd_log_va(level, format, ap);
+	va_end(ap);
+}
+
+%}
+
+/* Overwrite declaration to apply typemaps */
+int fd_sess_fromsid ( uint8_t * string, size_t len, struct session ** OUTPUT, int * BOOL_OUT);
+
+
+
+/*********************************************************
+ Now, create wrappers for (almost) all objects from fD API 
+ *********************************************************/
+%include "freeDiameter/freeDiameter-host.h"
+%include "freeDiameter/libfdproto.h"
+%include "freeDiameter/libfdcore.h"
+
+/* Most of the functions from the API are not directly usable "as is".
+See the specific following files and the dbg_interactive.py.sample file
+for more usable python-style versions.
+*/
+
+%include "lists.i"
+%include "dictionary.i"
+%include "sessions.i"
+%include "routing.i"
+%include "messages.i"
+%include "dispatch.i"
+%include "queues.i"
+
+%include "peers.i"
+%include "events.i"
+%include "endpoints.i"
+%include "hooks.i"
+
+%include "posix.i"
diff --git a/extensions/dbg_interactive/dictionary.i b/extensions/dbg_interactive/dictionary.i
new file mode 100644
index 0000000..41c9be8
--- /dev/null
+++ b/extensions/dbg_interactive/dictionary.i
@@ -0,0 +1,417 @@
+/*********************************************************************************************************
+* Software License Agreement (BSD License)                                                               *
+* Author: Sebastien Decugis <sdecugis@freediameter.net>							 *
+*													 *
+* Copyright (c) 2013, WIDE Project and NICT								 *
+* All rights reserved.											 *
+* 													 *
+* Redistribution and use of this software in source and binary forms, with or without modification, are  *
+* permitted provided that the following conditions are met:						 *
+* 													 *
+* * Redistributions of source code must retain the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer.										 *
+*    													 *
+* * Redistributions in binary form must reproduce the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer in the documentation and/or other						 *
+*   materials provided with the distribution.								 *
+* 													 *
+* * Neither the name of the WIDE Project or NICT nor the 						 *
+*   names of its contributors may be used to endorse or 						 *
+*   promote products derived from this software without 						 *
+*   specific prior written permission of WIDE Project and 						 *
+*   NICT.												 *
+* 													 *
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED *
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
+* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR *
+* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 	 *
+* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 	 *
+* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR *
+* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF   *
+* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.								 *
+*********************************************************************************************************/
+
+/* Do not include this directly, use dbg_interactive.i instead */
+
+/****** DICTIONARY *********/
+
+struct dictionary {
+};
+
+%extend dictionary {
+	dictionary() {
+		struct dictionary * r = NULL;
+		int ret = fd_dict_init(&r);
+		if (ret != 0) {
+			DI_ERROR(ret, NULL, NULL);
+			return NULL;
+		}
+		return r;
+	}
+	~dictionary() {
+		struct dictionary *d = self;
+		int ret = fd_dict_fini(&d);
+		if (ret != 0) {
+			DI_ERROR(ret, NULL, NULL);
+		}
+		return;
+	}
+	void dump() {
+		char * buf = NULL;
+		size_t len;
+		printf("%s", fd_dict_dump(&buf, &len, NULL, $self));
+		free(buf);
+	}
+	PyObject * vendors_list() {
+		uint32_t *list = NULL, *li;
+		PyObject * ret;
+		SWIG_PYTHON_THREAD_BEGIN_BLOCK;
+		ret = PyList_New(0);
+		list = fd_dict_get_vendorid_list($self);
+		for (li = list; *li != 0; li++) {
+			PyList_Append(ret, PyInt_FromLong((long)*li));
+		}
+		free(list);
+		SWIG_PYTHON_THREAD_END_BLOCK;
+		return ret;
+	}
+	struct dict_object * new_obj(enum dict_object_type type, void * data, struct dict_object * parent = NULL) {
+		struct dict_object * obj = NULL;
+		int ret = fd_dict_new($self, type, data, parent, &obj);
+		if (ret != 0) {
+			DI_ERROR(ret, NULL, NULL);
+			return NULL;
+		}
+		return obj;
+	}
+	struct dict_object * search(enum dict_object_type type, int criteria, int what_by_val) {
+		struct dict_object * obj = NULL;
+		int ret = fd_dict_search ( $self, type, criteria, &what_by_val, &obj, ENOENT );
+		if (ret != 0) {
+			DI_ERROR(ret, NULL, NULL);
+			return NULL;
+		}
+		return obj;
+	}
+	struct dict_object * search(enum dict_object_type type, int criteria, char * what_by_string) {
+		struct dict_object * obj = NULL;
+		int ret = fd_dict_search ( $self, type, criteria, what_by_string, &obj, ENOENT );
+		if (ret != 0) {
+			DI_ERROR(ret, NULL, NULL);
+			return NULL;
+		}
+		return obj;
+	}
+	struct dict_object * search(enum dict_object_type type, int criteria, void * what) {
+		struct dict_object * obj = NULL;
+		int ret = fd_dict_search ( $self, type, criteria, what, &obj, ENOENT );
+		if (ret != 0) {
+			DI_ERROR(ret, NULL, NULL);
+			return NULL;
+		}
+		return obj;
+	}
+	struct dict_object * error_cmd() {
+		struct dict_object * obj = NULL;
+		int ret = fd_dict_get_error_cmd ( $self, &obj );
+		if (ret != 0) {
+			DI_ERROR(ret, NULL, NULL);
+			return NULL;
+		}
+		return obj;
+	}
+}
+
+%nodefaultctor dict_object;
+struct dict_object {
+};
+
+%extend dict_object {
+	void dump() {
+		char * buf = NULL;
+		size_t len;
+		printf("%s", fd_dict_dump_object(&buf, &len, NULL, $self));
+		free(buf);
+	}
+	enum dict_object_type gettype() {
+		enum dict_object_type t;
+		int ret = fd_dict_gettype ( $self, &t);
+		if (ret != 0) {
+			DI_ERROR(ret, NULL, NULL);
+			return 0;
+		}
+		return t;
+	}
+	struct dictionary * getdict() {
+		struct dictionary *d;
+		int ret = fd_dict_getdict ( $self, &d );
+		if (ret != 0) {
+			DI_ERROR(ret, NULL, NULL);
+			return NULL;
+		}
+		return d;
+	}
+	/* Since casting the pointer requires intelligence, we do it here instead of giving it to SWIG */
+	PyObject * getval() {
+		/* first, get the type */
+		enum dict_object_type t;
+		int ret = fd_dict_gettype ( $self, &t);
+		if (ret != 0) {
+			DI_ERROR(ret, NULL, NULL);
+			return NULL;
+		}
+		switch (t) {
+%define %GETVAL_CASE(TYPE,STRUCT)
+			case TYPE: {
+				PyObject * v = NULL;
+				struct STRUCT * data = NULL;
+				data = malloc(sizeof(struct STRUCT));
+				if (!data) {
+					DI_ERROR_MALLOC;
+					return NULL;
+				}
+				ret = fd_dict_getval($self, data);
+				if (ret != 0) {
+					DI_ERROR(ret, NULL, NULL);
+					free(data);
+					return NULL;
+				}
+				SWIG_PYTHON_THREAD_BEGIN_BLOCK;
+				v = SWIG_NewPointerObj((void *)data, SWIGTYPE_p_##STRUCT, SWIG_POINTER_OWN );
+				Py_XINCREF(v);
+				SWIG_PYTHON_THREAD_END_BLOCK;
+				return v;
+			} break
+%enddef
+			%GETVAL_CASE( DICT_VENDOR, 	dict_vendor_data );
+			%GETVAL_CASE( DICT_APPLICATION, dict_application_data );
+			%GETVAL_CASE( DICT_TYPE, 	dict_type_data );
+			%GETVAL_CASE( DICT_ENUMVAL, 	dict_enumval_data );
+			%GETVAL_CASE( DICT_AVP, 	dict_avp_data );
+			%GETVAL_CASE( DICT_COMMAND, 	dict_cmd_data );
+			%GETVAL_CASE( DICT_RULE, 	dict_rule_data );
+			default:
+				DI_ERROR(EINVAL, PyExc_SystemError, "Internal error: Got invalid object type");
+		}
+		return NULL;
+	}
+}
+
+
+/* The following wrapper leaks memory each time an union avp_value is assigned an octet string.
+ TODO: fix this leak by better understanding SWIG... 
+   -- the alternative is to uncomment the "free" statements below, but then it is easy to
+   create a segmentation fault by assigning first an integer, then an octetstring.
+ */
+%extend avp_value {
+	/* The following hack in the proxy file allows assigning the octet string directly like this:
+	avp_value.os = "blabla"
+	*/
+	%pythoncode
+	{
+    __swig_setmethods__["os"] = _fDpy.avp_value_os_set
+    if _newclass:os = _swig_property(_fDpy.avp_value_os_get, _fDpy.avp_value_os_set)
+	}
+	void os_set(char *STRING, size_t LENGTH) {
+		/* free($self->os.data);  -- do not free, in case the previous value was not an OS */
+		$self->os.data = malloc(LENGTH);
+		if (!$self->os.data) {
+			DI_ERROR_MALLOC;
+			return;
+		}
+		memcpy($self->os.data, STRING, LENGTH);
+		$self->os.len = LENGTH;
+	}
+	void os_set(avp_value_os * os) {
+		/* free($self->os.data);  -- do not free, in case the previous value was not an OS */
+		$self->os.data = malloc(os->len);
+		if (!$self->os.data) {
+			DI_ERROR_MALLOC;
+			return;
+		}
+		memcpy($self->os.data, os->data, os->len);
+		$self->os.len = os->len;
+	}
+};
+
+%extend avp_value_os {
+	void dump() {
+		%#define LEN_MAX 20
+		int i, n=LEN_MAX;
+		if ($self->len < LEN_MAX)
+			n = $self->len;
+		fd_log_debug("l:%u, v:[", $self->len);
+		for (i=0; i < n; i++)
+			fd_log_debug("%02.2X", $self->data[i]);
+		fd_log_debug("] '%.*s%s'", n, $self->data, n == LEN_MAX ? "..." : "");
+	}
+	%cstring_output_allocate_size(char ** outbuffer, size_t * outlen, free(*$1));
+	void as_str ( char ** outbuffer, size_t * outlen ) {
+		char * b;
+		if (!$self->len) {
+			*outlen = 0;
+			*outbuffer = NULL;
+			return;
+		}
+		b = malloc($self->len);
+		if (!b) {
+			DI_ERROR_MALLOC;
+			return;
+		}
+		memcpy(b, $self->data, $self->len);
+		*outlen = $self->len;
+		*outbuffer = b;
+	}
+}
+
+
+/* Allow constructors with parameters for the dict_*_data */
+%extend dict_vendor_data {
+	dict_vendor_data(uint32_t id = 0, char * name = NULL) {
+		struct dict_vendor_data * d = (struct dict_vendor_data *)calloc(1, sizeof(struct dict_vendor_data));
+		if (!d) {
+			DI_ERROR_MALLOC;
+			return NULL;
+		}
+		d->vendor_id = id;
+		if (name) {
+			d->vendor_name = strdup(name);
+			if (!d->vendor_name) {
+				DI_ERROR_MALLOC;
+				free(d);
+				return NULL;
+			}
+		}
+		return d;
+	}
+}
+
+%extend dict_application_data {
+	dict_application_data(uint32_t id = 0, char * name = NULL) {
+		struct dict_application_data * d = (struct dict_application_data *)calloc(1, sizeof(struct dict_application_data));
+		if (!d) {
+			DI_ERROR_MALLOC;
+			return NULL;
+		}
+		d->application_id = id;
+		if (name) {
+			d->application_name = strdup(name);
+			if (!d->application_name) {
+				DI_ERROR_MALLOC;
+				free(d);
+				return NULL;
+			}
+		}
+		return d;
+	}
+}
+
+%extend dict_type_data {
+	dict_type_data(enum dict_avp_basetype base = 0, char * name = NULL) {
+		struct dict_type_data * d = (struct dict_type_data *)calloc(1, sizeof(struct dict_type_data));
+		if (!d) {
+			DI_ERROR_MALLOC;
+			return NULL;
+		}
+		d->type_base = base;
+		if (name) {
+			d->type_name = strdup(name);
+			if (!d->type_name) {
+				DI_ERROR_MALLOC;
+				free(d);
+				return NULL;
+			}
+		}
+		return d;
+	}
+}
+
+%extend dict_enumval_data {
+	dict_enumval_data(char * name = NULL, uint32_t v = 0) {
+		struct dict_enumval_data * d = (struct dict_enumval_data *)calloc(1, sizeof(struct dict_enumval_data));
+		if (!d) {
+			DI_ERROR_MALLOC;
+			return NULL;
+		}
+		if (name) {
+			d->enum_name = strdup(name);
+			if (!d->enum_name) {
+				DI_ERROR_MALLOC;
+				free(d);
+				return NULL;
+			}
+		}
+		d->enum_value.u32 = v;
+		return d;
+	}
+}
+
+%extend dict_avp_data {
+	dict_avp_data(uint32_t code = 0, char * name = NULL, enum dict_avp_basetype basetype = 0, uint32_t vendor = 0, int mandatory=0) {
+		struct dict_avp_data * d = (struct dict_avp_data *)calloc(1, sizeof(struct dict_avp_data));
+		if (!d) {
+			DI_ERROR_MALLOC;
+			return NULL;
+		}
+		if (name) {
+			d->avp_name = strdup(name);
+			if (!d->avp_name) {
+				DI_ERROR_MALLOC;
+				free(d);
+				return NULL;
+			}
+		}
+		d->avp_code = code;
+		d->avp_basetype = basetype;
+		d->avp_vendor = vendor;
+		if (vendor) {
+			d->avp_flag_val |= AVP_FLAG_VENDOR;
+			d->avp_flag_mask |= AVP_FLAG_VENDOR;
+		}
+		d->avp_flag_mask |= AVP_FLAG_MANDATORY;
+		if (mandatory)
+			d->avp_flag_val |= AVP_FLAG_MANDATORY;
+		return d;
+	}
+}
+
+%extend dict_cmd_data {
+	dict_cmd_data(uint32_t code = 0, char * name = NULL, int request = 1) {
+		struct dict_cmd_data * d = (struct dict_cmd_data *)calloc(1, sizeof(struct dict_cmd_data));
+		if (!d) {
+			DI_ERROR_MALLOC;
+			return NULL;
+		}
+		if (name) {
+			d->cmd_name = strdup(name);
+			if (!d->cmd_name) {
+				DI_ERROR_MALLOC;
+				free(d);
+				return NULL;
+			}
+		}
+		d->cmd_code = code;
+		d->cmd_flag_mask = CMD_FLAG_REQUEST | CMD_FLAG_PROXIABLE;
+		d->cmd_flag_val = CMD_FLAG_PROXIABLE | ( request ? CMD_FLAG_REQUEST : 0 );
+		return d;
+	}
+}
+
+%extend dict_rule_data {
+	dict_rule_data(struct dict_object *avp = NULL, enum rule_position pos = 0, int min = -1, int max = -1 ) {
+		struct dict_rule_data * d = (struct dict_rule_data *)calloc(1, sizeof(struct dict_rule_data));
+		if (!d) {
+			DI_ERROR_MALLOC;
+			return NULL;
+		}
+		d->rule_avp = avp;
+		d->rule_position = pos;
+		d->rule_order = 1;
+		d->rule_min = min;
+		d->rule_max = max;
+		return d;
+	}
+}
+
diff --git a/extensions/dbg_interactive/dispatch.i b/extensions/dbg_interactive/dispatch.i
new file mode 100644
index 0000000..bc39251
--- /dev/null
+++ b/extensions/dbg_interactive/dispatch.i
@@ -0,0 +1,146 @@
+/*********************************************************************************************************
+* Software License Agreement (BSD License)                                                               *
+* Author: Sebastien Decugis <sdecugis@freediameter.net>							 *
+*													 *
+* Copyright (c) 2013, WIDE Project and NICT								 *
+* All rights reserved.											 *
+* 													 *
+* Redistribution and use of this software in source and binary forms, with or without modification, are  *
+* permitted provided that the following conditions are met:						 *
+* 													 *
+* * Redistributions of source code must retain the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer.										 *
+*    													 *
+* * Redistributions in binary form must reproduce the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer in the documentation and/or other						 *
+*   materials provided with the distribution.								 *
+* 													 *
+* * Neither the name of the WIDE Project or NICT nor the 						 *
+*   names of its contributors may be used to endorse or 						 *
+*   promote products derived from this software without 						 *
+*   specific prior written permission of WIDE Project and 						 *
+*   NICT.												 *
+* 													 *
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED *
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
+* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR *
+* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 	 *
+* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 	 *
+* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR *
+* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF   *
+* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.								 *
+*********************************************************************************************************/
+
+/* Do not include this directly, use dbg_interactive.i instead */
+
+/****** DISPATCH *********/
+
+
+%{
+/* call it (will be called from a different thread than the interpreter, when message arrives) */
+static int call_the_python_dispatch_callback(struct msg **msg, struct avp *avp, struct session *session, void * pycb, enum disp_action *action) {
+	PyObject *PyMsg, *PyAvp, *PySess;
+	PyObject *cb, *result = NULL;
+	int ret = 0;
+	
+	if (!pycb) {
+		fd_log_debug("Internal error: missing the callback!");
+		return ENOTSUP;
+	}
+	cb = pycb;
+	
+	SWIG_PYTHON_THREAD_BEGIN_BLOCK;
+	/* Convert the arguments */
+	PyMsg  = SWIG_NewPointerObj((void *)*msg,     SWIGTYPE_p_msg,     0 );
+	PyAvp  = SWIG_NewPointerObj((void *) avp,     SWIGTYPE_p_avp,     0 );
+	PySess = SWIG_NewPointerObj((void *) session, SWIGTYPE_p_session, 0 );
+	
+	/* Call the function */
+	result = PyObject_CallFunction(cb, "(OOO)", PyMsg, PyAvp, PySess);
+	
+	/* The result is supposedly composed of: [ ret, *msg, *action ] */
+	if ((result == NULL) || (!PyList_Check(result)) || (PyList_Size(result) != 3)) {
+		fd_log_debug("Error: The Python callback did not return [ ret, msg, action ].");
+		ret = EINVAL;
+		goto out;
+	}
+	
+	/* Convert the return values */
+	if (!SWIG_IsOK(SWIG_AsVal_int(PyList_GetItem(result, 0), &ret))) {
+		fd_log_debug("Error: Cannot convert the first return value to integer.");
+		ret = EINVAL;
+		goto out;
+	}
+	if (ret) {
+		TRACE_DEBUG(INFO, "The Python callback returned the error code %d (%s)", ret, strerror(ret));
+		goto out;
+	}
+	
+	if (!SWIG_IsOK(SWIG_ConvertPtr(PyList_GetItem(result, 1), (void *)msg, SWIGTYPE_p_msg, SWIG_POINTER_DISOWN))) {
+		fd_log_debug("Error: Cannot convert the second return value to message.");
+		ret = EINVAL;
+		goto out;
+	}
+	
+	if (!SWIG_IsOK(SWIG_AsVal_int(PyList_GetItem(result, 2), (int *)action))) {
+		fd_log_debug("Error: Cannot convert the third return value to integer.");
+		ret = EINVAL;
+		goto out;
+	}
+	
+	TRACE_DEBUG(FULL, "Python callback return: *action = %d", *action);
+out:	
+	Py_XDECREF(result);
+	
+	SWIG_PYTHON_THREAD_END_BLOCK;
+	return ret;
+}
+%}
+
+struct disp_hdl {
+};
+
+%nodefaultctor disp_hdl;
+%extend disp_hdl {
+	disp_hdl(PyObject * PyCb, enum disp_how how, struct disp_when * when) {
+		struct disp_hdl * hdl = NULL;
+		int ret;
+		
+		Py_XINCREF(PyCb);
+		
+		ret = fd_disp_register ( call_the_python_dispatch_callback, how, when, PyCb, &hdl );
+		if (ret != 0) {
+			DI_ERROR(ret, NULL, NULL);
+			return NULL;
+		}
+		return hdl;
+	}
+	~disp_hdl() {
+		struct disp_hdl * hdl = self;
+		PyObject * cb = NULL;
+		int ret = fd_disp_unregister(&hdl, (void *)&cb);
+		if (ret != 0) {
+			DI_ERROR(ret, NULL, NULL);
+		}
+		Py_XDECREF(cb);
+		return;
+	}
+}
+
+
+%extend disp_when {
+	disp_when(struct dict_object * app = NULL, struct dict_object * command = NULL, struct dict_object * avp = NULL, struct dict_object * value = NULL) {
+      		struct disp_when * w = (struct disp_when *)calloc(1, sizeof(struct disp_when));
+		if (!w) {
+			DI_ERROR_MALLOC;
+			return NULL;
+		}
+		w->app = app;
+		w->command = command;
+		w->avp = avp;
+		w->value = value;
+		return w;
+	}
+}
diff --git a/extensions/dbg_interactive/endpoints.i b/extensions/dbg_interactive/endpoints.i
new file mode 100644
index 0000000..329f379
--- /dev/null
+++ b/extensions/dbg_interactive/endpoints.i
@@ -0,0 +1,133 @@
+/*********************************************************************************************************
+* Software License Agreement (BSD License)                                                               *
+* Author: Sebastien Decugis <sdecugis@freediameter.net>							 *
+*													 *
+* Copyright (c) 2013, WIDE Project and NICT								 *
+* All rights reserved.											 *
+* 													 *
+* Redistribution and use of this software in source and binary forms, with or without modification, are  *
+* permitted provided that the following conditions are met:						 *
+* 													 *
+* * Redistributions of source code must retain the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer.										 *
+*    													 *
+* * Redistributions in binary form must reproduce the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer in the documentation and/or other						 *
+*   materials provided with the distribution.								 *
+* 													 *
+* * Neither the name of the WIDE Project or NICT nor the 						 *
+*   names of its contributors may be used to endorse or 						 *
+*   promote products derived from this software without 						 *
+*   specific prior written permission of WIDE Project and 						 *
+*   NICT.												 *
+* 													 *
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED *
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
+* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR *
+* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 	 *
+* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 	 *
+* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR *
+* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF   *
+* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.								 *
+*********************************************************************************************************/
+
+/* Do not include this directly, use dbg_interactive.i instead */
+
+/****** ENDPOINTS *********/
+
+%{
+
+#include <sys/socket.h>
+#include <netdb.h>
+
+%}
+
+%extend fd_endpoint {
+	fd_endpoint() {
+		struct fd_endpoint *np = (struct fd_endpoint *)calloc(1, sizeof(struct fd_endpoint));
+		if (!np) {
+			DI_ERROR_MALLOC;
+			return NULL;
+		}
+		fd_list_init(&np->chain, np);
+		return np;
+	}
+	
+	fd_endpoint(const char * endpoint, uint16_t port = 0, uint32_t flags = EP_FL_CONF) {
+		struct addrinfo hints;
+		struct addrinfo *ai = NULL;
+		int ret;
+		
+		memset(&hints, 0, sizeof(hints));
+		hints.ai_family= AF_UNSPEC;
+		hints.ai_flags = AI_NUMERICHOST;
+		
+		ret = getaddrinfo(endpoint, NULL, &hints, &ai);
+		if (ret) {
+			DI_ERROR(ret, PyExc_ValueError, gai_strerror(ret));
+			return NULL;
+		}
+		
+		if (port) {
+			switch (ai->ai_family) {
+				case AF_INET:
+					((sSA4 *)ai->ai_addr)->sin_port = htons(port);
+					break;
+				case AF_INET6:
+					((sSA6 *)ai->ai_addr)->sin6_port = htons(port);
+					break;
+				default:
+					DI_ERROR(EINVAL, PyExc_RuntimeError, "Unknown family returned by getaddrinfo");
+					return NULL;
+			}
+		}
+		
+		struct fd_endpoint *np = (struct fd_endpoint *)calloc(1, sizeof(struct fd_endpoint));
+		if (!np) {
+			DI_ERROR_MALLOC;
+			return NULL;
+		}
+		fd_list_init(&np->chain, np);
+		
+		memcpy(&np->s.sa, ai->ai_addr, ai->ai_addrlen);
+		
+		freeaddrinfo(ai);
+		
+		np->flags = flags;
+		
+		return np;
+	}
+	
+	~fd_endpoint() {
+		fd_list_unlink(&$self->chain);
+		free($self);
+	}
+	
+	/* Merge to a list */
+	%delobject add_merge;
+	void add_merge(struct fd_list * eplist) {
+		int ret;
+		
+		if (!eplist) {
+			DI_ERROR(EINVAL, NULL, NULL);
+			return;
+		}
+		
+		ret = fd_ep_add_merge( eplist, &$self->s.sa, sSAlen(&$self->s.sa), $self->flags );
+		if (ret) {
+			DI_ERROR(ret, NULL, NULL);
+			return;
+		}
+		
+		return;
+	}
+	
+	void dump() {
+		char * buf = NULL;
+		size_t len;
+		printf("%s", fd_ep_dump_one(&buf, &len, NULL, 1, $self));
+		free(buf);
+	}
+}
diff --git a/extensions/dbg_interactive/events.i b/extensions/dbg_interactive/events.i
new file mode 100644
index 0000000..a70c89e
--- /dev/null
+++ b/extensions/dbg_interactive/events.i
@@ -0,0 +1,73 @@
+/*********************************************************************************************************
+* Software License Agreement (BSD License)                                                               *
+* Author: Sebastien Decugis <sdecugis@freediameter.net>							 *
+*													 *
+* Copyright (c) 2011, WIDE Project and NICT								 *
+* All rights reserved.											 *
+* 													 *
+* Redistribution and use of this software in source and binary forms, with or without modification, are  *
+* permitted provided that the following conditions are met:						 *
+* 													 *
+* * Redistributions of source code must retain the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer.										 *
+*    													 *
+* * Redistributions in binary form must reproduce the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer in the documentation and/or other						 *
+*   materials provided with the distribution.								 *
+* 													 *
+* * Neither the name of the WIDE Project or NICT nor the 						 *
+*   names of its contributors may be used to endorse or 						 *
+*   promote products derived from this software without 						 *
+*   specific prior written permission of WIDE Project and 						 *
+*   NICT.												 *
+* 													 *
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED *
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
+* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR *
+* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 	 *
+* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 	 *
+* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR *
+* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF   *
+* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.								 *
+*********************************************************************************************************/
+
+/* Do not include this directly, use dbg_interactive.i instead */
+
+/****** EVENTS *********/
+
+%extend fd_event {
+	fd_event(int code, char *STRING, size_t LENGTH) {
+		struct fd_event * fd = calloc(1, sizeof(struct fd_event));
+		if (!fd) {
+			DI_ERROR_MALLOC;
+			return NULL;
+		}
+		fd->code = code;
+		fd->data = os0dup(STRING, LENGTH);
+		if (!fd->data) {
+			DI_ERROR_MALLOC;
+			return NULL;
+		};
+		fd->size = LENGTH;
+		return fd;
+	}
+	
+	fd_event(int code, int value) {
+		struct fd_event * fd = calloc(1, sizeof(struct fd_event));
+		if (!fd) {
+			DI_ERROR_MALLOC;
+			return NULL;
+		}
+		fd->code = code;
+		fd->data = malloc(sizeof(int));
+		if (!fd->data) {
+			DI_ERROR_MALLOC;
+			return NULL;
+		};
+		*((int *)fd->data) = value;
+		fd->size = sizeof(int);
+		return fd;
+	}
+}	
diff --git a/extensions/dbg_interactive/helper/xxd.c b/extensions/dbg_interactive/helper/xxd.c
new file mode 100644
index 0000000..490f571
--- /dev/null
+++ b/extensions/dbg_interactive/helper/xxd.c
@@ -0,0 +1,787 @@
+/* fD note: This source file comes from the VIM source package. All credits go to the original authors */
+
+/* xxd: my hexdump facility. jw
+ *
+ *  2.10.90 changed to word output
+ *  3.03.93 new indent style, dumb bug inserted and fixed.
+ *	    -c option, mls
+ * 26.04.94 better option parser, -ps, -l, -s added.
+ *  1.07.94 -r badly needs - as input file.  Per default autoskip over
+ *	       consecutive lines of zeroes, as unix od does.
+ *	    -a shows them too.
+ *	    -i dump as c-style #include "file.h"
+ *  1.11.95 if "xxd -i" knows the filename, an 'unsigned char filename_bits[]'
+ *	    array is written in correct c-syntax.
+ *	    -s improved, now defaults to absolute seek, relative requires a '+'.
+ *	    -r improved, now -r -s -0x... is supported.
+ *	       change/suppress leading '\0' bytes.
+ *	    -l n improved: stops exactly after n bytes.
+ *	    -r improved, better handling of partial lines with trailing garbage.
+ *	    -r improved, now -r -p works again!
+ *	    -r improved, less flushing, much faster now! (that was silly)
+ *  3.04.96 Per repeated request of a single person: autoskip defaults to off.
+ * 15.05.96 -v added. They want to know the version.
+ *	    -a fixed, to show last line inf file ends in all zeros.
+ *	    -u added: Print upper case hex-letters, as preferred by unix bc.
+ *	    -h added to usage message. Usage message extended.
+ *	    Now using outfile if specified even in normal mode, aehem.
+ *	    No longer mixing of ints and longs. May help doze people.
+ *	    Added binify ioctl for same reason. (Enough Doze stress for 1996!)
+ * 16.05.96 -p improved, removed occasional superfluous linefeed.
+ * 20.05.96 -l 0 fixed. tried to read anyway.
+ * 21.05.96 -i fixed. now honours -u, and prepends __ to numeric filenames.
+ *	    compile -DWIN32 for NT or W95. George V. Reilly, * -v improved :-)
+ *	    support --gnuish-longhorn-options
+ * 25.05.96 MAC support added: CodeWarrior already uses ``outline'' in Types.h
+ *	    which is included by MacHeaders (Axel Kielhorn). Renamed to
+ *	    xxdline().
+ *  7.06.96 -i printed 'int' instead of 'char'. *blush*
+ *	    added Bram's OS2 ifdefs...
+ * 18.07.96 gcc -Wall @ SunOS4 is now slient.
+ *	    Added osver for MSDOS/DJGPP/WIN32.
+ * 29.08.96 Added size_t to strncmp() for Amiga.
+ * 24.03.97 Windows NT support (Phil Hanna). Clean exit for Amiga WB (Bram)
+ * 02.04.97 Added -E option, to have EBCDIC translation instead of ASCII
+ *	    (azc10@yahoo.com)
+ * 22.05.97 added -g (group octets) option (jcook@namerica.kla.com).
+ * 23.09.98 nasty -p -r misfeature fixed: slightly wrong output, when -c was
+ *	    missing or wrong.
+ * 26.09.98 Fixed: 'xxd -i infile outfile' did not truncate outfile.
+ * 27.10.98 Fixed: -g option parser required blank.
+ *	    option -b added: 01000101 binary output in normal format.
+ * 16.05.00 Added VAXC changes by Stephen P. Wall
+ * 16.05.00 Improved MMS file and merge for VMS by Zoltan Arpadffy
+ *
+ * (c) 1990-1998 by Juergen Weigert (jnweiger@informatik.uni-erlangen.de)
+ *
+ * Small changes made afterwards by Bram Moolenaar et al.
+ *
+ * Distribute freely and credit me,
+ * make money and share with me,
+ * lose money and don't ask me.
+ */
+
+/* Visual Studio 2005 has 'deprecated' many of the standard CRT functions */
+#if _MSC_VER >= 1400
+# define _CRT_SECURE_NO_DEPRECATE
+# define _CRT_NONSTDC_NO_DEPRECATE
+#endif
+#if !defined(CYGWIN) && (defined(CYGWIN32) || defined(__CYGWIN__) || defined(__CYGWIN32__))
+# define CYGWIN
+#endif
+
+#include <stdio.h>
+#ifdef VAXC
+# include <file.h>
+#else
+# include <fcntl.h>
+#endif
+#ifdef __TSC__
+# define MSDOS
+#endif
+#if !defined(OS2) && defined(__EMX__)
+# define OS2
+#endif
+#if defined(MSDOS) || defined(WIN32) || defined(OS2) || defined(__BORLANDC__) \
+  || defined(CYGWIN)
+# include <io.h>	/* for setmode() */
+#else
+# ifdef UNIX
+#  include <unistd.h>
+# endif
+#endif
+#include <stdlib.h>
+#include <string.h>	/* for strncmp() */
+#include <ctype.h>	/* for isalnum() */
+#if __MWERKS__ && !defined(BEBOX)
+# include <unix.h>	/* for fdopen() on MAC */
+#endif
+
+#if defined(__BORLANDC__) && __BORLANDC__ <= 0x0410 && !defined(fileno)
+/* Missing define and prototype grabbed from the BC 4.0 <stdio.h> */
+# define fileno(f)       ((f)->fd)
+FILE   _FAR *_Cdecl _FARFUNC fdopen(int __handle, char _FAR *__type);
+#endif
+
+
+/*  This corrects the problem of missing prototypes for certain functions
+ *  in some GNU installations (e.g. SunOS 4.1.x).
+ *  Darren Hiebert <darren@hmi.com> (sparc-sun-sunos4.1.3_U1/2.7.2.2)
+ */
+#if defined(__GNUC__) && defined(__STDC__)
+# ifndef __USE_FIXED_PROTOTYPES__
+#  define __USE_FIXED_PROTOTYPES__
+# endif
+#endif
+
+#ifndef __USE_FIXED_PROTOTYPES__
+/*
+ * This is historic and works only if the compiler really has no prototypes:
+ *
+ * Include prototypes for Sun OS 4.x, when using an ANSI compiler.
+ * FILE is defined on OS 4.x, not on 5.x (Solaris).
+ * if __SVR4 is defined (some Solaris versions), don't include this.
+ */
+#if defined(sun) && defined(FILE) && !defined(__SVR4) && defined(__STDC__)
+#  define __P(a) a
+/* excerpt from my sun_stdlib.h */
+extern int fprintf __P((FILE *, char *, ...));
+extern int fputs   __P((char *, FILE *));
+extern int _flsbuf __P((unsigned char, FILE *));
+extern int _filbuf __P((FILE *));
+extern int fflush  __P((FILE *));
+extern int fclose  __P((FILE *));
+extern int fseek   __P((FILE *, long, int));
+extern int rewind  __P((FILE *));
+
+extern void perror __P((char *));
+# endif
+#endif
+
+extern long int strtol();
+extern long int ftell();
+
+char version[] = "xxd V1.10 27oct98 by Juergen Weigert";
+#ifdef WIN32
+char osver[] = " (Win32)";
+#else
+# ifdef DJGPP
+char osver[] = " (dos 32 bit)";
+# else
+#  ifdef MSDOS
+char osver[] = " (dos 16 bit)";
+#  else
+char osver[] = "";
+#  endif
+# endif
+#endif
+
+#if defined(MSDOS) || defined(WIN32) || defined(OS2)
+# define BIN_READ(yes)  ((yes) ? "rb" : "rt")
+# define BIN_WRITE(yes) ((yes) ? "wb" : "wt")
+# define BIN_CREAT(yes) ((yes) ? (O_CREAT|O_BINARY) : O_CREAT)
+# define BIN_ASSIGN(fp, yes) setmode(fileno(fp), (yes) ? O_BINARY : O_TEXT)
+# define PATH_SEP '\\'
+#elif defined(CYGWIN)
+# define BIN_READ(yes)  ((yes) ? "rb" : "rt")
+# define BIN_WRITE(yes) ((yes) ? "wb" : "w")
+# define BIN_CREAT(yes) ((yes) ? (O_CREAT|O_BINARY) : O_CREAT)
+# define BIN_ASSIGN(fp, yes) ((yes) ? (void) setmode(fileno(fp), O_BINARY) : (void) (fp))
+# define PATH_SEP '/'
+#else
+# ifdef VMS
+#  define BIN_READ(dummy)  "r"
+#  define BIN_WRITE(dummy) "w"
+#  define BIN_CREAT(dummy) O_CREAT
+#  define BIN_ASSIGN(fp, dummy) fp
+#  define PATH_SEP ']'
+#  define FILE_SEP '.'
+# else
+#  define BIN_READ(dummy)  "r"
+#  define BIN_WRITE(dummy) "w"
+#  define BIN_CREAT(dummy) O_CREAT
+#  define BIN_ASSIGN(fp, dummy) fp
+#  define PATH_SEP '/'
+# endif
+#endif
+
+/* open has only to arguments on the Mac */
+#if __MWERKS__
+# define OPEN(name, mode, umask) open(name, mode)
+#else
+# define OPEN(name, mode, umask) open(name, mode, umask)
+#endif
+
+#ifdef AMIGA
+# define STRNCMP(s1, s2, l) strncmp(s1, s2, (size_t)l)
+#else
+# define STRNCMP(s1, s2, l) strncmp(s1, s2, l)
+#endif
+
+#ifndef __P
+# if defined(__STDC__) || defined(MSDOS) || defined(WIN32) || defined(OS2) \
+		|| defined(__BORLANDC__)
+#  define __P(a) a
+# else
+#  define __P(a) ()
+# endif
+#endif
+
+/* Let's collect some prototypes */
+/* CodeWarrior is really picky about missing prototypes */
+static void exit_with_usage __P((char *));
+static int huntype __P((FILE *, FILE *, FILE *, char *, int, int, long));
+static void xxdline __P((FILE *, char *, int));
+
+#define TRY_SEEK	/* attempt to use lseek, or skip forward by reading */
+#define COLS 256	/* change here, if you ever need more columns */
+#define LLEN (11 + (9*COLS-1)/1 + COLS + 2)
+
+char hexxa[] = "0123456789abcdef0123456789ABCDEF", *hexx = hexxa;
+
+/* the different hextypes known by this program: */
+#define HEX_NORMAL 0
+#define HEX_POSTSCRIPT 1
+#define HEX_CINCLUDE 2
+#define HEX_BITS 3		/* not hex a dump, but bits: 01111001 */
+
+static void
+exit_with_usage(pname)
+char *pname;
+{
+  fprintf(stderr, "Usage:\n       %s [options] [infile [outfile]]\n", pname);
+  fprintf(stderr, "    or\n       %s -r [-s [-]offset] [-c cols] [-ps] [infile [outfile]]\n", pname);
+  fprintf(stderr, "Options:\n");
+  fprintf(stderr, "    -a          toggle autoskip: A single '*' replaces nul-lines. Default off.\n");
+  fprintf(stderr, "    -b          binary digit dump (incompatible with -ps,-i,-r). Default hex.\n");
+  fprintf(stderr, "    -c cols     format <cols> octets per line. Default 16 (-i: 12, -ps: 30).\n");
+  fprintf(stderr, "    -E          show characters in EBCDIC. Default ASCII.\n");
+  fprintf(stderr, "    -g          number of octets per group in normal output. Default 2.\n");
+  fprintf(stderr, "    -h          print this summary.\n");
+  fprintf(stderr, "    -i          output in C include file style.\n");
+  fprintf(stderr, "    -l len      stop after <len> octets.\n");
+  fprintf(stderr, "    -ps         output in postscript plain hexdump style.\n");
+  fprintf(stderr, "    -r          reverse operation: convert (or patch) hexdump into binary.\n");
+  fprintf(stderr, "    -r -s off   revert with <off> added to file positions found in hexdump.\n");
+  fprintf(stderr, "    -s %sseek  start at <seek> bytes abs. %sinfile offset.\n",
+#ifdef TRY_SEEK
+	  "[+][-]", "(or +: rel.) ");
+#else
+	  "", "");
+#endif
+  fprintf(stderr, "    -u          use upper case hex letters.\n");
+  fprintf(stderr, "    -v          show version: \"%s%s\".\n", version, osver);
+  exit(1);
+}
+
+/*
+ * Max. cols binary characters are decoded from the input stream per line.
+ * Two adjacent garbage characters after evaluated data delimit valid data.
+ * Everything up to the next newline is discarded.
+ *
+ * The name is historic and came from 'undo type opt h'.
+ */
+static int
+huntype(fpi, fpo, fperr, pname, cols, hextype, base_off)
+FILE *fpi, *fpo, *fperr;
+char *pname;
+int cols, hextype;
+long base_off;
+{
+  int c, ign_garb = 1, n1 = -1, n2 = 0, n3, p = cols;
+  long have_off = 0, want_off = 0;
+
+  rewind(fpi);
+
+  while ((c = getc(fpi)) != EOF)
+    {
+      if (c == '\r')	/* Doze style input file? */
+	continue;
+
+      /* Allow multiple spaces.  This doesn't work when there is normal text
+       * after the hex codes in the last line that looks like hex, thus only
+       * use it for PostScript format. */
+      if (hextype == HEX_POSTSCRIPT && (c == ' ' || c == '\n' || c == '\t'))
+	continue;
+
+      n3 = n2;
+      n2 = n1;
+
+      if (c >= '0' && c <= '9')
+	n1 = c - '0';
+      else if (c >= 'a' && c <= 'f')
+	n1 = c - 'a' + 10;
+      else if (c >= 'A' && c <= 'F')
+	n1 = c - 'A' + 10;
+      else
+	{
+	  n1 = -1;
+	  if (ign_garb)
+	    continue;
+	}
+
+      ign_garb = 0;
+
+      if (p >= cols)
+	{
+	  if (!hextype)
+	    {
+	      if (n1 < 0)
+		{
+		  p = 0;
+		  continue;
+		}
+	      want_off = (want_off << 4) | n1;
+	      continue;
+	    }
+	  else
+	    p = 0;
+	}
+
+      if (base_off + want_off != have_off)
+	{
+	  fflush(fpo);
+#ifdef TRY_SEEK
+	  c = fseek(fpo, base_off + want_off - have_off, 1);
+	  if (c >= 0)
+	    have_off = base_off + want_off;
+#endif
+	  if (base_off + want_off < have_off)
+	    {
+	      fprintf(fperr, "%s: sorry, cannot seek backwards.\n", pname);
+	      return 5;
+	    }
+	  for (; have_off < base_off + want_off; have_off++)
+	    putc(0, fpo);
+	}
+
+      if (n2 >= 0 && n1 >= 0)
+	{
+	  putc((n2 << 4) | n1, fpo);
+	  have_off++;
+	  want_off++;
+	  n1 = -1;
+	  if ((++p >= cols) && !hextype)
+	    {
+	      /* skip rest of line as garbage */
+	      want_off = 0;
+	      while ((c = getc(fpi)) != '\n' && c != EOF)
+		;
+	      ign_garb = 1;
+	    }
+	}
+      else if (n1 < 0 && n2 < 0 && n3 < 0)
+	{
+	  /* already stumbled into garbage, skip line, wait and see */
+	  if (!hextype)
+	    want_off = 0;
+	  while ((c = getc(fpi)) != '\n' && c != EOF)
+	    ;
+	  ign_garb = 1;
+	}
+    }
+  fflush(fpo);
+#ifdef TRY_SEEK
+  fseek(fpo, 0L, 2);
+#endif
+  fclose(fpo);
+  fclose(fpi);
+  return 0;
+}
+
+/*
+ * Print line l. If nz is false, xxdline regards the line a line of
+ * zeroes. If there are three or more consecutive lines of zeroes,
+ * they are replaced by a single '*' character.
+ *
+ * If the output ends with more than two lines of zeroes, you
+ * should call xxdline again with l being the last line and nz
+ * negative. This ensures that the last line is shown even when
+ * it is all zeroes.
+ *
+ * If nz is always positive, lines are never suppressed.
+ */
+static void
+xxdline(fp, l, nz)
+FILE *fp;
+char *l;
+int nz;
+{
+  static char z[LLEN+1];
+  static int zero_seen = 0;
+
+  if (!nz && zero_seen == 1)
+    strcpy(z, l);
+
+  if (nz || !zero_seen++)
+    {
+      if (nz)
+	{
+	  if (nz < 0)
+	    zero_seen--;
+	  if (zero_seen == 2)
+	    fputs(z, fp);
+	  if (zero_seen > 2)
+	    fputs("*\n", fp);
+	}
+      if (nz >= 0 || zero_seen > 0)
+	fputs(l, fp);
+      if (nz)
+	zero_seen = 0;
+    }
+}
+
+/* This is an EBCDIC to ASCII conversion table */
+/* from a proposed BTL standard April 16, 1979 */
+static unsigned char etoa64[] =
+{
+    0040,0240,0241,0242,0243,0244,0245,0246,
+    0247,0250,0325,0056,0074,0050,0053,0174,
+    0046,0251,0252,0253,0254,0255,0256,0257,
+    0260,0261,0041,0044,0052,0051,0073,0176,
+    0055,0057,0262,0263,0264,0265,0266,0267,
+    0270,0271,0313,0054,0045,0137,0076,0077,
+    0272,0273,0274,0275,0276,0277,0300,0301,
+    0302,0140,0072,0043,0100,0047,0075,0042,
+    0303,0141,0142,0143,0144,0145,0146,0147,
+    0150,0151,0304,0305,0306,0307,0310,0311,
+    0312,0152,0153,0154,0155,0156,0157,0160,
+    0161,0162,0136,0314,0315,0316,0317,0320,
+    0321,0345,0163,0164,0165,0166,0167,0170,
+    0171,0172,0322,0323,0324,0133,0326,0327,
+    0330,0331,0332,0333,0334,0335,0336,0337,
+    0340,0341,0342,0343,0344,0135,0346,0347,
+    0173,0101,0102,0103,0104,0105,0106,0107,
+    0110,0111,0350,0351,0352,0353,0354,0355,
+    0175,0112,0113,0114,0115,0116,0117,0120,
+    0121,0122,0356,0357,0360,0361,0362,0363,
+    0134,0237,0123,0124,0125,0126,0127,0130,
+    0131,0132,0364,0365,0366,0367,0370,0371,
+    0060,0061,0062,0063,0064,0065,0066,0067,
+    0070,0071,0372,0373,0374,0375,0376,0377
+};
+
+int
+main(argc, argv)
+int argc;
+char *argv[];
+{
+  FILE *fp, *fpo;
+  int c, e, p = 0, relseek = 1, negseek = 0, revert = 0;
+  int cols = 0, nonzero = 0, autoskip = 0, hextype = HEX_NORMAL;
+  int ebcdic = 0;
+  int octspergrp = -1;	/* number of octets grouped in output */
+  int grplen;		/* total chars per octet group */
+  long length = -1, n = 0, seekoff = 0;
+  char l[LLEN+1];
+  char *pname, *pp;
+
+#ifdef AMIGA
+  /* This program doesn't work when started from the Workbench */
+  if (argc == 0)
+    exit(1);
+#endif
+
+  pname = argv[0];
+  for (pp = pname; *pp; )
+    if (*pp++ == PATH_SEP)
+      pname = pp;
+#ifdef FILE_SEP
+  for (pp = pname; *pp; pp++)
+    if (*pp == FILE_SEP)
+      {
+	*pp = '\0';
+	break;
+      }
+#endif
+
+  while (argc >= 2)
+    {
+      pp = argv[1] + (!STRNCMP(argv[1], "--", 2) && argv[1][2]);
+	   if (!STRNCMP(pp, "-a", 2)) autoskip = 1 - autoskip;
+      else if (!STRNCMP(pp, "-b", 2)) hextype = HEX_BITS;
+      else if (!STRNCMP(pp, "-u", 2)) hexx = hexxa + 16;
+      else if (!STRNCMP(pp, "-p", 2)) hextype = HEX_POSTSCRIPT;
+      else if (!STRNCMP(pp, "-i", 2)) hextype = HEX_CINCLUDE;
+      else if (!STRNCMP(pp, "-r", 2)) revert++;
+      else if (!STRNCMP(pp, "-E", 2)) ebcdic++;
+      else if (!STRNCMP(pp, "-v", 2))
+	{
+	  fprintf(stderr, "%s%s\n", version, osver);
+	  exit(0);
+	}
+      else if (!STRNCMP(pp, "-c", 2))
+	{
+	  if (pp[2] && STRNCMP("ols", pp + 2, 3))
+	    cols = (int)strtol(pp + 2, NULL, 0);
+	  else
+	    {
+	      if (!argv[2])
+		exit_with_usage(pname);
+	      cols = (int)strtol(argv[2], NULL, 0);
+	      argv++;
+	      argc--;
+	    }
+	}
+      else if (!STRNCMP(pp, "-g", 2))
+	{
+	  if (pp[2] && STRNCMP("group", pp + 2, 5))
+	    octspergrp = (int)strtol(pp + 2, NULL, 0);
+	  else
+	    {
+	      if (!argv[2])
+		exit_with_usage(pname);
+	      octspergrp = (int)strtol(argv[2], NULL, 0);
+	      argv++;
+	      argc--;
+	    }
+	}
+      else if (!STRNCMP(pp, "-s", 2))
+	{
+	  relseek = 0;
+	  negseek = 0;
+	  if (pp[2] && STRNCMP("kip", pp+2, 3) && STRNCMP("eek", pp+2, 3))
+	    {
+#ifdef TRY_SEEK
+	      if (pp[2] == '+')
+		relseek++;
+	      if (pp[2+relseek] == '-')
+		negseek++;
+#endif
+	      seekoff = strtol(pp + 2+relseek+negseek, (char **)NULL, 0);
+	    }
+	  else
+	    {
+	      if (!argv[2])
+		exit_with_usage(pname);
+#ifdef TRY_SEEK
+	      if (argv[2][0] == '+')
+		relseek++;
+	      if (argv[2][relseek] == '-')
+		negseek++;
+#endif
+	      seekoff = strtol(argv[2] + relseek+negseek, (char **)NULL, 0);
+	      argv++;
+	      argc--;
+	    }
+	}
+      else if (!STRNCMP(pp, "-l", 2))
+	{
+	  if (pp[2] && STRNCMP("en", pp + 2, 2))
+	    length = strtol(pp + 2, (char **)NULL, 0);
+	  else
+	    {
+	      if (!argv[2])
+		exit_with_usage(pname);
+	      length = strtol(argv[2], (char **)NULL, 0);
+	      argv++;
+	      argc--;
+	    }
+	}
+      else if (!strcmp(pp, "--"))	/* end of options */
+	{
+	  argv++;
+	  argc--;
+	  break;
+	}
+      else if (pp[0] == '-' && pp[1])	/* unknown option */
+	exit_with_usage(pname);
+      else
+	break;				/* not an option */
+
+      argv++;				/* advance to next argument */
+      argc--;
+    }
+
+  if (!cols)
+    switch (hextype)
+      {
+      case HEX_POSTSCRIPT:	cols = 30; break;
+      case HEX_CINCLUDE:	cols = 12; break;
+      case HEX_BITS:		cols = 6; break;
+      case HEX_NORMAL:
+      default:			cols = 16; break;
+      }
+
+  if (octspergrp < 0)
+    switch (hextype)
+      {
+      case HEX_BITS:		octspergrp = 1; break;
+      case HEX_NORMAL:		octspergrp = 2; break;
+      case HEX_POSTSCRIPT:
+      case HEX_CINCLUDE:
+      default:			octspergrp = 0; break;
+      }
+
+  if (cols < 1 || ((hextype == HEX_NORMAL || hextype == HEX_BITS)
+							    && (cols > COLS)))
+    {
+      fprintf(stderr, "%s: invalid number of columns (max. %d).\n", pname, COLS);
+      exit(1);
+    }
+
+  if (octspergrp < 1)
+    octspergrp = cols;
+
+  if (argc > 3)
+    exit_with_usage(pname);
+
+  if (argc == 1 || (argv[1][0] == '-' && !argv[1][1]))
+    BIN_ASSIGN(fp = stdin, !revert);
+  else
+    {
+      if ((fp = fopen(argv[1], BIN_READ(!revert))) == NULL)
+	{
+	  fprintf(stderr,"%s: ", pname);
+	  perror(argv[1]);
+	  return 2;
+	}
+    }
+
+  if (argc < 3 || (argv[2][0] == '-' && !argv[2][1]))
+    BIN_ASSIGN(fpo = stdout, revert);
+  else
+    {
+      int fd;
+      int mode = revert ? O_WRONLY : (O_TRUNC|O_WRONLY);
+
+      if (((fd = OPEN(argv[2], mode | BIN_CREAT(revert), 0666)) < 0) ||
+	  (fpo = fdopen(fd, BIN_WRITE(revert))) == NULL)
+	{
+	  fprintf(stderr, "%s: ", pname);
+	  perror(argv[2]);
+	  return 3;
+	}
+      rewind(fpo);
+    }
+
+  if (revert)
+    {
+      if (hextype && (hextype != HEX_POSTSCRIPT))
+	{
+	  fprintf(stderr, "%s: sorry, cannot revert this type of hexdump\n", pname);
+	  return -1;
+	}
+      return huntype(fp, fpo, stderr, pname, cols, hextype,
+		negseek ? -seekoff : seekoff);
+    }
+
+  if (seekoff || negseek || !relseek)
+    {
+#ifdef TRY_SEEK
+      if (relseek)
+	e = fseek(fp, negseek ? -seekoff : seekoff, 1);
+      else
+	e = fseek(fp, negseek ? -seekoff : seekoff, negseek ? 2 : 0);
+      if (e < 0 && negseek)
+	{
+	  fprintf(stderr, "%s: sorry cannot seek.\n", pname);
+	  return 4;
+	}
+      if (e >= 0)
+	seekoff = ftell(fp);
+      else
+#endif
+	{
+	  long s = seekoff;
+
+	  while (s--)
+	    (void)getc(fp);
+	}
+    }
+
+  if (hextype == HEX_CINCLUDE)
+    {
+      if (fp != stdin)
+	{
+	  fprintf(fpo, "unsigned char %s", isdigit((int)argv[1][0]) ? "__" : "");
+	  for (e = 0; (c = argv[1][e]) != 0; e++)
+	    putc(isalnum(c) ? c : '_', fpo);
+	  fputs("[] = {\n", fpo);
+	}
+
+      p = 0;
+      while ((length < 0 || p < length) && (c = getc(fp)) != EOF)
+	{
+	  fprintf(fpo, (hexx == hexxa) ? "%s0x%02x" : "%s0X%02X",
+	    (p % cols) ? ", " : ",\n  "+2*!p,  c);
+	  p++;
+	}
+
+      if (p)
+	fputs("\n};\n"+3*(fp == stdin), fpo);
+
+      if (fp != stdin)
+	{
+	  fprintf(fpo, "unsigned int %s", isdigit((int)argv[1][0]) ? "__" : "");
+	  for (e = 0; (c = argv[1][e]) != 0; e++)
+	    putc(isalnum(c) ? c : '_', fpo);
+	  fprintf(fpo, "_len = %d;\n", p);
+	}
+
+      fclose(fp);
+      fclose(fpo);
+      return 0;
+    }
+
+  if (hextype == HEX_POSTSCRIPT)
+    {
+      p = cols;
+      while ((length < 0 || n < length) && (e = getc(fp)) != EOF)
+	{
+	  putchar(hexx[(e >> 4) & 0xf]);
+	  putchar(hexx[(e     ) & 0xf]);
+	  n++;
+	  if (!--p)
+	    {
+	      putchar('\n');
+	      p = cols;
+	    }
+	}
+      if (p < cols)
+	putchar('\n');
+      fclose(fp);
+      fclose(fpo);
+      return 0;
+    }
+
+  /* hextype: HEX_NORMAL or HEX_BITS */
+
+  if (hextype == HEX_NORMAL)
+    grplen = octspergrp + octspergrp + 1;	/* chars per octet group */
+  else	/* hextype == HEX_BITS */
+    grplen = 8 * octspergrp + 1;
+
+  while ((length < 0 || n < length) && (e = getc(fp)) != EOF)
+    {
+      if (p == 0)
+	{
+	  sprintf(l, "%07lx: ", n + seekoff);
+	  for (c = 9; c < LLEN; l[c++] = ' ');
+	}
+      if (hextype == HEX_NORMAL)
+	{
+	  l[c = (9 + (grplen * p) / octspergrp)] = hexx[(e >> 4) & 0xf];
+	  l[++c]			       = hexx[ e       & 0xf];
+	}
+      else /* hextype == HEX_BITS */
+	{
+	  int i;
+
+	  c = (9 + (grplen * p) / octspergrp) - 1;
+	  for (i = 7; i >= 0; i--)
+	    l[++c] = (e & (1 << i)) ? '1' : '0';
+	}
+      if (ebcdic)
+	e = (e < 64) ? '.' : etoa64[e-64];
+      /* When changing this update definition of LLEN above. */
+      l[11 + (grplen * cols - 1)/octspergrp + p] =
+#ifdef __MVS__
+	  (e >= 64)
+#else
+	  (e > 31 && e < 127)
+#endif
+	  ? e : '.';
+      if (e)
+	nonzero++;
+      n++;
+      if (++p == cols)
+	{
+	  l[c = (11 + (grplen * cols - 1)/octspergrp + p)] = '\n'; l[++c] = '\0';
+	  xxdline(fpo, l, autoskip ? nonzero : 1);
+	  nonzero = 0;
+	  p = 0;
+	}
+    }
+  if (p)
+    {
+      l[c = (11 + (grplen * cols - 1)/octspergrp + p)] = '\n'; l[++c] = '\0';
+      xxdline(fpo, l, 1);
+    }
+  else if (autoskip)
+    xxdline(fpo, l, -1);	/* last chance to flush out suppressed lines */
+
+  fclose(fp);
+  fclose(fpo);
+  return 0;
+}
diff --git a/extensions/dbg_interactive/hooks.i b/extensions/dbg_interactive/hooks.i
new file mode 100644
index 0000000..98cbc58
--- /dev/null
+++ b/extensions/dbg_interactive/hooks.i
@@ -0,0 +1,190 @@
+/*********************************************************************************************************
+* Software License Agreement (BSD License)                                                               *
+* Author: Sebastien Decugis <sdecugis@freediameter.net>							 *
+*													 *
+* Copyright (c) 2013, WIDE Project and NICT								 *
+* All rights reserved.											 *
+* 													 *
+* Redistribution and use of this software in source and binary forms, with or without modification, are  *
+* permitted provided that the following conditions are met:						 *
+* 													 *
+* * Redistributions of source code must retain the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer.										 *
+*    													 *
+* * Redistributions in binary form must reproduce the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer in the documentation and/or other						 *
+*   materials provided with the distribution.								 *
+* 													 *
+* * Neither the name of the WIDE Project or NICT nor the 						 *
+*   names of its contributors may be used to endorse or 						 *
+*   promote products derived from this software without 						 *
+*   specific prior written permission of WIDE Project and 						 *
+*   NICT.												 *
+* 													 *
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED *
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
+* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR *
+* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 	 *
+* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 	 *
+* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR *
+* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF   *
+* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.								 *
+*********************************************************************************************************/
+
+/* Do not include this directly, use dbg_interactive.i instead */
+
+/****** HOOKS *********/
+
+
+/* Functions to handle the PMD */
+%{
+
+struct fd_hook_permsgdata {
+	PyObject *PyPML;
+};
+
+static void init_permsgdata (struct fd_hook_permsgdata * pmd) {
+	/* The PMD is None by default */
+	Py_INCREF(Py_None);
+	pmd->PyPML = Py_None;
+}
+
+static void fini_permsgdata (struct fd_hook_permsgdata * pmd) {
+	Py_DECREF(pmd->PyPML);
+}
+
+%}
+
+struct fd_hook_data_hdl {
+};
+
+%nodefaultctor fd_hook_data_hdl;
+%extend fd_hook_data_hdl {
+	fd_hook_data_hdl() {
+		struct fd_hook_data_hdl * hdl = NULL;
+		int ret;
+		
+		ret = fd_hook_data_register ( sizeof(struct fd_hook_permsgdata), init_permsgdata, fini_permsgdata, &hdl );
+		if (ret != 0) {
+			DI_ERROR(ret, NULL, NULL);
+			return NULL;
+		}
+		return hdl;
+	}
+}
+
+
+/* Now the hook itself */
+%{
+static void call_the_python_hook_callback(enum fd_hook_type type, struct msg * msg, struct peer_hdr * peer, void * other, struct fd_hook_permsgdata *pmd, void * regdata) {
+	PyObject *cb, *result = NULL;
+	PyObject *PyType, *PyMsg, *PyPeer, *PyOther, *PyOldPmd;
+	
+	if (!regdata) {
+		LOG_E("Internal error: missing the callback!");
+		return;
+	}
+	cb = regdata;
+
+	SWIG_PYTHON_THREAD_BEGIN_BLOCK;
+	/* Convert the arguments */
+	PyType = PyLong_FromLong(type);
+	Py_INCREF(PyType);
+	
+	PyMsg  = SWIG_NewPointerObj((void *) msg,     SWIGTYPE_p_msg,     0 );
+	
+	PyPeer = SWIG_NewPointerObj((void *) peer,    SWIGTYPE_p_peer_hdr,     0 );
+	if (other == NULL) {
+		PyOther=Py_None;
+		Py_INCREF(Py_None);
+	} else {
+		switch (type) {
+		case HOOK_DATA_RECEIVED:
+			PyOther= SWIG_NewPointerObj( other, SWIGTYPE_p_fd_cnx_rcvdata, 0 );
+			break;
+			
+		case HOOK_MESSAGE_RECEIVED:
+		case HOOK_MESSAGE_ROUTING_ERROR:
+		case HOOK_MESSAGE_DROPPED:
+		case HOOK_PEER_CONNECT_FAILED:
+			PyOther= SWIG_NewPointerObj( other, SWIGTYPE_p_char, 0 );
+			break;
+			
+		case HOOK_MESSAGE_PARSING_ERROR:
+			if (msg) {
+				PyOther= SWIG_NewPointerObj( other, SWIGTYPE_p_char, 0 );
+			} else {
+				PyOther= SWIG_NewPointerObj( other, SWIGTYPE_p_fd_cnx_rcvdata, 0 );
+			}
+			break;
+		default:
+			/* In other cases, other should be NULL */
+			LOG_E("Internal error: got a value of *other");
+		}
+		
+	}
+	
+	if (pmd == NULL) {
+		Py_INCREF(Py_None);
+		PyOldPmd=Py_None;
+	} else {
+		PyOldPmd=pmd->PyPML;
+	}
+	
+	/* Call the function */
+	result = PyObject_CallFunction(cb, "(OOOOO)", PyType, PyMsg, PyPeer, PyOther, PyOldPmd);
+	
+	SWIG_PYTHON_THREAD_END_BLOCK;
+	if (pmd == NULL)
+		return;
+	
+	Py_DECREF(pmd->PyPML);
+	Py_INCREF(result);
+	pmd->PyPML = result;
+}
+%}
+
+
+
+struct fd_hook_hdl {
+};
+
+%nodefaultctor fd_hook_hdl;
+%extend fd_hook_hdl {
+	fd_hook_hdl(uint32_t type_mask, PyObject * PyCb) {
+		struct fd_hook_hdl *hdl;
+		int ret;
+		
+		Py_XINCREF(PyCb);
+		
+		ret = fd_hook_register ( type_mask, call_the_python_hook_callback, PyCb, NULL, &hdl );
+		if (ret != 0) {
+			DI_ERROR(ret, NULL, NULL);
+			return NULL;
+		}
+		return hdl;
+	}
+	fd_hook_hdl(uint32_t type_mask, PyObject * PyCb, struct fd_hook_data_hdl *datahdl) {
+		struct fd_hook_hdl *hdl;
+		int ret;
+		
+		Py_XINCREF(PyCb);
+		
+		ret = fd_hook_register ( type_mask, call_the_python_hook_callback, PyCb, datahdl, &hdl );
+		if (ret != 0) {
+			DI_ERROR(ret, NULL, NULL);
+			return NULL;
+		}
+		return hdl;
+	}
+	~fd_hook_hdl() {
+		struct fd_hook_hdl * hdl = self;
+		int ret = fd_hook_unregister(hdl);
+		if (ret != 0) {
+			DI_ERROR(ret, NULL, NULL);
+		}
+		return;
+	}
+}
diff --git a/extensions/dbg_interactive/lists.i b/extensions/dbg_interactive/lists.i
new file mode 100644
index 0000000..6ac26f2
--- /dev/null
+++ b/extensions/dbg_interactive/lists.i
@@ -0,0 +1,132 @@
+/*********************************************************************************************************
+* Software License Agreement (BSD License)                                                               *
+* Author: Sebastien Decugis <sdecugis@freediameter.net>							 *
+*													 *
+* Copyright (c) 2013, WIDE Project and NICT								 *
+* All rights reserved.											 *
+* 													 *
+* Redistribution and use of this software in source and binary forms, with or without modification, are  *
+* permitted provided that the following conditions are met:						 *
+* 													 *
+* * Redistributions of source code must retain the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer.										 *
+*    													 *
+* * Redistributions in binary form must reproduce the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer in the documentation and/or other						 *
+*   materials provided with the distribution.								 *
+* 													 *
+* * Neither the name of the WIDE Project or NICT nor the 						 *
+*   names of its contributors may be used to endorse or 						 *
+*   promote products derived from this software without 						 *
+*   specific prior written permission of WIDE Project and 						 *
+*   NICT.												 *
+* 													 *
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED *
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
+* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR *
+* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 	 *
+* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 	 *
+* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR *
+* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF   *
+* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.								 *
+*********************************************************************************************************/
+
+/* Do not include this directly, use dbg_interactive.i instead */
+
+/****** LISTS *********/
+
+%extend fd_list {
+	/* allow a parameter in the constructor, and perform the fd_list_init operation */
+	fd_list(void * o = NULL) {
+		struct fd_list * li;
+		li = (struct fd_list *) malloc(sizeof(struct fd_list));
+		if (!li) {
+			DI_ERROR_MALLOC;
+			return NULL;
+		}
+		fd_list_init(li, o);
+		return li;
+	}
+	/* Unlink before freeing */
+	~fd_list() {
+		fd_list_unlink($self);
+		free($self);
+	}
+	/* For debug, show the values of the list */
+	void dump() {
+		fd_log_debug("list: %p", $self);
+		fd_log_debug("  - next: %p", $self->next);
+		fd_log_debug("  - prev: %p", $self->prev);
+		fd_log_debug("  - head: %p", $self->head);
+		fd_log_debug("  - o   : %p", $self->o);
+	}
+	/* Insert before/after wrapper */
+	void insert_prev(struct fd_list * li) {
+		fd_list_insert_before($self, li);
+	}
+	void insert_next(struct fd_list * li) {
+		fd_list_insert_after($self, li);
+	}
+	/* Test for emptyness */
+	PyObject * isempty() {
+		PyObject * ret;
+		if (FD_IS_LIST_EMPTY($self))
+			ret = Py_True;
+		else
+			ret = Py_False;
+		Py_XINCREF(ret);
+		return ret;
+	}
+	/* Concatenate two lists */
+	void concat(struct fd_list * li) {
+		fd_list_move_end($self, li);
+	}
+	/* Unlink without freeing */
+	void detach() {
+		fd_list_unlink($self);
+	}
+	
+	/* Return the list as python list of elements */
+	PyObject * enum_as(char * type = NULL, int dont_use_o = 0) {
+		struct fd_list *li;
+		swig_type_info * desttype = NULL;
+		PyObject * rl;
+		
+		if ($self->head != $self) {
+			DI_ERROR(EINVAL, NULL, "This method can only be called on the list sentinel.");
+			return NULL;
+		}
+		
+		if (type) {
+			desttype = SWIG_TypeQuery(type);
+			if (!desttype) {
+				DI_ERROR(EINVAL, NULL, "Unable to resolve this type. Please check the form: 'struct blahbla *'");
+				return NULL;
+			}
+		}
+		if (desttype == NULL) {
+			/* fallback to fd_list */
+			desttype = SWIGTYPE_p_fd_list;
+			/* in this case, don't follow the 'o' link */
+			dont_use_o = 1;
+		}
+		
+		rl = PyList_New(0);
+		SWIG_PYTHON_THREAD_BEGIN_BLOCK;
+		for (li = $self->next; li != $self; li = li->next) {
+			void * obj = NULL;
+			if (dont_use_o || li->o == NULL)
+				obj = li;
+			else
+				obj = li->o;
+			PyList_Append(rl, SWIG_NewPointerObj(obj, desttype, 0 ));
+		}
+		Py_XINCREF(rl);
+		SWIG_PYTHON_THREAD_END_BLOCK;
+		
+		return rl;
+	}
+};
+
diff --git a/extensions/dbg_interactive/messages.i b/extensions/dbg_interactive/messages.i
new file mode 100644
index 0000000..3d13e5d
--- /dev/null
+++ b/extensions/dbg_interactive/messages.i
@@ -0,0 +1,615 @@
+/*********************************************************************************************************
+* Software License Agreement (BSD License)                                                               *
+* Author: Sebastien Decugis <sdecugis@freediameter.net>							 *
+*													 *
+* Copyright (c) 2013, WIDE Project and NICT								 *
+* All rights reserved.											 *
+* 													 *
+* Redistribution and use of this software in source and binary forms, with or without modification, are  *
+* permitted provided that the following conditions are met:						 *
+* 													 *
+* * Redistributions of source code must retain the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer.										 *
+*    													 *
+* * Redistributions in binary form must reproduce the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer in the documentation and/or other						 *
+*   materials provided with the distribution.								 *
+* 													 *
+* * Neither the name of the WIDE Project or NICT nor the 						 *
+*   names of its contributors may be used to endorse or 						 *
+*   promote products derived from this software without 						 *
+*   specific prior written permission of WIDE Project and 						 *
+*   NICT.												 *
+* 													 *
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED *
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
+* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR *
+* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 	 *
+* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 	 *
+* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR *
+* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF   *
+* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.								 *
+*********************************************************************************************************/
+
+/* Do not include this directly, use dbg_interactive.i instead */
+
+/****** MESSAGES *********/
+
+%{
+struct anscb_py_layer {
+	PyObject * cb;
+	PyObject * expcb;
+	PyObject * data;
+};
+
+/* If a python callback was provided, it is received in cbdata */
+static void anscb_python(void *cbdata, struct msg ** msg) {
+	/* The python callback is received in cbdata */
+	PyObject * result, *PyMsg;
+	struct anscb_py_layer * l = cbdata;
+	
+	if (!l) {
+		fd_log_debug("Internal error! Python callback disappeared...");
+		return;
+	}
+	
+	if (l->cb) {
+	
+		SWIG_PYTHON_THREAD_BEGIN_BLOCK;
+
+		if (!msg || !*msg) {
+			PyMsg = Py_None;
+		} else {
+			PyMsg = SWIG_NewPointerObj((void *)*msg,     SWIGTYPE_p_msg,     0 );
+		}
+
+		result = PyObject_CallFunction(l->cb, "(OO)", PyMsg, l->data);
+		Py_XDECREF(l->cb);
+		Py_XDECREF(l->expcb);
+		Py_XDECREF(l->data);
+		free(l);
+
+		/* The callback is supposed to return a message or NULL */
+		if (!SWIG_IsOK(SWIG_ConvertPtr(result, (void *)msg, SWIGTYPE_p_msg, SWIG_POINTER_DISOWN))) {
+			fd_log_debug("Error: Cannot convert the return value to message.");
+			*msg = NULL;
+		}
+
+		Py_XDECREF(result);
+
+		SWIG_PYTHON_THREAD_END_BLOCK;
+		
+	}
+	/* else */
+		/* Only the timeout was specified, without a callback */
+		/* in this case, just delete the message */
+		/* it actually happens automatically when we do nothing. */
+}
+
+static void expcb_python(void *cbdata, DiamId_t sentto, size_t senttolen, struct msg ** msg) {
+	/* The python callback is received in cbdata */
+	PyObject * result, *PyMsg;
+	struct anscb_py_layer * l = cbdata;
+	
+	if (!l) {
+		fd_log_debug("Internal error! Python callback disappeared...");
+		return;
+	}
+	
+	SWIG_PYTHON_THREAD_BEGIN_BLOCK;
+
+	if (!msg || !*msg) {
+		PyMsg = Py_None;
+	} else {
+		PyMsg = SWIG_NewPointerObj((void *)*msg,     SWIGTYPE_p_msg,     0 );
+	}
+
+	result = PyObject_CallFunction(l->expcb, "(Os#O)", PyMsg, sentto, senttolen, l->data);
+	Py_XDECREF(l->cb);
+	Py_XDECREF(l->expcb);
+	Py_XDECREF(l->data);
+	free(l);
+
+	/* The callback is supposed to return a message or NULL */
+	if (!SWIG_IsOK(SWIG_ConvertPtr(result, (void *)msg, SWIGTYPE_p_msg, SWIG_POINTER_DISOWN))) {
+		fd_log_debug("Error: Cannot convert the return value to message.");
+		*msg = NULL;
+	}
+
+	Py_XDECREF(result);
+
+	SWIG_PYTHON_THREAD_END_BLOCK;
+		
+}
+
+
+
+%}
+
+struct msg {
+};
+
+%extend msg {
+	msg(struct dict_object * model=NULL, int flags = MSGFL_ALLOC_ETEID) {
+		struct msg * m = NULL;
+		int ret = fd_msg_new( model, flags, &m);
+		if (ret != 0) {
+			DI_ERROR(ret, NULL, NULL);
+		}
+		return m;
+	}
+	/* construct also from a binary buffer */
+	msg(char * STRING, size_t LENGTH) {
+		int ret;
+		struct msg * m = NULL;
+		/* First, copy the string */
+		unsigned char * buf = malloc(LENGTH);
+		if (buf == NULL) {
+			DI_ERROR_MALLOC;
+			return NULL;
+		}
+		memcpy(buf, STRING, LENGTH);
+		ret = fd_msg_parse_buffer(&buf, LENGTH, &m);
+		if (ret != 0) {
+			DI_ERROR(ret, NULL, NULL);
+			free(buf);
+			return NULL;
+		}
+		return m;
+	}
+	~msg() {
+		int ret = fd_msg_free($self);
+		if (ret != 0) {
+			DI_ERROR(ret, NULL, NULL);
+		}
+	}
+	
+	/* SEND THE MESSAGE */
+	%delobject send; /* when this has been called, the msg must not be freed anymore */
+	void send(PyObject * PyCb = NULL, PyObject * data = NULL, PyObject * PyExpCb = NULL, unsigned int timeout = 0) {
+		int ret;
+		struct msg * m = $self;
+		struct anscb_py_layer * l = NULL;
+		
+		if (PyCb || timeout) {
+			l = malloc(sizeof(struct anscb_py_layer));
+			if (!l) {
+				DI_ERROR_MALLOC;
+				return;
+			}
+
+			Py_XINCREF(PyCb);
+			Py_XINCREF(data);
+			Py_XINCREF(PyExpCb);
+			l->expcb = PyExpCb;
+			l->cb = PyCb;
+			l->data = data;
+		}
+		
+		if (timeout) {
+			struct timespec ts;
+			(void) clock_gettime(CLOCK_REALTIME, &ts);
+			ts.tv_sec += timeout;
+			ret = fd_msg_send_timeout(&m, anscb_python, l, expcb_python, &ts);
+		} else {
+			ret = fd_msg_send(&m, PyCb ? anscb_python : NULL, l);
+		}
+		if (ret != 0) {
+			DI_ERROR(ret, NULL, NULL);
+		}
+	}
+	
+	/* Create an answer */
+	%delobject create_answer; /* when this has been called, the original msg should not be freed anymore */
+	struct msg * create_answer(struct dictionary * dict = NULL, int flags = 0) {
+		/* if dict is not provided, attempt to get it from the request model */
+		struct dictionary * d = dict;
+		struct msg * m = $self;
+		int ret;
+		if (!d) {
+			struct dict_object * mo = NULL;
+			ret = fd_msg_model($self, &mo);
+			if (ret != 0) {
+				DI_ERROR(ret, NULL, "Error retrieving query model.");
+				return NULL;
+			}
+			if (mo == NULL) {
+				/* use the fD dictionary by default */
+				d = fd_g_config->cnf_dict;
+			} else {
+				ret = fd_dict_getdict ( mo, &d );
+				if (ret != 0) {
+					DI_ERROR(ret, NULL, "Error retrieving query's dictionary.");
+					return NULL;
+				}
+			}
+		}
+		ret = fd_msg_new_answer_from_req(d, &m, flags);
+		if (ret != 0) {
+			DI_ERROR(ret, NULL, "Cannot guess the dictionary to use, please provide it as parameter.");
+			return NULL;
+		}
+		
+		return m;
+	}
+	/* Return the first child AVP if any */
+	struct avp * first_child() {
+		struct avp * a = NULL;
+		int ret = fd_msg_browse($self, MSG_BRW_FIRST_CHILD, &a, NULL);
+		if (ret != 0) {
+			DI_ERROR(ret, NULL, NULL);
+		}
+		return a;
+	}
+	
+	/* Enumerable list of children AVP */
+	%newobject children;
+	PyObject * children() {
+		struct avp * a = NULL;
+		PyObject * rl;
+		int ret = fd_msg_browse($self, MSG_BRW_FIRST_CHILD, &a, NULL);
+		if (ret != 0) {
+			DI_ERROR(ret, NULL, NULL);
+			return NULL;
+		}
+		SWIG_PYTHON_THREAD_BEGIN_BLOCK;
+		rl = PyList_New(0);
+		while (a) {
+			PyList_Append(rl, SWIG_NewPointerObj((void *)a, SWIGTYPE_p_avp, 0 /* do not own the AVPs */ ));
+			ret = fd_msg_browse(a, MSG_BRW_NEXT, &a, NULL);
+			if (ret != 0) {
+				DI_ERROR(ret, NULL, NULL);
+				return NULL;
+			}
+		}
+		Py_XINCREF(rl);
+		SWIG_PYTHON_THREAD_END_BLOCK;
+		return rl;
+	}
+	
+	/* Add a new AVP */
+	void add_child(struct avp *DISOWN, int begin = 0) {
+		int ret = fd_msg_avp_add ( $self, begin ? MSG_BRW_FIRST_CHILD : MSG_BRW_LAST_CHILD, DISOWN);
+		if (ret != 0) {
+			DI_ERROR(ret, NULL, NULL);
+		}
+	}
+	
+	/* Search an AVP */
+	struct avp * search(struct dict_object * what) {
+		struct avp * a = NULL;
+		int ret = fd_msg_search_avp($self, what, &a);
+		if (ret != 0) {
+			DI_ERROR(ret, NULL, NULL);
+			return NULL;
+		}
+		return a;
+	}
+	
+	/* Dump */
+	void dump (int tree = 1) {
+		char * buf = NULL;
+		size_t len;
+		printf("%s", fd_msg_dump_treeview(&buf, &len, NULL, $self, NULL, 0, tree));
+		free(buf);
+	}
+	
+	/* Model */
+	struct dict_object * model() {
+		struct dict_object * m = NULL;
+		int ret = fd_msg_model($self, &m);
+		if (ret != 0) {
+			DI_ERROR(ret, NULL, NULL);
+			return NULL;
+		}
+		return m;
+	}
+	
+	/* Header */
+	struct msg_hdr * header() {
+		struct msg_hdr * h = NULL;
+		int ret = fd_msg_hdr($self, &h);
+		if (ret != 0) {
+			DI_ERROR(ret, NULL, NULL);
+			return NULL;
+		}
+		return h;
+	}
+	
+	/* Get query if message is an answer */
+	struct msg * get_query() {
+		struct msg * q = NULL;
+		int ret = fd_msg_answ_getq($self, &q);
+		if (ret != 0) {
+			DI_ERROR(ret, NULL, NULL);
+			return NULL;
+		}
+		return q;
+	}
+	
+	/* Get / Set routing data */
+	struct rt_data * get_rtd() {
+		struct rt_data * r = NULL;
+		int ret = fd_msg_rt_get($self, &r);
+		if (ret != 0) {
+			DI_ERROR(ret, NULL, NULL);
+			return NULL;
+		}
+		return r;
+	}
+	void set_rtd(struct rt_data *DISOWN) {
+		struct rt_data * r = DISOWN;
+		int ret = fd_msg_rt_associate($self, r);
+		if (ret != 0) {
+			DI_ERROR(ret, NULL, NULL);
+		}
+		return;
+	}
+	
+	/* Is routable? */
+	PyObject * is_routable() {
+		PyObject * r;
+		if (fd_msg_is_routable($self))
+			r = Py_True;
+		else
+			r = Py_False;
+		Py_XINCREF(r);
+		return r;
+	}
+	
+	/* Is request? (shortcut) */
+	PyObject * is_request() {
+		PyObject * r;
+		int ret;
+		struct msg_hdr * h;
+		
+		ret = fd_msg_hdr($self, &h);
+		if (ret != 0) {
+			DI_ERROR(ret, NULL, NULL);
+		}
+		if (h->msg_flags & CMD_FLAG_REQUEST) 
+			r = Py_True;
+		else
+			r = Py_False;
+		Py_XINCREF(r);
+		return r;
+	}
+	
+	/* Get the source */
+	%cstring_output_allocate_size(char ** outid, size_t * outlen, /* do not free */);
+	void source(char ** outid, size_t * outlen) {
+		int ret = fd_msg_source_get($self, outid, outlen);
+		if (ret != 0) {
+			DI_ERROR(ret, NULL, NULL);
+			return;
+		}
+		return;
+	}
+	
+	/* Get the session */
+	%newobject get_session; /* it may be created or not, it is harmless because we only reclaim in ~session */
+	struct session *get_session(struct dictionary * dict = NULL) {
+		struct session *s = NULL;
+		struct dictionary * d = dict;
+		int ret = 0;
+		if (d == NULL)
+			d = fd_g_config->cnf_dict; /* default: use daemon's */
+		ret = fd_msg_sess_get(d, $self, &s, NULL);
+		if (ret != 0) {
+			DI_ERROR(ret, NULL, NULL);
+			return NULL;
+		}
+		return s;
+	}
+	
+	/* Bufferize */
+	%cstring_output_allocate_size(char ** outbuffer, size_t * outlen, free(*$1));
+	void bufferize ( char ** outbuffer, size_t * outlen ) {
+		int ret = fd_msg_bufferize ( $self, (void *)outbuffer, outlen );
+		if (ret != 0) {
+			DI_ERROR(ret, NULL, NULL);
+		}
+	}
+	
+	/* Dictionary parsing */
+	%newobject parse_dict;
+	struct fd_pei * parse_dict(struct dictionary * dict=NULL) {
+		int ret;
+		struct fd_pei pei, *e = NULL;
+		struct dictionary * d = dict;
+		memset(&pei, 0, sizeof(struct fd_pei));
+		if (d == NULL)
+			d = fd_g_config->cnf_dict; /* default: use daemon's */
+		
+		ret = fd_msg_parse_dict ( $self, d, &pei );
+		if (ret != 0) {
+			e = malloc(sizeof(struct fd_pei));
+			if (!e) {
+				DI_ERROR_MALLOC;
+				return NULL;
+			}
+			memcpy(e, &pei, sizeof(struct fd_pei));
+		}
+		return e; /* returns NULL when everything went OK */
+	}
+	
+	/* Rules parsing */
+	%newobject parse_rules;
+	struct fd_pei * parse_rules(struct dictionary * dict=NULL) {
+		int ret;
+		struct fd_pei pei, *e = NULL;
+		struct dictionary * d = dict;
+		memset(&pei, 0, sizeof(struct fd_pei));
+		if (d == NULL)
+			d = fd_g_config->cnf_dict; /* default: use daemon's */
+		
+		ret = fd_msg_parse_rules ( $self, d, &pei );
+		if (ret != 0) {
+			e = malloc(sizeof(struct fd_pei));
+			if (!e) {
+				DI_ERROR_MALLOC;
+				return NULL;
+			}
+			memcpy(e, &pei, sizeof(struct fd_pei));
+		}
+		return e; /* returns NULL when everything went OK */
+	}
+	
+	/* Update the length info in header */
+	void update_length() {
+		int ret = fd_msg_update_length ( $self );
+		if (ret) {
+			DI_ERROR(ret, NULL, NULL);
+		}
+	}
+	
+	/* Set the result code */
+	void rescode_set(char * rescode = "DIAMETER_SUCCESS", char * errormsg = NULL, struct avp * optavp = NULL, int type_id = 0) {
+		int ret = fd_msg_rescode_set( $self, rescode, errormsg, optavp, type_id );
+		if (ret) {
+			DI_ERROR(ret, NULL, NULL);
+		}
+	}
+	
+	/* Add the origin */
+	void add_origin(int osi = 0) {
+		int ret = fd_msg_add_origin( $self, osi );
+		if (ret) {
+			DI_ERROR(ret, NULL, NULL);
+		}
+	}
+	
+}
+
+struct avp {
+};
+
+%extend avp {
+	avp(struct dict_object * model = NULL, int flags = 0) {
+		struct avp * a = NULL;
+		int ret = fd_msg_avp_new( model, flags, &a);
+		if (ret != 0) {
+			DI_ERROR(ret, NULL, NULL);
+		}
+		return a;
+	}
+	~avp() {
+		int ret = fd_msg_free($self);
+		if (ret != 0) {
+			DI_ERROR(ret, NULL, NULL);
+		}
+	}
+	
+	/* Return the first child AVP if any */
+	struct avp * first_child() {
+		struct avp * a = NULL;
+		int ret = fd_msg_browse($self, MSG_BRW_FIRST_CHILD, &a, NULL);
+		if (ret != 0) {
+			DI_ERROR(ret, NULL, NULL);
+		}
+		return a;
+	}
+	
+	/* Enumerable list of children AVP */
+	%newobject children;
+	PyObject * children() {
+		struct avp * a = NULL;
+		PyObject * rl;
+		int ret = fd_msg_browse($self, MSG_BRW_FIRST_CHILD, &a, NULL);
+		if (ret != 0) {
+			DI_ERROR(ret, NULL, NULL);
+			return NULL;
+		}
+		SWIG_PYTHON_THREAD_BEGIN_BLOCK;
+		rl = PyList_New(0);
+		while (a) {
+			PyList_Append(rl, SWIG_NewPointerObj((void *)a, SWIGTYPE_p_avp, 0 /* the AVPs are not owned */ ));
+			ret = fd_msg_browse(a, MSG_BRW_NEXT, &a, NULL);
+			if (ret != 0) {
+				DI_ERROR(ret, NULL, NULL);
+				return NULL;
+			}
+		}
+		Py_XINCREF(rl);
+		SWIG_PYTHON_THREAD_END_BLOCK;
+		return rl;
+	}
+	
+	/* Add a new AVP */
+	void add_next(struct avp *avp) {
+		int ret = fd_msg_avp_add ( $self, MSG_BRW_NEXT, avp);
+		if (ret != 0) {
+			DI_ERROR(ret, NULL, NULL);
+		}
+	}
+	void add_prev(struct avp *avp) {
+		int ret = fd_msg_avp_add ( $self, MSG_BRW_PREV, avp);
+		if (ret != 0) {
+			DI_ERROR(ret, NULL, NULL);
+		}
+	}
+	void add_child(struct avp *DISOWN, int begin = 0) {
+		int ret = fd_msg_avp_add ( $self, begin ? MSG_BRW_FIRST_CHILD : MSG_BRW_LAST_CHILD, DISOWN);
+		if (ret != 0) {
+			DI_ERROR(ret, NULL, NULL);
+		}
+	}
+	
+	/* Get the next AVP at the same level */
+	struct avp * get_next() {
+		struct avp * a = NULL;
+		int ret = fd_msg_browse($self, MSG_BRW_NEXT, &a, NULL);
+		if (ret != 0) {
+			DI_ERROR(ret, NULL, NULL);
+		}
+		return a;
+	}
+	
+	/* Dump */
+	void dump (int tree = 1) {
+		char * buf = NULL;
+		size_t len;
+		printf("%s", fd_msg_dump_treeview(&buf, &len, NULL, $self, NULL, 0, tree));
+		free(buf);
+	}
+	
+	/* Model */
+	struct dict_object * model() {
+		struct dict_object * m = NULL;
+		int ret = fd_msg_model($self, &m);
+		if (ret != 0) {
+			DI_ERROR(ret, NULL, NULL);
+			return NULL;
+		}
+		return m;
+	}
+	
+	/* Header */
+	struct avp_hdr * header() {
+		struct avp_hdr * h = NULL;
+		int ret = fd_msg_avp_hdr($self, &h);
+		if (ret != 0) {
+			DI_ERROR(ret, NULL, NULL);
+			return NULL;
+		}
+		return h;
+	}
+	
+	/* set value */
+	void setval(union avp_value * val) {
+		int ret = fd_msg_avp_setvalue ( $self, val );
+		if (ret != 0) {
+			DI_ERROR(ret, NULL, NULL);
+		}
+	}
+	
+	/* Update the length info in header */
+	void update_length() {
+		int ret = fd_msg_update_length ( $self );
+		if (ret) {
+			DI_ERROR(ret, NULL, NULL);
+		}
+	}
+}
diff --git a/extensions/dbg_interactive/peers.i b/extensions/dbg_interactive/peers.i
new file mode 100644
index 0000000..a256cf7
--- /dev/null
+++ b/extensions/dbg_interactive/peers.i
@@ -0,0 +1,227 @@
+/*********************************************************************************************************
+* Software License Agreement (BSD License)                                                               *
+* Author: Sebastien Decugis <sdecugis@freediameter.net>							 *
+*													 *
+* Copyright (c) 2013, WIDE Project and NICT								 *
+* All rights reserved.											 *
+* 													 *
+* Redistribution and use of this software in source and binary forms, with or without modification, are  *
+* permitted provided that the following conditions are met:						 *
+* 													 *
+* * Redistributions of source code must retain the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer.										 *
+*    													 *
+* * Redistributions in binary form must reproduce the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer in the documentation and/or other						 *
+*   materials provided with the distribution.								 *
+* 													 *
+* * Neither the name of the WIDE Project or NICT nor the 						 *
+*   names of its contributors may be used to endorse or 						 *
+*   promote products derived from this software without 						 *
+*   specific prior written permission of WIDE Project and 						 *
+*   NICT.												 *
+* 													 *
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED *
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
+* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR *
+* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 	 *
+* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 	 *
+* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR *
+* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF   *
+* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.								 *
+*********************************************************************************************************/
+
+/* Do not include this directly, use dbg_interactive.i instead */
+
+/****** PEERS *********/
+
+%{
+static void fd_add_cb(struct peer_info *peer, void *data) {
+	/* Callback called when the peer connection completes (or fails) */
+	PyObject *PyPeer, *PyFunc;
+	PyObject *result = NULL;
+	
+	if (!data) {
+		TRACE_DEBUG(INFO, "Internal error: missing callback");
+		return;
+	}
+	PyFunc = data;
+	
+	SWIG_PYTHON_THREAD_BEGIN_BLOCK;
+	
+	/* Convert the argument */
+	PyPeer  = SWIG_NewPointerObj((void *)peer,     SWIGTYPE_p_peer_info,     0 );
+	
+	/* Call the function */
+	result = PyObject_CallFunction(PyFunc, "(O)", PyPeer);
+	
+	Py_XDECREF(result);
+	Py_XDECREF(PyFunc);
+	
+	SWIG_PYTHON_THREAD_END_BLOCK;
+	return;
+}
+%}
+
+%extend peer_info {
+	peer_info () {
+		struct peer_info *np = (struct peer_info *)calloc(1, sizeof(struct peer_info));
+		if (!np) {
+			DI_ERROR_MALLOC;
+			return NULL;
+		}
+		
+		fd_list_init(&np->pi_endpoints, NULL);
+		
+		return np;
+	}
+
+	/* Wrapper around fd_peer_add to allow calling the python callback */
+	%delobject add;
+	void add(PyObject * PyCb=NULL) {
+		int ret;
+		
+		if (PyCb) {
+			Py_XINCREF(PyCb);
+			ret = fd_peer_add ( $self, "dbg_interactive", fd_add_cb, PyCb );
+		} else {
+			ret = fd_peer_add ( $self, "dbg_interactive", NULL, NULL );
+		}
+		if (ret != 0) {
+			DI_ERROR(ret, NULL, NULL);
+		}
+	}
+}
+
+%inline %{
+static struct peer_hdr * peer_search(char *STRING, size_t LENGTH) {
+	struct peer_hdr *r = NULL;
+	int ret = fd_peer_getbyid( STRING, LENGTH, 0, &r );
+	if (ret) {
+		DI_ERROR(ret, NULL, NULL);
+		return NULL;
+	}
+	return r;
+}
+%}
+
+%{
+static PyObject * validate_cb_py = NULL;
+static PyObject * validate_cb2_py = NULL;
+
+/* C wrapper that calls validate_cb2_py */
+int call_the_python_validate_callback2(struct peer_info * info) {
+	PyObject *PyInfo;
+	PyObject *result = NULL;
+	int ret = 0;
+	
+	if (!validate_cb2_py) {
+		fd_log_debug("Internal error: missing the callback2!");
+		return ENOTSUP;
+	}
+	
+	SWIG_PYTHON_THREAD_BEGIN_BLOCK;
+	/* Convert the arguments */
+	PyInfo  = SWIG_NewPointerObj((void *)info,     SWIGTYPE_p_peer_info,     0 );
+	
+	/* Call the function */
+	result = PyObject_CallFunction(validate_cb2_py, "(O)", PyInfo);
+	
+	/* The result is an integer */
+	if ((result == NULL) || !SWIG_IsOK(SWIG_AsVal_int(result, &ret))) {
+		fd_log_debug("Error: The Python callback did not return an integer.");
+		ret = EINVAL;
+		goto out;
+	}
+	
+out:	
+	Py_XDECREF(result);
+	SWIG_PYTHON_THREAD_END_BLOCK;
+	return ret;
+}
+
+/* C wrapper that calls validate_cb_py */
+int call_the_python_validate_callback(struct peer_info * info, int * auth, int (**cb2)(struct peer_info *)) {
+	PyObject *PyInfo;
+	PyObject *result = NULL;
+	int ret = 0;
+	
+	if (!validate_cb_py) {
+		fd_log_debug("Internal error: missing the callback!");
+		return ENOTSUP;
+	}
+	
+	SWIG_PYTHON_THREAD_BEGIN_BLOCK;
+	/* Convert the arguments */
+	PyInfo  = SWIG_NewPointerObj((void *)info,     SWIGTYPE_p_peer_info,     0 );
+	
+	/* Call the function */
+	result = PyObject_CallFunction(validate_cb_py, "(O)", PyInfo);
+	
+	/* The result is supposedly -1, 1, or a cb2 */
+	if (result == NULL) {
+		fd_log_debug("Error: The Python callback did not return a value.");
+		ret = EINVAL;
+		goto out;
+	}
+	
+	if (PyCallable_Check(result)) {
+		if (cb2) {
+			if (validate_cb2_py && (validate_cb2_py != result)) {
+				fd_log_debug("Only 1 register callback2 is supported currently");
+				ret = ENOTSUP;
+				goto out;
+			}
+			validate_cb2_py = result;
+			*cb2 = call_the_python_validate_callback2;
+			*auth = 1;
+			goto out_nodec;
+		} else {
+			*auth = 1;
+			goto out; /* ignore the callback since it won't be used */
+		}
+	} else { /* In this case, the return value must be -1, 0, or 1 */
+		if (!SWIG_IsOK(SWIG_AsVal_int(result, auth))) {
+			fd_log_debug("Error: Cannot convert the return value to integer.");
+			ret = EINVAL;
+			goto out;
+		}
+	}
+	
+out:	
+	Py_XDECREF(result);
+out_nodec:	
+	SWIG_PYTHON_THREAD_END_BLOCK;
+	TRACE_DEBUG(FULL, "ret=%d, *auth=%d, cb2=%p, *cb2=%p", ret, *auth, cb2, cb2 ? *cb2 : NULL);
+	return ret;
+}
+
+%}
+
+%inline %{
+static void peer_validate_register(PyObject * PyCb) {
+	int ret ;
+	
+	if (!PyCb) {
+		DI_ERROR(EINVAL, NULL, "The callback must be provided");
+		return;
+	}
+	
+	if (validate_cb_py) {
+		if (PyCb != validate_cb_py) {
+			DI_ERROR(ENOTSUP, PyExc_RuntimeError, "Only 1 register callback is supported currently");
+			return;
+		}
+	} else {
+		validate_cb_py = PyCb;
+		Py_XINCREF(PyCb);
+	}
+	
+	ret = fd_peer_validate_register ( call_the_python_validate_callback );
+	if (ret) {
+		DI_ERROR(ret, NULL, NULL);
+	}
+}
+%}
diff --git a/extensions/dbg_interactive/posix.i b/extensions/dbg_interactive/posix.i
new file mode 100644
index 0000000..ceafeb6
--- /dev/null
+++ b/extensions/dbg_interactive/posix.i
@@ -0,0 +1,194 @@
+/*********************************************************************************************************
+* Software License Agreement (BSD License)                                                               *
+* Author: Sebastien Decugis <sdecugis@freediameter.net>							 *
+*													 *
+* Copyright (c) 2012, WIDE Project and NICT								 *
+* All rights reserved.											 *
+* 													 *
+* Redistribution and use of this software in source and binary forms, with or without modification, are  *
+* permitted provided that the following conditions are met:						 *
+* 													 *
+* * Redistributions of source code must retain the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer.										 *
+*    													 *
+* * Redistributions in binary form must reproduce the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer in the documentation and/or other						 *
+*   materials provided with the distribution.								 *
+* 													 *
+* * Neither the name of the WIDE Project or NICT nor the 						 *
+*   names of its contributors may be used to endorse or 						 *
+*   promote products derived from this software without 						 *
+*   specific prior written permission of WIDE Project and 						 *
+*   NICT.												 *
+* 													 *
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED *
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
+* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR *
+* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 	 *
+* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 	 *
+* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR *
+* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF   *
+* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.								 *
+*********************************************************************************************************/
+
+/* Do not include this directly, use dbg_interactive.i instead */
+
+/****** POSIX wrappers around useful functions for fD *********/
+
+/**** MUTEX ****/
+typedef struct {
+} pthread_mutex_t;
+
+%extend pthread_mutex_t {
+	pthread_mutex_t() {
+		int ret = 0;
+		pthread_mutex_t * r = calloc(1, sizeof(pthread_mutex_t));
+		if (!r) {
+			DI_ERROR_MALLOC;
+			return NULL;
+		}
+		ret = pthread_mutex_init(r, NULL);
+		if (ret) {
+			DI_ERROR(ret, NULL, NULL);
+			free(r);
+			return NULL;
+		}
+		return r;
+	}
+	~pthread_mutex_t() {
+		int ret = 0;
+		ret = pthread_mutex_destroy($self);
+		if (ret) {
+			DI_ERROR(ret, NULL, NULL);
+			return;
+		}
+		free($self);
+		return;
+	}
+	void lock() {
+		int ret = pthread_mutex_lock($self);
+		if (ret) {
+			DI_ERROR(ret, NULL, NULL);
+		}
+	}
+	void unlock() {
+		int ret = pthread_mutex_unlock($self);
+		if (ret) {
+			DI_ERROR(ret, NULL, NULL);
+		}
+	}
+}
+
+/**** CONDVAR ****/
+typedef struct {
+} pthread_cond_t;
+
+%extend pthread_cond_t {
+	pthread_cond_t() {
+		int ret = 0;
+		pthread_cond_t * r = calloc(1, sizeof(pthread_cond_t));
+		if (!r) {
+			DI_ERROR_MALLOC;
+			return NULL;
+		}
+		ret = pthread_cond_init(r, NULL);
+		if (ret) {
+			DI_ERROR(ret, NULL, NULL);
+			free(r);
+			return NULL;
+		}
+		return r;
+	}
+	~pthread_cond_t() {
+		int ret = 0;
+		ret = pthread_cond_destroy($self);
+		if (ret) {
+			DI_ERROR(ret, NULL, NULL);
+			return;
+		}
+		free($self);
+		return;
+	}
+	void signal() {
+		int ret = pthread_cond_signal($self);
+		if (ret) {
+			DI_ERROR(ret, NULL, NULL);
+		}
+	}
+	void broadcast() {
+		int ret = pthread_cond_broadcast($self);
+		if (ret) {
+			DI_ERROR(ret, NULL, NULL);
+		}
+	}
+	void wait(pthread_mutex_t * mutex) {
+		int ret = pthread_cond_wait($self, mutex);
+		if (ret) {
+			DI_ERROR(ret, NULL, NULL);
+		}
+	}
+	void timedwait(pthread_mutex_t * mutex, long seconds) {
+		struct timespec ts;
+		int ret;
+		
+		clock_gettime(CLOCK_REALTIME, &ts);
+		ts.tv_sec += seconds;
+		
+		ret = pthread_cond_timedwait($self, mutex, &ts);
+		if (ret && (ret != ETIMEDOUT)) {
+			DI_ERROR(ret, NULL, NULL);
+		}
+	}
+}
+
+/**** RWLOCK ****/
+typedef struct {
+} pthread_rwlock_t;
+
+%extend pthread_rwlock_t {
+	pthread_rwlock_t() {
+		int ret = 0;
+		pthread_rwlock_t * r = calloc(1, sizeof(pthread_rwlock_t));
+		if (!r) {
+			DI_ERROR_MALLOC;
+			return NULL;
+		}
+		ret = pthread_rwlock_init(r, NULL);
+		if (ret) {
+			DI_ERROR(ret, NULL, NULL);
+			free(r);
+			return NULL;
+		}
+		return r;
+	}
+	~pthread_rwlock_t() {
+		int ret = 0;
+		ret = pthread_rwlock_destroy($self);
+		if (ret) {
+			DI_ERROR(ret, NULL, NULL);
+			return;
+		}
+		free($self);
+		return;
+	}
+	void rdlock() {
+		int ret = pthread_rwlock_rdlock($self);
+		if (ret) {
+			DI_ERROR(ret, NULL, NULL);
+		}
+	}
+	void wrlock() {
+		int ret = pthread_rwlock_wrlock($self);
+		if (ret) {
+			DI_ERROR(ret, NULL, NULL);
+		}
+	}
+	void unlock() {
+		int ret = pthread_rwlock_unlock($self);
+		if (ret) {
+			DI_ERROR(ret, NULL, NULL);
+		}
+	}
+}
diff --git a/extensions/dbg_interactive/queues.i b/extensions/dbg_interactive/queues.i
new file mode 100644
index 0000000..ff1728d
--- /dev/null
+++ b/extensions/dbg_interactive/queues.i
@@ -0,0 +1,198 @@
+/*********************************************************************************************************
+* Software License Agreement (BSD License)                                                               *
+* Author: Sebastien Decugis <sdecugis@freediameter.net>							 *
+*													 *
+* Copyright (c) 2013, WIDE Project and NICT								 *
+* All rights reserved.											 *
+* 													 *
+* Redistribution and use of this software in source and binary forms, with or without modification, are  *
+* permitted provided that the following conditions are met:						 *
+* 													 *
+* * Redistributions of source code must retain the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer.										 *
+*    													 *
+* * Redistributions in binary form must reproduce the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer in the documentation and/or other						 *
+*   materials provided with the distribution.								 *
+* 													 *
+* * Neither the name of the WIDE Project or NICT nor the 						 *
+*   names of its contributors may be used to endorse or 						 *
+*   promote products derived from this software without 						 *
+*   specific prior written permission of WIDE Project and 						 *
+*   NICT.												 *
+* 													 *
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED *
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
+* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR *
+* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 	 *
+* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 	 *
+* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR *
+* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF   *
+* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.								 *
+*********************************************************************************************************/
+
+/* Do not include this directly, use dbg_interactive.i instead */
+
+/****** FIFO QUEUES *********/
+
+struct fifo {
+};
+
+%extend fifo {
+	fifo(int max = 0) {
+		struct fifo * q = NULL;
+		int ret = fd_fifo_new(&q, max);
+		if (ret != 0) {
+			DI_ERROR(ret, NULL, NULL);
+			return NULL;
+		}
+		return q;
+	}
+	~fifo() {
+		struct fifo *q = self;
+		fd_fifo_del(&q);
+	}
+	
+	/* Move all elements to another queue */
+	void move(struct fifo * to) {
+		int ret = fd_fifo_move($self, to, NULL);
+		if (ret != 0) {
+			DI_ERROR(ret, NULL, NULL);
+		}
+	}
+	
+	/* Get the length of the queue (nb elements) */
+	int length() {
+		return fd_fifo_length ( $self ) ;
+	}
+
+	/* Is the threashold function useful here? TODO... */
+	
+	/* Post an item */
+	void post(PyObject * item, char * type = NULL) {
+		int ret;
+		if (type) {
+			void * real_obj = NULL;
+			swig_type_info * desttype = NULL;
+			desttype = SWIG_TypeQuery(type);
+			if (!desttype) {
+				DI_ERROR(EINVAL, NULL, "Unable to resolve this type. Please check the form: 'struct blahbla *'");
+				return;
+			}
+			/* Now, get the "real" value under the shadow umbrella */
+			ret = SWIG_ConvertPtr(item, &real_obj, desttype, SWIG_POINTER_DISOWN );
+			if (!SWIG_IsOK(ret)) {
+				DI_ERROR(EINVAL, SWIG_ErrorType(ret), "Unable to convert the item to given type");
+				return;
+			}
+			ret = fd_fifo_post($self, &real_obj);
+		} else {
+			PyObject * i = item;
+			Py_XINCREF(i);
+			ret = fd_fifo_post($self, &i);
+		}
+		if (ret != 0) {
+			DI_ERROR(ret, NULL, NULL);
+		}
+	}
+	
+	/* Get (blocking) */
+	PyObject * get(char * type = NULL) {
+		int ret;
+		PyObject * i = NULL;
+		void * obj = NULL;
+		swig_type_info * desttype = NULL;
+		if (type) {
+			desttype = SWIG_TypeQuery(type);
+			if (!desttype) {
+				DI_ERROR(EINVAL, NULL, "Unable to resolve this type. Please check the form: 'struct blahbla *'");
+				return NULL;
+			}
+		}
+		
+		ret = fd_fifo_get($self, &obj);
+		if (ret != 0) {
+			DI_ERROR(ret, NULL, NULL);
+		}
+		
+		if (type) {
+			return SWIG_NewPointerObj(obj, desttype, 0 );
+		} else {
+			i = obj;
+			return i;
+		}
+	}
+	
+	/* TryGet (non-blocking, returns None on empty queue) */
+	PyObject * tryget(char * type = NULL) {
+		int ret;
+		PyObject * i = NULL;
+		void * obj = NULL;
+		swig_type_info * desttype = NULL;
+		if (type) {
+			desttype = SWIG_TypeQuery(type);
+			if (!desttype) {
+				DI_ERROR(EINVAL, NULL, "Unable to resolve this type. Please check the form: 'struct blahbla *'");
+				return NULL;
+			}
+		}
+		
+		ret = fd_fifo_tryget($self, &obj);
+		if (ret == EWOULDBLOCK) {
+			Py_INCREF(Py_None);
+			return Py_None;
+		}
+		if (ret != 0) {
+			DI_ERROR(ret, NULL, NULL);
+		}
+		
+		if (type) {
+			return SWIG_NewPointerObj(obj, desttype, 0 );
+		} else {
+			i = obj;
+			return i;
+		}
+	}
+	
+	/* TimedGet (blocking for a while) */
+	PyObject * timedget(long seconds, char * type = NULL) {
+		int ret;
+		PyObject * i = NULL;
+		struct timespec ts;
+		void * obj = NULL;
+		swig_type_info * desttype = NULL;
+		if (type) {
+			desttype = SWIG_TypeQuery(type);
+			if (!desttype) {
+				DI_ERROR(EINVAL, NULL, "Unable to resolve this type. Please check the form: 'struct blahbla *'");
+				return NULL;
+			}
+		}
+		
+		clock_gettime(CLOCK_REALTIME, &ts);
+		ts.tv_sec += seconds;
+		
+		ret = fd_fifo_timedget($self, &obj, &ts);
+		if (ret == ETIMEDOUT) {
+			Py_INCREF(Py_None);
+			return Py_None;
+		}
+		if (ret != 0) {
+			DI_ERROR(ret, NULL, NULL);
+		}
+		
+		if (type) {
+			return SWIG_NewPointerObj(obj, desttype, 0 );
+		} else {
+			i = obj;
+			return i;
+		}
+	}
+	
+}		
+	
+	
+	
+	
diff --git a/extensions/dbg_interactive/routing.i b/extensions/dbg_interactive/routing.i
new file mode 100644
index 0000000..324674f
--- /dev/null
+++ b/extensions/dbg_interactive/routing.i
@@ -0,0 +1,251 @@
+/*********************************************************************************************************
+* Software License Agreement (BSD License)                                                               *
+* Author: Sebastien Decugis <sdecugis@freediameter.net>							 *
+*													 *
+* Copyright (c) 2013, WIDE Project and NICT								 *
+* All rights reserved.											 *
+* 													 *
+* Redistribution and use of this software in source and binary forms, with or without modification, are  *
+* permitted provided that the following conditions are met:						 *
+* 													 *
+* * Redistributions of source code must retain the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer.										 *
+*    													 *
+* * Redistributions in binary form must reproduce the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer in the documentation and/or other						 *
+*   materials provided with the distribution.								 *
+* 													 *
+* * Neither the name of the WIDE Project or NICT nor the 						 *
+*   names of its contributors may be used to endorse or 						 *
+*   promote products derived from this software without 						 *
+*   specific prior written permission of WIDE Project and 						 *
+*   NICT.												 *
+* 													 *
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED *
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
+* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR *
+* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 	 *
+* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 	 *
+* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR *
+* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF   *
+* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.								 *
+*********************************************************************************************************/
+
+/* Do not include this directly, use dbg_interactive.i instead */
+
+/****** ROUTING *********/
+
+struct rt_data {
+};
+
+%extend rt_data {
+	rt_data() {
+		struct rt_data * r = NULL;
+		int ret = fd_rtd_init(&r);
+		if (ret != 0) {
+			DI_ERROR(ret, NULL, NULL);
+			return NULL;
+		}
+		return r;
+	}
+	~rt_data() {
+		struct rt_data *r = self;
+		fd_rtd_free(&r);
+	}
+	%apply (char *STRING, int LENGTH) { (char * peerid, size_t peeridlen) };
+	%apply (char *STRING, int LENGTH) { (char * realm, size_t realmlen) };
+	void add(char * peerid, size_t peeridlen, char * realm, size_t realmlen) {
+		int ret = fd_rtd_candidate_add($self, peerid, peeridlen, realm, realmlen);
+		if (ret != 0) {
+			DI_ERROR(ret, NULL, NULL);
+		}
+	}
+	void remove(char * STRING, size_t LENGTH) {
+		fd_rtd_candidate_del($self, (os0_t)STRING, LENGTH);
+	}
+	int error(char * peerid, size_t peeridlen, char * STRING, size_t LENGTH, uint32_t rcode) {
+		int n;
+		int ret =  fd_rtd_error_add($self, peerid, peeridlen, (os0_t)STRING, LENGTH, rcode, NULL, &n);
+		if (ret != 0) {
+			DI_ERROR(ret, NULL, NULL);
+		}
+		return n;
+	}
+	struct fd_list * extract(int score = 0) {
+		struct fd_list * li = NULL;
+		fd_rtd_candidate_extract($self, &li, score);
+		return li;
+	}
+}
+
+
+
+%extend rtd_candidate {
+	void dump() {
+		fd_log_debug("candidate %p", $self);
+		fd_log_debug("  id : %s",  $self->diamid);
+		fd_log_debug("  rlm: %s", $self->realm);
+		fd_log_debug("  sc : %d", $self->score);
+	}
+}
+
+
+%{
+/* call it (will be called from a different thread than the interpreter, when message arrives) */
+static int call_the_python_rt_fwd_callback(void * pycb, struct msg **msg) {
+	PyObject *PyMsg;
+	PyObject *cb, *result = NULL;
+	int ret = 0;
+	
+	if (!pycb) {
+		fd_log_debug("Internal error: missing the callback!");
+		return ENOTSUP;
+	}
+	cb = pycb;
+	
+	SWIG_PYTHON_THREAD_BEGIN_BLOCK;
+	/* Convert the arguments */
+	PyMsg  = SWIG_NewPointerObj((void *)*msg,     SWIGTYPE_p_msg,     0 );
+	
+	/* Call the function */
+	result = PyObject_CallFunction(cb, "(O)", PyMsg);
+	
+	/* The result is supposedly composed of: [ ret, *msg ] */
+	if ((result == NULL) || (!PyList_Check(result)) || (PyList_Size(result) != 2)) {
+		fd_log_debug("Error: The Python callback did not return [ ret, msg ].");
+		ret = EINVAL;
+		goto out;
+	}
+	
+	/* Convert the return values */
+	if (!SWIG_IsOK(SWIG_AsVal_int(PyList_GetItem(result, 0), &ret))) {
+		fd_log_debug("Error: Cannot convert the first return value to integer.");
+		ret = EINVAL;
+		goto out;
+	}
+	if (ret) {
+		TRACE_DEBUG(INFO, "The Python callback returned the error code %d (%s)", ret, strerror(ret));
+		goto out;
+	}
+	
+	if (!SWIG_IsOK(SWIG_ConvertPtr(PyList_GetItem(result, 1), (void *)msg, SWIGTYPE_p_msg, SWIG_POINTER_DISOWN))) {
+		fd_log_debug("Error: Cannot convert the second return value to message.");
+		ret = EINVAL;
+		goto out;
+	}
+	
+out:	
+	Py_XDECREF(result);
+	
+	SWIG_PYTHON_THREAD_END_BLOCK;
+	return ret;
+}
+%}
+
+
+struct fd_rt_fwd_hdl {
+};
+
+%extend fd_rt_fwd_hdl{
+	fd_rt_fwd_hdl(PyObject * PyCb, enum fd_rt_fwd_dir dir) {
+		struct fd_rt_fwd_hdl * r = NULL;
+		int ret;
+		
+		Py_XINCREF(PyCb);
+
+		ret = fd_rt_fwd_register( call_the_python_rt_fwd_callback, PyCb, dir, &r );
+		if (ret != 0) {
+			DI_ERROR(ret, NULL, NULL);
+			return NULL;
+		}
+		return r;
+	}
+	
+	~fd_rt_fwd_hdl() {
+		PyObject * func;
+		int ret = fd_rt_fwd_unregister ( $self, (void *) &func );
+		if (ret != 0) {
+			DI_ERROR(ret, NULL, NULL);
+			return;
+		}
+		Py_XDECREF(func);
+		return;
+	}
+}
+
+
+%{
+/* call it (will be called from a different thread than the interpreter, when message arrives) */
+static int call_the_python_rt_out_callback(void * pycb, struct msg **msg, struct fd_list * candidates) {
+	PyObject *PyMsg, *PyCands;
+	PyObject *cb, *result = NULL;
+	int ret = 0;
+	
+	if (!pycb) {
+		fd_log_debug("Internal error: missing the callback!");
+		return ENOTSUP;
+	}
+	cb = pycb;
+	
+	SWIG_PYTHON_THREAD_BEGIN_BLOCK;
+	/* Convert the arguments */
+	PyMsg   = SWIG_NewPointerObj((void *)*msg,       SWIGTYPE_p_msg,     0 );
+	PyCands = SWIG_NewPointerObj((void *)candidates, SWIGTYPE_p_fd_list, 0 );
+	
+	/* Call the function */
+	result = PyObject_CallFunction(cb, "(OO)", PyMsg, PyCands);
+	
+	/* The result is supposedly composed of: [ ret, *msg ] */
+	if (result == NULL){
+		fd_log_debug("Error: The Python callback raised an exception.");
+		ret = EINVAL;
+		goto out;
+	}
+	
+	/* Convert the return values */
+	if (!SWIG_IsOK(SWIG_AsVal_int(result, &ret))) {
+		fd_log_debug("Error: Cannot convert the return value to integer.");
+		ret = EINVAL;
+		goto out;
+	}
+out:	
+	Py_XDECREF(result);
+	
+	SWIG_PYTHON_THREAD_END_BLOCK;
+	return ret;
+}
+%}
+
+
+struct fd_rt_out_hdl {
+};
+
+%extend fd_rt_out_hdl{
+	fd_rt_out_hdl(PyObject * PyCb, int priority = 0) {
+		struct fd_rt_out_hdl * r = NULL;
+		int ret;
+		
+		Py_XINCREF(PyCb);
+
+		ret = fd_rt_out_register( call_the_python_rt_out_callback, PyCb, priority, &r );
+		if (ret != 0) {
+			DI_ERROR(ret, NULL, NULL);
+			return NULL;
+		}
+		return r;
+	}
+	
+	~fd_rt_out_hdl() {
+		PyObject * func;
+		int ret = fd_rt_out_unregister ( $self, (void *) &func );
+		if (ret != 0) {
+			DI_ERROR(ret, NULL, NULL);
+			return;
+		}
+		Py_XDECREF(func);
+		return;
+	}
+}
+
diff --git a/extensions/dbg_interactive/sessions.i b/extensions/dbg_interactive/sessions.i
new file mode 100644
index 0000000..180a150
--- /dev/null
+++ b/extensions/dbg_interactive/sessions.i
@@ -0,0 +1,210 @@
+/*********************************************************************************************************
+* Software License Agreement (BSD License)                                                               *
+* Author: Sebastien Decugis <sdecugis@freediameter.net>							 *
+*													 *
+* Copyright (c) 2013, WIDE Project and NICT								 *
+* All rights reserved.											 *
+* 													 *
+* Redistribution and use of this software in source and binary forms, with or without modification, are  *
+* permitted provided that the following conditions are met:						 *
+* 													 *
+* * Redistributions of source code must retain the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer.										 *
+*    													 *
+* * Redistributions in binary form must reproduce the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer in the documentation and/or other						 *
+*   materials provided with the distribution.								 *
+* 													 *
+* * Neither the name of the WIDE Project or NICT nor the 						 *
+*   names of its contributors may be used to endorse or 						 *
+*   promote products derived from this software without 						 *
+*   specific prior written permission of WIDE Project and 						 *
+*   NICT.												 *
+* 													 *
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED *
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
+* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR *
+* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 	 *
+* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 	 *
+* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR *
+* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF   *
+* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.								 *
+*********************************************************************************************************/
+
+/* Do not include this directly, use dbg_interactive.i instead */
+
+/****** SESSIONS *********/
+
+%{
+struct sess_state {
+	PyObject * pystate;
+};
+
+/* call it (might be called from a different thread than the interpreter, when session times out) */
+static void call_the_python_cleanup_callback(struct sess_state * state, os0_t sid, void * cb) {
+	PyObject *result;
+	if (!cb) {
+		fd_log_debug("Internal error: missing callback object!");
+		return;
+	}
+	
+	/* Call the function */
+	SWIG_PYTHON_THREAD_BEGIN_BLOCK;
+	result = PyObject_CallFunction((PyObject *)cb, "(Os)", state, sid);
+	Py_XDECREF(result);
+	SWIG_PYTHON_THREAD_END_BLOCK;
+	return;
+}
+%}
+
+struct session_handler {
+};
+
+%nodefaultctor session_handler;
+%extend session_handler {
+	session_handler(PyObject * PyCb) {
+		struct session_handler * hdl = NULL;
+		int ret;
+		
+		Py_XINCREF(PyCb);
+		
+		ret = fd_sess_handler_create ( &hdl, call_the_python_cleanup_callback, NULL, PyCb );
+		if (ret != 0) {
+			DI_ERROR(ret, NULL, NULL);
+			return NULL;
+		}
+		return hdl;
+	}
+	~session_handler() {
+		struct session_handler * hdl = self;
+		PyObject * cb = NULL;
+		
+		int ret = fd_sess_handler_destroy(&hdl, (void *)&cb);
+		if (ret != 0) {
+			DI_ERROR(ret, NULL, NULL);
+		}
+		/* Now free the callback */
+		Py_XDECREF(cb);
+		return;
+	}
+	void dump() {
+		char * buf = NULL;
+		size_t len;
+		printf("%s", fd_sess_dump_hdl(&buf, &len, NULL, $self));
+		free(buf);
+	}
+}
+
+
+struct session {
+};
+
+%extend session {
+	/* The first two versions create a new session string. The third one allow to use an existing string. */
+	session() {
+		int ret;
+		struct session * s = NULL;
+		ret = fd_sess_new(&s, fd_g_config->cnf_diamid, fd_g_config->cnf_diamid_len, (os0_t)"dbg_interactive", CONSTSTRLEN("dbg_interactive"));
+		if (ret != 0) {
+			DI_ERROR(ret, NULL, NULL);
+			return NULL;
+		}
+		return s;
+	}
+	session(char * diamid, char * STRING, size_t LENGTH) {
+		int ret;
+		struct session * s = NULL;
+		ret = fd_sess_new(&s, diamid, 0, (os0_t)STRING, LENGTH);
+		if (ret != 0) {
+			DI_ERROR(ret, NULL, NULL);
+			return NULL;
+		}
+		return s;
+	}
+	session(char * STRING, size_t LENGTH) {
+		int ret, n;
+		struct session * s = NULL;
+		ret = fd_sess_fromsid((os0_t)STRING, LENGTH, &s, &n);
+		if (ret != 0) {
+			DI_ERROR(ret, NULL, NULL);
+			return NULL;
+		}
+		/* When defining n as OUTPUT parameter, we get something strange... Use fd_sess_fromsid if you need it */
+		#if 0
+		if (n) {
+			fd_log_debug("A new session has been created");
+		} else {
+			fd_log_debug("A session with same id already existed");
+		}
+		#endif /* 0 */
+		
+		return s;
+	}
+	~session() {
+		struct session * s = self;
+		int ret = fd_sess_reclaim(&s);
+		if (ret != 0) {
+			DI_ERROR(ret, NULL, NULL);
+		}
+		return;
+	}
+	
+	%cstring_output_allocate_size(char ** outsid, size_t * sidlen, /* do not free */);
+	void getsid(char ** outsid, size_t * sidlen) {
+		int ret;
+		ret = fd_sess_getsid( $self, (void *)outsid, sidlen);
+		if (ret != 0) {
+			DI_ERROR(ret, NULL, NULL);
+			return;
+		}
+		return;
+	}
+	void settimeout(long seconds) {
+		struct timespec timeout;
+		int ret;
+		clock_gettime(CLOCK_REALTIME, &timeout);
+		timeout.tv_sec += seconds;
+		ret = fd_sess_settimeout( $self, &timeout );
+		if (ret != 0) {
+			DI_ERROR(ret, NULL, NULL);
+		}
+	}
+	void dump() {
+		char * buf = NULL;
+		size_t len = 0;
+		printf("%s", fd_sess_dump(&buf, &len, NULL, $self, 1) );
+		free(buf);
+	}
+	void store(struct session_handler * handler, PyObject * DISOWN) {
+		int ret;
+		struct sess_state * st = NULL;
+		st = malloc(sizeof(struct sess_state));
+		st->pystate = DISOWN;
+		Py_XINCREF(DISOWN);
+		ret = fd_sess_state_store(handler, $self, (void *) &st);
+		if (ret != 0) {
+			DI_ERROR(ret, NULL, NULL);
+		}
+	}
+	%newobject retrieve;
+	PyObject * retrieve(struct session_handler * handler) {
+		int ret;
+		struct sess_state * st = NULL;
+		PyObject * state = NULL;
+		ret = fd_sess_state_retrieve(handler, $self, (void *) &st);
+		if (ret != 0) {
+			DI_ERROR(ret, NULL, NULL);
+			return NULL;
+		}
+		if (st == NULL) {
+			Py_INCREF(Py_None);
+			return Py_None;
+		}
+		state = st->pystate;
+		free(st);
+		return state;
+	}
+}	
+
diff --git a/extensions/dbg_monitor/CMakeLists.txt b/extensions/dbg_monitor/CMakeLists.txt
new file mode 100644
index 0000000..ddc8df7
--- /dev/null
+++ b/extensions/dbg_monitor/CMakeLists.txt
@@ -0,0 +1,12 @@
+# Monitoring extension
+PROJECT("Monitor extension" C)
+FD_ADD_EXTENSION(dbg_monitor dbg_monitor.c)
+
+
+####
+## INSTALL section ##
+
+INSTALL(TARGETS dbg_monitor
+	LIBRARY DESTINATION ${INSTALL_EXTENSIONS_SUFFIX}
+	COMPONENT freeDiameter-debug-tools)
+
diff --git a/extensions/dbg_monitor/dbg_monitor.c b/extensions/dbg_monitor/dbg_monitor.c
new file mode 100644
index 0000000..de7c13a
--- /dev/null
+++ b/extensions/dbg_monitor/dbg_monitor.c
@@ -0,0 +1,170 @@
+/*********************************************************************************************************
+* Software License Agreement (BSD License)                                                               *
+* Author: Sebastien Decugis <sdecugis@freediameter.net>							 *
+*													 *
+* Copyright (c) 2013, WIDE Project and NICT								 *
+* All rights reserved.											 *
+* 													 *
+* Redistribution and use of this software in source and binary forms, with or without modification, are  *
+* permitted provided that the following conditions are met:						 *
+* 													 *
+* * Redistributions of source code must retain the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer.										 *
+*    													 *
+* * Redistributions in binary form must reproduce the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer in the documentation and/or other						 *
+*   materials provided with the distribution.								 *
+* 													 *
+* * Neither the name of the WIDE Project or NICT nor the 						 *
+*   names of its contributors may be used to endorse or 						 *
+*   promote products derived from this software without 						 *
+*   specific prior written permission of WIDE Project and 						 *
+*   NICT.												 *
+* 													 *
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED *
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
+* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR *
+* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 	 *
+* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 	 *
+* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR *
+* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF   *
+* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.								 *
+*********************************************************************************************************/
+
+/* Monitoring extension:
+ - periodically display queues and peers information
+ - upon SIGUSR2, display additional debug information
+ */
+
+#include <freeDiameter/extension.h>
+#include <signal.h>
+
+#ifndef MONITOR_SIGNAL
+#define MONITOR_SIGNAL	SIGUSR2
+#endif /* MONITOR_SIGNAL */
+
+static int 	 monitor_main(char * conffile);
+
+EXTENSION_ENTRY("dbg_monitor", monitor_main);
+
+
+
+/* Display information about a queue */
+static void display_info(char * queue_desc, char * peer, int current_count, int limit_count, int highest_count, long long total_count,
+			struct timespec * total, struct timespec * blocking, struct timespec * last)
+{
+	long long us = (total->tv_sec * 1000000) + (total->tv_nsec / 1000);
+	long double throughput = (long double)total_count * 1000000;
+	throughput /= us;
+	if (peer) {
+		TRACE_DEBUG(INFO, "'%s'@'%s': cur:%d/%d, h:%d, T:%lld in %ld.%06lds (%.2LFitems/s), blocked:%ld.%06lds, last processing:%ld.%06lds",
+			queue_desc, peer, current_count, limit_count, highest_count,
+			total_count, total->tv_sec, total->tv_nsec/1000, throughput,
+			blocking->tv_sec, blocking->tv_nsec/1000, last->tv_sec, last->tv_nsec/1000);
+	} else {
+		TRACE_DEBUG(INFO, "Global '%s': cur:%d/%d, h:%d, T:%lld in %ld.%06lds (%.2LFitems/s), blocked:%ld.%06lds, last processing:%ld.%06lds",
+			queue_desc, current_count, limit_count, highest_count,
+			total_count, total->tv_sec, total->tv_nsec/1000, throughput,
+			blocking->tv_sec, blocking->tv_nsec/1000, last->tv_sec, last->tv_nsec/1000);
+	}
+}
+
+/* Thread to display periodical debug information */
+static pthread_t thr;
+static void * mn_thr(void * arg)
+{
+	int i = 0;
+	fd_log_threadname("Monitor thread");
+	char * buf = NULL;
+	size_t len;
+	
+	/* Loop */
+	while (1) {
+		int current_count, limit_count, highest_count;
+		long long total_count;
+		struct timespec total, blocking, last;
+		struct fd_list * li;
+	
+		#ifdef DEBUG
+		for (i++; i % 30; i++) {
+			fd_log_debug("[dbg_monitor] %ih%*im%*is", i/3600, 2, (i/60) % 60 , 2, i%60); /* This makes it easier to detect inactivity periods in the log file */
+			sleep(1);
+		}
+		#else /* DEBUG */
+		sleep(3599); /* 1 hour */
+		#endif /* DEBUG */
+		TRACE_DEBUG(INFO, "[dbg_monitor] Dumping queues statistics");
+		
+		CHECK_FCT_DO( fd_stat_getstats(STAT_G_LOCAL, NULL, &current_count, &limit_count, &highest_count, &total_count, &total, &blocking, &last), );
+		display_info("Local delivery", NULL, current_count, limit_count, highest_count, total_count, &total, &blocking, &last);
+		
+		CHECK_FCT_DO( fd_stat_getstats(STAT_G_INCOMING, NULL, &current_count, &limit_count, &highest_count, &total_count, &total, &blocking, &last), );
+		display_info("Total received", NULL, current_count, limit_count, highest_count, total_count, &total, &blocking, &last);
+		
+		CHECK_FCT_DO( fd_stat_getstats(STAT_G_OUTGOING, NULL, &current_count, &limit_count, &highest_count, &total_count, &total, &blocking, &last), );
+		display_info("Total sending", NULL, current_count, limit_count, highest_count, total_count, &total, &blocking, &last);
+		
+		
+		CHECK_FCT_DO( pthread_rwlock_rdlock(&fd_g_peers_rw), /* continue */ );
+
+		for (li = fd_g_peers.next; li != &fd_g_peers; li = li->next) {
+			struct peer_hdr * p = (struct peer_hdr *)li->o;
+			
+			TRACE_DEBUG(INFO, "%s", fd_peer_dump(&buf, &len, NULL, p, 1));
+			
+			CHECK_FCT_DO( fd_stat_getstats(STAT_P_PSM, p, &current_count, &limit_count, &highest_count, &total_count, &total, &blocking, &last), );
+			display_info("Events, incl. recept", p->info.pi_diamid, current_count, limit_count, highest_count, total_count, &total, &blocking, &last);
+			
+			CHECK_FCT_DO( fd_stat_getstats(STAT_P_TOSEND, p, &current_count, &limit_count, &highest_count, &total_count, &total, &blocking, &last), );
+			display_info("Outgoing", p->info.pi_diamid, current_count, limit_count, highest_count, total_count, &total, &blocking, &last);
+			
+		}
+
+		CHECK_FCT_DO( pthread_rwlock_unlock(&fd_g_peers_rw), /* continue */ );
+		
+		TRACE_DEBUG(INFO, "[dbg_monitor] Dumping servers information");
+		TRACE_DEBUG(INFO, "%s", fd_servers_dump(&buf, &len, NULL, 1));
+		
+		sleep(1);
+	}
+	
+	free(buf);
+	return NULL;
+}
+
+/* Function called on receipt of MONITOR_SIGNAL */
+static void got_sig()
+{
+	char * buf = NULL;
+	size_t len;
+	TRACE_DEBUG(INFO, "[dbg_monitor] Dumping config information");
+	TRACE_DEBUG(INFO, "%s", fd_conf_dump(&buf, &len, NULL));
+	TRACE_DEBUG(INFO, "[dbg_monitor] Dumping extensions information");
+	TRACE_DEBUG(INFO, "%s", fd_ext_dump(&buf, &len, NULL));
+	TRACE_DEBUG(INFO, "[dbg_monitor] Dumping dictionary information");
+	TRACE_DEBUG(INFO, "%s", fd_dict_dump(&buf, &len, NULL, fd_g_config->cnf_dict));
+	free(buf);
+}
+
+/* Entry point */
+static int monitor_main(char * conffile)
+{
+	TRACE_ENTRY("%p", conffile);
+	
+	/* Catch signal SIGUSR1 */
+	CHECK_FCT( fd_event_trig_regcb(MONITOR_SIGNAL, "dbg_monitor", got_sig));
+	
+	CHECK_POSIX( pthread_create( &thr, NULL, mn_thr, NULL ) );
+	return 0;
+}
+
+/* Cleanup */
+void fd_ext_fini(void)
+{
+	TRACE_ENTRY();
+	CHECK_FCT_DO( fd_thr_term(&thr), /* continue */ );
+	return ;
+}
+
diff --git a/extensions/dbg_msg_dumps/CMakeLists.txt b/extensions/dbg_msg_dumps/CMakeLists.txt
new file mode 100644
index 0000000..3348ac9
--- /dev/null
+++ b/extensions/dbg_msg_dumps/CMakeLists.txt
@@ -0,0 +1,11 @@
+PROJECT("Messages dump extension" C)
+FD_ADD_EXTENSION(dbg_msg_dumps dbg_msg_dumps.c)
+
+
+####
+## INSTALL section ##
+
+INSTALL(TARGETS dbg_msg_dumps
+	LIBRARY DESTINATION ${INSTALL_EXTENSIONS_SUFFIX}
+	COMPONENT freeDiameter-debug-tools)
+
diff --git a/extensions/dbg_msg_dumps/dbg_msg_dumps.c b/extensions/dbg_msg_dumps/dbg_msg_dumps.c
new file mode 100644
index 0000000..a26b14c
--- /dev/null
+++ b/extensions/dbg_msg_dumps/dbg_msg_dumps.c
@@ -0,0 +1,415 @@
+/*********************************************************************************************************
+* Software License Agreement (BSD License)                                                               *
+* Author: Sebastien Decugis <sdecugis@freediameter.net>							 *
+*													 *
+* Copyright (c) 2015, WIDE Project and NICT								 *
+* All rights reserved.											 *
+* 													 *
+* Redistribution and use of this software in source and binary forms, with or without modification, are  *
+* permitted provided that the following conditions are met:						 *
+* 													 *
+* * Redistributions of source code must retain the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer.										 *
+*    													 *
+* * Redistributions in binary form must reproduce the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer in the documentation and/or other						 *
+*   materials provided with the distribution.								 *
+* 													 *
+* * Neither the name of the WIDE Project or NICT nor the 						 *
+*   names of its contributors may be used to endorse or 						 *
+*   promote products derived from this software without 						 *
+*   specific prior written permission of WIDE Project and 						 *
+*   NICT.												 *
+* 													 *
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED *
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
+* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR *
+* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 	 *
+* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 	 *
+* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR *
+* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF   *
+* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.								 *
+*********************************************************************************************************/
+
+/* This extension uses the hooks mechanism to display the full content of received and sent messages, for
+   learning & debugging purpose.
+   Do NOT use this extension in production environment because it will slow down all operation. */
+   
+/* You can add a configuration parameter on the LoadExtension line, e.g. 
+LoadExtension="dbg_msg_dump.fdx":"0x149";
+The value is an hexadecimal value with the following bits meaning: */
+#define HK_ERRORS_QUIET    0x0001	 /* errors are not dumped -- removes the default handling as well */
+#define HK_ERRORS_COMPACT  0x0002	 /* errors in compact mode */
+#define HK_ERRORS_FULL     0x0004  	 /* errors in full mode (1 line with all the data) */
+#define HK_ERRORS_TREE     0x0008  	 /* errors in treeview mode (message split over multiple lines) */
+
+#define HK_SNDRCV_QUIET    0x0010	 /* send+rcv are not dumped -- removes the default handling as well */
+#define HK_SNDRCV_COMPACT  0x0020	 /* send+rcv in compact mode */
+#define HK_SNDRCV_FULL     0x0040  	 /* send+rcv in full mode */
+#define HK_SNDRCV_TREE     0x0080  	 /* send+rcv in tree mode */
+
+#define HK_ROUTING_QUIET   0x0100  	 /* routing decisions are not dumped -- removes the default handling as well */
+#define HK_ROUTING_COMPACT 0x0200  	 /* routing decisions in compact mode */
+#define HK_ROUTING_FULL    0x0400  	 /* routing decisions in full mode */
+#define HK_ROUTING_TREE    0x0800  	 /* routing decisions in tree mode */
+
+#define HK_PEERS_QUIET     0x1000  	 /* peers connections events are not dumped -- removes the default handling as well */
+#define HK_PEERS_COMPACT   0x2000  	 /* peers connections events in compact mode */
+#define HK_PEERS_FULL      0x4000  	 /* peers connections events in full mode */
+#define HK_PEERS_TREE      0x8000  	 /* peers connections events in tree mode */
+/*
+Default value is HK_ERRORS_TREE + HK_SNDRCV_TREE + HK_PEERS_TREE
+*/
+
+#include <freeDiameter/extension.h>
+
+static struct fd_hook_hdl *md_hdl[4] = {NULL,NULL,NULL,NULL};
+static uint32_t dump_level = HK_ERRORS_TREE | HK_SNDRCV_TREE | HK_PEERS_TREE; /* default */
+static char * buf = NULL;
+static size_t len;
+static pthread_mutex_t mtx = PTHREAD_MUTEX_INITIALIZER;
+
+/* The callback called when messages are received and sent */
+static void md_hook_cb_tree(enum fd_hook_type type, struct msg * msg, struct peer_hdr * peer, void * other, struct fd_hook_permsgdata *pmd, void * regdata)
+{
+	char * peer_name = peer ? peer->info.pi_diamid : "<unknown peer>";
+	
+	CHECK_POSIX_DO( pthread_mutex_lock(&mtx), );
+	
+	if (msg) {
+		CHECK_MALLOC_DO( fd_msg_dump_treeview(&buf, &len, NULL, msg, fd_g_config->cnf_dict, (type == HOOK_MESSAGE_PARSING_ERROR) ? 0 : 1, 1), 
+			{ LOG_E("Error while dumping a message"); pthread_mutex_unlock(&mtx); return; } );
+	}
+	
+	switch (type) {
+/* errors */
+	case HOOK_MESSAGE_FAILOVER:
+		LOG_E("FAILOVER from '%s':", peer_name);
+		LOG_SPLIT(FD_LOG_ERROR, "     ", buf, NULL);
+		break;
+	case HOOK_MESSAGE_PARSING_ERROR:
+		if (msg) {
+			DiamId_t id = NULL;
+			if (fd_msg_source_get( msg, &id, NULL ))
+				id = (DiamId_t)"<error getting source>";
+			if (!id)
+				id = (DiamId_t)"<local>";
+			LOG_E("PARSING ERROR: '%s' from '%s': ", (char *)other, (char *)id);
+			LOG_SPLIT(FD_LOG_ERROR, "     ", buf, NULL);
+		} else {
+			struct fd_cnx_rcvdata *rcv_data = other;
+			CHECK_MALLOC_DO(fd_dump_extend_hexdump(&buf, &len, NULL, rcv_data->buffer, rcv_data->length, 0, 0), break);
+			LOG_E("PARSING ERROR: %zdB msg from '%s': %s", rcv_data->length, peer_name, buf);
+		}
+		break;
+	case HOOK_MESSAGE_PARSING_ERROR2:
+		LOG_E("PARSING ERROR, returning:");
+		LOG_SPLIT(FD_LOG_ERROR, "     ", buf, NULL);
+		break;
+	case HOOK_MESSAGE_ROUTING_ERROR:
+		LOG_E("ROUTING ERROR '%s' for: ", (char *)other);
+		LOG_SPLIT(FD_LOG_ERROR, "     ", buf, NULL);
+		break;
+	case HOOK_MESSAGE_DROPPED:
+		LOG_E("DROPPED '%s'", (char *)other);
+		LOG_SPLIT(FD_LOG_ERROR, "     ", buf, NULL);
+		break;
+	
+/* send receive */
+	case HOOK_MESSAGE_RECEIVED:
+		LOG_N("RCV from '%s':", peer_name);
+		LOG_SPLIT(FD_LOG_NOTICE, "     ", buf, NULL);
+		break;
+	case HOOK_MESSAGE_SENDING:
+		LOG_N("SNDING to '%s':", peer_name);
+		LOG_SPLIT(FD_LOG_NOTICE, "     ", buf, NULL);
+		break;
+	case HOOK_MESSAGE_SENT:
+		LOG_N("SND to '%s':", peer_name);
+		LOG_SPLIT(FD_LOG_NOTICE, "     ", buf, NULL);
+		break;
+	
+/* routing */
+	case HOOK_MESSAGE_LOCAL:
+		LOG_N("ISSUED:");
+		LOG_SPLIT(FD_LOG_NOTICE, "     ", buf, NULL);
+		break;
+	case HOOK_MESSAGE_ROUTING_FORWARD:
+		LOG_N("FORWARDING: %s", buf);
+		LOG_SPLIT(FD_LOG_NOTICE, "     ", buf, NULL);
+		break;
+	case HOOK_MESSAGE_ROUTING_LOCAL:
+		LOG_N("DISPATCHING: %s", buf);
+		LOG_SPLIT(FD_LOG_NOTICE, "     ", buf, NULL);
+		break;
+	
+/* peers */
+	case HOOK_PEER_CONNECT_FAILED:
+		LOG_N("CONNECT FAILED to %s: %s", peer_name, (char *)other);
+		break;
+	case HOOK_PEER_CONNECT_SUCCESS:
+		{
+			char protobuf[40];
+			if (peer) {
+				CHECK_FCT_DO(fd_peer_cnx_proto_info(peer, protobuf, sizeof(protobuf)), break );
+			} else {
+				protobuf[0] = '-';
+				protobuf[1] = '\0';
+			}
+			LOG_N("CONNECTED TO '%s' (%s):", peer_name, protobuf);
+			LOG_SPLIT(FD_LOG_NOTICE, "     ", buf, NULL);
+		}
+		break;
+
+/* Not handled */
+	case HOOK_DATA_RECEIVED:
+		break;
+	}
+	
+	CHECK_POSIX_DO( pthread_mutex_unlock(&mtx), );
+}
+
+static void md_hook_cb_full(enum fd_hook_type type, struct msg * msg, struct peer_hdr * peer, void * other, struct fd_hook_permsgdata *pmd, void * regdata)
+{
+	char * peer_name = peer ? peer->info.pi_diamid : "<unknown peer>";
+	
+	CHECK_POSIX_DO( pthread_mutex_lock(&mtx), );
+	
+	if (msg) {
+		CHECK_MALLOC_DO( fd_msg_dump_full(&buf, &len, NULL, msg, fd_g_config->cnf_dict, (type == HOOK_MESSAGE_PARSING_ERROR) ? 0 : 1, 1), 
+			{ LOG_E("Error while dumping a message"); pthread_mutex_unlock(&mtx); return; } );
+	}
+	
+	switch (type) {
+/* errors */
+	case HOOK_MESSAGE_FAILOVER:
+		LOG_E("FAILOVER from '%s': %s", peer_name, buf);
+		break;
+	case HOOK_MESSAGE_PARSING_ERROR:
+		if (msg) {
+			DiamId_t id = NULL;
+			if (fd_msg_source_get( msg, &id, NULL ))
+				id = (DiamId_t)"<error getting source>";
+			if (!id)
+				id = (DiamId_t)"<local>";
+			LOG_E("PARSING ERROR: '%s' from '%s': %s", (char *)other, (char *)id, buf);
+		} else {
+			struct fd_cnx_rcvdata *rcv_data = other;
+			CHECK_MALLOC_DO(fd_dump_extend_hexdump(&buf, &len, NULL, rcv_data->buffer, rcv_data->length, 0, 0), break);
+			LOG_E("PARSING ERROR: %zdB msg from '%s': %s", rcv_data->length, peer_name, buf);
+		}
+		break;
+	case HOOK_MESSAGE_PARSING_ERROR2:
+		LOG_E("PARSING ERROR, returning: %s", buf);
+		break;
+	case HOOK_MESSAGE_ROUTING_ERROR:
+		LOG_E("ROUTING ERROR '%s' for: %s", (char *)other, buf);
+		break;
+	case HOOK_MESSAGE_DROPPED:
+		LOG_E("DROPPED '%s' %s", (char *)other, buf);
+		break;
+	
+/* send receive */
+	case HOOK_MESSAGE_RECEIVED:
+		LOG_N("RCV from '%s': %s", peer_name, buf);
+		break;
+	case HOOK_MESSAGE_SENDING:
+		LOG_N("SNDING to '%s': %s", peer_name, buf);
+		break;
+	case HOOK_MESSAGE_SENT:
+		LOG_N("SND to '%s': %s", peer_name, buf);
+		break;
+	
+/* routing */
+	case HOOK_MESSAGE_LOCAL:
+		LOG_N("ISSUED: %s", buf);
+		break;
+	case HOOK_MESSAGE_ROUTING_FORWARD:
+		LOG_N("FORWARDING: %s", buf);
+		break;
+	case HOOK_MESSAGE_ROUTING_LOCAL:
+		LOG_N("DISPATCHING: %s", buf);
+		break;
+	
+/* peers */
+	case HOOK_PEER_CONNECT_FAILED:
+		LOG_N("CONNECT FAILED to %s: %s", peer_name, (char *)other);
+		break;
+	case HOOK_PEER_CONNECT_SUCCESS: {
+			char protobuf[40];
+			if (peer) {
+				CHECK_FCT_DO(fd_peer_cnx_proto_info(peer, protobuf, sizeof(protobuf)), break );
+			} else {
+				protobuf[0] = '-';
+				protobuf[1] = '\0';
+			}
+			LOG_N("CONNECTED TO '%s' (%s): %s", peer_name, protobuf, buf);
+		}
+		break;
+/* Not handled */
+	case HOOK_DATA_RECEIVED:
+		break;
+	}
+	
+	CHECK_POSIX_DO( pthread_mutex_unlock(&mtx), );
+}
+
+static void md_hook_cb_compact(enum fd_hook_type type, struct msg * msg, struct peer_hdr * peer, void * other, struct fd_hook_permsgdata *pmd, void * regdata)
+{
+	char * peer_name = peer ? peer->info.pi_diamid : "<unknown peer>";
+	
+	CHECK_POSIX_DO( pthread_mutex_lock(&mtx), );
+	
+	if (msg) {
+		CHECK_MALLOC_DO( fd_msg_dump_summary(&buf, &len, NULL, msg, fd_g_config->cnf_dict, 0, 0), 
+			{ LOG_E("Error while dumping a message"); pthread_mutex_unlock(&mtx); return; } );
+	}
+	
+	switch (type) {
+/* errors */
+	case HOOK_MESSAGE_FAILOVER:
+		LOG_E("FAILOVER from '%s': %s", peer_name, buf);
+		break;
+	case HOOK_MESSAGE_PARSING_ERROR:
+		if (msg) {
+			DiamId_t id = NULL;
+			if (fd_msg_source_get( msg, &id, NULL ))
+				id = (DiamId_t)"<error getting source>";
+			if (!id)
+				id = (DiamId_t)"<local>";
+			LOG_E("PARSING ERROR: '%s' from '%s': %s", (char *)other, (char *)id, buf);
+		} else {
+			struct fd_cnx_rcvdata *rcv_data = other;
+			CHECK_MALLOC_DO(fd_dump_extend_hexdump(&buf, &len, NULL, rcv_data->buffer, rcv_data->length, 0, 0), break);
+			LOG_E("PARSING ERROR: %zdB msg from '%s': %s", rcv_data->length, peer_name, buf);
+		}
+		break;
+	case HOOK_MESSAGE_PARSING_ERROR2:
+		LOG_E("PARSING ERROR, returning: %s", buf);
+		break;
+	case HOOK_MESSAGE_ROUTING_ERROR:
+		LOG_E("ROUTING ERROR '%s' for: %s", (char *)other, buf);
+		break;
+	case HOOK_MESSAGE_DROPPED:
+		LOG_E("DROPPED '%s' %s", (char *)other, buf);
+		break;
+	
+/* send receive */
+	case HOOK_MESSAGE_RECEIVED:
+		LOG_N("RCV from '%s': %s", peer_name, buf);
+		break;
+	case HOOK_MESSAGE_SENDING:
+		LOG_N("SNDING to '%s': %s", peer_name, buf);
+		break;
+	case HOOK_MESSAGE_SENT:
+		LOG_N("SND to '%s': %s", peer_name, buf);
+		break;
+	
+/* routing */
+	case HOOK_MESSAGE_LOCAL:
+		LOG_N("ISSUED: %s", buf);
+		break;
+	case HOOK_MESSAGE_ROUTING_FORWARD:
+		LOG_N("FORWARDING: %s", buf);
+		break;
+	case HOOK_MESSAGE_ROUTING_LOCAL:
+		LOG_N("DISPATCHING: %s", buf);
+		break;
+	
+/* peers */
+	case HOOK_PEER_CONNECT_FAILED:
+		LOG_N("CONNECT FAILED to %s: %s", peer_name, (char *)other);
+		break;
+	case HOOK_PEER_CONNECT_SUCCESS: {
+			char protobuf[40];
+			if (peer) {
+				CHECK_FCT_DO(fd_peer_cnx_proto_info(peer, protobuf, sizeof(protobuf)), break );
+			} else {
+				protobuf[0] = '-';
+				protobuf[1] = '\0';
+			}
+			LOG_N("CONNECTED TO '%s' (%s)", peer_name, protobuf);
+		}
+		break;
+/* Not handled */
+	case HOOK_DATA_RECEIVED:
+		break;
+	}
+	
+	CHECK_POSIX_DO( pthread_mutex_unlock(&mtx), );
+}
+
+static void md_hook_cb_quiet(enum fd_hook_type type, struct msg * msg, struct peer_hdr * peer, void * other, struct fd_hook_permsgdata *pmd, void * regdata)
+{
+}
+
+/* Entry point */
+static int md_main(char * conffile)
+{
+	uint32_t mask_errors, mask_sndrcv, mask_routing, mask_peers;
+	uint32_t mask_quiet, mask_compact, mask_full, mask_tree;
+	TRACE_ENTRY("%p", conffile);
+	
+	if (conffile != NULL) {
+		char * endp;
+		dump_level = (uint32_t)strtoul(conffile, &endp, 16);
+		CHECK_PARAMS_DO( *endp == '\0', {
+			LOG_E("Configuration parameter must be in the form \"0xNNNN\"");
+			return EINVAL; });
+	}
+	
+	mask_errors = HOOK_MASK( HOOK_MESSAGE_FAILOVER, HOOK_MESSAGE_PARSING_ERROR, HOOK_MESSAGE_PARSING_ERROR2, HOOK_MESSAGE_ROUTING_ERROR, HOOK_MESSAGE_DROPPED  );
+	mask_sndrcv = HOOK_MASK( HOOK_MESSAGE_RECEIVED, HOOK_MESSAGE_SENT ); /* We don t access SENDING hook here */
+	mask_routing= HOOK_MASK( HOOK_MESSAGE_LOCAL, HOOK_MESSAGE_ROUTING_FORWARD, HOOK_MESSAGE_ROUTING_LOCAL );
+	mask_peers  = HOOK_MASK( HOOK_PEER_CONNECT_FAILED, HOOK_PEER_CONNECT_SUCCESS );
+	
+	mask_quiet  = (dump_level & HK_ERRORS_QUIET)  ? mask_errors : 0;
+	mask_quiet |= (dump_level & HK_SNDRCV_QUIET)  ? mask_sndrcv : 0;
+	mask_quiet |= (dump_level & HK_ROUTING_QUIET) ? mask_routing : 0;
+	mask_quiet |= (dump_level & HK_PEERS_QUIET)   ? mask_peers : 0;
+	
+	mask_compact  = (dump_level & HK_ERRORS_COMPACT)  ? mask_errors : 0;
+	mask_compact |= (dump_level & HK_SNDRCV_COMPACT)  ? mask_sndrcv : 0;
+	mask_compact |= (dump_level & HK_ROUTING_COMPACT) ? mask_routing : 0;
+	mask_compact |= (dump_level & HK_PEERS_COMPACT)   ? mask_peers : 0;
+	
+	mask_full  = (dump_level & HK_ERRORS_FULL)  ? mask_errors : 0;
+	mask_full |= (dump_level & HK_SNDRCV_FULL)  ? mask_sndrcv : 0;
+	mask_full |= (dump_level & HK_ROUTING_FULL) ? mask_routing : 0;
+	mask_full |= (dump_level & HK_PEERS_FULL)   ? mask_peers : 0;
+	
+	mask_tree  = (dump_level & HK_ERRORS_TREE)  ? mask_errors : 0;
+	mask_tree |= (dump_level & HK_SNDRCV_TREE)  ? mask_sndrcv : 0;
+	mask_tree |= (dump_level & HK_ROUTING_TREE) ? mask_routing : 0;
+	mask_tree |= (dump_level & HK_PEERS_TREE)   ? mask_peers : 0;
+	
+	if (mask_quiet) {
+		CHECK_FCT( fd_hook_register( mask_quiet, md_hook_cb_quiet, NULL, NULL, &md_hdl[0]) );
+	}
+	if (mask_compact) {
+		CHECK_FCT( fd_hook_register( mask_compact, md_hook_cb_compact, NULL, NULL, &md_hdl[1]) );
+	}
+	if (mask_full) {
+		CHECK_FCT( fd_hook_register( mask_full, md_hook_cb_full, NULL, NULL, &md_hdl[2]) );
+	}
+	if (mask_tree) {
+		CHECK_FCT( fd_hook_register( mask_tree, md_hook_cb_tree, NULL, NULL, &md_hdl[3]) );
+	}
+
+	return 0;
+}
+
+/* Cleanup */
+void fd_ext_fini(void)
+{
+	TRACE_ENTRY();
+	if (md_hdl[0]) { CHECK_FCT_DO( fd_hook_unregister( md_hdl[0] ), ); }
+	if (md_hdl[1]) { CHECK_FCT_DO( fd_hook_unregister( md_hdl[1] ), ); }
+	if (md_hdl[2]) { CHECK_FCT_DO( fd_hook_unregister( md_hdl[2] ), ); }
+	if (md_hdl[2]) { CHECK_FCT_DO( fd_hook_unregister( md_hdl[3] ), ); }
+	return ;
+}
+
+EXTENSION_ENTRY("dbg_msg_dumps", md_main);
diff --git a/extensions/dbg_msg_timings/CMakeLists.txt b/extensions/dbg_msg_timings/CMakeLists.txt
new file mode 100644
index 0000000..338a3e0
--- /dev/null
+++ b/extensions/dbg_msg_timings/CMakeLists.txt
@@ -0,0 +1,12 @@
+# Messages timing extension
+PROJECT("Messages timing extension" C)
+FD_ADD_EXTENSION(dbg_msg_timings dbg_msg_timings.c)
+
+
+####
+## INSTALL section ##
+
+INSTALL(TARGETS dbg_msg_timings
+	LIBRARY DESTINATION ${INSTALL_EXTENSIONS_SUFFIX}
+	COMPONENT freeDiameter-debug-tools)
+
diff --git a/extensions/dbg_msg_timings/dbg_msg_timings.c b/extensions/dbg_msg_timings/dbg_msg_timings.c
new file mode 100644
index 0000000..6c66069
--- /dev/null
+++ b/extensions/dbg_msg_timings/dbg_msg_timings.c
@@ -0,0 +1,133 @@
+/*********************************************************************************************************
+* Software License Agreement (BSD License)                                                               *
+* Author: Sebastien Decugis <sdecugis@freediameter.net>							 *
+*													 *
+* Copyright (c) 2013, WIDE Project and NICT								 *
+* All rights reserved.											 *
+* 													 *
+* Redistribution and use of this software in source and binary forms, with or without modification, are  *
+* permitted provided that the following conditions are met:						 *
+* 													 *
+* * Redistributions of source code must retain the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer.										 *
+*    													 *
+* * Redistributions in binary form must reproduce the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer in the documentation and/or other						 *
+*   materials provided with the distribution.								 *
+* 													 *
+* * Neither the name of the WIDE Project or NICT nor the 						 *
+*   names of its contributors may be used to endorse or 						 *
+*   promote products derived from this software without 						 *
+*   specific prior written permission of WIDE Project and 						 *
+*   NICT.												 *
+* 													 *
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED *
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
+* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR *
+* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 	 *
+* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 	 *
+* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR *
+* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF   *
+* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.								 *
+*********************************************************************************************************/
+
+/* This extension uses the hooks mechanism to compute some timing information related to messages */
+
+#include <freeDiameter/extension.h>
+
+struct fd_hook_permsgdata {
+	struct timespec received_on;
+	struct timespec sent_on;
+};
+
+static struct fd_hook_data_hdl *mt_data_hdl = NULL;
+static struct fd_hook_hdl *mt_hdl = NULL;
+
+/* The callback called when messages are received and sent */
+static void mt_hook_cb(enum fd_hook_type type, struct msg * msg, struct peer_hdr * peer, void * other, struct fd_hook_permsgdata *pmd, void * regdata)
+{
+	struct msg_hdr * hdr;
+	char * buf = NULL;
+	size_t len;
+	
+	ASSERT(pmd);
+	
+	if (type == HOOK_DATA_RECEIVED) {
+		/* We just store the timestamp it was received on */
+		(void)clock_gettime(CLOCK_REALTIME, &pmd->received_on);
+		return;
+	}
+	
+	ASSERT(msg);
+	
+	/* Check if this message is request or answer */
+	CHECK_FCT_DO( fd_msg_hdr(msg, &hdr), return);
+	
+	if (type == HOOK_MESSAGE_RECEIVED) {
+		ASSERT(pmd->received_on.tv_sec); /* otherwise it means the HOOK_DATA_RECEIVED hook was not trigged for this message */
+		if (hdr->msg_flags & CMD_FLAG_REQUEST) {
+			/* We have received a new request, nothing special to do */
+		} else {
+			/* This is an answer, check how long it took to get it */
+			struct fd_hook_permsgdata *qpmd = fd_hook_get_request_pmd(mt_data_hdl, msg);
+			struct timespec delay;
+			ASSERT(qpmd); /* If we do not have it, we must find out why */
+			ASSERT(qpmd->sent_on.tv_sec); /* same, would mean the HOOK_MESSAGE_SENT hook was not trigged */
+			TS_DIFFERENCE( &delay, &qpmd->sent_on, &pmd->received_on );
+			CHECK_MALLOC_DO( fd_msg_dump_summary(&buf, &len, NULL, msg, NULL, 0, 1), return );
+			LOG_N("[TIMING] RCV ANS %ld.%06ld sec <-'%s': %s", (long)delay.tv_sec, delay.tv_nsec / 1000, peer ? peer->info.pi_diamid : "<unidentified>", buf);
+		}
+	} else if (type == HOOK_MESSAGE_SENT) {
+		DiamId_t source = NULL;
+		
+		(void)clock_gettime(CLOCK_REALTIME, &pmd->sent_on);
+		
+		/* Is this a forwarded message ? */
+		CHECK_FCT_DO( fd_msg_source_get(msg, &source, NULL), return );
+		if (source) {
+			struct timespec delay;
+			ASSERT(pmd->received_on.tv_sec);
+			TS_DIFFERENCE( &delay, &pmd->received_on, &pmd->sent_on );
+			CHECK_MALLOC_DO( fd_msg_dump_summary(&buf, &len, NULL, msg, NULL, 0, 1), return );
+			LOG_N("[TIMING] FWD %ld.%06ld sec '%s'->'%s': %s", (long)delay.tv_sec, delay.tv_nsec / 1000, source, peer ? peer->info.pi_diamid : "<unidentified>", buf);
+		} else if (hdr->msg_flags & CMD_FLAG_REQUEST) {
+			/* We are sending a request issued locally, nothing special to log */
+		} else {
+			/* We have generated an anwer, log the time it took since the corresponding request was received */
+			struct fd_hook_permsgdata *qpmd = fd_hook_get_request_pmd(mt_data_hdl, msg);
+			if (qpmd->received_on.tv_sec) {
+				struct timespec delay;
+				TS_DIFFERENCE( &delay, &qpmd->received_on, &pmd->sent_on );
+				CHECK_MALLOC_DO( fd_msg_dump_summary(&buf, &len, NULL, msg, NULL, 0, 1), return );
+				LOG_N("[TIMING] ANS %ld.%06ld sec ->'%s': %s", (long)delay.tv_sec, delay.tv_nsec / 1000, peer ? peer->info.pi_diamid : "<unidentified>", buf);
+			}
+		}
+	}
+		
+	free(buf);
+}
+
+/* Entry point */
+static int mt_main(char * conffile)
+{
+	TRACE_ENTRY("%p", conffile);
+	
+	CHECK_FCT( fd_hook_data_register( sizeof(struct fd_hook_permsgdata), NULL, NULL, &mt_data_hdl ) );
+	
+	CHECK_FCT( fd_hook_register( HOOK_MASK( HOOK_MESSAGE_RECEIVED, HOOK_MESSAGE_SENT, HOOK_DATA_RECEIVED ), 
+					mt_hook_cb, NULL, mt_data_hdl, &mt_hdl) );
+	
+	return 0;
+}
+
+/* Cleanup */
+void fd_ext_fini(void)
+{
+	TRACE_ENTRY();
+	CHECK_FCT_DO( fd_hook_unregister( mt_hdl ), );
+	return ;
+}
+
+EXTENSION_ENTRY("dbg_msg_timing", mt_main);
diff --git a/extensions/dbg_rt/CMakeLists.txt b/extensions/dbg_rt/CMakeLists.txt
new file mode 100644
index 0000000..6ce7084
--- /dev/null
+++ b/extensions/dbg_rt/CMakeLists.txt
@@ -0,0 +1,13 @@
+# The rt_debug extension
+PROJECT("Routing module debug extension" C)
+
+# Compile as a module
+FD_ADD_EXTENSION(dbg_rt dbg_rt.c)
+
+
+####
+## INSTALL section ##
+
+INSTALL(TARGETS dbg_rt
+	LIBRARY DESTINATION ${INSTALL_EXTENSIONS_SUFFIX}
+	COMPONENT freeDiameter-debug-tools)
diff --git a/extensions/dbg_rt/dbg_rt.c b/extensions/dbg_rt/dbg_rt.c
new file mode 100644
index 0000000..906e18e
--- /dev/null
+++ b/extensions/dbg_rt/dbg_rt.c
@@ -0,0 +1,106 @@
+/*********************************************************************************************************
+* Software License Agreement (BSD License)                                                               *
+* Author: Sebastien Decugis <sdecugis@freediameter.net>							 *
+*													 *
+* Copyright (c) 2013, WIDE Project and NICT								 *
+* All rights reserved.											 *
+* 													 *
+* Redistribution and use of this software in source and binary forms, with or without modification, are  *
+* permitted provided that the following conditions are met:						 *
+* 													 *
+* * Redistributions of source code must retain the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer.										 *
+*    													 *
+* * Redistributions in binary form must reproduce the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer in the documentation and/or other						 *
+*   materials provided with the distribution.								 *
+* 													 *
+* * Neither the name of the WIDE Project or NICT nor the 						 *
+*   names of its contributors may be used to endorse or 						 *
+*   promote products derived from this software without 						 *
+*   specific prior written permission of WIDE Project and 						 *
+*   NICT.												 *
+* 													 *
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED *
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
+* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR *
+* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 	 *
+* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 	 *
+* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR *
+* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF   *
+* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.								 *
+*********************************************************************************************************/
+
+/* 
+ * Debug-only extension for routing module; 
+ * displays state information at the end of routing information process.
+ */
+#include <freeDiameter/extension.h>
+
+static struct fd_rt_fwd_hdl * fwd_hdl = NULL;
+static struct fd_rt_out_hdl * out_hdl = NULL;
+
+/* Proxying debug callback */
+static int dbgrt_fwd_cb(void * cbdata, struct msg ** msg)
+{
+	char * buf = NULL; size_t buflen;
+	TRACE_ENTRY("%p %p", cbdata, msg);
+	
+	LOG_D("[dbg_rt] FWD routing message: %p", msg ? *msg : NULL);
+	if (msg) {
+		CHECK_MALLOC( fd_msg_dump_treeview(&buf, &buflen, NULL, *msg, NULL, 0, 1) );
+		LOG_D("%s", buf);
+	}
+	free(buf);
+	return 0;
+}
+
+/* Path selection debug callback */
+static int dbgrt_out_cb(void * cbdata, struct msg ** pmsg, struct fd_list * candidates)
+{
+	struct fd_list * li;
+	struct msg * msg = *pmsg;
+	char * buf = NULL; size_t buflen;
+	
+	TRACE_ENTRY("%p %p %p", cbdata, msg, candidates);
+	
+	LOG_D("[dbg_rt] OUT routing message: %p", msg);
+	CHECK_MALLOC( fd_msg_dump_treeview(&buf, &buflen, NULL, msg, NULL, 0, 1) );
+	LOG_D("%s", buf);
+	LOG_D("[dbg_rt] Current list of candidates (%p): (score - id)", msg);
+	
+	for (li = candidates->next; li != candidates; li = li->next) {
+		struct rtd_candidate *c = (struct rtd_candidate *) li;
+		LOG_D("[dbg_rt]   %d -\t%s", c->score, c->diamid);
+	}
+	
+	return 0;
+}
+
+/* Register the callbacks to the daemon */
+static int dbgrt_main(char * conffile)
+{
+	TRACE_ENTRY("%p", conffile);
+	
+	CHECK_FCT( fd_rt_fwd_register ( dbgrt_fwd_cb, NULL, RT_FWD_ALL, &fwd_hdl ) );
+	CHECK_FCT( fd_rt_out_register ( dbgrt_out_cb, NULL, -1 /* so that it is called late */, &out_hdl ) );
+
+	return 0;
+}
+
+/* Cleanup the callbacks */
+void fd_ext_fini(void)
+{
+	TRACE_ENTRY();
+	
+	/* Unregister the modules */
+	CHECK_FCT_DO( fd_rt_fwd_unregister ( fwd_hdl, NULL ), /* continue */ );
+	CHECK_FCT_DO( fd_rt_out_unregister ( out_hdl, NULL ), /* continue */ );
+	
+	return ;
+}
+
+/* Define the entry point function */
+EXTENSION_ENTRY("dbg_rt", dbgrt_main);
diff --git a/extensions/dict_3gpp2_avps/3gpp2_avps.did b/extensions/dict_3gpp2_avps/3gpp2_avps.did
new file mode 100644
index 0000000..7c1da3c
--- /dev/null
+++ b/extensions/dict_3gpp2_avps/3gpp2_avps.did
@@ -0,0 +1 @@
+dict_3gpp2_avps
diff --git a/extensions/dict_3gpp2_avps/CMakeLists.txt b/extensions/dict_3gpp2_avps/CMakeLists.txt
new file mode 100644
index 0000000..ceda190
--- /dev/null
+++ b/extensions/dict_3gpp2_avps/CMakeLists.txt
@@ -0,0 +1,16 @@
+# The dict_3gpp2_avps extension
+PROJECT("dict_3gpp2_avps library generated by FdGen " C)
+
+# Compile as a module
+FD_ADD_EXTENSION(dict_3gpp2_avps dict_3gpp2_avps.c)
+
+
+####
+## INSTALL section ##
+
+INSTALL(TARGETS dict_3gpp2_avps
+	LIBRARY DESTINATION ${INSTALL_EXTENSIONS_SUFFIX}
+COMPONENT freeDiameter-dictionary-3GPP2_AVPS)
+
+
+
diff --git a/extensions/dict_3gpp2_avps/dict_3gpp2_avps.c b/extensions/dict_3gpp2_avps/dict_3gpp2_avps.c
new file mode 100644
index 0000000..a03b51c
--- /dev/null
+++ b/extensions/dict_3gpp2_avps/dict_3gpp2_avps.c
@@ -0,0 +1,184 @@
+/*
+* Copyright (c) 2017 Sprint
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*    http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+/****************
+ Generated By: fdtool enhancements to diafuzzer
+ License: same as freeDiameter
+****************/
+
+
+/* 
+ * Dictionary definitions of objects specified in 3gpp2_avps.
+ */
+#include <freeDiameter/extension.h>
+
+#define PROTO_VER "unspecified"
+#define GEN_DATE  1506697184.91
+
+const char *_3gpp2_avps_proto_ver = PROTO_VER;
+const double _3gpp2_avps_gen_date = GEN_DATE;
+
+/* The content of this file follows the same structure as dict_base_proto.c */
+
+#define CHECK_dict_new( _type, _data, _parent, _ref )                                     \
+{                                                                                         \
+    int _ret = fd_dict_new( fd_g_config->cnf_dict, (_type), (_data), (_parent), (_ref) ); \
+    if ( _ret != 0 && _ret != EEXIST )                                                    \
+       return _ret;                                                                       \
+}
+
+#define CHECK_dict_search( _type, _criteria, _what, _result )		\
+    CHECK_FCT(  fd_dict_search( fd_g_config->cnf_dict, (_type), (_criteria), (_what), (_result), ENOENT) );
+
+struct local_rules_definition {
+    struct dict_avp_request avp_vendor_plus_name;
+    enum rule_position	position;
+    int 			min;
+    int			max;
+};
+
+#define RULE_ORDER( _position ) ((((_position) == RULE_FIXED_HEAD) || ((_position) == RULE_FIXED_TAIL)) ? 1 : 0 )
+
+/* Attention! This version of the macro uses AVP_BY_NAME_AND_VENDOR, in contrast to most other copies! */
+#define PARSE_loc_rules( _rulearray, _parent) {                                                         \
+        int __ar;                                                                                       \
+        for (__ar=0; __ar < sizeof(_rulearray) / sizeof((_rulearray)[0]); __ar++) {                     \
+                struct dict_rule_data __data = { NULL,                                                  \
+                        (_rulearray)[__ar].position,                                                    \
+                        0,                                                                              \
+                        (_rulearray)[__ar].min,                                                         \
+                        (_rulearray)[__ar].max};                                                        \
+                __data.rule_order = RULE_ORDER(__data.rule_position);                                   \
+                CHECK_FCT(  fd_dict_search(                                                             \
+                        fd_g_config->cnf_dict,                                                          \
+                        DICT_AVP,                                                                       \
+                        AVP_BY_NAME_AND_VENDOR,                                                         \
+                        &(_rulearray)[__ar].avp_vendor_plus_name,                                       \
+                        &__data.rule_avp, 0 ) );                                                        \
+                if ( !__data.rule_avp ) {                                                               \
+                        TRACE_DEBUG(INFO, "AVP Not found: '%s'", (_rulearray)[__ar].avp_vendor_plus_name.avp_name);             \
+                        return ENOENT;                                                                  \
+                }                                                                                       \
+                {                                                                                       \
+                         int _ret = fd_dict_new( fd_g_config->cnf_dict, DICT_RULE, &(__data), (_parent), NULL ); \
+                         if ( _ret != 0 && _ret != EEXIST )      {                                      \
+                                TRACE_DEBUG(INFO, "Error on rule with AVP '%s'",                        \
+                                            (_rulearray)[__ar].avp_vendor_plus_name.avp_name);          \
+                                return EINVAL;                                                          \
+                         }                                                                              \
+                }                                                                                       \
+        }                                                                                               \
+}
+
+#define CHECK_vendor_new( _data ) { \
+        struct dict_object * vendor_found; \
+        if (fd_dict_search(fd_g_config->cnf_dict,DICT_VENDOR,VENDOR_BY_ID,&_data.vendor_id,&vendor_found,ENOENT) == ENOENT) { \
+                CHECK_FCT(fd_dict_new(fd_g_config->cnf_dict, DICT_VENDOR, &_data, NULL, NULL)); \
+        } \
+}
+
+#define enumval_def_u32( _val_, _str_ )		\
+    { _str_, 		{ .u32 = _val_ }}
+
+#define enumval_def_os( _len_, _val_, _str_ )				\
+    { _str_, 		{ .os = { .data = (unsigned char *)_val_, .len = _len_ }}}
+
+
+static int dict_3gpp2_avps_load_defs(char * conffile)
+{
+   TRACE_ENTRY("%p", conffile);
+	/* Application Section */
+	{
+		/* Create the vendors */		{
+			struct dict_vendor_data vendor_data = { 5535, "3GPP2" };
+			CHECK_dict_new(DICT_VENDOR, &vendor_data, NULL, NULL)
+		}
+	}
+
+
+   /* AVP section */
+   {
+		struct dict_object * Address_type;
+		struct dict_object * UTF8String_type;
+		struct dict_object * DiameterIdentity_type;
+		struct dict_object * DiameterURI_type;
+		struct dict_object * Time_type;
+		struct dict_object * IPFilterRule_type;
+
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "Address", &Address_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "UTF8String", &UTF8String_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "DiameterIdentity", &DiameterIdentity_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "DiameterURI", &DiameterURI_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "Time", &Time_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "IPFilterRule", &IPFilterRule_type);
+		/* 3GPP2-BSID */
+		{
+			struct dict_avp_data data = {
+				9010,	/* Code */
+				5535,	/* Vendor */
+				"3GPP2-BSID",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, UTF8String_type, NULL);
+		};
+
+	
+   }
+
+   /* Commands section */
+   {
+
+   }
+
+   return 0;
+}
+
+static int dict_3gpp2_avps_load_rules(char * conffile)
+{
+   /* Grouped AVP section */
+   {
+
+   }	
+
+   /* Commands section */
+   {
+
+   }
+
+   LOG_D( "Extension 'Dictionary definitions for 3gpp2_avps (None)' initialized");
+   return 0;
+}
+
+int dict_entry(char * conffile)
+{
+	dict_3gpp2_avps_load_defs(conffile);
+	return dict_3gpp2_avps_load_rules(conffile);
+}
+
+const char* dict_3gpp2_avps_proto_ver(char * conffile) {
+	return _3gpp2_avps_proto_ver;
+}
+
+const double dict_3gpp2_avps_gen_ts(char * conffile) {
+	return _3gpp2_avps_gen_date;
+}
+
+EXTENSION_ENTRY2("dict_3gpp2_avps", dict_3gpp2_avps_load_defs, dict_3gpp2_avps_load_rules);
+
+
+
diff --git a/extensions/dict_CreditControl/CMakeLists.txt b/extensions/dict_CreditControl/CMakeLists.txt
new file mode 100644
index 0000000..6ae7d43
--- /dev/null
+++ b/extensions/dict_CreditControl/CMakeLists.txt
@@ -0,0 +1,16 @@
+# The dict_CreditControl extension
+PROJECT("dict_CreditControl library generated by FdGen " C)
+
+# Compile as a module
+FD_ADD_EXTENSION(dict_CreditControl dict_CreditControl.c)
+
+
+####
+## INSTALL section ##
+
+INSTALL(TARGETS dict_CreditControl
+	LIBRARY DESTINATION ${INSTALL_EXTENSIONS_SUFFIX}
+COMPONENT freeDiameter-dictionary-CREDITCONTROL)
+
+
+
diff --git a/extensions/dict_CreditControl/CreditControl.did b/extensions/dict_CreditControl/CreditControl.did
new file mode 100644
index 0000000..668abaa
--- /dev/null
+++ b/extensions/dict_CreditControl/CreditControl.did
@@ -0,0 +1,5 @@
+dict_rfc4004_avps
+dict_rfc7155_avps
+dict_rfc5777_avps
+dict_rfc4006bis_avps
+dict_CreditControl
diff --git a/extensions/dict_CreditControl/dict_CreditControl.c b/extensions/dict_CreditControl/dict_CreditControl.c
new file mode 100644
index 0000000..3d3ba7c
--- /dev/null
+++ b/extensions/dict_CreditControl/dict_CreditControl.c
@@ -0,0 +1,286 @@
+/*
+* Copyright (c) 2017 Sprint
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*    http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+/****************
+ Generated By: fdtool enhancements to diafuzzer
+ License: same as freeDiameter
+****************/
+
+
+/* 
+ * Dictionary definitions of objects specified in CreditControl (rfc4006bis).
+ */
+#include <freeDiameter/extension.h>
+
+#define PROTO_VER "rfc4006bis"
+#define GEN_DATE  1506697121.72
+
+const char *creditcontrol_proto_ver = PROTO_VER;
+const double creditcontrol_gen_date = GEN_DATE;
+
+/* The content of this file follows the same structure as dict_base_proto.c */
+
+#define CHECK_dict_new( _type, _data, _parent, _ref )                                     \
+{                                                                                         \
+    int _ret = fd_dict_new( fd_g_config->cnf_dict, (_type), (_data), (_parent), (_ref) ); \
+    if ( _ret != 0 && _ret != EEXIST )                                                    \
+       return _ret;                                                                       \
+}
+
+#define CHECK_dict_search( _type, _criteria, _what, _result )		\
+    CHECK_FCT(  fd_dict_search( fd_g_config->cnf_dict, (_type), (_criteria), (_what), (_result), ENOENT) );
+
+struct local_rules_definition {
+    struct dict_avp_request avp_vendor_plus_name;
+    enum rule_position	position;
+    int 			min;
+    int			max;
+};
+
+#define RULE_ORDER( _position ) ((((_position) == RULE_FIXED_HEAD) || ((_position) == RULE_FIXED_TAIL)) ? 1 : 0 )
+
+/* Attention! This version of the macro uses AVP_BY_NAME_AND_VENDOR, in contrast to most other copies! */
+#define PARSE_loc_rules( _rulearray, _parent) {                                                         \
+        int __ar;                                                                                       \
+        for (__ar=0; __ar < sizeof(_rulearray) / sizeof((_rulearray)[0]); __ar++) {                     \
+                struct dict_rule_data __data = { NULL,                                                  \
+                        (_rulearray)[__ar].position,                                                    \
+                        0,                                                                              \
+                        (_rulearray)[__ar].min,                                                         \
+                        (_rulearray)[__ar].max};                                                        \
+                __data.rule_order = RULE_ORDER(__data.rule_position);                                   \
+                CHECK_FCT(  fd_dict_search(                                                             \
+                        fd_g_config->cnf_dict,                                                          \
+                        DICT_AVP,                                                                       \
+                        AVP_BY_NAME_AND_VENDOR,                                                         \
+                        &(_rulearray)[__ar].avp_vendor_plus_name,                                       \
+                        &__data.rule_avp, 0 ) );                                                        \
+                if ( !__data.rule_avp ) {                                                               \
+                        TRACE_DEBUG(INFO, "AVP Not found: '%s'", (_rulearray)[__ar].avp_vendor_plus_name.avp_name);             \
+                        return ENOENT;                                                                  \
+                }                                                                                       \
+                {                                                                                       \
+                         int _ret = fd_dict_new( fd_g_config->cnf_dict, DICT_RULE, &(__data), (_parent), NULL ); \
+                         if ( _ret != 0 && _ret != EEXIST )      {                                      \
+                                TRACE_DEBUG(INFO, "Error on rule with AVP '%s'",                        \
+                                            (_rulearray)[__ar].avp_vendor_plus_name.avp_name);          \
+                                return EINVAL;                                                          \
+                         }                                                                              \
+                }                                                                                       \
+        }                                                                                               \
+}
+
+#define CHECK_vendor_new( _data ) { \
+        struct dict_object * vendor_found; \
+        if (fd_dict_search(fd_g_config->cnf_dict,DICT_VENDOR,VENDOR_BY_ID,&_data.vendor_id,&vendor_found,ENOENT) == ENOENT) { \
+                CHECK_FCT(fd_dict_new(fd_g_config->cnf_dict, DICT_VENDOR, &_data, NULL, NULL)); \
+        } \
+}
+
+#define enumval_def_u32( _val_, _str_ )		\
+    { _str_, 		{ .u32 = _val_ }}
+
+#define enumval_def_os( _len_, _val_, _str_ )				\
+    { _str_, 		{ .os = { .data = (unsigned char *)_val_, .len = _len_ }}}
+
+
+static int dict_creditcontrol_load_defs(char * conffile)
+{
+   TRACE_ENTRY("%p", conffile);
+	struct dict_object * app_id4;
+
+	/* Application Section */
+	{
+	  {
+			struct dict_application_data data = { 4, "CreditControl" };
+			CHECK_dict_new( DICT_APPLICATION, &data, NULL, &app_id4)
+	  }
+	  /* Result codes */
+	  {
+			struct dict_object *type;
+			CHECK_dict_search(DICT_TYPE, TYPE_BY_NAME, "Enumerated(Result-Code)",&type);
+			struct dict_enumval_data        t_1 = { "is", { .u32=10 }};
+			struct dict_enumval_data        t_2 = { "Services", { .u32=3 }};
+			struct dict_enumval_data        t_3 = { "KS", { .u32=66251 }};
+
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_3, type, NULL);
+
+	  }
+	}
+
+
+   /* AVP section */
+   {
+		struct dict_object * Address_type;
+		struct dict_object * UTF8String_type;
+		struct dict_object * DiameterIdentity_type;
+		struct dict_object * DiameterURI_type;
+		struct dict_object * Time_type;
+		struct dict_object * IPFilterRule_type;
+
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "Address", &Address_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "UTF8String", &UTF8String_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "DiameterIdentity", &DiameterIdentity_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "DiameterURI", &DiameterURI_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "Time", &Time_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "IPFilterRule", &IPFilterRule_type);
+
+	
+   }
+
+   /* Commands section */
+   {
+		/* Credit-Control-Request */
+		{
+			struct dict_object* cmd;
+			struct dict_cmd_data data = {
+				272,	/* Code */
+				"Credit-Control-Request",	/* Name */
+				CMD_FLAG_REQUEST | CMD_FLAG_ERROR,	/* Fixed flags */
+				CMD_FLAG_REQUEST | CMD_FLAG_PROXIABLE,	/* Fixed flag values */
+			};
+
+			CHECK_dict_new( DICT_COMMAND, &data , app_id4, &cmd)
+		}
+		/* Credit-Control-Answer */
+		{
+			struct dict_object* cmd;
+			struct dict_cmd_data data = {
+				272,	/* Code */
+				"Credit-Control-Answer",	/* Name */
+				CMD_FLAG_REQUEST,	/* Fixed flags */
+				CMD_FLAG_PROXIABLE,	/* Fixed flag values */
+			};
+
+			CHECK_dict_new( DICT_COMMAND, &data , app_id4, &cmd)
+		}
+
+   }
+
+   return 0;
+}
+
+static int dict_creditcontrol_load_rules(char * conffile)
+{
+   /* Grouped AVP section */
+   {
+
+   }	
+
+   /* Commands section */
+   {
+	  /* Credit-Control-Request */
+	  {
+		struct dict_object* cmd;
+		CHECK_dict_search( DICT_COMMAND, CMD_BY_NAME, "Credit-Control-Request", &cmd)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 0, .avp_name = "Session-Id"}, RULE_FIXED_HEAD, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-Host"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-Realm"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Destination-Realm"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Auth-Application-Id"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Service-Context-Id"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "CC-Request-Type"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "CC-Request-Number"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Destination-Host"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "User-Name"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "CC-Sub-Session-Id"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Acct-Multi-Session-Id"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-State-Id"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Event-Timestamp"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Subscription-Id"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Subscription-Id-Extension"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Service-Identifier"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Termination-Cause"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Requested-Service-Unit"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Requested-Action"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Used-Service-Unit"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Multiple-Services-Indicator"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Multiple-Services-Credit-Control"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Service-Parameter-Info"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "CC-Correlation-Id"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "User-Equipment-Info"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "User-Equipment-Info-Extension"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Proxy-Info"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Route-Record"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules(rules, cmd);
+	  }
+	  /* Credit-Control-Answer */
+	  {
+		struct dict_object* cmd;
+		CHECK_dict_search( DICT_COMMAND, CMD_BY_NAME, "Credit-Control-Answer", &cmd)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 0, .avp_name = "Session-Id"}, RULE_FIXED_HEAD, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Result-Code"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-Host"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-Realm"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Auth-Application-Id"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "CC-Request-Type"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "CC-Request-Number"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "User-Name"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "CC-Session-Failover"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "CC-Sub-Session-Id"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Acct-Multi-Session-Id"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-State-Id"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Event-Timestamp"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Granted-Service-Unit"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Multiple-Services-Credit-Control"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Cost-Information"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Final-Unit-Indication"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "QoS-Final-Unit-Indication"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Check-Balance-Result"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Credit-Control-Failure-Handling"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Direct-Debiting-Failure-Handling"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Validity-Time"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Redirect-Host"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Redirect-Host-Usage"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Redirect-Max-Cache-Time"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Proxy-Info"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Route-Record"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Failed-AVP"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules(rules, cmd);
+	  }
+
+   }
+
+   LOG_D( "Extension 'Dictionary definitions for CreditControl (rfc4006bis)' initialized");
+   return 0;
+}
+
+int dict_entry(char * conffile)
+{
+	dict_creditcontrol_load_defs(conffile);
+	return dict_creditcontrol_load_rules(conffile);
+}
+
+const char* dict_creditcontrol_proto_ver(char * conffile) {
+	return creditcontrol_proto_ver;
+}
+
+const double dict_creditcontrol_gen_ts(char * conffile) {
+	return creditcontrol_gen_date;
+}
+
+EXTENSION_ENTRY2("dict_creditcontrol", dict_creditcontrol_load_defs, dict_creditcontrol_load_rules, "dict_rfc4006bis_avps", "dict_rfc7155_avps", "dict_rfc5777_avps");
+
+
+
diff --git a/extensions/dict_CxDx/CMakeLists.txt b/extensions/dict_CxDx/CMakeLists.txt
new file mode 100644
index 0000000..ea6c136
--- /dev/null
+++ b/extensions/dict_CxDx/CMakeLists.txt
@@ -0,0 +1,16 @@
+# The dict_CxDx extension
+PROJECT("dict_CxDx library generated by FdGen " C)
+
+# Compile as a module
+FD_ADD_EXTENSION(dict_CxDx dict_CxDx.c)
+
+
+####
+## INSTALL section ##
+
+INSTALL(TARGETS dict_CxDx
+	LIBRARY DESTINATION ${INSTALL_EXTENSIONS_SUFFIX}
+COMPONENT freeDiameter-dictionary-CXDX)
+
+
+
diff --git a/extensions/dict_CxDx/CxDx.did b/extensions/dict_CxDx/CxDx.did
new file mode 100644
index 0000000..c6407fb
--- /dev/null
+++ b/extensions/dict_CxDx/CxDx.did
@@ -0,0 +1,9 @@
+dict_ts29229_avps
+dict_rfc7683_avps
+dict_etsi283034_avps
+dict_rfc4590_avps
+dict_draftload_avps
+dict_rfc7944_avps
+dict_rfc4004_avps
+dict_rfc7155_avps
+dict_CxDx
diff --git a/extensions/dict_CxDx/dict_CxDx.c b/extensions/dict_CxDx/dict_CxDx.c
new file mode 100644
index 0000000..8fc87f2
--- /dev/null
+++ b/extensions/dict_CxDx/dict_CxDx.c
@@ -0,0 +1,656 @@
+/*
+* Copyright (c) 2017 Sprint
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*    http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+/****************
+ Generated By: fdtool enhancements to diafuzzer
+ License: same as freeDiameter
+****************/
+
+
+/* 
+ * Dictionary definitions of objects specified in CxDx (e10).
+ */
+#include <freeDiameter/extension.h>
+
+#define PROTO_VER "e10"
+#define GEN_DATE  1506697212.25
+
+const char *cxdx_proto_ver = PROTO_VER;
+const double cxdx_gen_date = GEN_DATE;
+
+/* The content of this file follows the same structure as dict_base_proto.c */
+
+#define CHECK_dict_new( _type, _data, _parent, _ref )                                     \
+{                                                                                         \
+    int _ret = fd_dict_new( fd_g_config->cnf_dict, (_type), (_data), (_parent), (_ref) ); \
+    if ( _ret != 0 && _ret != EEXIST )                                                    \
+       return _ret;                                                                       \
+}
+
+#define CHECK_dict_search( _type, _criteria, _what, _result )		\
+    CHECK_FCT(  fd_dict_search( fd_g_config->cnf_dict, (_type), (_criteria), (_what), (_result), ENOENT) );
+
+struct local_rules_definition {
+    struct dict_avp_request avp_vendor_plus_name;
+    enum rule_position	position;
+    int 			min;
+    int			max;
+};
+
+#define RULE_ORDER( _position ) ((((_position) == RULE_FIXED_HEAD) || ((_position) == RULE_FIXED_TAIL)) ? 1 : 0 )
+
+/* Attention! This version of the macro uses AVP_BY_NAME_AND_VENDOR, in contrast to most other copies! */
+#define PARSE_loc_rules( _rulearray, _parent) {                                                         \
+        int __ar;                                                                                       \
+        for (__ar=0; __ar < sizeof(_rulearray) / sizeof((_rulearray)[0]); __ar++) {                     \
+                struct dict_rule_data __data = { NULL,                                                  \
+                        (_rulearray)[__ar].position,                                                    \
+                        0,                                                                              \
+                        (_rulearray)[__ar].min,                                                         \
+                        (_rulearray)[__ar].max};                                                        \
+                __data.rule_order = RULE_ORDER(__data.rule_position);                                   \
+                CHECK_FCT(  fd_dict_search(                                                             \
+                        fd_g_config->cnf_dict,                                                          \
+                        DICT_AVP,                                                                       \
+                        AVP_BY_NAME_AND_VENDOR,                                                         \
+                        &(_rulearray)[__ar].avp_vendor_plus_name,                                       \
+                        &__data.rule_avp, 0 ) );                                                        \
+                if ( !__data.rule_avp ) {                                                               \
+                        TRACE_DEBUG(INFO, "AVP Not found: '%s'", (_rulearray)[__ar].avp_vendor_plus_name.avp_name);             \
+                        return ENOENT;                                                                  \
+                }                                                                                       \
+                {                                                                                       \
+                         int _ret = fd_dict_new( fd_g_config->cnf_dict, DICT_RULE, &(__data), (_parent), NULL ); \
+                         if ( _ret != 0 && _ret != EEXIST )      {                                      \
+                                TRACE_DEBUG(INFO, "Error on rule with AVP '%s'",                        \
+                                            (_rulearray)[__ar].avp_vendor_plus_name.avp_name);          \
+                                return EINVAL;                                                          \
+                         }                                                                              \
+                }                                                                                       \
+        }                                                                                               \
+}
+
+#define CHECK_vendor_new( _data ) { \
+        struct dict_object * vendor_found; \
+        if (fd_dict_search(fd_g_config->cnf_dict,DICT_VENDOR,VENDOR_BY_ID,&_data.vendor_id,&vendor_found,ENOENT) == ENOENT) { \
+                CHECK_FCT(fd_dict_new(fd_g_config->cnf_dict, DICT_VENDOR, &_data, NULL, NULL)); \
+        } \
+}
+
+#define enumval_def_u32( _val_, _str_ )		\
+    { _str_, 		{ .u32 = _val_ }}
+
+#define enumval_def_os( _len_, _val_, _str_ )				\
+    { _str_, 		{ .os = { .data = (unsigned char *)_val_, .len = _len_ }}}
+
+
+static int dict_cxdx_load_defs(char * conffile)
+{
+   TRACE_ENTRY("%p", conffile);
+	struct dict_object * app_id16777216;
+
+	/* Application Section */
+	{
+	  {
+			struct dict_object * vendor;
+			CHECK_dict_search(DICT_VENDOR, VENDOR_BY_NAME, "3GPP", &vendor)
+			struct dict_application_data data = { 16777216, "CxDx" };
+			CHECK_dict_new( DICT_APPLICATION, &data, vendor, &app_id16777216)
+	  }
+	  /* Result codes */
+	  {
+			struct dict_object *type;
+			CHECK_dict_search(DICT_TYPE, TYPE_BY_NAME, "Enumerated(Result-Code)",&type);
+			struct dict_enumval_data        t_1 = { "Discovery_of_supported_interface_versions", { .u32=1 }};
+			struct dict_enumval_data        t_2 = { "Supported_features", { .u32=2 }};
+			struct dict_enumval_data        t_3 = { "Interface_versions", { .u32=3 }};
+			struct dict_enumval_data        t_4 = { "Application_ID_value", { .u32=4 }};
+			struct dict_enumval_data        t_5 = { "Special_Requirements", { .u32=7 }};
+
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_3, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_4, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_5, type, NULL);
+
+	  }
+	}
+
+
+   /* AVP section */
+   {
+		struct dict_object * Address_type;
+		struct dict_object * UTF8String_type;
+		struct dict_object * DiameterIdentity_type;
+		struct dict_object * DiameterURI_type;
+		struct dict_object * Time_type;
+		struct dict_object * IPFilterRule_type;
+
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "Address", &Address_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "UTF8String", &UTF8String_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "DiameterIdentity", &DiameterIdentity_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "DiameterURI", &DiameterURI_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "Time", &Time_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "IPFilterRule", &IPFilterRule_type);
+
+	
+   }
+
+   /* Commands section */
+   {
+		/* User-Authorization-Request */
+		{
+			struct dict_object* cmd;
+			struct dict_cmd_data data = {
+				300,	/* Code */
+				"User-Authorization-Request",	/* Name */
+				CMD_FLAG_REQUEST | CMD_FLAG_ERROR,	/* Fixed flags */
+				CMD_FLAG_REQUEST | CMD_FLAG_PROXIABLE,	/* Fixed flag values */
+			};
+
+			CHECK_dict_new( DICT_COMMAND, &data , app_id16777216, &cmd)
+		}
+		/* User-Authorization-Answer */
+		{
+			struct dict_object* cmd;
+			struct dict_cmd_data data = {
+				300,	/* Code */
+				"User-Authorization-Answer",	/* Name */
+				CMD_FLAG_REQUEST,	/* Fixed flags */
+				CMD_FLAG_PROXIABLE,	/* Fixed flag values */
+			};
+
+			CHECK_dict_new( DICT_COMMAND, &data , app_id16777216, &cmd)
+		}
+		/* Server-Assignment-Request */
+		{
+			struct dict_object* cmd;
+			struct dict_cmd_data data = {
+				301,	/* Code */
+				"Server-Assignment-Request",	/* Name */
+				CMD_FLAG_REQUEST | CMD_FLAG_ERROR,	/* Fixed flags */
+				CMD_FLAG_REQUEST | CMD_FLAG_PROXIABLE,	/* Fixed flag values */
+			};
+
+			CHECK_dict_new( DICT_COMMAND, &data , app_id16777216, &cmd)
+		}
+		/* Server-Assignment-Answer */
+		{
+			struct dict_object* cmd;
+			struct dict_cmd_data data = {
+				301,	/* Code */
+				"Server-Assignment-Answer",	/* Name */
+				CMD_FLAG_REQUEST,	/* Fixed flags */
+				CMD_FLAG_PROXIABLE,	/* Fixed flag values */
+			};
+
+			CHECK_dict_new( DICT_COMMAND, &data , app_id16777216, &cmd)
+		}
+		/* Location-Info-Request */
+		{
+			struct dict_object* cmd;
+			struct dict_cmd_data data = {
+				302,	/* Code */
+				"Location-Info-Request",	/* Name */
+				CMD_FLAG_REQUEST | CMD_FLAG_ERROR,	/* Fixed flags */
+				CMD_FLAG_REQUEST | CMD_FLAG_PROXIABLE,	/* Fixed flag values */
+			};
+
+			CHECK_dict_new( DICT_COMMAND, &data , app_id16777216, &cmd)
+		}
+		/* Location-Info-Answer */
+		{
+			struct dict_object* cmd;
+			struct dict_cmd_data data = {
+				302,	/* Code */
+				"Location-Info-Answer",	/* Name */
+				CMD_FLAG_REQUEST,	/* Fixed flags */
+				CMD_FLAG_PROXIABLE,	/* Fixed flag values */
+			};
+
+			CHECK_dict_new( DICT_COMMAND, &data , app_id16777216, &cmd)
+		}
+		/* Multimedia-Auth-Request */
+		{
+			struct dict_object* cmd;
+			struct dict_cmd_data data = {
+				303,	/* Code */
+				"Multimedia-Auth-Request",	/* Name */
+				CMD_FLAG_REQUEST | CMD_FLAG_ERROR,	/* Fixed flags */
+				CMD_FLAG_REQUEST | CMD_FLAG_PROXIABLE,	/* Fixed flag values */
+			};
+
+			CHECK_dict_new( DICT_COMMAND, &data , app_id16777216, &cmd)
+		}
+		/* Multimedia-Auth-Answer */
+		{
+			struct dict_object* cmd;
+			struct dict_cmd_data data = {
+				303,	/* Code */
+				"Multimedia-Auth-Answer",	/* Name */
+				CMD_FLAG_REQUEST,	/* Fixed flags */
+				CMD_FLAG_PROXIABLE,	/* Fixed flag values */
+			};
+
+			CHECK_dict_new( DICT_COMMAND, &data , app_id16777216, &cmd)
+		}
+		/* Registration-Termination-Request */
+		{
+			struct dict_object* cmd;
+			struct dict_cmd_data data = {
+				304,	/* Code */
+				"Registration-Termination-Request",	/* Name */
+				CMD_FLAG_REQUEST | CMD_FLAG_ERROR,	/* Fixed flags */
+				CMD_FLAG_REQUEST | CMD_FLAG_PROXIABLE,	/* Fixed flag values */
+			};
+
+			CHECK_dict_new( DICT_COMMAND, &data , app_id16777216, &cmd)
+		}
+		/* Registration-Termination-Answer */
+		{
+			struct dict_object* cmd;
+			struct dict_cmd_data data = {
+				304,	/* Code */
+				"Registration-Termination-Answer",	/* Name */
+				CMD_FLAG_REQUEST,	/* Fixed flags */
+				CMD_FLAG_PROXIABLE,	/* Fixed flag values */
+			};
+
+			CHECK_dict_new( DICT_COMMAND, &data , app_id16777216, &cmd)
+		}
+		/* Push-Profile-Request */
+		{
+			struct dict_object* cmd;
+			struct dict_cmd_data data = {
+				305,	/* Code */
+				"Push-Profile-Request",	/* Name */
+				CMD_FLAG_REQUEST | CMD_FLAG_ERROR,	/* Fixed flags */
+				CMD_FLAG_REQUEST | CMD_FLAG_PROXIABLE,	/* Fixed flag values */
+			};
+
+			CHECK_dict_new( DICT_COMMAND, &data , app_id16777216, &cmd)
+		}
+		/* Push-Profile-Answer */
+		{
+			struct dict_object* cmd;
+			struct dict_cmd_data data = {
+				305,	/* Code */
+				"Push-Profile-Answer",	/* Name */
+				CMD_FLAG_REQUEST,	/* Fixed flags */
+				CMD_FLAG_PROXIABLE,	/* Fixed flag values */
+			};
+
+			CHECK_dict_new( DICT_COMMAND, &data , app_id16777216, &cmd)
+		}
+
+   }
+
+   return 0;
+}
+
+static int dict_cxdx_load_rules(char * conffile)
+{
+   /* Grouped AVP section */
+   {
+
+   }	
+
+   /* Commands section */
+   {
+	  /* User-Authorization-Request */
+	  {
+		struct dict_object* cmd;
+		CHECK_dict_search( DICT_COMMAND, CMD_BY_NAME, "User-Authorization-Request", &cmd)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 0, .avp_name = "Session-Id"}, RULE_FIXED_HEAD, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "DRMP"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Vendor-Specific-Application-Id"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Auth-Session-State"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-Host"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-Realm"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Destination-Host"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Destination-Realm"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "User-Name"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "OC-Supported-Features"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Supported-Features"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Public-Identity"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Visited-Network-Identifier"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "User-Authorization-Type"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "UAR-Flags"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Proxy-Info"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Route-Record"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules(rules, cmd);
+	  }
+	  /* User-Authorization-Answer */
+	  {
+		struct dict_object* cmd;
+		CHECK_dict_search( DICT_COMMAND, CMD_BY_NAME, "User-Authorization-Answer", &cmd)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 0, .avp_name = "Session-Id"}, RULE_FIXED_HEAD, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "DRMP"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Vendor-Specific-Application-Id"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Result-Code"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Experimental-Result"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Auth-Session-State"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-Host"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-Realm"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "OC-Supported-Features"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "OC-OLR"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Load"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Supported-Features"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Server-Name"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Server-Capabilities"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Failed-AVP"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Proxy-Info"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Route-Record"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules(rules, cmd);
+	  }
+	  /* Server-Assignment-Request */
+	  {
+		struct dict_object* cmd;
+		CHECK_dict_search( DICT_COMMAND, CMD_BY_NAME, "Server-Assignment-Request", &cmd)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 0, .avp_name = "Session-Id"}, RULE_FIXED_HEAD, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "DRMP"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Vendor-Specific-Application-Id"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Auth-Session-State"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-Host"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-Realm"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Destination-Host"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Destination-Realm"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "User-Name"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "OC-Supported-Features"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Supported-Features"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Public-Identity"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Wildcarded-Public-Identity"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Server-Name"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Server-Assignment-Type"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "User-Data-Already-Available"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "SCSCF-Restoration-Info"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Multiple-Registration-Indication"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Session-Priority"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "SAR-Flags"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Proxy-Info"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Route-Record"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules(rules, cmd);
+	  }
+	  /* Server-Assignment-Answer */
+	  {
+		struct dict_object* cmd;
+		CHECK_dict_search( DICT_COMMAND, CMD_BY_NAME, "Server-Assignment-Answer", &cmd)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 0, .avp_name = "Session-Id"}, RULE_FIXED_HEAD, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "DRMP"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Vendor-Specific-Application-Id"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Result-Code"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Experimental-Result"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Auth-Session-State"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-Host"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-Realm"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "User-Name"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "OC-Supported-Features"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "OC-OLR"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Load"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Supported-Features"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "User-Data"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Charging-Information"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Associated-Identities"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Loose-Route-Indication"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "SCSCF-Restoration-Info"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Associated-Registered-Identities"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Server-Name"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Wildcarded-Public-Identity"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Priviledged-Sender-Indication"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Allowed-WAF-WWSF-Identities"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Failed-AVP"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Proxy-Info"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Route-Record"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules(rules, cmd);
+	  }
+	  /* Location-Info-Request */
+	  {
+		struct dict_object* cmd;
+		CHECK_dict_search( DICT_COMMAND, CMD_BY_NAME, "Location-Info-Request", &cmd)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 0, .avp_name = "Session-Id"}, RULE_FIXED_HEAD, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "DRMP"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Vendor-Specific-Application-Id"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Auth-Session-State"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-Host"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-Realm"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Destination-Host"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Destination-Realm"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Originating-Request"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "OC-Supported-Features"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Supported-Features"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Public-Identity"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "User-Authorization-Type"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Session-Priority"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Proxy-Info"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Route-Record"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules(rules, cmd);
+	  }
+	  /* Location-Info-Answer */
+	  {
+		struct dict_object* cmd;
+		CHECK_dict_search( DICT_COMMAND, CMD_BY_NAME, "Location-Info-Answer", &cmd)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 0, .avp_name = "Session-Id"}, RULE_FIXED_HEAD, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "DRMP"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Vendor-Specific-Application-Id"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Result-Code"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Experimental-Result"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Auth-Session-State"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-Host"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-Realm"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "OC-Supported-Features"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "OC-OLR"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Load"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Supported-Features"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Server-Name"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Server-Capabilities"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Wildcarded-Public-Identity"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "LIA-Flags"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Failed-AVP"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Proxy-Info"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Route-Record"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules(rules, cmd);
+	  }
+	  /* Multimedia-Auth-Request */
+	  {
+		struct dict_object* cmd;
+		CHECK_dict_search( DICT_COMMAND, CMD_BY_NAME, "Multimedia-Auth-Request", &cmd)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 0, .avp_name = "Session-Id"}, RULE_FIXED_HEAD, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "DRMP"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Vendor-Specific-Application-Id"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Auth-Session-State"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-Host"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-Realm"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Destination-Realm"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Destination-Host"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "User-Name"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "OC-Supported-Features"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Supported-Features"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Public-Identity"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "SIP-Auth-Data-Item"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "SIP-Number-Auth-Items"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Server-Name"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Proxy-Info"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Route-Record"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules(rules, cmd);
+	  }
+	  /* Multimedia-Auth-Answer */
+	  {
+		struct dict_object* cmd;
+		CHECK_dict_search( DICT_COMMAND, CMD_BY_NAME, "Multimedia-Auth-Answer", &cmd)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 0, .avp_name = "Session-Id"}, RULE_FIXED_HEAD, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "DRMP"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Vendor-Specific-Application-Id"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Result-Code"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Experimental-Result"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Auth-Session-State"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-Host"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-Realm"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "User-Name"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "OC-Supported-Features"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "OC-OLR"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Load"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Supported-Features"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Public-Identity"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "SIP-Number-Auth-Items"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "SIP-Auth-Data-Item"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Failed-AVP"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Proxy-Info"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Route-Record"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules(rules, cmd);
+	  }
+	  /* Registration-Termination-Request */
+	  {
+		struct dict_object* cmd;
+		CHECK_dict_search( DICT_COMMAND, CMD_BY_NAME, "Registration-Termination-Request", &cmd)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 0, .avp_name = "Session-Id"}, RULE_FIXED_HEAD, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "DRMP"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Vendor-Specific-Application-Id"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Auth-Session-State"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-Host"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-Realm"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Destination-Host"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Destination-Realm"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "User-Name"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Associated-Identities"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Supported-Features"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Public-Identity"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Deregistration-Reason"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Proxy-Info"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Route-Record"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules(rules, cmd);
+	  }
+	  /* Registration-Termination-Answer */
+	  {
+		struct dict_object* cmd;
+		CHECK_dict_search( DICT_COMMAND, CMD_BY_NAME, "Registration-Termination-Answer", &cmd)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 0, .avp_name = "Session-Id"}, RULE_FIXED_HEAD, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Session-Id"}, RULE_FIXED_HEAD, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "DRMP"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Vendor-Specific-Application-Id"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Result-Code"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Experimental-Result"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Auth-Session-State"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-Host"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-Realm"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Associated-Identities"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Supported-Features"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Identity-with-Emergency-Registration"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Failed-AVP"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Proxy-Info"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Route-Record"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules(rules, cmd);
+	  }
+	  /* Push-Profile-Request */
+	  {
+		struct dict_object* cmd;
+		CHECK_dict_search( DICT_COMMAND, CMD_BY_NAME, "Push-Profile-Request", &cmd)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 0, .avp_name = "Session-Id"}, RULE_FIXED_HEAD, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "DRMP"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Vendor-Specific-Application-Id"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Auth-Session-State"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-Host"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-Realm"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Destination-Host"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Destination-Realm"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "User-Name"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Supported-Features"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "User-Data"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Charging-Information"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "SIP-Auth-Data-Item"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Allowed-WAF-WWSF-Identities"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Proxy-Info"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Route-Record"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules(rules, cmd);
+	  }
+	  /* Push-Profile-Answer */
+	  {
+		struct dict_object* cmd;
+		CHECK_dict_search( DICT_COMMAND, CMD_BY_NAME, "Push-Profile-Answer", &cmd)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 0, .avp_name = "Session-Id"}, RULE_FIXED_HEAD, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "DRMP"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Vendor-Specific-Application-Id"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Result-Code"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Experimental-Result"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Auth-Session-State"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-Host"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-Realm"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Supported-Features"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Failed-AVP"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Proxy-Info"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Route-Record"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules(rules, cmd);
+	  }
+
+   }
+
+   LOG_D( "Extension 'Dictionary definitions for CxDx (e10)' initialized");
+   return 0;
+}
+
+int dict_entry(char * conffile)
+{
+	dict_cxdx_load_defs(conffile);
+	return dict_cxdx_load_rules(conffile);
+}
+
+const char* dict_cxdx_proto_ver(char * conffile) {
+	return cxdx_proto_ver;
+}
+
+const double dict_cxdx_gen_ts(char * conffile) {
+	return cxdx_gen_date;
+}
+
+EXTENSION_ENTRY2("dict_cxdx", dict_cxdx_load_defs, dict_cxdx_load_rules, "dict_ts29229_avps", "dict_draftload_avps", "dict_rfc4590_avps", "dict_rfc7683_avps", "dict_rfc7155_avps", "dict_etsi283034_avps", "dict_rfc7944_avps");
+
+
+
diff --git a/extensions/dict_Gx/CMakeLists.txt b/extensions/dict_Gx/CMakeLists.txt
new file mode 100644
index 0000000..e04526e
--- /dev/null
+++ b/extensions/dict_Gx/CMakeLists.txt
@@ -0,0 +1,16 @@
+# The dict_Gx extension
+PROJECT("dict_Gx library generated by FdGen " C)
+
+# Compile as a module
+FD_ADD_EXTENSION(dict_Gx dict_Gx.c)
+
+
+####
+## INSTALL section ##
+
+INSTALL(TARGETS dict_Gx
+	LIBRARY DESTINATION ${INSTALL_EXTENSIONS_SUFFIX}
+COMPONENT freeDiameter-dictionary-GX)
+
+
+
diff --git a/extensions/dict_Gx/Gx.did b/extensions/dict_Gx/Gx.did
new file mode 100644
index 0000000..33d3e5f
--- /dev/null
+++ b/extensions/dict_Gx/Gx.did
@@ -0,0 +1,39 @@
+dict_rfc6942_avps
+dict_ts29468_avps
+dict_ts29154_avps
+dict_ts29214_avps
+dict_ts29215_avps
+dict_ts29217_avps
+dict_3gpp2_avps
+dict_ts29343_avps
+dict_ts29338_avps
+dict_ts29128_avps
+dict_ts29344_avps
+dict_ts29345_avps
+dict_ts32299_avps
+dict_rfc6734_avps
+dict_rfc5778_avps
+dict_rfc5580_avps
+dict_rfc4072_avps
+dict_ts29273_avps
+dict_ts29173_avps
+dict_ts29337_avps
+dict_etsi283034_avps
+dict_rfc4590_avps
+dict_ts29229_avps
+dict_draftload_avps
+dict_ts29329_avps
+dict_ts29368_avps
+dict_ts29336_avps
+dict_ts29061_avps
+dict_rfc5447_avps
+dict_ts29272_avps
+dict_rfc7683_avps
+dict_rfc7944_avps
+dict_ts29212_avps
+dict_CreditControl
+dict_rfc4004_avps
+dict_rfc7155_avps
+dict_rfc5777_avps
+dict_rfc4006bis_avps
+dict_Gx
diff --git a/extensions/dict_Gx/dict_Gx.c b/extensions/dict_Gx/dict_Gx.c
new file mode 100644
index 0000000..c0f5990
--- /dev/null
+++ b/extensions/dict_Gx/dict_Gx.c
@@ -0,0 +1,437 @@
+/*
+* Copyright (c) 2017 Sprint
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*    http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+/****************
+ Generated By: fdtool enhancements to diafuzzer
+ License: same as freeDiameter
+****************/
+
+
+/* 
+ * Dictionary definitions of objects specified in Gx (e30).
+ */
+#include <freeDiameter/extension.h>
+
+#define PROTO_VER "e30"
+#define GEN_DATE  1506697205.07
+
+const char *gx_proto_ver = PROTO_VER;
+const double gx_gen_date = GEN_DATE;
+
+/* The content of this file follows the same structure as dict_base_proto.c */
+
+#define CHECK_dict_new( _type, _data, _parent, _ref )                                     \
+{                                                                                         \
+    int _ret = fd_dict_new( fd_g_config->cnf_dict, (_type), (_data), (_parent), (_ref) ); \
+    if ( _ret != 0 && _ret != EEXIST )                                                    \
+       return _ret;                                                                       \
+}
+
+#define CHECK_dict_search( _type, _criteria, _what, _result )		\
+    CHECK_FCT(  fd_dict_search( fd_g_config->cnf_dict, (_type), (_criteria), (_what), (_result), ENOENT) );
+
+struct local_rules_definition {
+    struct dict_avp_request avp_vendor_plus_name;
+    enum rule_position	position;
+    int 			min;
+    int			max;
+};
+
+#define RULE_ORDER( _position ) ((((_position) == RULE_FIXED_HEAD) || ((_position) == RULE_FIXED_TAIL)) ? 1 : 0 )
+
+/* Attention! This version of the macro uses AVP_BY_NAME_AND_VENDOR, in contrast to most other copies! */
+#define PARSE_loc_rules( _rulearray, _parent) {                                                         \
+        int __ar;                                                                                       \
+        for (__ar=0; __ar < sizeof(_rulearray) / sizeof((_rulearray)[0]); __ar++) {                     \
+                struct dict_rule_data __data = { NULL,                                                  \
+                        (_rulearray)[__ar].position,                                                    \
+                        0,                                                                              \
+                        (_rulearray)[__ar].min,                                                         \
+                        (_rulearray)[__ar].max};                                                        \
+                __data.rule_order = RULE_ORDER(__data.rule_position);                                   \
+                CHECK_FCT(  fd_dict_search(                                                             \
+                        fd_g_config->cnf_dict,                                                          \
+                        DICT_AVP,                                                                       \
+                        AVP_BY_NAME_AND_VENDOR,                                                         \
+                        &(_rulearray)[__ar].avp_vendor_plus_name,                                       \
+                        &__data.rule_avp, 0 ) );                                                        \
+                if ( !__data.rule_avp ) {                                                               \
+                        TRACE_DEBUG(INFO, "AVP Not found: '%s'", (_rulearray)[__ar].avp_vendor_plus_name.avp_name);             \
+                        return ENOENT;                                                                  \
+                }                                                                                       \
+                {                                                                                       \
+                         int _ret = fd_dict_new( fd_g_config->cnf_dict, DICT_RULE, &(__data), (_parent), NULL ); \
+                         if ( _ret != 0 && _ret != EEXIST )      {                                      \
+                                TRACE_DEBUG(INFO, "Error on rule with AVP '%s'",                        \
+                                            (_rulearray)[__ar].avp_vendor_plus_name.avp_name);          \
+                                return EINVAL;                                                          \
+                         }                                                                              \
+                }                                                                                       \
+        }                                                                                               \
+}
+
+#define CHECK_vendor_new( _data ) { \
+        struct dict_object * vendor_found; \
+        if (fd_dict_search(fd_g_config->cnf_dict,DICT_VENDOR,VENDOR_BY_ID,&_data.vendor_id,&vendor_found,ENOENT) == ENOENT) { \
+                CHECK_FCT(fd_dict_new(fd_g_config->cnf_dict, DICT_VENDOR, &_data, NULL, NULL)); \
+        } \
+}
+
+#define enumval_def_u32( _val_, _str_ )		\
+    { _str_, 		{ .u32 = _val_ }}
+
+#define enumval_def_os( _len_, _val_, _str_ )				\
+    { _str_, 		{ .os = { .data = (unsigned char *)_val_, .len = _len_ }}}
+
+
+static int dict_gx_load_defs(char * conffile)
+{
+   TRACE_ENTRY("%p", conffile);
+	struct dict_object * app_id16777224;
+
+	/* Application Section */
+	{
+	  {
+			struct dict_object * vendor;
+			CHECK_dict_search(DICT_VENDOR, VENDOR_BY_NAME, "3GPP", &vendor)
+			struct dict_application_data data = { 16777224, "Gx" };
+			CHECK_dict_new( DICT_APPLICATION, &data, vendor, &app_id16777224)
+	  }
+	  /* Result codes */
+	  {
+			struct dict_object *type;
+			CHECK_dict_search(DICT_TYPE, TYPE_BY_NAME, "Enumerated(Result-Code)",&type);
+			struct dict_enumval_data        t_1 = { "DIAMETER_USER_UNKNOWN", { .u32=5030 }};
+			struct dict_enumval_data        t_2 = { "DIAMETER_ERROR_LATE_OVERLAPPING_REQUEST", { .u32=5453 }};
+			struct dict_enumval_data        t_3 = { "DIAMETER_ERROR_TIMED_OUT_REQUEST", { .u32=5454 }};
+			struct dict_enumval_data        t_4 = { "DIAMETER_ERROR_INITIAL_PARAMETERS", { .u32=5140 }};
+			struct dict_enumval_data        t_5 = { "DIAMETER_ERROR_TRIGGER_EVENT", { .u32=5141 }};
+			struct dict_enumval_data        t_6 = { "DIAMETER_PCC_RULE_EVENT", { .u32=5142 }};
+			struct dict_enumval_data        t_7 = { "DIAMETER_ERROR_BEARER_NOT_AUTHORIZED", { .u32=5143 }};
+			struct dict_enumval_data        t_8 = { "DIAMETER_ERROR_TRAFFIC_MAPPING_INFO_REJECTED", { .u32=5144 }};
+			struct dict_enumval_data        t_9 = { "DIAMETER_ERROR_CONFLICTING_REQUEST", { .u32=5147 }};
+			struct dict_enumval_data        t_10 = { "DIAMETER_ADC_RULE_EVENT", { .u32=5148 }};
+			struct dict_enumval_data        t_11 = { "DIAMETER_ERROR_NBIFOM_NOT_AUTHORIZED", { .u32=5149 }};
+			struct dict_enumval_data        t_12 = { "DIAMETER_PCC_BEARER_EVENT", { .u32=4141 }};
+			struct dict_enumval_data        t_13 = { "DIAMETER_AN_GW_FAILED", { .u32=4143 }};
+			struct dict_enumval_data        t_14 = { "DIAMETER_PENDING_TRANSACTION", { .u32=4144 }};
+
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_3, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_4, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_5, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_6, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_7, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_8, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_9, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_10, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_11, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_12, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_13, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_14, type, NULL);
+
+	  }
+	}
+
+
+   /* AVP section */
+   {
+		struct dict_object * Address_type;
+		struct dict_object * UTF8String_type;
+		struct dict_object * DiameterIdentity_type;
+		struct dict_object * DiameterURI_type;
+		struct dict_object * Time_type;
+		struct dict_object * IPFilterRule_type;
+
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "Address", &Address_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "UTF8String", &UTF8String_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "DiameterIdentity", &DiameterIdentity_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "DiameterURI", &DiameterURI_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "Time", &Time_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "IPFilterRule", &IPFilterRule_type);
+
+	
+   }
+
+   /* Commands section */
+   {
+
+   }
+
+   return 0;
+}
+
+static int dict_gx_load_rules(char * conffile)
+{
+   /* Grouped AVP section */
+   {
+
+   }	
+
+   /* Commands section */
+   {
+	  /* Credit-Control-Request */
+	  {
+		struct dict_object* cmd;
+		CHECK_dict_search( DICT_COMMAND, CMD_BY_NAME, "Credit-Control-Request", &cmd)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 0, .avp_name = "Session-Id"}, RULE_FIXED_HEAD, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "DRMP"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Auth-Application-Id"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-Host"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-Realm"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Destination-Realm"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "CC-Request-Type"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "CC-Request-Number"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Credit-Management-Status"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Destination-Host"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-State-Id"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Subscription-Id"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "OC-Supported-Features"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Supported-Features"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "TDF-Information"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Network-Request-Support"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Packet-Filter-Information"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Packet-Filter-Operation"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Bearer-Identifier"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Bearer-Operation"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Dynamic-Address-Flag"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Dynamic-Address-Flag-Extension"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "PDN-Connection-Charging-ID"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Framed-IP-Address"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Framed-IPv6-Prefix"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "IP-CAN-Type"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "3GPP-RAT-Type"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "AN-Trusted"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "RAT-Type"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Termination-Cause"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "User-Equipment-Info"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "QoS-Information"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "QoS-Negotiation"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "QoS-Upgrade"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Default-EPS-Bearer-QoS"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Default-QoS-Information"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "AN-GW-Address"}, RULE_OPTIONAL, 0, 2 },
+			{ { .avp_vendor = 10415, .avp_name = "AN-GW-Status"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "3GPP-SGSN-MCC-MNC"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "3GPP-SGSN-Address"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "3GPP-SGSN-Ipv6-Address"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "3GPP-GGSN-Address"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "3GPP-GGSN-Ipv6-Address"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "3GPP-Selection-Mode"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "RAI"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "3GPP-User-Location-Info"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Fixed-User-Location-Info"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "User-Location-Info-Time"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "User-CSG-Information"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "TWAN-Identifier"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "3GPP-MS-TimeZone"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "RAN-NAS-Release-Cause"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "3GPP-Charging-Characteristics"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Called-Station-Id"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "PDN-Connection-ID"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Bearer-Usage"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Online"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Offline"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "TFT-Packet-Filter-Information"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Charging-Rule-Report"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Application-Detection-Information"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Event-Trigger"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Event-Report-Indication"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Access-Network-Charging-Address"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Access-Network-Charging-Identifier-Gx"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "CoA-Information"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Usage-Monitoring-Information"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "NBIFOM-Support"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "NBIFOM-Mode"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Default-Access"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Origination-Time-Stamp"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Maximum-Wait-Time"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Access-Availability-Change-Reason"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Routing-Rule-Install"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Routing-Rule-Remove"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "HeNB-Local-IP-Address"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "UE-Local-IP-Address"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "UDP-Source-Port"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Presence-Reporting-Area-Information"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 13019, .avp_name = "Logical-Access-Id"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 13019, .avp_name = "Physical-Access-Id"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Proxy-Info"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Route-Record"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "3GPP-PS-Data-Off-Status"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules(rules, cmd);
+	  }
+	  /* Credit-Control-Answer */
+	  {
+		struct dict_object* cmd;
+		CHECK_dict_search( DICT_COMMAND, CMD_BY_NAME, "Credit-Control-Answer", &cmd)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 0, .avp_name = "Session-Id"}, RULE_FIXED_HEAD, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "DRMP"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Auth-Application-Id"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-Host"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-Realm"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Result-Code"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Experimental-Result"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "CC-Request-Type"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "CC-Request-Number"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "OC-Supported-Features"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "OC-OLR"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Supported-Features"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Bearer-Control-Mode"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Event-Trigger"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Event-Report-Indication"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-State-Id"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Redirect-Host"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Redirect-Host-Usage"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Redirect-Max-Cache-Time"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Charging-Rule-Remove"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Charging-Rule-Install"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Charging-Information"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Online"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Offline"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "QoS-Information"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Revalidation-Time"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Default-EPS-Bearer-QoS"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Default-QoS-Information"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Bearer-Usage"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Usage-Monitoring-Information"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "CSG-Information-Reporting"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "User-CSG-Information"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "PRA-Install"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "PRA-Remove"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Presence-Reporting-Area-Information"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Session-Release-Cause"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "NBIFOM-Support"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "NBIFOM-Mode"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Default-Access"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "RAN-Rule-Support"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Routing-Rule-Report"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Conditional-Policy-Information"}, RULE_OPTIONAL, 0, 4 },
+			{ { .avp_vendor = 10415, .avp_name = "Removal-Of-Access"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "IP-CAN-Type"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Error-Message"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Error-Reporting-Host"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Failed-AVP"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Proxy-Info"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Route-Record"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Load"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules(rules, cmd);
+	  }
+	  /* Re-Auth-Request */
+	  {
+		struct dict_object* cmd;
+		CHECK_dict_search( DICT_COMMAND, CMD_BY_NAME, "Re-Auth-Request", &cmd)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 0, .avp_name = "Session-Id"}, RULE_FIXED_HEAD, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "DRMP"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Auth-Application-Id"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-Host"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-Realm"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Destination-Realm"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Destination-Host"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Re-Auth-Request-Type"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Session-Release-Cause"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-State-Id"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "OC-Supported-Features"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Event-Trigger"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Event-Report-Indication"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Charging-Rule-Remove"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Charging-Rule-Install"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Default-EPS-Bearer-QoS"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "QoS-Information"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Default-QoS-Information"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Revalidation-Time"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Usage-Monitoring-Information"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "PCSCF-Restoration-Indication"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Conditional-Policy-Information"}, RULE_OPTIONAL, 0, 4 },
+			{ { .avp_vendor = 10415, .avp_name = "Removal-Of-Access"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "IP-CAN-Type"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "PRA-Install"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "PRA-Remove"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Proxy-Info"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Route-Record"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules(rules, cmd);
+	  }
+	  /* Re-Auth-Answer */
+	  {
+		struct dict_object* cmd;
+		CHECK_dict_search( DICT_COMMAND, CMD_BY_NAME, "Re-Auth-Answer", &cmd)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 0, .avp_name = "Session-Id"}, RULE_FIXED_HEAD, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "DRMP"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-Host"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-Realm"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Result-Code"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Experimental-Result"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-State-Id"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "OC-Supported-Features"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "OC-OLR"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "IP-CAN-Type"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "RAT-Type"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "AN-Trusted"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "AN-GW-Address"}, RULE_OPTIONAL, 0, 2 },
+			{ { .avp_vendor = 10415, .avp_name = "3GPP-SGSN-MCC-MNC"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "3GPP-SGSN-Address"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "3GPP-SGSN-Ipv6-Address"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "RAI"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "3GPP-User-Location-Info"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "User-Location-Info-Time"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "NetLoc-Access-Support"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "User-CSG-Information"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "3GPP-MS-TimeZone"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Default-QoS-Information"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Charging-Rule-Report"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Error-Message"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Error-Reporting-Host"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Failed-AVP"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Proxy-Info"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules(rules, cmd);
+	  }
+
+   }
+
+   LOG_D( "Extension 'Dictionary definitions for Gx (e30)' initialized");
+   return 0;
+}
+
+int dict_entry(char * conffile)
+{
+	dict_gx_load_defs(conffile);
+	return dict_gx_load_rules(conffile);
+}
+
+const char* dict_gx_proto_ver(char * conffile) {
+	return gx_proto_ver;
+}
+
+const double dict_gx_gen_ts(char * conffile) {
+	return gx_gen_date;
+}
+
+EXTENSION_ENTRY2("dict_gx", dict_gx_load_defs, dict_gx_load_rules, "dict_ts32299_avps", "dict_ts29212_avps", "dict_ts29273_avps", "dict_ts29214_avps", "dict_ts29272_avps", "dict_ts29229_avps", "dict_ts29061_avps", "dict_CreditControl", "dict_rfc4006bis_avps", "dict_draftload_avps", "dict_rfc7683_avps", "dict_rfc7155_avps", "dict_etsi283034_avps", "dict_3gpp2_avps", "dict_rfc7944_avps");
+
+
+
diff --git a/extensions/dict_NAS/CMakeLists.txt b/extensions/dict_NAS/CMakeLists.txt
new file mode 100644
index 0000000..ace49ff
--- /dev/null
+++ b/extensions/dict_NAS/CMakeLists.txt
@@ -0,0 +1,16 @@
+# The dict_NAS extension
+PROJECT("dict_NAS library generated by FdGen " C)
+
+# Compile as a module
+FD_ADD_EXTENSION(dict_NAS dict_NAS.c)
+
+
+####
+## INSTALL section ##
+
+INSTALL(TARGETS dict_NAS
+	LIBRARY DESTINATION ${INSTALL_EXTENSIONS_SUFFIX}
+COMPONENT freeDiameter-dictionary-dict_NAS)
+
+
+
diff --git a/extensions/dict_NAS/NAS.did b/extensions/dict_NAS/NAS.did
new file mode 100644
index 0000000..5e6af9e
--- /dev/null
+++ b/extensions/dict_NAS/NAS.did
@@ -0,0 +1,3 @@
+dict_rfc4004_avps
+dict_rfc7155_avps
+dict_NAS
diff --git a/extensions/dict_NAS/dict_NAS.c b/extensions/dict_NAS/dict_NAS.c
new file mode 100644
index 0000000..eeaa8c0
--- /dev/null
+++ b/extensions/dict_NAS/dict_NAS.c
@@ -0,0 +1,555 @@
+/*
+* Copyright (c) 2017 Sprint
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*    http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+/****************
+ Generated By: fdtool enhancements to diafuzzer
+ License: same as freeDiameter
+****************/
+
+
+/* 
+ * Dictionary definitions of objects specified in NAS.
+ */
+#include <freeDiameter/extension.h>
+
+#define PROTO_VER "unspecified"
+#define GEN_DATE  1506697121.58
+
+const char *nas_proto_ver = PROTO_VER;
+const double nas_gen_date = GEN_DATE;
+
+/* The content of this file follows the same structure as dict_base_proto.c */
+
+#define CHECK_dict_new( _type, _data, _parent, _ref )                                     \
+{                                                                                         \
+    int _ret = fd_dict_new( fd_g_config->cnf_dict, (_type), (_data), (_parent), (_ref) ); \
+    if ( _ret != 0 && _ret != EEXIST )                                                    \
+       return _ret;                                                                       \
+}
+
+#define CHECK_dict_search( _type, _criteria, _what, _result )		\
+    CHECK_FCT(  fd_dict_search( fd_g_config->cnf_dict, (_type), (_criteria), (_what), (_result), ENOENT) );
+
+struct local_rules_definition {
+    struct dict_avp_request avp_vendor_plus_name;
+    enum rule_position	position;
+    int 			min;
+    int			max;
+};
+
+#define RULE_ORDER( _position ) ((((_position) == RULE_FIXED_HEAD) || ((_position) == RULE_FIXED_TAIL)) ? 1 : 0 )
+
+/* Attention! This version of the macro uses AVP_BY_NAME_AND_VENDOR, in contrast to most other copies! */
+#define PARSE_loc_rules( _rulearray, _parent) {                                                         \
+        int __ar;                                                                                       \
+        for (__ar=0; __ar < sizeof(_rulearray) / sizeof((_rulearray)[0]); __ar++) {                     \
+                struct dict_rule_data __data = { NULL,                                                  \
+                        (_rulearray)[__ar].position,                                                    \
+                        0,                                                                              \
+                        (_rulearray)[__ar].min,                                                         \
+                        (_rulearray)[__ar].max};                                                        \
+                __data.rule_order = RULE_ORDER(__data.rule_position);                                   \
+                CHECK_FCT(  fd_dict_search(                                                             \
+                        fd_g_config->cnf_dict,                                                          \
+                        DICT_AVP,                                                                       \
+                        AVP_BY_NAME_AND_VENDOR,                                                         \
+                        &(_rulearray)[__ar].avp_vendor_plus_name,                                       \
+                        &__data.rule_avp, 0 ) );                                                        \
+                if ( !__data.rule_avp ) {                                                               \
+                        TRACE_DEBUG(INFO, "AVP Not found: '%s'", (_rulearray)[__ar].avp_vendor_plus_name.avp_name);             \
+                        return ENOENT;                                                                  \
+                }                                                                                       \
+                {                                                                                       \
+                         int _ret = fd_dict_new( fd_g_config->cnf_dict, DICT_RULE, &(__data), (_parent), NULL ); \
+                         if ( _ret != 0 && _ret != EEXIST )      {                                      \
+                                TRACE_DEBUG(INFO, "Error on rule with AVP '%s'",                        \
+                                            (_rulearray)[__ar].avp_vendor_plus_name.avp_name);          \
+                                return EINVAL;                                                          \
+                         }                                                                              \
+                }                                                                                       \
+        }                                                                                               \
+}
+
+#define CHECK_vendor_new( _data ) { \
+        struct dict_object * vendor_found; \
+        if (fd_dict_search(fd_g_config->cnf_dict,DICT_VENDOR,VENDOR_BY_ID,&_data.vendor_id,&vendor_found,ENOENT) == ENOENT) { \
+                CHECK_FCT(fd_dict_new(fd_g_config->cnf_dict, DICT_VENDOR, &_data, NULL, NULL)); \
+        } \
+}
+
+#define enumval_def_u32( _val_, _str_ )		\
+    { _str_, 		{ .u32 = _val_ }}
+
+#define enumval_def_os( _len_, _val_, _str_ )				\
+    { _str_, 		{ .os = { .data = (unsigned char *)_val_, .len = _len_ }}}
+
+
+static int dict_nas_load_defs(char * conffile)
+{
+   TRACE_ENTRY("%p", conffile);
+	struct dict_object * app_id0;
+	struct dict_object * app_id1;
+
+	/* Application Section */
+	{
+	  {
+			struct dict_application_data data = { 0, "NAS-app0" };
+			CHECK_dict_new( DICT_APPLICATION, &data, NULL, &app_id0)
+	  }
+	  {
+			struct dict_application_data data = { 1, "NAS" };
+			CHECK_dict_new( DICT_APPLICATION, &data, NULL, &app_id1)
+	  }
+	  /* Result codes */
+	  {
+			struct dict_object *type;
+			CHECK_dict_search(DICT_TYPE, TYPE_BY_NAME, "Enumerated(Result-Code)",&type);
+			struct dict_enumval_data        t_1 = { "Bangkok", { .u32=10260 }};
+
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+
+	  }
+	}
+
+
+   /* AVP section */
+   {
+		struct dict_object * Address_type;
+		struct dict_object * UTF8String_type;
+		struct dict_object * DiameterIdentity_type;
+		struct dict_object * DiameterURI_type;
+		struct dict_object * Time_type;
+		struct dict_object * IPFilterRule_type;
+
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "Address", &Address_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "UTF8String", &UTF8String_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "DiameterIdentity", &DiameterIdentity_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "DiameterURI", &DiameterURI_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "Time", &Time_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "IPFilterRule", &IPFilterRule_type);
+
+	
+   }
+
+   /* Commands section */
+   {
+		/* AA-Request */
+		{
+			struct dict_object* cmd;
+			struct dict_cmd_data data = {
+				265,	/* Code */
+				"AA-Request",	/* Name */
+				CMD_FLAG_REQUEST | CMD_FLAG_ERROR,	/* Fixed flags */
+				CMD_FLAG_REQUEST | CMD_FLAG_PROXIABLE,	/* Fixed flag values */
+			};
+
+			CHECK_dict_new( DICT_COMMAND, &data , app_id1, &cmd)
+		}
+		/* AA-Answer */
+		{
+			struct dict_object* cmd;
+			struct dict_cmd_data data = {
+				265,	/* Code */
+				"AA-Answer",	/* Name */
+				CMD_FLAG_REQUEST,	/* Fixed flags */
+				CMD_FLAG_PROXIABLE,	/* Fixed flag values */
+			};
+
+			CHECK_dict_new( DICT_COMMAND, &data , app_id1, &cmd)
+		}
+
+   }
+
+   return 0;
+}
+
+static int dict_nas_load_rules(char * conffile)
+{
+   /* Grouped AVP section */
+   {
+
+   }	
+
+   /* Commands section */
+   {
+	  /* AA-Request */
+	  {
+		struct dict_object* cmd;
+		CHECK_dict_search( DICT_COMMAND, CMD_BY_NAME, "AA-Request", &cmd)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 0, .avp_name = "Session-Id"}, RULE_FIXED_HEAD, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Auth-Application-Id"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-Host"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-Realm"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Destination-Realm"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Auth-Request-Type"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Destination-Host"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "NAS-Identifier"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "NAS-IP-Address"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "NAS-IPv6-Address"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "NAS-Port"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "NAS-Port-Id"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "NAS-Port-Type"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-AAA-Protocol"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-State-Id"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Port-Limit"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "User-Name"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "User-Password"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Service-Type"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "State"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Authorization-Lifetime"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Auth-Grace-Period"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Auth-Session-State"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Callback-Number"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Called-Station-Id"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Calling-Station-Id"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Originating-Line-Info"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Connect-Info"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "CHAP-Auth"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "CHAP-Challenge"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Framed-Compression"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Framed-Interface-Id"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Framed-IP-Address"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Framed-IPv6-Prefix"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Framed-IP-Netmask"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Framed-MTU"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Framed-Protocol"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "ARAP-Password"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules(rules, cmd);
+	  }
+	  /* AA-Answer */
+	  {
+		struct dict_object* cmd;
+		CHECK_dict_search( DICT_COMMAND, CMD_BY_NAME, "AA-Answer", &cmd)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 0, .avp_name = "Session-Id"}, RULE_FIXED_HEAD, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Auth-Application-Id"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Auth-Request-Type"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Result-Code"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-Host"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-Realm"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "User-Name"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Service-Type"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Class"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules(rules, cmd);
+	  }
+	  /* Re-Auth-Request */
+	  {
+		struct dict_object* cmd;
+		CHECK_dict_search( DICT_COMMAND, CMD_BY_NAME, "Re-Auth-Request", &cmd)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 0, .avp_name = "Session-Id"}, RULE_FIXED_HEAD, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-Host"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-Realm"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Destination-Realm"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Destination-Host"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Auth-Application-Id"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Re-Auth-Request-Type"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "User-Name"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-AAA-Protocol"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-State-Id"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "NAS-Identifier"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "NAS-IP-Address"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "NAS-IPv6-Address"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "NAS-Port"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "NAS-Port-Id"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "NAS-Port-Type"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Service-Type"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Framed-IP-Address"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules(rules, cmd);
+	  }
+	  /* Re-Auth-Answer */
+	  {
+		struct dict_object* cmd;
+		CHECK_dict_search( DICT_COMMAND, CMD_BY_NAME, "Re-Auth-Answer", &cmd)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 0, .avp_name = "Session-Id"}, RULE_FIXED_HEAD, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Result-Code"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-Host"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-Realm"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "User-Name"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-AAA-Protocol"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-State-Id"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Error-Message"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Error-Reporting-Host"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Failed-AVP"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Redirect-Host"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Redirect-Host-Usage"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Redirect-Max-Cache-Time"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Service-Type"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Configuration-Token"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Idle-Timeout"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Authorization-Lifetime"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Auth-Grace-Period"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Re-Auth-Request-Type"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "State"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Class"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Reply-Message"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Prompt"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules(rules, cmd);
+	  }
+	  /* Abort-Session-Request */
+	  {
+		struct dict_object* cmd;
+		CHECK_dict_search( DICT_COMMAND, CMD_BY_NAME, "Abort-Session-Request", &cmd)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 0, .avp_name = "Session-Id"}, RULE_FIXED_HEAD, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-Host"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-Realm"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Destination-Realm"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Destination-Host"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Auth-Application-Id"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "User-Name"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-AAA-Protocol"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-State-Id"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "NAS-Identifier"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "NAS-IP-Address"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "NAS-IPv6-Address"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "NAS-Port"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "NAS-Port-Id"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "NAS-Port-Type"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Service-Type"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Framed-IP-Address"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Framed-IPv6-Prefix"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Framed-Interface-Id"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules(rules, cmd);
+	  }
+	  /* Abort-Session-Answer */
+	  {
+		struct dict_object* cmd;
+		CHECK_dict_search( DICT_COMMAND, CMD_BY_NAME, "Abort-Session-Answer", &cmd)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 0, .avp_name = "Session-Id"}, RULE_FIXED_HEAD, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Result-Code"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-Host"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-Realm"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "User-Name"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-AAA-Protocol"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-State-Id"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "State"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Error-Message"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Error-Reporting-Host"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Failed-AVP"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Redirect-Host"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Redirect-Host-Usage"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Redirect-Max-Cache-Time"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Proxy-Info"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules(rules, cmd);
+	  }
+	  /* Session-Termination-Request */
+	  {
+		struct dict_object* cmd;
+		CHECK_dict_search( DICT_COMMAND, CMD_BY_NAME, "Session-Termination-Request", &cmd)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 0, .avp_name = "Session-Id"}, RULE_FIXED_HEAD, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-Host"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-Realm"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Destination-Realm"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Auth-Application-Id"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Termination-Cause"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "User-Name"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Destination-Host"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Class"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-AAA-Protocol"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-State-Id"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Proxy-Info"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Route-Record"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules(rules, cmd);
+	  }
+	  /* Session-Termination-Answer */
+	  {
+		struct dict_object* cmd;
+		CHECK_dict_search( DICT_COMMAND, CMD_BY_NAME, "Session-Termination-Answer", &cmd)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 0, .avp_name = "Session-Id"}, RULE_FIXED_HEAD, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Result-Code"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-Host"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-Realm"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "User-Name"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Class"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Error-Message"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Error-Reporting-Host"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Failed-AVP"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-AAA-Protocol"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-State-Id"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Redirect-Host"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Redirect-Host-Usage"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Redirect-Max-Cache-Time"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Proxy-Info"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules(rules, cmd);
+	  }
+	  /* Accounting-Request */
+	  {
+		struct dict_object* cmd;
+		CHECK_dict_search( DICT_COMMAND, CMD_BY_NAME, "Accounting-Request", &cmd)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 0, .avp_name = "Session-Id"}, RULE_FIXED_HEAD, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-Host"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-Realm"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Destination-Realm"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Accounting-Record-Type"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Accounting-Record-Number"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Acct-Application-Id"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "User-Name"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Accounting-Sub-Session-Id"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Acct-Session-Id"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Acct-Multi-Session-Id"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-AAA-Protocol"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-State-Id"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Destination-Host"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Event-Timestamp"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Acct-Delay-Time"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "NAS-Identifier"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "NAS-IP-Address"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "NAS-IPv6-Address"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "NAS-Port"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "NAS-Port-Id"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "NAS-Port-Type"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Class"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Service-Type"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Termination-Cause"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Accounting-Input-Octets"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Accounting-Input-Packets"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Accounting-Output-Octets"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Accounting-Output-Packets"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Acct-Authentic"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Accounting-Auth-Method"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Acct-Link-Count"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Acct-Session-Time"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Acct-Tunnel-Connection"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Acct-Tunnel-Packets-Lost"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Callback-Id"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Callback-Number"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Called-Station-Id"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Calling-Station-Id"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Connect-Info"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Originating-Line-Info"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Authorization-Lifetime"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Session-Timeout"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Idle-Timeout"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Port-Limit"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Accounting-Realtime-Required"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Acct-Interim-Interval"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Filter-Id"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "NAS-Filter-Rule"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "QoS-Filter-Rule"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Framed-Appletalk-Link"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Framed-Appletalk-Network"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Framed-Appletalk-Zone"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Framed-Compression"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Framed-Interface-Id"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Framed-IP-Address"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Framed-IP-Netmask"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Framed-IPv6-Prefix"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Framed-IPv6-Pool"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Framed-IPv6-Route"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Framed-IPX-Network"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Framed-MTU"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Framed-Pool"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Framed-Protocol"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Framed-Route"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Framed-Routing"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Login-IP-Host"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Login-IPv6-Host"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Login-LAT-Group"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Login-LAT-Node"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Login-LAT-Port"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Login-LAT-Service"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Login-Service"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Login-TCP-Port"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Tunneling"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Proxy-Info"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Route-Record"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules(rules, cmd);
+	  }
+	  /* Accounting-Answer */
+	  {
+		struct dict_object* cmd;
+		CHECK_dict_search( DICT_COMMAND, CMD_BY_NAME, "Accounting-Answer", &cmd)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 0, .avp_name = "Session-Id"}, RULE_FIXED_HEAD, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Result-Code"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-Host"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-Realm"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Accounting-Record-Type"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Accounting-Record-Number"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Acct-Application-Id"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "User-Name"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Accounting-Sub-Session-Id"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Acct-Session-Id"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Acct-Multi-Session-Id"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Event-Timestamp"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Error-Message"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Error-Reporting-Host"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Failed-AVP"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-AAA-Protocol"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-State-Id"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "NAS-Identifier"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "NAS-IP-Address"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "NAS-IPv6-Address"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "NAS-Port"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "NAS-Port-Id"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "NAS-Port-Type"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Service-Type"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Termination-Cause"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Accounting-Realtime-Required"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules(rules, cmd);
+	  }
+
+   }
+
+   LOG_D( "Extension 'Dictionary definitions for NAS (None)' initialized");
+   return 0;
+}
+
+int dict_entry(char * conffile)
+{
+	dict_nas_load_defs(conffile);
+	return dict_nas_load_rules(conffile);
+}
+
+const char* dict_nas_proto_ver(char * conffile) {
+	return nas_proto_ver;
+}
+
+const double dict_nas_gen_ts(char * conffile) {
+	return nas_gen_date;
+}
+
+EXTENSION_ENTRY2("dict_nas", dict_nas_load_defs, dict_nas_load_rules, "dict_rfc7155_avps");
+
+
+
diff --git a/extensions/dict_Rf/CMakeLists.txt b/extensions/dict_Rf/CMakeLists.txt
new file mode 100644
index 0000000..6073671
--- /dev/null
+++ b/extensions/dict_Rf/CMakeLists.txt
@@ -0,0 +1,16 @@
+# The dict_Rf extension
+PROJECT("dict_Rf library generated by FdGen " C)
+
+# Compile as a module
+FD_ADD_EXTENSION(dict_Rf dict_Rf.c)
+
+
+####
+## INSTALL section ##
+
+INSTALL(TARGETS dict_Rf
+	LIBRARY DESTINATION ${INSTALL_EXTENSIONS_SUFFIX}
+COMPONENT freeDiameter-dictionary-RF)
+
+
+
diff --git a/extensions/dict_Rf/Rf.did b/extensions/dict_Rf/Rf.did
new file mode 100644
index 0000000..72ff4f6
--- /dev/null
+++ b/extensions/dict_Rf/Rf.did
@@ -0,0 +1,38 @@
+dict_rfc6942_avps
+dict_ts29468_avps
+dict_ts29154_avps
+dict_ts29214_avps
+dict_ts29215_avps
+dict_ts29217_avps
+dict_ts29337_avps
+dict_ts29343_avps
+dict_ts29338_avps
+dict_ts29128_avps
+dict_ts29344_avps
+dict_ts29345_avps
+dict_ts29173_avps
+dict_ts32299_avps
+dict_rfc6734_avps
+dict_rfc5580_avps
+dict_rfc4072_avps
+dict_ts29273_avps
+dict_rfc4006bis_avps
+dict_ts29212_avps
+dict_ts29061_avps
+dict_ts29272_avps
+dict_rfc5447_avps
+dict_rfc5778_avps
+dict_rfc5777_avps
+dict_ts29336_avps
+dict_etsi283034_avps
+dict_rfc4590_avps
+dict_rfc4004_avps
+dict_rfc7155_avps
+dict_ts29229_avps
+dict_rfc7683_avps
+dict_draftload_avps
+dict_rfc7944_avps
+dict_ts29329_avps
+dict_ts29368_avps
+dict_3gpp2_avps
+dict_Rf
diff --git a/extensions/dict_Rf/dict_Rf.c b/extensions/dict_Rf/dict_Rf.c
new file mode 100644
index 0000000..4edee61
--- /dev/null
+++ b/extensions/dict_Rf/dict_Rf.c
@@ -0,0 +1,235 @@
+/*
+* Copyright (c) 2017 Sprint
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*    http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+/****************
+ Generated By: fdtool enhancements to diafuzzer
+ License: same as freeDiameter
+****************/
+
+
+/* 
+ * Dictionary definitions of objects specified in Rf (e30).
+ */
+#include <freeDiameter/extension.h>
+
+#define PROTO_VER "e30"
+#define GEN_DATE  1506697125.6
+
+const char *rf_proto_ver = PROTO_VER;
+const double rf_gen_date = GEN_DATE;
+
+/* The content of this file follows the same structure as dict_base_proto.c */
+
+#define CHECK_dict_new( _type, _data, _parent, _ref )                                     \
+{                                                                                         \
+    int _ret = fd_dict_new( fd_g_config->cnf_dict, (_type), (_data), (_parent), (_ref) ); \
+    if ( _ret != 0 && _ret != EEXIST )                                                    \
+       return _ret;                                                                       \
+}
+
+#define CHECK_dict_search( _type, _criteria, _what, _result )		\
+    CHECK_FCT(  fd_dict_search( fd_g_config->cnf_dict, (_type), (_criteria), (_what), (_result), ENOENT) );
+
+struct local_rules_definition {
+    struct dict_avp_request avp_vendor_plus_name;
+    enum rule_position	position;
+    int 			min;
+    int			max;
+};
+
+#define RULE_ORDER( _position ) ((((_position) == RULE_FIXED_HEAD) || ((_position) == RULE_FIXED_TAIL)) ? 1 : 0 )
+
+/* Attention! This version of the macro uses AVP_BY_NAME_AND_VENDOR, in contrast to most other copies! */
+#define PARSE_loc_rules( _rulearray, _parent) {                                                         \
+        int __ar;                                                                                       \
+        for (__ar=0; __ar < sizeof(_rulearray) / sizeof((_rulearray)[0]); __ar++) {                     \
+                struct dict_rule_data __data = { NULL,                                                  \
+                        (_rulearray)[__ar].position,                                                    \
+                        0,                                                                              \
+                        (_rulearray)[__ar].min,                                                         \
+                        (_rulearray)[__ar].max};                                                        \
+                __data.rule_order = RULE_ORDER(__data.rule_position);                                   \
+                CHECK_FCT(  fd_dict_search(                                                             \
+                        fd_g_config->cnf_dict,                                                          \
+                        DICT_AVP,                                                                       \
+                        AVP_BY_NAME_AND_VENDOR,                                                         \
+                        &(_rulearray)[__ar].avp_vendor_plus_name,                                       \
+                        &__data.rule_avp, 0 ) );                                                        \
+                if ( !__data.rule_avp ) {                                                               \
+                        TRACE_DEBUG(INFO, "AVP Not found: '%s'", (_rulearray)[__ar].avp_vendor_plus_name.avp_name);             \
+                        return ENOENT;                                                                  \
+                }                                                                                       \
+                {                                                                                       \
+                         int _ret = fd_dict_new( fd_g_config->cnf_dict, DICT_RULE, &(__data), (_parent), NULL ); \
+                         if ( _ret != 0 && _ret != EEXIST )      {                                      \
+                                TRACE_DEBUG(INFO, "Error on rule with AVP '%s'",                        \
+                                            (_rulearray)[__ar].avp_vendor_plus_name.avp_name);          \
+                                return EINVAL;                                                          \
+                         }                                                                              \
+                }                                                                                       \
+        }                                                                                               \
+}
+
+#define CHECK_vendor_new( _data ) { \
+        struct dict_object * vendor_found; \
+        if (fd_dict_search(fd_g_config->cnf_dict,DICT_VENDOR,VENDOR_BY_ID,&_data.vendor_id,&vendor_found,ENOENT) == ENOENT) { \
+                CHECK_FCT(fd_dict_new(fd_g_config->cnf_dict, DICT_VENDOR, &_data, NULL, NULL)); \
+        } \
+}
+
+#define enumval_def_u32( _val_, _str_ )		\
+    { _str_, 		{ .u32 = _val_ }}
+
+#define enumval_def_os( _len_, _val_, _str_ )				\
+    { _str_, 		{ .os = { .data = (unsigned char *)_val_, .len = _len_ }}}
+
+
+static int dict_rf_load_defs(char * conffile)
+{
+   TRACE_ENTRY("%p", conffile);
+	struct dict_object * app_id3;
+
+	/* Application Section */
+	{
+	  {
+			struct dict_object * vendor;
+			CHECK_dict_search(DICT_VENDOR, VENDOR_BY_NAME, "3GPP", &vendor)
+			struct dict_application_data data = { 3, "Rf" };
+			CHECK_dict_new( DICT_APPLICATION, &data, vendor, &app_id3)
+	  }
+	}
+
+
+   /* AVP section */
+   {
+		struct dict_object * Address_type;
+		struct dict_object * UTF8String_type;
+		struct dict_object * DiameterIdentity_type;
+		struct dict_object * DiameterURI_type;
+		struct dict_object * Time_type;
+		struct dict_object * IPFilterRule_type;
+
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "Address", &Address_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "UTF8String", &UTF8String_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "DiameterIdentity", &DiameterIdentity_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "DiameterURI", &DiameterURI_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "Time", &Time_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "IPFilterRule", &IPFilterRule_type);
+
+	
+   }
+
+   /* Commands section */
+   {
+
+   }
+
+   return 0;
+}
+
+static int dict_rf_load_rules(char * conffile)
+{
+   /* Grouped AVP section */
+   {
+
+   }	
+
+   /* Commands section */
+   {
+	  /* Accounting-Request */
+	  {
+		struct dict_object* cmd;
+		CHECK_dict_search( DICT_COMMAND, CMD_BY_NAME, "Accounting-Request", &cmd)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 0, .avp_name = "Session-Id"}, RULE_FIXED_HEAD, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-Host"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-Realm"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Destination-Realm"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Accounting-Record-Type"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Accounting-Record-Number"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Acct-Application-Id"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Vendor-Specific-Application-Id"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "User-Name"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Destination-Host"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Accounting-Sub-Session-Id"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Acct-Session-Id"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Acct-Multi-Session-Id"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Acct-Interim-Interval"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Accounting-Realtime-Required"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-State-Id"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Event-Timestamp"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Proxy-Info"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Route-Record"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Service-Context-Id"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Service-Information"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules(rules, cmd);
+	  }
+	  /* Accounting-Answer */
+	  {
+		struct dict_object* cmd;
+		CHECK_dict_search( DICT_COMMAND, CMD_BY_NAME, "Accounting-Answer", &cmd)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 0, .avp_name = "Session-Id"}, RULE_FIXED_HEAD, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Result-Code"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-Host"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-Realm"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Accounting-Record-Type"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Accounting-Record-Number"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Acct-Application-Id"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Vendor-Specific-Application-Id"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "User-Name"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Accounting-Sub-Session-Id"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Acct-Session-Id"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Acct-Multi-Session-Id"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Error-Message"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Error-Reporting-Host"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Acct-Interim-Interval"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Failed-AVP"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Accounting-Realtime-Required"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-State-Id"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Event-Timestamp"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Proxy-Info"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules(rules, cmd);
+	  }
+
+   }
+
+   LOG_D( "Extension 'Dictionary definitions for Rf (e30)' initialized");
+   return 0;
+}
+
+int dict_entry(char * conffile)
+{
+	dict_rf_load_defs(conffile);
+	return dict_rf_load_rules(conffile);
+}
+
+const char* dict_rf_proto_ver(char * conffile) {
+	return rf_proto_ver;
+}
+
+const double dict_rf_gen_ts(char * conffile) {
+	return rf_gen_date;
+}
+
+EXTENSION_ENTRY2("dict_rf", dict_rf_load_defs, dict_rf_load_rules, "dict_ts32299_avps", "dict_ts29272_avps", "dict_ts29273_avps", "dict_ts29212_avps", "dict_ts29336_avps", "dict_ts29128_avps", "dict_ts29214_avps", "dict_ts29345_avps", "dict_ts29337_avps", "dict_ts29344_avps", "dict_ts29368_avps", "dict_ts29217_avps", "dict_ts29229_avps", "dict_ts29338_avps", "dict_ts29468_avps", "dict_ts29329_avps", "dict_ts29061_avps", "dict_rfc5778_avps", "dict_ts29173_avps", "dict_rfc4006bis_avps", "dict_ts29343_avps", "dict_rfc7155_avps", "dict_rfc5447_avps", "dict_rfc7683_avps", "dict_rfc4590_avps", "dict_draftload_avps", "dict_rfc4004_avps", "dict_rfc5777_avps", "dict_etsi283034_avps", "dict_3gpp2_avps", "dict_rfc7944_avps");
+
+
+
diff --git a/extensions/dict_Ro/CMakeLists.txt b/extensions/dict_Ro/CMakeLists.txt
new file mode 100644
index 0000000..a37c7de
--- /dev/null
+++ b/extensions/dict_Ro/CMakeLists.txt
@@ -0,0 +1,16 @@
+# The dict_Ro extension
+PROJECT("dict_Ro library generated by FdGen " C)
+
+# Compile as a module
+FD_ADD_EXTENSION(dict_Ro dict_Ro.c)
+
+
+####
+## INSTALL section ##
+
+INSTALL(TARGETS dict_Ro
+	LIBRARY DESTINATION ${INSTALL_EXTENSIONS_SUFFIX}
+COMPONENT freeDiameter-dictionary-RO)
+
+
+
diff --git a/extensions/dict_Ro/Ro.did b/extensions/dict_Ro/Ro.did
new file mode 100644
index 0000000..1600d85
--- /dev/null
+++ b/extensions/dict_Ro/Ro.did
@@ -0,0 +1,39 @@
+dict_CreditControl
+dict_rfc6942_avps
+dict_ts29468_avps
+dict_ts29154_avps
+dict_ts29214_avps
+dict_ts29215_avps
+dict_ts29217_avps
+dict_ts29337_avps
+dict_ts29343_avps
+dict_ts29338_avps
+dict_ts29128_avps
+dict_ts29344_avps
+dict_ts29345_avps
+dict_ts29173_avps
+dict_ts32299_avps
+dict_rfc6734_avps
+dict_rfc5580_avps
+dict_rfc4072_avps
+dict_ts29273_avps
+dict_rfc4006bis_avps
+dict_ts29212_avps
+dict_ts29061_avps
+dict_ts29272_avps
+dict_rfc5447_avps
+dict_rfc5778_avps
+dict_rfc5777_avps
+dict_ts29336_avps
+dict_etsi283034_avps
+dict_rfc4590_avps
+dict_rfc4004_avps
+dict_rfc7155_avps
+dict_ts29229_avps
+dict_rfc7683_avps
+dict_draftload_avps
+dict_rfc7944_avps
+dict_ts29329_avps
+dict_ts29368_avps
+dict_3gpp2_avps
+dict_Ro
diff --git a/extensions/dict_Ro/dict_Ro.c b/extensions/dict_Ro/dict_Ro.c
new file mode 100644
index 0000000..a8799f7
--- /dev/null
+++ b/extensions/dict_Ro/dict_Ro.c
@@ -0,0 +1,310 @@
+/*
+* Copyright (c) 2017 Sprint
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*    http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+/****************
+ Generated By: fdtool enhancements to diafuzzer
+ License: same as freeDiameter
+****************/
+
+
+/* 
+ * Dictionary definitions of objects specified in Ro (e30).
+ */
+#include <freeDiameter/extension.h>
+
+#define PROTO_VER "e30"
+#define GEN_DATE  1506697129.62
+
+const char *ro_proto_ver = PROTO_VER;
+const double ro_gen_date = GEN_DATE;
+
+/* The content of this file follows the same structure as dict_base_proto.c */
+
+#define CHECK_dict_new( _type, _data, _parent, _ref )                                     \
+{                                                                                         \
+    int _ret = fd_dict_new( fd_g_config->cnf_dict, (_type), (_data), (_parent), (_ref) ); \
+    if ( _ret != 0 && _ret != EEXIST )                                                    \
+       return _ret;                                                                       \
+}
+
+#define CHECK_dict_search( _type, _criteria, _what, _result )		\
+    CHECK_FCT(  fd_dict_search( fd_g_config->cnf_dict, (_type), (_criteria), (_what), (_result), ENOENT) );
+
+struct local_rules_definition {
+    struct dict_avp_request avp_vendor_plus_name;
+    enum rule_position	position;
+    int 			min;
+    int			max;
+};
+
+#define RULE_ORDER( _position ) ((((_position) == RULE_FIXED_HEAD) || ((_position) == RULE_FIXED_TAIL)) ? 1 : 0 )
+
+/* Attention! This version of the macro uses AVP_BY_NAME_AND_VENDOR, in contrast to most other copies! */
+#define PARSE_loc_rules( _rulearray, _parent) {                                                         \
+        int __ar;                                                                                       \
+        for (__ar=0; __ar < sizeof(_rulearray) / sizeof((_rulearray)[0]); __ar++) {                     \
+                struct dict_rule_data __data = { NULL,                                                  \
+                        (_rulearray)[__ar].position,                                                    \
+                        0,                                                                              \
+                        (_rulearray)[__ar].min,                                                         \
+                        (_rulearray)[__ar].max};                                                        \
+                __data.rule_order = RULE_ORDER(__data.rule_position);                                   \
+                CHECK_FCT(  fd_dict_search(                                                             \
+                        fd_g_config->cnf_dict,                                                          \
+                        DICT_AVP,                                                                       \
+                        AVP_BY_NAME_AND_VENDOR,                                                         \
+                        &(_rulearray)[__ar].avp_vendor_plus_name,                                       \
+                        &__data.rule_avp, 0 ) );                                                        \
+                if ( !__data.rule_avp ) {                                                               \
+                        TRACE_DEBUG(INFO, "AVP Not found: '%s'", (_rulearray)[__ar].avp_vendor_plus_name.avp_name);             \
+                        return ENOENT;                                                                  \
+                }                                                                                       \
+                {                                                                                       \
+                         int _ret = fd_dict_new( fd_g_config->cnf_dict, DICT_RULE, &(__data), (_parent), NULL ); \
+                         if ( _ret != 0 && _ret != EEXIST )      {                                      \
+                                TRACE_DEBUG(INFO, "Error on rule with AVP '%s'",                        \
+                                            (_rulearray)[__ar].avp_vendor_plus_name.avp_name);          \
+                                return EINVAL;                                                          \
+                         }                                                                              \
+                }                                                                                       \
+        }                                                                                               \
+}
+
+#define CHECK_vendor_new( _data ) { \
+        struct dict_object * vendor_found; \
+        if (fd_dict_search(fd_g_config->cnf_dict,DICT_VENDOR,VENDOR_BY_ID,&_data.vendor_id,&vendor_found,ENOENT) == ENOENT) { \
+                CHECK_FCT(fd_dict_new(fd_g_config->cnf_dict, DICT_VENDOR, &_data, NULL, NULL)); \
+        } \
+}
+
+#define enumval_def_u32( _val_, _str_ )		\
+    { _str_, 		{ .u32 = _val_ }}
+
+#define enumval_def_os( _len_, _val_, _str_ )				\
+    { _str_, 		{ .os = { .data = (unsigned char *)_val_, .len = _len_ }}}
+
+
+static int dict_ro_load_defs(char * conffile)
+{
+   TRACE_ENTRY("%p", conffile);
+	struct dict_object * app_id3;
+	struct dict_object * app_id4;
+
+	/* Application Section */
+	{
+	  {
+			struct dict_object * vendor;
+			CHECK_dict_search(DICT_VENDOR, VENDOR_BY_NAME, "3GPP", &vendor)
+			struct dict_application_data data = { 3, "Ro-app3" };
+			CHECK_dict_new( DICT_APPLICATION, &data, vendor, &app_id3)
+	  }
+	  {
+			struct dict_object * vendor;
+			CHECK_dict_search(DICT_VENDOR, VENDOR_BY_NAME, "3GPP", &vendor)
+			struct dict_application_data data = { 4, "Ro" };
+			CHECK_dict_new( DICT_APPLICATION, &data, vendor, &app_id4)
+	  }
+	}
+
+
+   /* AVP section */
+   {
+		struct dict_object * Address_type;
+		struct dict_object * UTF8String_type;
+		struct dict_object * DiameterIdentity_type;
+		struct dict_object * DiameterURI_type;
+		struct dict_object * Time_type;
+		struct dict_object * IPFilterRule_type;
+
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "Address", &Address_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "UTF8String", &UTF8String_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "DiameterIdentity", &DiameterIdentity_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "DiameterURI", &DiameterURI_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "Time", &Time_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "IPFilterRule", &IPFilterRule_type);
+
+	
+   }
+
+   /* Commands section */
+   {
+
+   }
+
+   return 0;
+}
+
+static int dict_ro_load_rules(char * conffile)
+{
+   /* Grouped AVP section */
+   {
+
+   }	
+
+   /* Commands section */
+   {
+	  /* Credit-Control-Request */
+	  {
+		struct dict_object* cmd;
+		CHECK_dict_search( DICT_COMMAND, CMD_BY_NAME, "Credit-Control-Request", &cmd)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 0, .avp_name = "Session-Id"}, RULE_FIXED_HEAD, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-Host"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-Realm"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Destination-Realm"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Auth-Application-Id"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Service-Context-Id"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "CC-Request-Type"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "CC-Request-Number"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Destination-Host"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "User-Name"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "CC-Sub-Session-Id"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Acct-Multi-Session-Id"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-State-Id"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Event-Timestamp"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Subscription-Id"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Service-Identifier"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Termination-Cause"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Requested-Service-Unit"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Requested-Action"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Used-Service-Unit"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "AoC-Request-Type"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Multiple-Services-Indicator"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Multiple-Services-Credit-Control"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Service-Parameter-Info"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "CC-Correlation-Id"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "User-Equipment-Info"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Proxy-Info"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Route-Record"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Service-Information"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules(rules, cmd);
+	  }
+	  /* Credit-Control-Answer */
+	  {
+		struct dict_object* cmd;
+		CHECK_dict_search( DICT_COMMAND, CMD_BY_NAME, "Credit-Control-Answer", &cmd)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 0, .avp_name = "Session-Id"}, RULE_FIXED_HEAD, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Result-Code"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-Host"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-Realm"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Auth-Application-Id"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "CC-Request-Type"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "CC-Request-Number"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "User-Name"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "CC-Session-Failover"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "CC-Sub-Session-Id"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Acct-Multi-Session-Id"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-State-Id"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Event-Timestamp"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Granted-Service-Unit"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Multiple-Services-Credit-Control"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Cost-Information"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Low-Balance-Indication"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Remaining-Balance"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Final-Unit-Indication"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Check-Balance-Result"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Credit-Control-Failure-Handling"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Direct-Debiting-Failure-Handling"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Validity-Time"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Redirect-Host"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Redirect-Host-Usage"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Redirect-Max-Cache-Time"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Proxy-Info"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Route-Record"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Failed-AVP"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Service-Information"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules(rules, cmd);
+	  }
+	  /* Re-Auth-Request */
+	  {
+		struct dict_object* cmd;
+		CHECK_dict_search( DICT_COMMAND, CMD_BY_NAME, "Re-Auth-Request", &cmd)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 0, .avp_name = "Session-Id"}, RULE_FIXED_HEAD, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-Host"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-Realm"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Destination-Realm"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Destination-Host"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Auth-Application-Id"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Re-Auth-Request-Type"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "User-Name"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-State-Id"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Proxy-Info"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Route-Record"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "CC-Sub-Session-Id"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "G-S-U-Pool-Identifier"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Service-Identifier"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Rating-Group"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules(rules, cmd);
+	  }
+	  /* Re-Auth-Answer */
+	  {
+		struct dict_object* cmd;
+		CHECK_dict_search( DICT_COMMAND, CMD_BY_NAME, "Re-Auth-Answer", &cmd)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 0, .avp_name = "Session-Id"}, RULE_FIXED_HEAD, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Result-Code"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-Host"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-Realm"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "User-Name"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-State-Id"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Error-Message"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Error-Reporting-Host"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Failed-AVP"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Redirect-Host"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Redirect-Host-Usage"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Redirect-Max-Cache-Time"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Proxy-Info"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "CC-Sub-Session-Id"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "G-S-U-Pool-Identifier"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Service-Identifier"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Rating-Group"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules(rules, cmd);
+	  }
+
+   }
+
+   LOG_D( "Extension 'Dictionary definitions for Ro (e30)' initialized");
+   return 0;
+}
+
+int dict_entry(char * conffile)
+{
+	dict_ro_load_defs(conffile);
+	return dict_ro_load_rules(conffile);
+}
+
+const char* dict_ro_proto_ver(char * conffile) {
+	return ro_proto_ver;
+}
+
+const double dict_ro_gen_ts(char * conffile) {
+	return ro_gen_date;
+}
+
+EXTENSION_ENTRY2("dict_ro", dict_ro_load_defs, dict_ro_load_rules, "dict_ts32299_avps", "dict_ts29272_avps", "dict_ts29273_avps", "dict_ts29212_avps", "dict_ts29336_avps", "dict_ts29128_avps", "dict_ts29214_avps", "dict_ts29345_avps", "dict_ts29337_avps", "dict_ts29344_avps", "dict_ts29368_avps", "dict_ts29217_avps", "dict_ts29229_avps", "dict_ts29338_avps", "dict_ts29468_avps", "dict_ts29329_avps", "dict_ts29061_avps", "dict_rfc5778_avps", "dict_ts29173_avps", "dict_CreditControl", "dict_rfc4006bis_avps", "dict_ts29343_avps", "dict_rfc7155_avps", "dict_rfc5447_avps", "dict_rfc7683_avps", "dict_rfc4590_avps", "dict_draftload_avps", "dict_rfc4004_avps", "dict_rfc5777_avps", "dict_etsi283034_avps", "dict_3gpp2_avps", "dict_rfc7944_avps");
+
+
+
diff --git a/extensions/dict_Rx/CMakeLists.txt b/extensions/dict_Rx/CMakeLists.txt
new file mode 100644
index 0000000..8ac999c
--- /dev/null
+++ b/extensions/dict_Rx/CMakeLists.txt
@@ -0,0 +1,16 @@
+# The dict_Rx extension
+PROJECT("dict_Rx library generated by FdGen " C)
+
+# Compile as a module
+FD_ADD_EXTENSION(dict_Rx dict_Rx.c)
+
+
+####
+## INSTALL section ##
+
+INSTALL(TARGETS dict_Rx
+	LIBRARY DESTINATION ${INSTALL_EXTENSIONS_SUFFIX}
+COMPONENT freeDiameter-dictionary-RX)
+
+
+
diff --git a/extensions/dict_Rx/Rx.did b/extensions/dict_Rx/Rx.did
new file mode 100644
index 0000000..8e16935
--- /dev/null
+++ b/extensions/dict_Rx/Rx.did
@@ -0,0 +1,39 @@
+dict_NAS
+dict_rfc6942_avps
+dict_rfc6734_avps
+dict_rfc5580_avps
+dict_ts29468_avps
+dict_ts29154_avps
+dict_ts29214_avps
+dict_ts29215_avps
+dict_ts29217_avps
+dict_3gpp2_avps
+dict_ts29343_avps
+dict_ts29128_avps
+dict_ts29344_avps
+dict_ts29345_avps
+dict_ts32299_avps
+dict_rfc5778_avps
+dict_ts29338_avps
+dict_ts29173_avps
+dict_ts29337_avps
+dict_etsi283034_avps
+dict_rfc4590_avps
+dict_ts29229_avps
+dict_draftload_avps
+dict_ts29329_avps
+dict_ts29368_avps
+dict_ts29336_avps
+dict_ts29061_avps
+dict_ts29272_avps
+dict_rfc7683_avps
+dict_rfc5777_avps
+dict_rfc4006bis_avps
+dict_ts29212_avps
+dict_rfc4072_avps
+dict_rfc5447_avps
+dict_ts29273_avps
+dict_rfc4004_avps
+dict_rfc7155_avps
+dict_rfc7944_avps
+dict_Rx
diff --git a/extensions/dict_Rx/dict_Rx.c b/extensions/dict_Rx/dict_Rx.c
new file mode 100644
index 0000000..19ad57d
--- /dev/null
+++ b/extensions/dict_Rx/dict_Rx.c
@@ -0,0 +1,471 @@
+/*
+* Copyright (c) 2017 Sprint
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*    http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+/****************
+ Generated By: fdtool enhancements to diafuzzer
+ License: same as freeDiameter
+****************/
+
+
+/* 
+ * Dictionary definitions of objects specified in Rx (e30).
+ */
+#include <freeDiameter/extension.h>
+
+#define PROTO_VER "e30"
+#define GEN_DATE  1506697208.6
+
+const char *rx_proto_ver = PROTO_VER;
+const double rx_gen_date = GEN_DATE;
+
+/* The content of this file follows the same structure as dict_base_proto.c */
+
+#define CHECK_dict_new( _type, _data, _parent, _ref )                                     \
+{                                                                                         \
+    int _ret = fd_dict_new( fd_g_config->cnf_dict, (_type), (_data), (_parent), (_ref) ); \
+    if ( _ret != 0 && _ret != EEXIST )                                                    \
+       return _ret;                                                                       \
+}
+
+#define CHECK_dict_search( _type, _criteria, _what, _result )		\
+    CHECK_FCT(  fd_dict_search( fd_g_config->cnf_dict, (_type), (_criteria), (_what), (_result), ENOENT) );
+
+struct local_rules_definition {
+    struct dict_avp_request avp_vendor_plus_name;
+    enum rule_position	position;
+    int 			min;
+    int			max;
+};
+
+#define RULE_ORDER( _position ) ((((_position) == RULE_FIXED_HEAD) || ((_position) == RULE_FIXED_TAIL)) ? 1 : 0 )
+
+/* Attention! This version of the macro uses AVP_BY_NAME_AND_VENDOR, in contrast to most other copies! */
+#define PARSE_loc_rules( _rulearray, _parent) {                                                         \
+        int __ar;                                                                                       \
+        for (__ar=0; __ar < sizeof(_rulearray) / sizeof((_rulearray)[0]); __ar++) {                     \
+                struct dict_rule_data __data = { NULL,                                                  \
+                        (_rulearray)[__ar].position,                                                    \
+                        0,                                                                              \
+                        (_rulearray)[__ar].min,                                                         \
+                        (_rulearray)[__ar].max};                                                        \
+                __data.rule_order = RULE_ORDER(__data.rule_position);                                   \
+                CHECK_FCT(  fd_dict_search(                                                             \
+                        fd_g_config->cnf_dict,                                                          \
+                        DICT_AVP,                                                                       \
+                        AVP_BY_NAME_AND_VENDOR,                                                         \
+                        &(_rulearray)[__ar].avp_vendor_plus_name,                                       \
+                        &__data.rule_avp, 0 ) );                                                        \
+                if ( !__data.rule_avp ) {                                                               \
+                        TRACE_DEBUG(INFO, "AVP Not found: '%s'", (_rulearray)[__ar].avp_vendor_plus_name.avp_name);             \
+                        return ENOENT;                                                                  \
+                }                                                                                       \
+                {                                                                                       \
+                         int _ret = fd_dict_new( fd_g_config->cnf_dict, DICT_RULE, &(__data), (_parent), NULL ); \
+                         if ( _ret != 0 && _ret != EEXIST )      {                                      \
+                                TRACE_DEBUG(INFO, "Error on rule with AVP '%s'",                        \
+                                            (_rulearray)[__ar].avp_vendor_plus_name.avp_name);          \
+                                return EINVAL;                                                          \
+                         }                                                                              \
+                }                                                                                       \
+        }                                                                                               \
+}
+
+#define CHECK_vendor_new( _data ) { \
+        struct dict_object * vendor_found; \
+        if (fd_dict_search(fd_g_config->cnf_dict,DICT_VENDOR,VENDOR_BY_ID,&_data.vendor_id,&vendor_found,ENOENT) == ENOENT) { \
+                CHECK_FCT(fd_dict_new(fd_g_config->cnf_dict, DICT_VENDOR, &_data, NULL, NULL)); \
+        } \
+}
+
+#define enumval_def_u32( _val_, _str_ )		\
+    { _str_, 		{ .u32 = _val_ }}
+
+#define enumval_def_os( _len_, _val_, _str_ )				\
+    { _str_, 		{ .os = { .data = (unsigned char *)_val_, .len = _len_ }}}
+
+
+static int dict_rx_load_defs(char * conffile)
+{
+   TRACE_ENTRY("%p", conffile);
+	struct dict_object * app_id16777224;
+	struct dict_object * app_id16777229;
+
+	/* Application Section */
+	{
+	  {
+			struct dict_object * vendor;
+			CHECK_dict_search(DICT_VENDOR, VENDOR_BY_NAME, "3GPP", &vendor)
+			struct dict_application_data data = { 16777224, "Rx" };
+			CHECK_dict_new( DICT_APPLICATION, &data, vendor, &app_id16777224)
+	  }
+	  {
+			struct dict_object * vendor;
+			CHECK_dict_search(DICT_VENDOR, VENDOR_BY_NAME, "3GPP", &vendor)
+			struct dict_application_data data = { 16777229, "Rx-app16777229" };
+			CHECK_dict_new( DICT_APPLICATION, &data, vendor, &app_id16777229)
+	  }
+	  /* Result codes */
+	  {
+			struct dict_object *type;
+			CHECK_dict_search(DICT_TYPE, TYPE_BY_NAME, "Enumerated(Result-Code)",&type);
+			struct dict_enumval_data        t_1 = { "REQUESTED_SERVICE_TEMPORARILY_NOT_AUTHORIZED", { .u32=4261 }};
+			struct dict_enumval_data        t_2 = { "INVALID_SERVICE_INFORMATION", { .u32=5061 }};
+			struct dict_enumval_data        t_3 = { "FILTER_RESTRICTIONS", { .u32=5062 }};
+			struct dict_enumval_data        t_4 = { "REQUESTED_SERVICE_NOT_AUTHORIZED", { .u32=5063 }};
+			struct dict_enumval_data        t_5 = { "DUPLICATED_AF_SESSION", { .u32=5064 }};
+			struct dict_enumval_data        t_6 = { "IP-CAN_SESSION_NOT_AVAILABLE", { .u32=5065 }};
+			struct dict_enumval_data        t_7 = { "UNAUTHORIZED_NON_EMERGENCY_SESSION", { .u32=5066 }};
+			struct dict_enumval_data        t_8 = { "UNAUTHORIZED_SPONSORED_DATA_CONNECTIVITY", { .u32=5067 }};
+			struct dict_enumval_data        t_9 = { "TEMPORARY_NETWORK_FAILURE", { .u32=5068 }};
+
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_3, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_4, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_5, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_6, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_7, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_8, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_9, type, NULL);
+
+	  }
+	}
+
+
+   /* AVP section */
+   {
+		struct dict_object * Address_type;
+		struct dict_object * UTF8String_type;
+		struct dict_object * DiameterIdentity_type;
+		struct dict_object * DiameterURI_type;
+		struct dict_object * Time_type;
+		struct dict_object * IPFilterRule_type;
+
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "Address", &Address_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "UTF8String", &UTF8String_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "DiameterIdentity", &DiameterIdentity_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "DiameterURI", &DiameterURI_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "Time", &Time_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "IPFilterRule", &IPFilterRule_type);
+
+	
+   }
+
+   /* Commands section */
+   {
+
+   }
+
+   return 0;
+}
+
+static int dict_rx_load_rules(char * conffile)
+{
+   /* Grouped AVP section */
+   {
+
+   }	
+
+   /* Commands section */
+   {
+	  /* AA-Request */
+	  {
+		struct dict_object* cmd;
+		CHECK_dict_search( DICT_COMMAND, CMD_BY_NAME, "AA-Request", &cmd)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 0, .avp_name = "Session-Id"}, RULE_FIXED_HEAD, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "DRMP"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Auth-Application-Id"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-Host"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-Realm"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Destination-Realm"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Destination-Host"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "IP-Domain-Id"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Auth-Session-State"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "AF-Application-Identifier"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Media-Component-Description"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Service-Info-Status"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "AF-Charging-Identifier"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "SIP-Forking-Indication"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Specific-Action"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Subscription-Id"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "OC-Supported-Features"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Supported-Features"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 13019, .avp_name = "Reservation-Priority"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Framed-IP-Address"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Framed-IPv6-Prefix"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Called-Station-Id"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Service-URN"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Sponsored-Connectivity-Data"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "MPS-Identifier"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "GCS-Identifier"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "MCPTT-Identifier"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Rx-Request-Type"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Required-Access-Info"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "AF-Requested-Data"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Reference-Id"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Pre-emption-Control-Info"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-State-Id"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Proxy-Info"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Route-Record"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules(rules, cmd);
+	  }
+	  /* AA-Answer */
+	  {
+		struct dict_object* cmd;
+		CHECK_dict_search( DICT_COMMAND, CMD_BY_NAME, "AA-Answer", &cmd)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 0, .avp_name = "Session-Id"}, RULE_FIXED_HEAD, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "DRMP"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Auth-Application-Id"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-Host"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-Realm"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Result-Code"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Experimental-Result"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Auth-Session-State"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Access-Network-Charging-Identifier"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Access-Network-Charging-Address"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Acceptable-Service-Info"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "AN-GW-Address"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "AN-Trusted"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Service-Authorization-Info"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "IP-CAN-Type"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "NetLoc-Access-Support"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "RAT-Type"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Flows"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "OC-Supported-Features"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "OC-OLR"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Supported-Features"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Subscription-Id"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "User-Equipment-Info"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "3GPP-SGSN-MCC-MNC"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Class"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Error-Message"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Error-Reporting-Host"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Failed-AVP"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Retry-Interval"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-State-Id"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Redirect-Host"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Redirect-Host-Usage"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Redirect-Max-Cache-Time"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Proxy-Info"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Load"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules(rules, cmd);
+	  }
+	  /* Re-Auth-Request */
+	  {
+		struct dict_object* cmd;
+		CHECK_dict_search( DICT_COMMAND, CMD_BY_NAME, "Re-Auth-Request", &cmd)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 0, .avp_name = "Session-Id"}, RULE_FIXED_HEAD, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "DRMP"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-Host"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-Realm"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Destination-Realm"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Destination-Host"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Auth-Application-Id"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Specific-Action"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "OC-Supported-Features"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Access-Network-Charging-Identifier"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Access-Network-Charging-Address"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "AN-GW-Address"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "AN-Trusted"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Flows"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Subscription-Id"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Abort-Cause"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "IP-CAN-Type"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "NetLoc-Access-Support"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "RAT-Type"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Sponsored-Connectivity-Data"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "3GPP-User-Location-Info"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "User-Location-Info-Time"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "3GPP-MS-TimeZone"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "RAN-NAS-Release-Cause"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "3GPP-SGSN-MCC-MNC"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "TWAN-Identifier"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "TCP-Source-Port"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "UDP-Source-Port"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "UE-Local-IP-Address"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-State-Id"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Class"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Proxy-Info"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Route-Record"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules(rules, cmd);
+	  }
+	  /* Re-Auth-Answer */
+	  {
+		struct dict_object* cmd;
+		CHECK_dict_search( DICT_COMMAND, CMD_BY_NAME, "Re-Auth-Answer", &cmd)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 0, .avp_name = "Session-Id"}, RULE_FIXED_HEAD, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "DRMP"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-Host"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-Realm"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Result-Code"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Experimental-Result"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "OC-Supported-Features"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "OC-OLR"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Media-Component-Description"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Service-URN"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-State-Id"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Class"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Error-Message"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Error-Reporting-Host"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Redirect-Host"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Redirect-Host-Usage"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Redirect-Max-Cache-Time"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Failed-AVP"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Proxy-Info"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules(rules, cmd);
+	  }
+	  /* Session-Termination-Request */
+	  {
+		struct dict_object* cmd;
+		CHECK_dict_search( DICT_COMMAND, CMD_BY_NAME, "Session-Termination-Request", &cmd)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 0, .avp_name = "Session-Id"}, RULE_FIXED_HEAD, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "DRMP"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-Host"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-Realm"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Destination-Realm"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Auth-Application-Id"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Termination-Cause"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Destination-Host"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "OC-Supported-Features"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Required-Access-Info"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Class"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-State-Id"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Proxy-Info"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Route-Record"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules(rules, cmd);
+	  }
+	  /* Session-Termination-Answer */
+	  {
+		struct dict_object* cmd;
+		CHECK_dict_search( DICT_COMMAND, CMD_BY_NAME, "Session-Termination-Answer", &cmd)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 0, .avp_name = "Session-Id"}, RULE_FIXED_HEAD, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "DRMP"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-Host"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-Realm"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Result-Code"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Error-Message"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Error-Reporting-Host"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "OC-Supported-Features"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "OC-OLR"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Failed-AVP"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Sponsored-Connectivity-Data"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-State-Id"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "3GPP-User-Location-Info"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "User-Location-Info-Time"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "3GPP-MS-TimeZone"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "RAN-NAS-Release-Cause"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "3GPP-SGSN-MCC-MNC"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "TWAN-Identifier"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "TCP-Source-Port"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "UDP-Source-Port"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "UE-Local-IP-Address"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "NetLoc-Access-Support"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Class"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Redirect-Host"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Redirect-Host-Usage"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Redirect-Max-Cache-Time"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Proxy-Info"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Load"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules(rules, cmd);
+	  }
+	  /* Abort-Session-Request */
+	  {
+		struct dict_object* cmd;
+		CHECK_dict_search( DICT_COMMAND, CMD_BY_NAME, "Abort-Session-Request", &cmd)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 0, .avp_name = "Session-Id"}, RULE_FIXED_HEAD, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "DRMP"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-Host"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-Realm"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Destination-Realm"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Destination-Host"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Auth-Application-Id"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "OC-Supported-Features"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Abort-Cause"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-State-Id"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Proxy-Info"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Route-Record"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules(rules, cmd);
+	  }
+	  /* Abort-Session-Answer */
+	  {
+		struct dict_object* cmd;
+		CHECK_dict_search( DICT_COMMAND, CMD_BY_NAME, "Abort-Session-Answer", &cmd)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 0, .avp_name = "Session-Id"}, RULE_FIXED_HEAD, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "DRMP"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-Host"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-Realm"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Result-Code"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "OC-Supported-Features"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "OC-OLR"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-State-Id"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Error-Message"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Error-Reporting-Host"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Failed-AVP"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Redirect-Host"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Redirect-Host-Usage"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Redirect-Max-Cache-Time"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Proxy-Info"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules(rules, cmd);
+	  }
+
+   }
+
+   LOG_D( "Extension 'Dictionary definitions for Rx (e30)' initialized");
+   return 0;
+}
+
+int dict_entry(char * conffile)
+{
+	dict_rx_load_defs(conffile);
+	return dict_rx_load_rules(conffile);
+}
+
+const char* dict_rx_proto_ver(char * conffile) {
+	return rx_proto_ver;
+}
+
+const double dict_rx_gen_ts(char * conffile) {
+	return rx_gen_date;
+}
+
+EXTENSION_ENTRY2("dict_rx", dict_rx_load_defs, dict_rx_load_rules, "dict_ts32299_avps", "dict_ts29214_avps", "dict_ts29212_avps", "dict_ts29273_avps", "dict_ts29229_avps", "dict_ts29154_avps", "dict_ts29061_avps", "dict_NAS", "dict_rfc4006bis_avps", "dict_draftload_avps", "dict_rfc7683_avps", "dict_rfc7155_avps", "dict_etsi283034_avps", "dict_rfc7944_avps");
+
+
+
diff --git a/extensions/dict_S6as6d/CMakeLists.txt b/extensions/dict_S6as6d/CMakeLists.txt
new file mode 100644
index 0000000..828900d
--- /dev/null
+++ b/extensions/dict_S6as6d/CMakeLists.txt
@@ -0,0 +1,16 @@
+# The dict_S6as6d extension
+PROJECT("dict_S6as6d library generated by FdGen " C)
+
+# Compile as a module
+FD_ADD_EXTENSION(dict_S6as6d dict_S6as6d.c)
+
+
+####
+## INSTALL section ##
+
+INSTALL(TARGETS dict_S6as6d
+	LIBRARY DESTINATION ${INSTALL_EXTENSIONS_SUFFIX}
+COMPONENT freeDiameter-dictionary-S6AS6D)
+
+
+
diff --git a/extensions/dict_S6as6d/S6as6d.did b/extensions/dict_S6as6d/S6as6d.did
new file mode 100644
index 0000000..b4bdb34
--- /dev/null
+++ b/extensions/dict_S6as6d/S6as6d.did
@@ -0,0 +1,38 @@
+dict_rfc6942_avps
+dict_ts29468_avps
+dict_ts29343_avps
+dict_ts29128_avps
+dict_ts29344_avps
+dict_ts29345_avps
+dict_ts29337_avps
+dict_3gpp2_avps
+dict_ts29154_avps
+dict_ts29214_avps
+dict_ts29215_avps
+dict_ts29217_avps
+dict_ts29338_avps
+dict_ts29173_avps
+dict_ts29336_avps
+dict_rfc4590_avps
+dict_ts29229_avps
+dict_ts29329_avps
+dict_ts29368_avps
+dict_ts32299_avps
+dict_rfc6734_avps
+dict_rfc5778_avps
+dict_draftload_avps
+dict_etsi283034_avps
+dict_rfc5580_avps
+dict_rfc4072_avps
+dict_ts29273_avps
+dict_ts29272_avps
+dict_rfc7683_avps
+dict_rfc7944_avps
+dict_rfc5777_avps
+dict_rfc4006bis_avps
+dict_rfc7155_avps
+dict_ts29212_avps
+dict_ts29061_avps
+dict_rfc4004_avps
+dict_rfc5447_avps
+dict_S6as6d
diff --git a/extensions/dict_S6as6d/dict_S6as6d.c b/extensions/dict_S6as6d/dict_S6as6d.c
new file mode 100644
index 0000000..c39b75d
--- /dev/null
+++ b/extensions/dict_S6as6d/dict_S6as6d.c
@@ -0,0 +1,722 @@
+/*
+* Copyright (c) 2017 Sprint
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*    http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+/****************
+ Generated By: fdtool enhancements to diafuzzer
+ License: same as freeDiameter
+****************/
+
+
+/* 
+ * Dictionary definitions of objects specified in S6as6d (e30).
+ */
+#include <freeDiameter/extension.h>
+
+#define PROTO_VER "e30"
+#define GEN_DATE  1506697194.55
+
+const char *s6as6d_proto_ver = PROTO_VER;
+const double s6as6d_gen_date = GEN_DATE;
+
+/* The content of this file follows the same structure as dict_base_proto.c */
+
+#define CHECK_dict_new( _type, _data, _parent, _ref )                                     \
+{                                                                                         \
+    int _ret = fd_dict_new( fd_g_config->cnf_dict, (_type), (_data), (_parent), (_ref) ); \
+    if ( _ret != 0 && _ret != EEXIST )                                                    \
+       return _ret;                                                                       \
+}
+
+#define CHECK_dict_search( _type, _criteria, _what, _result )		\
+    CHECK_FCT(  fd_dict_search( fd_g_config->cnf_dict, (_type), (_criteria), (_what), (_result), ENOENT) );
+
+struct local_rules_definition {
+    struct dict_avp_request avp_vendor_plus_name;
+    enum rule_position	position;
+    int 			min;
+    int			max;
+};
+
+#define RULE_ORDER( _position ) ((((_position) == RULE_FIXED_HEAD) || ((_position) == RULE_FIXED_TAIL)) ? 1 : 0 )
+
+/* Attention! This version of the macro uses AVP_BY_NAME_AND_VENDOR, in contrast to most other copies! */
+#define PARSE_loc_rules( _rulearray, _parent) {                                                         \
+        int __ar;                                                                                       \
+        for (__ar=0; __ar < sizeof(_rulearray) / sizeof((_rulearray)[0]); __ar++) {                     \
+                struct dict_rule_data __data = { NULL,                                                  \
+                        (_rulearray)[__ar].position,                                                    \
+                        0,                                                                              \
+                        (_rulearray)[__ar].min,                                                         \
+                        (_rulearray)[__ar].max};                                                        \
+                __data.rule_order = RULE_ORDER(__data.rule_position);                                   \
+                CHECK_FCT(  fd_dict_search(                                                             \
+                        fd_g_config->cnf_dict,                                                          \
+                        DICT_AVP,                                                                       \
+                        AVP_BY_NAME_AND_VENDOR,                                                         \
+                        &(_rulearray)[__ar].avp_vendor_plus_name,                                       \
+                        &__data.rule_avp, 0 ) );                                                        \
+                if ( !__data.rule_avp ) {                                                               \
+                        TRACE_DEBUG(INFO, "AVP Not found: '%s'", (_rulearray)[__ar].avp_vendor_plus_name.avp_name);             \
+                        return ENOENT;                                                                  \
+                }                                                                                       \
+                {                                                                                       \
+                         int _ret = fd_dict_new( fd_g_config->cnf_dict, DICT_RULE, &(__data), (_parent), NULL ); \
+                         if ( _ret != 0 && _ret != EEXIST )      {                                      \
+                                TRACE_DEBUG(INFO, "Error on rule with AVP '%s'",                        \
+                                            (_rulearray)[__ar].avp_vendor_plus_name.avp_name);          \
+                                return EINVAL;                                                          \
+                         }                                                                              \
+                }                                                                                       \
+        }                                                                                               \
+}
+
+#define CHECK_vendor_new( _data ) { \
+        struct dict_object * vendor_found; \
+        if (fd_dict_search(fd_g_config->cnf_dict,DICT_VENDOR,VENDOR_BY_ID,&_data.vendor_id,&vendor_found,ENOENT) == ENOENT) { \
+                CHECK_FCT(fd_dict_new(fd_g_config->cnf_dict, DICT_VENDOR, &_data, NULL, NULL)); \
+        } \
+}
+
+#define enumval_def_u32( _val_, _str_ )		\
+    { _str_, 		{ .u32 = _val_ }}
+
+#define enumval_def_os( _len_, _val_, _str_ )				\
+    { _str_, 		{ .os = { .data = (unsigned char *)_val_, .len = _len_ }}}
+
+
+static int dict_s6as6d_load_defs(char * conffile)
+{
+   TRACE_ENTRY("%p", conffile);
+	struct dict_object * app_id16777251;
+
+	/* Application Section */
+	{
+	  {
+			struct dict_object * vendor;
+			CHECK_dict_search(DICT_VENDOR, VENDOR_BY_NAME, "3GPP", &vendor)
+			struct dict_application_data data = { 16777251, "S6as6d" };
+			CHECK_dict_new( DICT_APPLICATION, &data, vendor, &app_id16777251)
+	  }
+	  /* Result codes */
+	  {
+			struct dict_object *type;
+			CHECK_dict_search(DICT_TYPE, TYPE_BY_NAME, "Enumerated(Result-Code)",&type);
+			struct dict_enumval_data        t_1 = { "General", { .u32=1 }};
+			struct dict_enumval_data        t_2 = { "HSS_behaviour", { .u32=2 }};
+			struct dict_enumval_data        t_3 = { "MME_SGSN_behaviour", { .u32=3 }};
+			struct dict_enumval_data        t_4 = { "Transient_Failures", { .u32=4 }};
+			struct dict_enumval_data        t_5 = { "User_identity_to_HSS_resolution", { .u32=8 }};
+
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_3, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_4, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_5, type, NULL);
+
+	  }
+	}
+
+
+   /* AVP section */
+   {
+		struct dict_object * Address_type;
+		struct dict_object * UTF8String_type;
+		struct dict_object * DiameterIdentity_type;
+		struct dict_object * DiameterURI_type;
+		struct dict_object * Time_type;
+		struct dict_object * IPFilterRule_type;
+
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "Address", &Address_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "UTF8String", &UTF8String_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "DiameterIdentity", &DiameterIdentity_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "DiameterURI", &DiameterURI_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "Time", &Time_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "IPFilterRule", &IPFilterRule_type);
+
+	
+   }
+
+   /* Commands section */
+   {
+		/* Update-Location-Request */
+		{
+			struct dict_object* cmd;
+			struct dict_cmd_data data = {
+				316,	/* Code */
+				"Update-Location-Request",	/* Name */
+				CMD_FLAG_REQUEST | CMD_FLAG_ERROR,	/* Fixed flags */
+				CMD_FLAG_REQUEST | CMD_FLAG_PROXIABLE,	/* Fixed flag values */
+			};
+
+			CHECK_dict_new( DICT_COMMAND, &data , app_id16777251, &cmd)
+		}
+		/* Update-Location-Answer */
+		{
+			struct dict_object* cmd;
+			struct dict_cmd_data data = {
+				316,	/* Code */
+				"Update-Location-Answer",	/* Name */
+				CMD_FLAG_REQUEST,	/* Fixed flags */
+				CMD_FLAG_PROXIABLE,	/* Fixed flag values */
+			};
+
+			CHECK_dict_new( DICT_COMMAND, &data , app_id16777251, &cmd)
+		}
+		/* Cancel-Location-Request */
+		{
+			struct dict_object* cmd;
+			struct dict_cmd_data data = {
+				317,	/* Code */
+				"Cancel-Location-Request",	/* Name */
+				CMD_FLAG_REQUEST | CMD_FLAG_ERROR,	/* Fixed flags */
+				CMD_FLAG_REQUEST | CMD_FLAG_PROXIABLE,	/* Fixed flag values */
+			};
+
+			CHECK_dict_new( DICT_COMMAND, &data , app_id16777251, &cmd)
+		}
+		/* Cancel-Location-Answer */
+		{
+			struct dict_object* cmd;
+			struct dict_cmd_data data = {
+				317,	/* Code */
+				"Cancel-Location-Answer",	/* Name */
+				CMD_FLAG_REQUEST,	/* Fixed flags */
+				CMD_FLAG_PROXIABLE,	/* Fixed flag values */
+			};
+
+			CHECK_dict_new( DICT_COMMAND, &data , app_id16777251, &cmd)
+		}
+		/* Authentication-Information-Request */
+		{
+			struct dict_object* cmd;
+			struct dict_cmd_data data = {
+				318,	/* Code */
+				"Authentication-Information-Request",	/* Name */
+				CMD_FLAG_REQUEST | CMD_FLAG_ERROR,	/* Fixed flags */
+				CMD_FLAG_REQUEST | CMD_FLAG_PROXIABLE,	/* Fixed flag values */
+			};
+
+			CHECK_dict_new( DICT_COMMAND, &data , app_id16777251, &cmd)
+		}
+		/* Authentication-Information-Answer */
+		{
+			struct dict_object* cmd;
+			struct dict_cmd_data data = {
+				318,	/* Code */
+				"Authentication-Information-Answer",	/* Name */
+				CMD_FLAG_REQUEST,	/* Fixed flags */
+				CMD_FLAG_PROXIABLE,	/* Fixed flag values */
+			};
+
+			CHECK_dict_new( DICT_COMMAND, &data , app_id16777251, &cmd)
+		}
+		/* Insert-Subscriber-Data-Request */
+		{
+			struct dict_object* cmd;
+			struct dict_cmd_data data = {
+				319,	/* Code */
+				"Insert-Subscriber-Data-Request",	/* Name */
+				CMD_FLAG_REQUEST | CMD_FLAG_ERROR,	/* Fixed flags */
+				CMD_FLAG_REQUEST | CMD_FLAG_PROXIABLE,	/* Fixed flag values */
+			};
+
+			CHECK_dict_new( DICT_COMMAND, &data , app_id16777251, &cmd)
+		}
+		/* Insert-Subscriber-Data-Answer */
+		{
+			struct dict_object* cmd;
+			struct dict_cmd_data data = {
+				319,	/* Code */
+				"Insert-Subscriber-Data-Answer",	/* Name */
+				CMD_FLAG_REQUEST,	/* Fixed flags */
+				CMD_FLAG_PROXIABLE,	/* Fixed flag values */
+			};
+
+			CHECK_dict_new( DICT_COMMAND, &data , app_id16777251, &cmd)
+		}
+		/* Delete-Subscriber-Data-Request */
+		{
+			struct dict_object* cmd;
+			struct dict_cmd_data data = {
+				320,	/* Code */
+				"Delete-Subscriber-Data-Request",	/* Name */
+				CMD_FLAG_REQUEST | CMD_FLAG_ERROR,	/* Fixed flags */
+				CMD_FLAG_REQUEST | CMD_FLAG_PROXIABLE,	/* Fixed flag values */
+			};
+
+			CHECK_dict_new( DICT_COMMAND, &data , app_id16777251, &cmd)
+		}
+		/* Delete-Subscriber-Data-Answer */
+		{
+			struct dict_object* cmd;
+			struct dict_cmd_data data = {
+				320,	/* Code */
+				"Delete-Subscriber-Data-Answer",	/* Name */
+				CMD_FLAG_REQUEST,	/* Fixed flags */
+				CMD_FLAG_PROXIABLE,	/* Fixed flag values */
+			};
+
+			CHECK_dict_new( DICT_COMMAND, &data , app_id16777251, &cmd)
+		}
+		/* Purge-UE-Request */
+		{
+			struct dict_object* cmd;
+			struct dict_cmd_data data = {
+				321,	/* Code */
+				"Purge-UE-Request",	/* Name */
+				CMD_FLAG_REQUEST | CMD_FLAG_ERROR,	/* Fixed flags */
+				CMD_FLAG_REQUEST | CMD_FLAG_PROXIABLE,	/* Fixed flag values */
+			};
+
+			CHECK_dict_new( DICT_COMMAND, &data , app_id16777251, &cmd)
+		}
+		/* Purge-UE-Answer */
+		{
+			struct dict_object* cmd;
+			struct dict_cmd_data data = {
+				321,	/* Code */
+				"Purge-UE-Answer",	/* Name */
+				CMD_FLAG_REQUEST,	/* Fixed flags */
+				CMD_FLAG_PROXIABLE,	/* Fixed flag values */
+			};
+
+			CHECK_dict_new( DICT_COMMAND, &data , app_id16777251, &cmd)
+		}
+		/* Reset-Request */
+		{
+			struct dict_object* cmd;
+			struct dict_cmd_data data = {
+				322,	/* Code */
+				"Reset-Request",	/* Name */
+				CMD_FLAG_REQUEST | CMD_FLAG_ERROR,	/* Fixed flags */
+				CMD_FLAG_REQUEST | CMD_FLAG_PROXIABLE,	/* Fixed flag values */
+			};
+
+			CHECK_dict_new( DICT_COMMAND, &data , app_id16777251, &cmd)
+		}
+		/* Reset-Answer */
+		{
+			struct dict_object* cmd;
+			struct dict_cmd_data data = {
+				322,	/* Code */
+				"Reset-Answer",	/* Name */
+				CMD_FLAG_REQUEST,	/* Fixed flags */
+				CMD_FLAG_PROXIABLE,	/* Fixed flag values */
+			};
+
+			CHECK_dict_new( DICT_COMMAND, &data , app_id16777251, &cmd)
+		}
+
+   }
+
+   return 0;
+}
+
+static int dict_s6as6d_load_rules(char * conffile)
+{
+   /* Grouped AVP section */
+   {
+
+   }	
+
+   /* Commands section */
+   {
+	  /* Update-Location-Request */
+	  {
+		struct dict_object* cmd;
+		CHECK_dict_search( DICT_COMMAND, CMD_BY_NAME, "Update-Location-Request", &cmd)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 0, .avp_name = "Session-Id"}, RULE_FIXED_HEAD, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "DRMP"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Vendor-Specific-Application-Id"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Auth-Session-State"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-Host"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-Realm"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Destination-Host"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Destination-Realm"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "User-Name"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "OC-Supported-Features"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Supported-Features"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Terminal-Information"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "RAT-Type"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "ULR-Flags"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "UE-SRVCC-Capability"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Visited-PLMN-Id"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "SGSN-Number"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Homogeneous-Support-of-IMS-Voice-Over-PS-Sessions"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "GMLC-Address"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Active-APN"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Equivalent-PLMN-List"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "MME-Number-for-MT-SMS"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "SMS-Register-Request"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "SGs-MME-Identity"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Coupled-Node-Diameter-ID"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Adjacent-PLMNs"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Supported-Services"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Proxy-Info"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Route-Record"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules(rules, cmd);
+	  }
+	  /* Update-Location-Answer */
+	  {
+		struct dict_object* cmd;
+		CHECK_dict_search( DICT_COMMAND, CMD_BY_NAME, "Update-Location-Answer", &cmd)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 0, .avp_name = "Session-Id"}, RULE_FIXED_HEAD, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "DRMP"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Vendor-Specific-Application-Id"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Result-Code"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Experimental-Result"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Error-Diagnostic"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Auth-Session-State"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-Host"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-Realm"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "OC-Supported-Features"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "OC-OLR"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Load"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Supported-Features"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "ULA-Flags"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Subscription-Data"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Reset-ID"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Failed-AVP"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Proxy-Info"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Route-Record"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules(rules, cmd);
+	  }
+	  /* Cancel-Location-Request */
+	  {
+		struct dict_object* cmd;
+		CHECK_dict_search( DICT_COMMAND, CMD_BY_NAME, "Cancel-Location-Request", &cmd)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 0, .avp_name = "Session-Id"}, RULE_FIXED_HEAD, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "DRMP"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Vendor-Specific-Application-Id"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Auth-Session-State"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-Host"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-Realm"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Destination-Host"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Destination-Realm"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "User-Name"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Supported-Features"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Cancellation-Type"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "CLR-Flags"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Proxy-Info"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Route-Record"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules(rules, cmd);
+	  }
+	  /* Cancel-Location-Answer */
+	  {
+		struct dict_object* cmd;
+		CHECK_dict_search( DICT_COMMAND, CMD_BY_NAME, "Cancel-Location-Answer", &cmd)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 0, .avp_name = "Session-Id"}, RULE_FIXED_HEAD, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "DRMP"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Vendor-Specific-Application-Id"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Supported-Features"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Result-Code"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Experimental-Result"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Auth-Session-State"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-Host"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-Realm"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Failed-AVP"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Proxy-Info"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Route-Record"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules(rules, cmd);
+	  }
+	  /* Authentication-Information-Request */
+	  {
+		struct dict_object* cmd;
+		CHECK_dict_search( DICT_COMMAND, CMD_BY_NAME, "Authentication-Information-Request", &cmd)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 0, .avp_name = "Session-Id"}, RULE_FIXED_HEAD, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "DRMP"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Vendor-Specific-Application-Id"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Auth-Session-State"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-Host"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-Realm"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Destination-Host"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Destination-Realm"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "User-Name"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "OC-Supported-Features"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Supported-Features"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Requested-EUTRAN-Authentication-Info"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Requested-UTRAN-GERAN-Authentication-Info"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Visited-PLMN-Id"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "AIR-Flags"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Proxy-Info"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Route-Record"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules(rules, cmd);
+	  }
+	  /* Authentication-Information-Answer */
+	  {
+		struct dict_object* cmd;
+		CHECK_dict_search( DICT_COMMAND, CMD_BY_NAME, "Authentication-Information-Answer", &cmd)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 0, .avp_name = "Session-Id"}, RULE_FIXED_HEAD, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "DRMP"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Vendor-Specific-Application-Id"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Result-Code"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Experimental-Result"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Error-Diagnostic"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Auth-Session-State"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-Host"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-Realm"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "OC-Supported-Features"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "OC-OLR"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Load"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Supported-Features"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Authentication-Info"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "UE-Usage-Type"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Failed-AVP"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Proxy-Info"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Route-Record"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules(rules, cmd);
+	  }
+	  /* Insert-Subscriber-Data-Request */
+	  {
+		struct dict_object* cmd;
+		CHECK_dict_search( DICT_COMMAND, CMD_BY_NAME, "Insert-Subscriber-Data-Request", &cmd)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 0, .avp_name = "Session-Id"}, RULE_FIXED_HEAD, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "DRMP"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Vendor-Specific-Application-Id"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Auth-Session-State"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-Host"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-Realm"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Destination-Host"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Destination-Realm"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "User-Name"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Supported-Features"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Subscription-Data"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "IDR-Flags"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Reset-ID"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Proxy-Info"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Route-Record"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules(rules, cmd);
+	  }
+	  /* Insert-Subscriber-Data-Answer */
+	  {
+		struct dict_object* cmd;
+		CHECK_dict_search( DICT_COMMAND, CMD_BY_NAME, "Insert-Subscriber-Data-Answer", &cmd)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 0, .avp_name = "Session-Id"}, RULE_FIXED_HEAD, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "DRMP"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Vendor-Specific-Application-Id"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Supported-Features"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Result-Code"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Experimental-Result"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Auth-Session-State"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-Host"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-Realm"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "IMS-Voice-Over-PS-Sessions-Supported"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Last-UE-Activity-Time"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "RAT-Type"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "IDA-Flags"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "EPS-User-State"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "EPS-Location-Information"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Local-Time-Zone"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Supported-Services"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Monitoring-Event-Report"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Monitoring-Event-Config-Status"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Failed-AVP"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Proxy-Info"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Route-Record"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules(rules, cmd);
+	  }
+	  /* Delete-Subscriber-Data-Request */
+	  {
+		struct dict_object* cmd;
+		CHECK_dict_search( DICT_COMMAND, CMD_BY_NAME, "Delete-Subscriber-Data-Request", &cmd)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 0, .avp_name = "Session-Id"}, RULE_FIXED_HEAD, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "DRMP"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Vendor-Specific-Application-Id"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Auth-Session-State"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-Host"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-Realm"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Destination-Host"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Destination-Realm"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "User-Name"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Supported-Features"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "DSR-Flags"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "SCEF-ID"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Context-Identifier"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Trace-Reference"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "TS-Code"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "SS-Code"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Proxy-Info"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Route-Record"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules(rules, cmd);
+	  }
+	  /* Delete-Subscriber-Data-Answer */
+	  {
+		struct dict_object* cmd;
+		CHECK_dict_search( DICT_COMMAND, CMD_BY_NAME, "Delete-Subscriber-Data-Answer", &cmd)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 0, .avp_name = "Session-Id"}, RULE_FIXED_HEAD, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "DRMP"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Vendor-Specific-Application-Id"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Supported-Features"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Result-Code"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Experimental-Result"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Auth-Session-State"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-Host"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-Realm"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "DSA-Flags"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Failed-AVP"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Proxy-Info"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Route-Record"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules(rules, cmd);
+	  }
+	  /* Purge-UE-Request */
+	  {
+		struct dict_object* cmd;
+		CHECK_dict_search( DICT_COMMAND, CMD_BY_NAME, "Purge-UE-Request", &cmd)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 0, .avp_name = "Session-Id"}, RULE_FIXED_HEAD, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "DRMP"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Vendor-Specific-Application-Id"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Auth-Session-State"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-Host"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-Realm"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Destination-Host"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Destination-Realm"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "User-Name"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "OC-Supported-Features"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "PUR-Flags"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Supported-Features"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "EPS-Location-Information"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Proxy-Info"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Route-Record"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules(rules, cmd);
+	  }
+	  /* Purge-UE-Answer */
+	  {
+		struct dict_object* cmd;
+		CHECK_dict_search( DICT_COMMAND, CMD_BY_NAME, "Purge-UE-Answer", &cmd)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 0, .avp_name = "Session-Id"}, RULE_FIXED_HEAD, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "DRMP"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Vendor-Specific-Application-Id"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Supported-Features"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Result-Code"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Experimental-Result"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Auth-Session-State"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-Host"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-Realm"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "OC-Supported-Features"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "OC-OLR"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Load"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "PUA-Flags"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Failed-AVP"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Proxy-Info"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Route-Record"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules(rules, cmd);
+	  }
+	  /* Reset-Request */
+	  {
+		struct dict_object* cmd;
+		CHECK_dict_search( DICT_COMMAND, CMD_BY_NAME, "Reset-Request", &cmd)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 0, .avp_name = "Session-Id"}, RULE_FIXED_HEAD, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "DRMP"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Vendor-Specific-Application-Id"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Auth-Session-State"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-Host"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-Realm"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Destination-Host"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Destination-Realm"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Supported-Features"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "User-Id"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Reset-ID"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Subscription-Data"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Subscription-Data-Deletion"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Proxy-Info"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Route-Record"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules(rules, cmd);
+	  }
+	  /* Reset-Answer */
+	  {
+		struct dict_object* cmd;
+		CHECK_dict_search( DICT_COMMAND, CMD_BY_NAME, "Reset-Answer", &cmd)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 0, .avp_name = "Session-Id"}, RULE_FIXED_HEAD, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "DRMP"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Vendor-Specific-Application-Id"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Supported-Features"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Result-Code"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Experimental-Result"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Auth-Session-State"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-Host"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-Realm"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Failed-AVP"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Proxy-Info"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Route-Record"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules(rules, cmd);
+	  }
+
+   }
+
+   LOG_D( "Extension 'Dictionary definitions for S6as6d (e30)' initialized");
+   return 0;
+}
+
+int dict_entry(char * conffile)
+{
+	dict_s6as6d_load_defs(conffile);
+	return dict_s6as6d_load_rules(conffile);
+}
+
+const char* dict_s6as6d_proto_ver(char * conffile) {
+	return s6as6d_proto_ver;
+}
+
+const double dict_s6as6d_gen_ts(char * conffile) {
+	return s6as6d_gen_date;
+}
+
+EXTENSION_ENTRY2("dict_s6as6d", dict_s6as6d_load_defs, dict_s6as6d_load_rules, "dict_ts29272_avps", "dict_ts32299_avps", "dict_ts29273_avps", "dict_ts29336_avps", "dict_ts29212_avps", "dict_ts29214_avps", "dict_ts29344_avps", "dict_ts29338_avps", "dict_ts29217_avps", "dict_ts29173_avps", "dict_ts29329_avps", "dict_ts29229_avps", "dict_rfc5778_avps", "dict_ts29061_avps", "dict_rfc5447_avps", "dict_draftload_avps", "dict_rfc7683_avps", "dict_rfc4004_avps", "dict_rfc5777_avps", "dict_rfc7944_avps");
+
+
+
diff --git a/extensions/dict_S6c/CMakeLists.txt b/extensions/dict_S6c/CMakeLists.txt
new file mode 100644
index 0000000..469e515
--- /dev/null
+++ b/extensions/dict_S6c/CMakeLists.txt
@@ -0,0 +1,16 @@
+# The S6c extension
+PROJECT("S6c library generated by FdGen " C)
+
+# Compile as a module
+FD_ADD_EXTENSION(dict_S6c dict_S6c.c)
+
+
+####
+## INSTALL section ##
+
+INSTALL(TARGETS dict_S6c
+	LIBRARY DESTINATION ${INSTALL_EXTENSIONS_SUFFIX}
+COMPONENT freeDiameter-dictionary-S6C)
+
+
+
diff --git a/extensions/dict_S6c/S6c.did b/extensions/dict_S6c/S6c.did
new file mode 100644
index 0000000..1dbb9db
--- /dev/null
+++ b/extensions/dict_S6c/S6c.did
@@ -0,0 +1,38 @@
+dict_rfc6942_avps
+dict_ts29468_avps
+dict_ts29154_avps
+dict_ts29214_avps
+dict_ts29215_avps
+dict_ts29217_avps
+dict_3gpp2_avps
+dict_ts29343_avps
+dict_ts29338_avps
+dict_ts29128_avps
+dict_ts29344_avps
+dict_ts29345_avps
+dict_ts32299_avps
+dict_rfc6734_avps
+dict_rfc5778_avps
+dict_rfc5580_avps
+dict_rfc4072_avps
+dict_ts29273_avps
+dict_rfc5777_avps
+dict_rfc4006bis_avps
+dict_ts29212_avps
+dict_ts29061_avps
+dict_rfc5447_avps
+dict_ts29272_avps
+dict_ts29173_avps
+dict_ts29337_avps
+dict_etsi283034_avps
+dict_rfc4590_avps
+dict_rfc4004_avps
+dict_rfc7155_avps
+dict_ts29229_avps
+dict_rfc7683_avps
+dict_draftload_avps
+dict_ts29329_avps
+dict_ts29368_avps
+dict_ts29336_avps
+dict_rfc7944_avps
+dict_S6c
diff --git a/extensions/dict_S6c/dict_S6c.c b/extensions/dict_S6c/dict_S6c.c
new file mode 100644
index 0000000..6e06b83
--- /dev/null
+++ b/extensions/dict_S6c/dict_S6c.c
@@ -0,0 +1,413 @@
+/*
+* Copyright (c) 2017 Sprint
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*    http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+/****************
+ Generated By: fdtool enhancements to diafuzzer
+ License: same as freeDiameter
+****************/
+
+
+/* 
+ * Dictionary definitions of objects specified in S6c (e10).
+ */
+#include <freeDiameter/extension.h>
+
+#define PROTO_VER "e10"
+#define GEN_DATE  1506697121.53
+
+const char *s6c_proto_ver = PROTO_VER;
+const double s6c_gen_date = GEN_DATE;
+
+/* The content of this file follows the same structure as dict_base_proto.c */
+
+#define CHECK_dict_new( _type, _data, _parent, _ref )                                     \
+{                                                                                         \
+    int _ret = fd_dict_new( fd_g_config->cnf_dict, (_type), (_data), (_parent), (_ref) ); \
+    if ( _ret != 0 && _ret != EEXIST )                                                    \
+       return _ret;                                                                       \
+}
+
+#define CHECK_dict_search( _type, _criteria, _what, _result )		\
+    CHECK_FCT(  fd_dict_search( fd_g_config->cnf_dict, (_type), (_criteria), (_what), (_result), ENOENT) );
+
+struct local_rules_definition {
+    struct dict_avp_request avp_vendor_plus_name;
+    enum rule_position	position;
+    int 			min;
+    int			max;
+};
+
+#define RULE_ORDER( _position ) ((((_position) == RULE_FIXED_HEAD) || ((_position) == RULE_FIXED_TAIL)) ? 1 : 0 )
+
+/* Attention! This version of the macro uses AVP_BY_NAME_AND_VENDOR, in contrast to most other copies! */
+#define PARSE_loc_rules( _rulearray, _parent) {                                                         \
+        int __ar;                                                                                       \
+        for (__ar=0; __ar < sizeof(_rulearray) / sizeof((_rulearray)[0]); __ar++) {                     \
+                struct dict_rule_data __data = { NULL,                                                  \
+                        (_rulearray)[__ar].position,                                                    \
+                        0,                                                                              \
+                        (_rulearray)[__ar].min,                                                         \
+                        (_rulearray)[__ar].max};                                                        \
+                __data.rule_order = RULE_ORDER(__data.rule_position);                                   \
+                CHECK_FCT(  fd_dict_search(                                                             \
+                        fd_g_config->cnf_dict,                                                          \
+                        DICT_AVP,                                                                       \
+                        AVP_BY_NAME_AND_VENDOR,                                                         \
+                        &(_rulearray)[__ar].avp_vendor_plus_name,                                       \
+                        &__data.rule_avp, 0 ) );                                                        \
+                if ( !__data.rule_avp ) {                                                               \
+                        TRACE_DEBUG(INFO, "AVP Not found: '%s'", (_rulearray)[__ar].avp_vendor_plus_name.avp_name);             \
+                        return ENOENT;                                                                  \
+                }                                                                                       \
+                {                                                                                       \
+                         int _ret = fd_dict_new( fd_g_config->cnf_dict, DICT_RULE, &(__data), (_parent), NULL ); \
+                         if ( _ret != 0 && _ret != EEXIST )      {                                      \
+                                TRACE_DEBUG(INFO, "Error on rule with AVP '%s'",                        \
+                                            (_rulearray)[__ar].avp_vendor_plus_name.avp_name);          \
+                                return EINVAL;                                                          \
+                         }                                                                              \
+                }                                                                                       \
+        }                                                                                               \
+}
+
+#define CHECK_vendor_new( _data ) { \
+        struct dict_object * vendor_found; \
+        if (fd_dict_search(fd_g_config->cnf_dict,DICT_VENDOR,VENDOR_BY_ID,&_data.vendor_id,&vendor_found,ENOENT) == ENOENT) { \
+                CHECK_FCT(fd_dict_new(fd_g_config->cnf_dict, DICT_VENDOR, &_data, NULL, NULL)); \
+        } \
+}
+
+#define enumval_def_u32( _val_, _str_ )		\
+    { _str_, 		{ .u32 = _val_ }}
+
+#define enumval_def_os( _len_, _val_, _str_ )				\
+    { _str_, 		{ .os = { .data = (unsigned char *)_val_, .len = _len_ }}}
+
+
+static int dict_s6c_load_defs(char * conffile)
+{
+   TRACE_ENTRY("%p", conffile);
+	struct dict_object * app_id16777312;
+
+	/* Application Section */
+	{
+	  {
+			struct dict_object * vendor;
+			CHECK_dict_search(DICT_VENDOR, VENDOR_BY_NAME, "3GPP", &vendor)
+			struct dict_application_data data = { 16777312, "S6c" };
+			CHECK_dict_new( DICT_APPLICATION, &data, vendor, &app_id16777312)
+	  }
+	  /* Result codes */
+	  {
+			struct dict_object *type;
+			CHECK_dict_search(DICT_TYPE, TYPE_BY_NAME, "Enumerated(Result-Code)",&type);
+			struct dict_enumval_data        t_1 = { "General", { .u32=1 }};
+			struct dict_enumval_data        t_2 = { "Permanent_Failures", { .u32=3 }};
+			struct dict_enumval_data        t_3 = { "Transient_Failures", { .u32=4 }};
+
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_3, type, NULL);
+
+	  }
+	}
+
+
+   /* AVP section */
+   {
+		struct dict_object * Address_type;
+		struct dict_object * UTF8String_type;
+		struct dict_object * DiameterIdentity_type;
+		struct dict_object * DiameterURI_type;
+		struct dict_object * Time_type;
+		struct dict_object * IPFilterRule_type;
+
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "Address", &Address_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "UTF8String", &UTF8String_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "DiameterIdentity", &DiameterIdentity_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "DiameterURI", &DiameterURI_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "Time", &Time_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "IPFilterRule", &IPFilterRule_type);
+
+	
+   }
+
+   /* Commands section */
+   {
+		/* Send-Routing-Info-for-SM-Request */
+		{
+			struct dict_object* cmd;
+			struct dict_cmd_data data = {
+				8388647,	/* Code */
+				"Send-Routing-Info-for-SM-Request",	/* Name */
+				CMD_FLAG_REQUEST | CMD_FLAG_ERROR,	/* Fixed flags */
+				CMD_FLAG_REQUEST | CMD_FLAG_PROXIABLE,	/* Fixed flag values */
+			};
+
+			CHECK_dict_new( DICT_COMMAND, &data , app_id16777312, &cmd)
+		}
+		/* Send-Routing-Info-for-SM-Answer */
+		{
+			struct dict_object* cmd;
+			struct dict_cmd_data data = {
+				8388647,	/* Code */
+				"Send-Routing-Info-for-SM-Answer",	/* Name */
+				CMD_FLAG_REQUEST,	/* Fixed flags */
+				CMD_FLAG_PROXIABLE,	/* Fixed flag values */
+			};
+
+			CHECK_dict_new( DICT_COMMAND, &data , app_id16777312, &cmd)
+		}
+		/* Alert-Service-Centre-Request */
+		{
+			struct dict_object* cmd;
+			struct dict_cmd_data data = {
+				8388648,	/* Code */
+				"Alert-Service-Centre-Request",	/* Name */
+				CMD_FLAG_REQUEST | CMD_FLAG_ERROR,	/* Fixed flags */
+				CMD_FLAG_REQUEST | CMD_FLAG_PROXIABLE,	/* Fixed flag values */
+			};
+
+			CHECK_dict_new( DICT_COMMAND, &data , app_id16777312, &cmd)
+		}
+		/* Alert-Service-Centre-Answer */
+		{
+			struct dict_object* cmd;
+			struct dict_cmd_data data = {
+				8388648,	/* Code */
+				"Alert-Service-Centre-Answer",	/* Name */
+				CMD_FLAG_REQUEST,	/* Fixed flags */
+				CMD_FLAG_PROXIABLE,	/* Fixed flag values */
+			};
+
+			CHECK_dict_new( DICT_COMMAND, &data , app_id16777312, &cmd)
+		}
+		/* Report-SM-Delivery-Status-Request */
+		{
+			struct dict_object* cmd;
+			struct dict_cmd_data data = {
+				8388649,	/* Code */
+				"Report-SM-Delivery-Status-Request",	/* Name */
+				CMD_FLAG_REQUEST | CMD_FLAG_ERROR,	/* Fixed flags */
+				CMD_FLAG_REQUEST | CMD_FLAG_PROXIABLE,	/* Fixed flag values */
+			};
+
+			CHECK_dict_new( DICT_COMMAND, &data , app_id16777312, &cmd)
+		}
+		/* Report-SM-Delivery-Status-Answer */
+		{
+			struct dict_object* cmd;
+			struct dict_cmd_data data = {
+				8388649,	/* Code */
+				"Report-SM-Delivery-Status-Answer",	/* Name */
+				CMD_FLAG_REQUEST,	/* Fixed flags */
+				CMD_FLAG_PROXIABLE,	/* Fixed flag values */
+			};
+
+			CHECK_dict_new( DICT_COMMAND, &data , app_id16777312, &cmd)
+		}
+
+   }
+
+   return 0;
+}
+
+static int dict_s6c_load_rules(char * conffile)
+{
+   /* Grouped AVP section */
+   {
+
+   }	
+
+   /* Commands section */
+   {
+	  /* Send-Routing-Info-for-SM-Request */
+	  {
+		struct dict_object* cmd;
+		CHECK_dict_search( DICT_COMMAND, CMD_BY_NAME, "Send-Routing-Info-for-SM-Request", &cmd)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 0, .avp_name = "Session-Id"}, RULE_FIXED_HEAD, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "DRMP"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Vendor-Specific-Application-Id"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Auth-Session-State"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-Host"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-Realm"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Destination-Host"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Destination-Realm"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "MSISDN"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "User-Name"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "SMSMI-Correlation-ID"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Supported-Features"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "SC-Address"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "SM-RP-MTI"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "SM-RP-SMEA"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "SRR-Flags"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "SM-Delivery-Not-Intended"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Proxy-Info"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Route-Record"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules(rules, cmd);
+	  }
+	  /* Send-Routing-Info-for-SM-Answer */
+	  {
+		struct dict_object* cmd;
+		CHECK_dict_search( DICT_COMMAND, CMD_BY_NAME, "Send-Routing-Info-for-SM-Answer", &cmd)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 0, .avp_name = "Session-Id"}, RULE_FIXED_HEAD, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "DRMP"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Vendor-Specific-Application-Id"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Result-Code"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Experimental-Result"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Auth-Session-State"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-Host"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-Realm"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "User-Name"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Supported-Features"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Serving-Node"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Additional-Serving-Node"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "LMSI"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "User-Identifier"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "MWD-Status"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "MME-Absent-User-Diagnostic-SM"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "MSC-Absent-User-Diagnostic-SM"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "SGSN-Absent-User-Diagnostic-SM"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Failed-AVP"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Proxy-Info"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Route-Record"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules(rules, cmd);
+	  }
+	  /* Alert-Service-Centre-Request */
+	  {
+		struct dict_object* cmd;
+		CHECK_dict_search( DICT_COMMAND, CMD_BY_NAME, "Alert-Service-Centre-Request", &cmd)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 0, .avp_name = "Session-Id"}, RULE_FIXED_HEAD, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "DRMP"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Vendor-Specific-Application-Id"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Auth-Session-State"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-Host"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-Realm"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Destination-Host"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Destination-Realm"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "SC-Address"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "User-Identifier"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "SMSMI-Correlation-ID"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Maximum-UE-Availability-Time"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "SMS-GMSC-Alert-Event"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Serving-Node"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Supported-Features"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Proxy-Info"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Route-Record"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules(rules, cmd);
+	  }
+	  /* Alert-Service-Centre-Answer */
+	  {
+		struct dict_object* cmd;
+		CHECK_dict_search( DICT_COMMAND, CMD_BY_NAME, "Alert-Service-Centre-Answer", &cmd)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 0, .avp_name = "Session-Id"}, RULE_FIXED_HEAD, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "DRMP"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Vendor-Specific-Application-Id"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Result-Code"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Experimental-Result"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Auth-Session-State"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-Host"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-Realm"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Supported-Features"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Failed-AVP"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Proxy-Info"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Route-Record"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules(rules, cmd);
+	  }
+	  /* Report-SM-Delivery-Status-Request */
+	  {
+		struct dict_object* cmd;
+		CHECK_dict_search( DICT_COMMAND, CMD_BY_NAME, "Report-SM-Delivery-Status-Request", &cmd)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 0, .avp_name = "Session-Id"}, RULE_FIXED_HEAD, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "DRMP"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Vendor-Specific-Application-Id"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Auth-Session-State"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-Host"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-Realm"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Destination-Host"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Destination-Realm"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Supported-Features"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "User-Identifier"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "SMSMI-Correlation-ID"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "SC-Address"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "SM-Delivery-Outcome"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "RDR-Flags"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Proxy-Info"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Route-Record"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules(rules, cmd);
+	  }
+	  /* Report-SM-Delivery-Status-Answer */
+	  {
+		struct dict_object* cmd;
+		CHECK_dict_search( DICT_COMMAND, CMD_BY_NAME, "Report-SM-Delivery-Status-Answer", &cmd)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 0, .avp_name = "Session-Id"}, RULE_FIXED_HEAD, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "DRMP"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Vendor-Specific-Application-Id"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Result-Code"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Experimental-Result"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Auth-Session-State"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-Host"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-Realm"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Supported-Features"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "User-Identifier"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Failed-AVP"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Proxy-Info"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Route-Record"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules(rules, cmd);
+	  }
+
+   }
+
+   LOG_D( "Extension 'Dictionary definitions for S6c (e10)' initialized");
+   return 0;
+}
+
+int dict_entry(char * conffile)
+{
+	dict_s6c_load_defs(conffile);
+	return dict_s6c_load_rules(conffile);
+}
+
+const char* dict_s6c_proto_ver(char * conffile) {
+	return s6c_proto_ver;
+}
+
+const double dict_s6c_gen_ts(char * conffile) {
+	return s6c_gen_date;
+}
+
+EXTENSION_ENTRY2("dict_s6c", dict_s6c_load_defs, dict_s6c_load_rules, "dict_ts29338_avps", "dict_ts29272_avps", "dict_ts29336_avps", "dict_ts29173_avps", "dict_ts29329_avps", "dict_ts29229_avps", "dict_rfc7944_avps");
+
+
+
diff --git a/extensions/dict_S6mS6n/CMakeLists.txt b/extensions/dict_S6mS6n/CMakeLists.txt
new file mode 100644
index 0000000..2df2008
--- /dev/null
+++ b/extensions/dict_S6mS6n/CMakeLists.txt
@@ -0,0 +1,16 @@
+# The dict_S6mS6n extension
+PROJECT("dict_S6mS6n library generated by FdGen " C)
+
+# Compile as a module
+FD_ADD_EXTENSION(dict_S6mS6n dict_S6mS6n.c)
+
+
+####
+## INSTALL section ##
+
+INSTALL(TARGETS dict_S6mS6n
+	LIBRARY DESTINATION ${INSTALL_EXTENSIONS_SUFFIX}
+COMPONENT freeDiameter-dictionary-S6MS6N)
+
+
+
diff --git a/extensions/dict_S6mS6n/S6mS6n.did b/extensions/dict_S6mS6n/S6mS6n.did
new file mode 100644
index 0000000..07aba84
--- /dev/null
+++ b/extensions/dict_S6mS6n/S6mS6n.did
@@ -0,0 +1,38 @@
+dict_rfc6942_avps
+dict_ts29468_avps
+dict_ts29154_avps
+dict_ts29214_avps
+dict_ts29215_avps
+dict_ts29217_avps
+dict_3gpp2_avps
+dict_ts29337_avps
+dict_ts29343_avps
+dict_ts29338_avps
+dict_ts29128_avps
+dict_ts29344_avps
+dict_ts29345_avps
+dict_ts29173_avps
+dict_ts32299_avps
+dict_rfc6734_avps
+dict_rfc5580_avps
+dict_rfc4072_avps
+dict_ts29273_avps
+dict_rfc4006bis_avps
+dict_ts29212_avps
+dict_ts29061_avps
+dict_ts29272_avps
+dict_rfc5447_avps
+dict_rfc5778_avps
+dict_rfc5777_avps
+dict_ts29336_avps
+dict_etsi283034_avps
+dict_rfc4590_avps
+dict_rfc4004_avps
+dict_rfc7155_avps
+dict_ts29229_avps
+dict_rfc7683_avps
+dict_draftload_avps
+dict_rfc7944_avps
+dict_ts29329_avps
+dict_ts29368_avps
+dict_S6mS6n
diff --git a/extensions/dict_S6mS6n/dict_S6mS6n.c b/extensions/dict_S6mS6n/dict_S6mS6n.c
new file mode 100644
index 0000000..94b38c7
--- /dev/null
+++ b/extensions/dict_S6mS6n/dict_S6mS6n.c
@@ -0,0 +1,250 @@
+/*
+* Copyright (c) 2017 Sprint
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*    http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+/****************
+ Generated By: fdtool enhancements to diafuzzer
+ License: same as freeDiameter
+****************/
+
+
+/* 
+ * Dictionary definitions of objects specified in S6mS6n (e10).
+ */
+#include <freeDiameter/extension.h>
+
+#define PROTO_VER "e10"
+#define GEN_DATE  1506697197.86
+
+const char *s6ms6n_proto_ver = PROTO_VER;
+const double s6ms6n_gen_date = GEN_DATE;
+
+/* The content of this file follows the same structure as dict_base_proto.c */
+
+#define CHECK_dict_new( _type, _data, _parent, _ref )                                     \
+{                                                                                         \
+    int _ret = fd_dict_new( fd_g_config->cnf_dict, (_type), (_data), (_parent), (_ref) ); \
+    if ( _ret != 0 && _ret != EEXIST )                                                    \
+       return _ret;                                                                       \
+}
+
+#define CHECK_dict_search( _type, _criteria, _what, _result )		\
+    CHECK_FCT(  fd_dict_search( fd_g_config->cnf_dict, (_type), (_criteria), (_what), (_result), ENOENT) );
+
+struct local_rules_definition {
+    struct dict_avp_request avp_vendor_plus_name;
+    enum rule_position	position;
+    int 			min;
+    int			max;
+};
+
+#define RULE_ORDER( _position ) ((((_position) == RULE_FIXED_HEAD) || ((_position) == RULE_FIXED_TAIL)) ? 1 : 0 )
+
+/* Attention! This version of the macro uses AVP_BY_NAME_AND_VENDOR, in contrast to most other copies! */
+#define PARSE_loc_rules( _rulearray, _parent) {                                                         \
+        int __ar;                                                                                       \
+        for (__ar=0; __ar < sizeof(_rulearray) / sizeof((_rulearray)[0]); __ar++) {                     \
+                struct dict_rule_data __data = { NULL,                                                  \
+                        (_rulearray)[__ar].position,                                                    \
+                        0,                                                                              \
+                        (_rulearray)[__ar].min,                                                         \
+                        (_rulearray)[__ar].max};                                                        \
+                __data.rule_order = RULE_ORDER(__data.rule_position);                                   \
+                CHECK_FCT(  fd_dict_search(                                                             \
+                        fd_g_config->cnf_dict,                                                          \
+                        DICT_AVP,                                                                       \
+                        AVP_BY_NAME_AND_VENDOR,                                                         \
+                        &(_rulearray)[__ar].avp_vendor_plus_name,                                       \
+                        &__data.rule_avp, 0 ) );                                                        \
+                if ( !__data.rule_avp ) {                                                               \
+                        TRACE_DEBUG(INFO, "AVP Not found: '%s'", (_rulearray)[__ar].avp_vendor_plus_name.avp_name);             \
+                        return ENOENT;                                                                  \
+                }                                                                                       \
+                {                                                                                       \
+                         int _ret = fd_dict_new( fd_g_config->cnf_dict, DICT_RULE, &(__data), (_parent), NULL ); \
+                         if ( _ret != 0 && _ret != EEXIST )      {                                      \
+                                TRACE_DEBUG(INFO, "Error on rule with AVP '%s'",                        \
+                                            (_rulearray)[__ar].avp_vendor_plus_name.avp_name);          \
+                                return EINVAL;                                                          \
+                         }                                                                              \
+                }                                                                                       \
+        }                                                                                               \
+}
+
+#define CHECK_vendor_new( _data ) { \
+        struct dict_object * vendor_found; \
+        if (fd_dict_search(fd_g_config->cnf_dict,DICT_VENDOR,VENDOR_BY_ID,&_data.vendor_id,&vendor_found,ENOENT) == ENOENT) { \
+                CHECK_FCT(fd_dict_new(fd_g_config->cnf_dict, DICT_VENDOR, &_data, NULL, NULL)); \
+        } \
+}
+
+#define enumval_def_u32( _val_, _str_ )		\
+    { _str_, 		{ .u32 = _val_ }}
+
+#define enumval_def_os( _len_, _val_, _str_ )				\
+    { _str_, 		{ .os = { .data = (unsigned char *)_val_, .len = _len_ }}}
+
+
+static int dict_s6ms6n_load_defs(char * conffile)
+{
+   TRACE_ENTRY("%p", conffile);
+	struct dict_object * app_id16777310;
+
+	/* Application Section */
+	{
+	  {
+			struct dict_object * vendor;
+			CHECK_dict_search(DICT_VENDOR, VENDOR_BY_NAME, "3GPP", &vendor)
+			struct dict_application_data data = { 16777310, "S6mS6n" };
+			CHECK_dict_new( DICT_APPLICATION, &data, vendor, &app_id16777310)
+	  }
+	}
+
+
+   /* AVP section */
+   {
+		struct dict_object * Address_type;
+		struct dict_object * UTF8String_type;
+		struct dict_object * DiameterIdentity_type;
+		struct dict_object * DiameterURI_type;
+		struct dict_object * Time_type;
+		struct dict_object * IPFilterRule_type;
+
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "Address", &Address_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "UTF8String", &UTF8String_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "DiameterIdentity", &DiameterIdentity_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "DiameterURI", &DiameterURI_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "Time", &Time_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "IPFilterRule", &IPFilterRule_type);
+
+	
+   }
+
+   /* Commands section */
+   {
+		/* Subscriber-Information-Request */
+		{
+			struct dict_object* cmd;
+			struct dict_cmd_data data = {
+				8388641,	/* Code */
+				"Subscriber-Information-Request",	/* Name */
+				CMD_FLAG_REQUEST | CMD_FLAG_ERROR,	/* Fixed flags */
+				CMD_FLAG_REQUEST | CMD_FLAG_PROXIABLE,	/* Fixed flag values */
+			};
+
+			CHECK_dict_new( DICT_COMMAND, &data , app_id16777310, &cmd)
+		}
+		/* Subscriber-Information-Answer */
+		{
+			struct dict_object* cmd;
+			struct dict_cmd_data data = {
+				8388641,	/* Code */
+				"Subscriber-Information-Answer",	/* Name */
+				CMD_FLAG_REQUEST,	/* Fixed flags */
+				CMD_FLAG_PROXIABLE,	/* Fixed flag values */
+			};
+
+			CHECK_dict_new( DICT_COMMAND, &data , app_id16777310, &cmd)
+		}
+
+   }
+
+   return 0;
+}
+
+static int dict_s6ms6n_load_rules(char * conffile)
+{
+   /* Grouped AVP section */
+   {
+
+   }	
+
+   /* Commands section */
+   {
+	  /* Subscriber-Information-Request */
+	  {
+		struct dict_object* cmd;
+		CHECK_dict_search( DICT_COMMAND, CMD_BY_NAME, "Subscriber-Information-Request", &cmd)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 0, .avp_name = "Session-Id"}, RULE_FIXED_HEAD, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "DRMP"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Auth-Session-State"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-Host"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-Realm"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Destination-Host"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Destination-Realm"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "User-Identifier"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Service-ID"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "SCS-Identity"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Service-Parameters"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "SIR-Flags"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "OC-Supported-Features"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Supported-Features"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Proxy-Info"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Route-Record"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules(rules, cmd);
+	  }
+	  /* Subscriber-Information-Answer */
+	  {
+		struct dict_object* cmd;
+		CHECK_dict_search( DICT_COMMAND, CMD_BY_NAME, "Subscriber-Information-Answer", &cmd)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 0, .avp_name = "Session-Id"}, RULE_FIXED_HEAD, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "DRMP"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Result-Code"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Experimental-Result"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Auth-Session-State"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-Host"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-Realm"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "OC-Supported-Features"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "OC-OLR"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Load"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Supported-Features"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "User-Identifier"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Service-Data"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Failed-AVP"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Proxy-Info"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Route-Record"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules(rules, cmd);
+	  }
+
+   }
+
+   LOG_D( "Extension 'Dictionary definitions for S6mS6n (e10)' initialized");
+   return 0;
+}
+
+int dict_entry(char * conffile)
+{
+	dict_s6ms6n_load_defs(conffile);
+	return dict_s6ms6n_load_rules(conffile);
+}
+
+const char* dict_s6ms6n_proto_ver(char * conffile) {
+	return s6ms6n_proto_ver;
+}
+
+const double dict_s6ms6n_gen_ts(char * conffile) {
+	return s6ms6n_gen_date;
+}
+
+EXTENSION_ENTRY2("dict_s6ms6n", dict_s6ms6n_load_defs, dict_s6ms6n_load_rules, "dict_ts32299_avps", "dict_ts29336_avps", "dict_ts29272_avps", "dict_ts29338_avps", "dict_ts29368_avps", "dict_ts29329_avps", "dict_ts29229_avps", "dict_ts29217_avps", "dict_ts29173_avps", "dict_rfc5778_avps", "dict_draftload_avps", "dict_rfc7683_avps", "dict_rfc5777_avps", "dict_rfc7944_avps");
+
+
+
diff --git a/extensions/dict_S6t/CMakeLists.txt b/extensions/dict_S6t/CMakeLists.txt
new file mode 100644
index 0000000..45782e2
--- /dev/null
+++ b/extensions/dict_S6t/CMakeLists.txt
@@ -0,0 +1,16 @@
+# The dict_S6t extension
+PROJECT("dict_S6t library generated by FdGen " C)
+
+# Compile as a module
+FD_ADD_EXTENSION(dict_S6t dict_S6t.c)
+
+
+####
+## INSTALL section ##
+
+INSTALL(TARGETS dict_S6t
+	LIBRARY DESTINATION ${INSTALL_EXTENSIONS_SUFFIX}
+COMPONENT freeDiameter-dictionary-S6T)
+
+
+
diff --git a/extensions/dict_S6t/S6t.did b/extensions/dict_S6t/S6t.did
new file mode 100644
index 0000000..c1d6a5b
--- /dev/null
+++ b/extensions/dict_S6t/S6t.did
@@ -0,0 +1,38 @@
+dict_rfc6942_avps
+dict_ts29468_avps
+dict_ts29154_avps
+dict_ts29214_avps
+dict_ts29215_avps
+dict_ts29217_avps
+dict_3gpp2_avps
+dict_ts29337_avps
+dict_ts29343_avps
+dict_ts29338_avps
+dict_ts29128_avps
+dict_ts29344_avps
+dict_ts29345_avps
+dict_ts29173_avps
+dict_ts32299_avps
+dict_rfc6734_avps
+dict_rfc5580_avps
+dict_rfc4072_avps
+dict_ts29273_avps
+dict_rfc4006bis_avps
+dict_ts29212_avps
+dict_ts29061_avps
+dict_ts29272_avps
+dict_rfc5447_avps
+dict_rfc5778_avps
+dict_rfc5777_avps
+dict_ts29336_avps
+dict_etsi283034_avps
+dict_rfc4590_avps
+dict_rfc4004_avps
+dict_rfc7155_avps
+dict_ts29229_avps
+dict_rfc7683_avps
+dict_draftload_avps
+dict_rfc7944_avps
+dict_ts29329_avps
+dict_ts29368_avps
+dict_S6t
diff --git a/extensions/dict_S6t/dict_S6t.c b/extensions/dict_S6t/dict_S6t.c
new file mode 100644
index 0000000..33bce71
--- /dev/null
+++ b/extensions/dict_S6t/dict_S6t.c
@@ -0,0 +1,397 @@
+/*
+* Copyright (c) 2017 Sprint
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*    http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+/****************
+ Generated By: fdtool enhancements to diafuzzer
+ License: same as freeDiameter
+****************/
+
+
+/* 
+ * Dictionary definitions of objects specified in S6t (e10).
+ */
+#include <freeDiameter/extension.h>
+
+#define PROTO_VER "e10"
+#define GEN_DATE  1508010210.19
+
+const char *s6t_proto_ver = PROTO_VER;
+const double s6t_gen_date = GEN_DATE;
+
+/* The content of this file follows the same structure as dict_base_proto.c */
+
+#define CHECK_dict_new( _type, _data, _parent, _ref )                                     \
+{                                                                                         \
+    int _ret = fd_dict_new( fd_g_config->cnf_dict, (_type), (_data), (_parent), (_ref) ); \
+    if ( _ret != 0 && _ret != EEXIST )                                                    \
+       return _ret;                                                                       \
+}
+
+#define CHECK_dict_search( _type, _criteria, _what, _result )		\
+    CHECK_FCT(  fd_dict_search( fd_g_config->cnf_dict, (_type), (_criteria), (_what), (_result), ENOENT) );
+
+struct local_rules_definition {
+    struct dict_avp_request avp_vendor_plus_name;
+    enum rule_position	position;
+    int 			min;
+    int			max;
+};
+
+#define RULE_ORDER( _position ) ((((_position) == RULE_FIXED_HEAD) || ((_position) == RULE_FIXED_TAIL)) ? 1 : 0 )
+
+/* Attention! This version of the macro uses AVP_BY_NAME_AND_VENDOR, in contrast to most other copies! */
+#define PARSE_loc_rules( _rulearray, _parent) {                                                         \
+        int __ar;                                                                                       \
+        for (__ar=0; __ar < sizeof(_rulearray) / sizeof((_rulearray)[0]); __ar++) {                     \
+                struct dict_rule_data __data = { NULL,                                                  \
+                        (_rulearray)[__ar].position,                                                    \
+                        0,                                                                              \
+                        (_rulearray)[__ar].min,                                                         \
+                        (_rulearray)[__ar].max};                                                        \
+                __data.rule_order = RULE_ORDER(__data.rule_position);                                   \
+                CHECK_FCT(  fd_dict_search(                                                             \
+                        fd_g_config->cnf_dict,                                                          \
+                        DICT_AVP,                                                                       \
+                        AVP_BY_NAME_AND_VENDOR,                                                         \
+                        &(_rulearray)[__ar].avp_vendor_plus_name,                                       \
+                        &__data.rule_avp, 0 ) );                                                        \
+                if ( !__data.rule_avp ) {                                                               \
+                        TRACE_DEBUG(INFO, "AVP Not found: '%s'", (_rulearray)[__ar].avp_vendor_plus_name.avp_name);             \
+                        return ENOENT;                                                                  \
+                }                                                                                       \
+                {                                                                                       \
+                         int _ret = fd_dict_new( fd_g_config->cnf_dict, DICT_RULE, &(__data), (_parent), NULL ); \
+                         if ( _ret != 0 && _ret != EEXIST )      {                                      \
+                                TRACE_DEBUG(INFO, "Error on rule with AVP '%s'",                        \
+                                            (_rulearray)[__ar].avp_vendor_plus_name.avp_name);          \
+                                return EINVAL;                                                          \
+                         }                                                                              \
+                }                                                                                       \
+        }                                                                                               \
+}
+
+#define CHECK_vendor_new( _data ) { \
+        struct dict_object * vendor_found; \
+        if (fd_dict_search(fd_g_config->cnf_dict,DICT_VENDOR,VENDOR_BY_ID,&_data.vendor_id,&vendor_found,ENOENT) == ENOENT) { \
+                CHECK_FCT(fd_dict_new(fd_g_config->cnf_dict, DICT_VENDOR, &_data, NULL, NULL)); \
+        } \
+}
+
+#define enumval_def_u32( _val_, _str_ )		\
+    { _str_, 		{ .u32 = _val_ }}
+
+#define enumval_def_os( _len_, _val_, _str_ )				\
+    { _str_, 		{ .os = { .data = (unsigned char *)_val_, .len = _len_ }}}
+
+
+static int dict_s6t_load_defs(char * conffile)
+{
+   TRACE_ENTRY("%p", conffile);
+	struct dict_object * app_id16777345;
+
+	/* Application Section */
+	{
+	  {
+			struct dict_object * vendor;
+			CHECK_dict_search(DICT_VENDOR, VENDOR_BY_NAME, "3GPP", &vendor)
+			struct dict_application_data data = { 16777345, "S6t" };
+			CHECK_dict_new( DICT_APPLICATION, &data, vendor, &app_id16777345)
+	  }
+	}
+
+
+   /* AVP section */
+   {
+		struct dict_object * Address_type;
+		struct dict_object * UTF8String_type;
+		struct dict_object * DiameterIdentity_type;
+		struct dict_object * DiameterURI_type;
+		struct dict_object * Time_type;
+		struct dict_object * IPFilterRule_type;
+
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "Address", &Address_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "UTF8String", &UTF8String_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "DiameterIdentity", &DiameterIdentity_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "DiameterURI", &DiameterURI_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "Time", &Time_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "IPFilterRule", &IPFilterRule_type);
+
+	
+   }
+
+   /* Commands section */
+   {
+		/* Configuration-Information-Request */
+		{
+			struct dict_object* cmd;
+			struct dict_cmd_data data = {
+				8388718,	/* Code */
+				"Configuration-Information-Request",	/* Name */
+				CMD_FLAG_REQUEST | CMD_FLAG_ERROR,	/* Fixed flags */
+				CMD_FLAG_REQUEST | CMD_FLAG_PROXIABLE,	/* Fixed flag values */
+			};
+
+			CHECK_dict_new( DICT_COMMAND, &data , app_id16777345, &cmd)
+		}
+		/* Configuration-Information-Answer */
+		{
+			struct dict_object* cmd;
+			struct dict_cmd_data data = {
+				8388718,	/* Code */
+				"Configuration-Information-Answer",	/* Name */
+				CMD_FLAG_REQUEST,	/* Fixed flags */
+				CMD_FLAG_PROXIABLE,	/* Fixed flag values */
+			};
+
+			CHECK_dict_new( DICT_COMMAND, &data , app_id16777345, &cmd)
+		}
+		/* Reporting-Information-Request */
+		{
+			struct dict_object* cmd;
+			struct dict_cmd_data data = {
+				8388719,	/* Code */
+				"Reporting-Information-Request",	/* Name */
+				CMD_FLAG_REQUEST | CMD_FLAG_ERROR,	/* Fixed flags */
+				CMD_FLAG_REQUEST | CMD_FLAG_PROXIABLE,	/* Fixed flag values */
+			};
+
+			CHECK_dict_new( DICT_COMMAND, &data , app_id16777345, &cmd)
+		}
+		/* Reporting-Information-Answer */
+		{
+			struct dict_object* cmd;
+			struct dict_cmd_data data = {
+				8388719,	/* Code */
+				"Reporting-Information-Answer",	/* Name */
+				CMD_FLAG_REQUEST,	/* Fixed flags */
+				CMD_FLAG_PROXIABLE,	/* Fixed flag values */
+			};
+
+			CHECK_dict_new( DICT_COMMAND, &data , app_id16777345, &cmd)
+		}
+		/* NIDD-Information-Request */
+		{
+			struct dict_object* cmd;
+			struct dict_cmd_data data = {
+				8388726,	/* Code */
+				"NIDD-Information-Request",	/* Name */
+				CMD_FLAG_REQUEST | CMD_FLAG_ERROR,	/* Fixed flags */
+				CMD_FLAG_REQUEST | CMD_FLAG_PROXIABLE,	/* Fixed flag values */
+			};
+
+			CHECK_dict_new( DICT_COMMAND, &data , app_id16777345, &cmd)
+		}
+		/* NIDD-Information-Answer */
+		{
+			struct dict_object* cmd;
+			struct dict_cmd_data data = {
+				8388726,	/* Code */
+				"NIDD-Information-Answer",	/* Name */
+				CMD_FLAG_REQUEST,	/* Fixed flags */
+				CMD_FLAG_PROXIABLE,	/* Fixed flag values */
+			};
+
+			CHECK_dict_new( DICT_COMMAND, &data , app_id16777345, &cmd)
+		}
+
+   }
+
+   return 0;
+}
+
+static int dict_s6t_load_rules(char * conffile)
+{
+   /* Grouped AVP section */
+   {
+
+   }	
+
+   /* Commands section */
+   {
+	  /* Configuration-Information-Request */
+	  {
+		struct dict_object* cmd;
+		CHECK_dict_search( DICT_COMMAND, CMD_BY_NAME, "Configuration-Information-Request", &cmd)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 0, .avp_name = "Session-Id"}, RULE_FIXED_HEAD, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "DRMP"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Auth-Session-State"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-Host"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-Realm"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Destination-Host"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Destination-Realm"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "User-Identifier"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "OC-Supported-Features"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Supported-Features"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Monitoring-Event-Configuration"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "CIR-Flags"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "AESE-Communication-Pattern"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Enhanced-Coverage-Restriction"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Group-Reporting-Guard-Timer"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Proxy-Info"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Route-Record"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules(rules, cmd);
+	  }
+	  /* Configuration-Information-Answer */
+	  {
+		struct dict_object* cmd;
+		CHECK_dict_search( DICT_COMMAND, CMD_BY_NAME, "Configuration-Information-Answer", &cmd)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 0, .avp_name = "Session-Id"}, RULE_FIXED_HEAD, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "DRMP"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Result-Code"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Experimental-Result"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Auth-Session-State"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-Host"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-Realm"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "OC-Supported-Features"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "OC-OLR"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Load"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Supported-Features"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "User-Identifier"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Monitoring-Event-Report"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Monitoring-Event-Config-Status"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "AESE-Communication-Pattern-Config-Status"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Supported-Services"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "S6t-HSS-Cause"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Enhanced-Coverage-Restriction-Data"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "CIA-Flags"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Failed-AVP"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Proxy-Info"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Route-Record"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules(rules, cmd);
+	  }
+	  /* Reporting-Information-Request */
+	  {
+		struct dict_object* cmd;
+		CHECK_dict_search( DICT_COMMAND, CMD_BY_NAME, "Reporting-Information-Request", &cmd)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 0, .avp_name = "Session-Id"}, RULE_FIXED_HEAD, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "DRMP"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Auth-Session-State"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-Host"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-Realm"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Destination-Host"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Destination-Realm"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Supported-Features"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "User-Identifier"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Monitoring-Event-Report"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Group-Monitoring-Event-Report"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "RIR-Flags"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Supported-Services"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Proxy-Info"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Route-Record"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules(rules, cmd);
+	  }
+	  /* Reporting-Information-Answer */
+	  {
+		struct dict_object* cmd;
+		CHECK_dict_search( DICT_COMMAND, CMD_BY_NAME, "Reporting-Information-Answer", &cmd)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 0, .avp_name = "Session-Id"}, RULE_FIXED_HEAD, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "DRMP"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Result-Code"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Experimental-Result"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Auth-Session-State"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-Host"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-Realm"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Supported-Features"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Failed-AVP"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Proxy-Info"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Route-Record"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules(rules, cmd);
+	  }
+	  /* NIDD-Information-Request */
+	  {
+		struct dict_object* cmd;
+		CHECK_dict_search( DICT_COMMAND, CMD_BY_NAME, "NIDD-Information-Request", &cmd)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 0, .avp_name = "Session-Id"}, RULE_FIXED_HEAD, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "DRMP"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Auth-Session-State"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-Host"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-Realm"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Destination-Host"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Destination-Realm"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "User-Identifier"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "OC-Supported-Features"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Supported-Features"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "NIDD-Authorization-Request"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "NIDD-Authorization-Update"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Proxy-Info"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Route-Record"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules(rules, cmd);
+	  }
+	  /* NIDD-Information-Answer */
+	  {
+		struct dict_object* cmd;
+		CHECK_dict_search( DICT_COMMAND, CMD_BY_NAME, "NIDD-Information-Answer", &cmd)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 0, .avp_name = "Session-Id"}, RULE_FIXED_HEAD, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "DRMP"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Result-Code"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Experimental-Result"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Auth-Session-State"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-Host"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-Realm"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "OC-Supported-Features"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "OC-OLR"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Load"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Supported-Features"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "User-Identifier"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "NIDD-Authorization-Response"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Failed-AVP"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Proxy-Info"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Route-Record"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules(rules, cmd);
+	  }
+
+   }
+
+   LOG_D( "Extension 'Dictionary definitions for S6t (e10)' initialized");
+   return 0;
+}
+
+int dict_entry(char * conffile)
+{
+	dict_s6t_load_defs(conffile);
+	return dict_s6t_load_rules(conffile);
+}
+
+const char* dict_proto_ver(char * conffile) {
+	return s6t_proto_ver;
+}
+
+const double dict_gen_ts(char * conffile) {
+	return s6t_gen_date;
+}
+
+EXTENSION_ENTRY2("dict_s6t", dict_s6t_load_defs, dict_s6t_load_rules, "dict_ts32299_avps", "dict_ts29336_avps", "dict_ts29272_avps", "dict_ts29338_avps", "dict_ts29368_avps", "dict_ts29329_avps", "dict_ts29229_avps", "dict_ts29217_avps", "dict_ts29173_avps", "dict_rfc5778_avps", "dict_draftload_avps", "dict_rfc7683_avps", "dict_rfc5777_avps", "dict_rfc7944_avps");
+
+
+
diff --git a/extensions/dict_S9/CMakeLists.txt b/extensions/dict_S9/CMakeLists.txt
new file mode 100644
index 0000000..af524de
--- /dev/null
+++ b/extensions/dict_S9/CMakeLists.txt
@@ -0,0 +1,16 @@
+# The dict_S9 extension
+PROJECT("dict_S9 library generated by FdGen " C)
+
+# Compile as a module
+FD_ADD_EXTENSION(dict_S9 dict_S9.c)
+
+
+####
+## INSTALL section ##
+
+INSTALL(TARGETS dict_S9
+	LIBRARY DESTINATION ${INSTALL_EXTENSIONS_SUFFIX}
+COMPONENT freeDiameter-dictionary-S9)
+
+
+
diff --git a/extensions/dict_S9/S9.did b/extensions/dict_S9/S9.did
new file mode 100644
index 0000000..64f69d1
--- /dev/null
+++ b/extensions/dict_S9/S9.did
@@ -0,0 +1,38 @@
+dict_rfc6942_avps
+dict_rfc6734_avps
+dict_rfc5580_avps
+dict_ts29468_avps
+dict_ts29154_avps
+dict_ts29214_avps
+dict_ts29215_avps
+dict_ts29217_avps
+dict_3gpp2_avps
+dict_ts29343_avps
+dict_ts29128_avps
+dict_ts29344_avps
+dict_ts29345_avps
+dict_ts32299_avps
+dict_rfc5778_avps
+dict_ts29338_avps
+dict_ts29173_avps
+dict_ts29337_avps
+dict_etsi283034_avps
+dict_rfc4590_avps
+dict_ts29229_avps
+dict_draftload_avps
+dict_ts29329_avps
+dict_ts29368_avps
+dict_ts29336_avps
+dict_ts29061_avps
+dict_ts29272_avps
+dict_rfc7683_avps
+dict_rfc5777_avps
+dict_rfc4006bis_avps
+dict_ts29212_avps
+dict_rfc4072_avps
+dict_rfc5447_avps
+dict_ts29273_avps
+dict_rfc4004_avps
+dict_rfc7155_avps
+dict_rfc7944_avps
+dict_S9
diff --git a/extensions/dict_S9/dict_S9.c b/extensions/dict_S9/dict_S9.c
new file mode 100644
index 0000000..5a93c8c
--- /dev/null
+++ b/extensions/dict_S9/dict_S9.c
@@ -0,0 +1,471 @@
+/*
+* Copyright (c) 2017 Sprint
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*    http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+/****************
+ Generated By: fdtool enhancements to diafuzzer
+ License: same as freeDiameter
+****************/
+
+
+/* 
+ * Dictionary definitions of objects specified in S9 (e10).
+ */
+#include <freeDiameter/extension.h>
+
+#define PROTO_VER "e10"
+#define GEN_DATE  1506697117.57
+
+const char *s9_proto_ver = PROTO_VER;
+const double s9_gen_date = GEN_DATE;
+
+/* The content of this file follows the same structure as dict_base_proto.c */
+
+#define CHECK_dict_new( _type, _data, _parent, _ref )                                     \
+{                                                                                         \
+    int _ret = fd_dict_new( fd_g_config->cnf_dict, (_type), (_data), (_parent), (_ref) ); \
+    if ( _ret != 0 && _ret != EEXIST )                                                    \
+       return _ret;                                                                       \
+}
+
+#define CHECK_dict_search( _type, _criteria, _what, _result )		\
+    CHECK_FCT(  fd_dict_search( fd_g_config->cnf_dict, (_type), (_criteria), (_what), (_result), ENOENT) );
+
+struct local_rules_definition {
+    struct dict_avp_request avp_vendor_plus_name;
+    enum rule_position	position;
+    int 			min;
+    int			max;
+};
+
+#define RULE_ORDER( _position ) ((((_position) == RULE_FIXED_HEAD) || ((_position) == RULE_FIXED_TAIL)) ? 1 : 0 )
+
+/* Attention! This version of the macro uses AVP_BY_NAME_AND_VENDOR, in contrast to most other copies! */
+#define PARSE_loc_rules( _rulearray, _parent) {                                                         \
+        int __ar;                                                                                       \
+        for (__ar=0; __ar < sizeof(_rulearray) / sizeof((_rulearray)[0]); __ar++) {                     \
+                struct dict_rule_data __data = { NULL,                                                  \
+                        (_rulearray)[__ar].position,                                                    \
+                        0,                                                                              \
+                        (_rulearray)[__ar].min,                                                         \
+                        (_rulearray)[__ar].max};                                                        \
+                __data.rule_order = RULE_ORDER(__data.rule_position);                                   \
+                CHECK_FCT(  fd_dict_search(                                                             \
+                        fd_g_config->cnf_dict,                                                          \
+                        DICT_AVP,                                                                       \
+                        AVP_BY_NAME_AND_VENDOR,                                                         \
+                        &(_rulearray)[__ar].avp_vendor_plus_name,                                       \
+                        &__data.rule_avp, 0 ) );                                                        \
+                if ( !__data.rule_avp ) {                                                               \
+                        TRACE_DEBUG(INFO, "AVP Not found: '%s'", (_rulearray)[__ar].avp_vendor_plus_name.avp_name);             \
+                        return ENOENT;                                                                  \
+                }                                                                                       \
+                {                                                                                       \
+                         int _ret = fd_dict_new( fd_g_config->cnf_dict, DICT_RULE, &(__data), (_parent), NULL ); \
+                         if ( _ret != 0 && _ret != EEXIST )      {                                      \
+                                TRACE_DEBUG(INFO, "Error on rule with AVP '%s'",                        \
+                                            (_rulearray)[__ar].avp_vendor_plus_name.avp_name);          \
+                                return EINVAL;                                                          \
+                         }                                                                              \
+                }                                                                                       \
+        }                                                                                               \
+}
+
+#define CHECK_vendor_new( _data ) { \
+        struct dict_object * vendor_found; \
+        if (fd_dict_search(fd_g_config->cnf_dict,DICT_VENDOR,VENDOR_BY_ID,&_data.vendor_id,&vendor_found,ENOENT) == ENOENT) { \
+                CHECK_FCT(fd_dict_new(fd_g_config->cnf_dict, DICT_VENDOR, &_data, NULL, NULL)); \
+        } \
+}
+
+#define enumval_def_u32( _val_, _str_ )		\
+    { _str_, 		{ .u32 = _val_ }}
+
+#define enumval_def_os( _len_, _val_, _str_ )				\
+    { _str_, 		{ .os = { .data = (unsigned char *)_val_, .len = _len_ }}}
+
+
+static int dict_s9_load_defs(char * conffile)
+{
+   TRACE_ENTRY("%p", conffile);
+	struct dict_object * app_id16777267;
+
+	/* Application Section */
+	{
+	  {
+			struct dict_object * vendor;
+			CHECK_dict_search(DICT_VENDOR, VENDOR_BY_NAME, "3GPP", &vendor)
+			struct dict_application_data data = { 16777267, "S9" };
+			CHECK_dict_new( DICT_APPLICATION, &data, vendor, &app_id16777267)
+	  }
+	  /* Result codes */
+	  {
+			struct dict_object *type;
+			CHECK_dict_search(DICT_TYPE, TYPE_BY_NAME, "Enumerated(Result-Code)",&type);
+			struct dict_enumval_data        t_1 = { "DIAMETER_USER_UNKNOWN", { .u32=5030 }};
+			struct dict_enumval_data        t_2 = { "DIAMETER_ERROR_LATE_OVERLAPPING_REQUEST", { .u32=5453 }};
+			struct dict_enumval_data        t_3 = { "DIAMETER_ERROR_TIMED_OUT_REQUEST", { .u32=5454 }};
+			struct dict_enumval_data        t_4 = { "DIAMETER_ERROR_INITIAL_PARAMETERS", { .u32=5140 }};
+			struct dict_enumval_data        t_5 = { "DIAMETER_ERROR_TRIGGER_EVENT", { .u32=5141 }};
+			struct dict_enumval_data        t_6 = { "DIAMETER_PCC_RULE_EVENT", { .u32=5142 }};
+			struct dict_enumval_data        t_7 = { "DIAMETER_ERROR_BEARER_NOT_AUTHORIZED", { .u32=5143 }};
+			struct dict_enumval_data        t_8 = { "DIAMETER_ERROR_TRAFFIC_MAPPING_INFO_REJECTED", { .u32=5144 }};
+			struct dict_enumval_data        t_9 = { "DIAMETER_ERROR_CONFLICTING_REQUEST", { .u32=5147 }};
+			struct dict_enumval_data        t_10 = { "DIAMETER_ADC_RULE_EVENT", { .u32=5148 }};
+			struct dict_enumval_data        t_11 = { "DIAMETER_ERROR_NBIFOM_NOT_AUTHORIZED", { .u32=5149 }};
+			struct dict_enumval_data        t_12 = { "DIAMETER_ERROR_SUBSESSION", { .u32=5470 }};
+			struct dict_enumval_data        t_13 = { "DIAMETER_ERROR_ONGOING_SESSION_ESTABLISHMENT", { .u32=5471 }};
+			struct dict_enumval_data        t_14 = { "DIAMETER_PCC_BEARER_EVENT", { .u32=4141 }};
+			struct dict_enumval_data        t_15 = { "DIAMETER_AN_GW_FAILED", { .u32=4143 }};
+			struct dict_enumval_data        t_16 = { "DIAMETER_PENDING_TRANSACTION", { .u32=4144 }};
+
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_3, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_4, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_5, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_6, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_7, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_8, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_9, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_10, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_11, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_12, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_13, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_14, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_15, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_16, type, NULL);
+
+	  }
+	}
+
+
+   /* AVP section */
+   {
+		struct dict_object * Address_type;
+		struct dict_object * UTF8String_type;
+		struct dict_object * DiameterIdentity_type;
+		struct dict_object * DiameterURI_type;
+		struct dict_object * Time_type;
+		struct dict_object * IPFilterRule_type;
+
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "Address", &Address_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "UTF8String", &UTF8String_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "DiameterIdentity", &DiameterIdentity_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "DiameterURI", &DiameterURI_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "Time", &Time_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "IPFilterRule", &IPFilterRule_type);
+
+	
+   }
+
+   /* Commands section */
+   {
+		/* Re-Authorization-Request */
+		{
+			struct dict_object* cmd;
+			struct dict_cmd_data data = {
+				258,	/* Code */
+				"Re-Authorization-Request",	/* Name */
+				CMD_FLAG_REQUEST | CMD_FLAG_ERROR,	/* Fixed flags */
+				CMD_FLAG_REQUEST | CMD_FLAG_PROXIABLE,	/* Fixed flag values */
+			};
+
+			CHECK_dict_new( DICT_COMMAND, &data , app_id16777267, &cmd)
+		}
+		/* Re-Authorization-Answer */
+		{
+			struct dict_object* cmd;
+			struct dict_cmd_data data = {
+				258,	/* Code */
+				"Re-Authorization-Answer",	/* Name */
+				CMD_FLAG_REQUEST,	/* Fixed flags */
+				CMD_FLAG_PROXIABLE,	/* Fixed flag values */
+			};
+
+			CHECK_dict_new( DICT_COMMAND, &data , app_id16777267, &cmd)
+		}
+		/* Trigger-Establishment-Request */
+		{
+			struct dict_object* cmd;
+			struct dict_cmd_data data = {
+				8388656,	/* Code */
+				"Trigger-Establishment-Request",	/* Name */
+				CMD_FLAG_REQUEST | CMD_FLAG_ERROR,	/* Fixed flags */
+				CMD_FLAG_REQUEST | CMD_FLAG_PROXIABLE,	/* Fixed flag values */
+			};
+
+			CHECK_dict_new( DICT_COMMAND, &data , app_id16777267, &cmd)
+		}
+		/* Trigger-Establishment-Answer */
+		{
+			struct dict_object* cmd;
+			struct dict_cmd_data data = {
+				8388656,	/* Code */
+				"Trigger-Establishment-Answer",	/* Name */
+				CMD_FLAG_REQUEST,	/* Fixed flags */
+				CMD_FLAG_PROXIABLE,	/* Fixed flag values */
+			};
+
+			CHECK_dict_new( DICT_COMMAND, &data , app_id16777267, &cmd)
+		}
+
+   }
+
+   return 0;
+}
+
+static int dict_s9_load_rules(char * conffile)
+{
+   /* Grouped AVP section */
+   {
+
+   }	
+
+   /* Commands section */
+   {
+	  /* CC-Request */
+	  {
+		struct dict_object* cmd;
+		CHECK_dict_search( DICT_COMMAND, CMD_BY_NAME, "CC-Request", &cmd)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 0, .avp_name = "Session-Id"}, RULE_FIXED_HEAD, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "DRMP"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Auth-Application-Id"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-Host"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-Realm"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Destination-Realm"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "CC-Request-Type"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "CC-Request-Number"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Destination-Host"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-State-Id"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Subscription-Id"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Framed-IP-Address"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Framed-IPv6-Prefix"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Supported-Features"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "OC-Supported-Features"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "QoS-Information"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "QoS-Rule-Report"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "AN-GW-Address"}, RULE_OPTIONAL, 0, 2 },
+			{ { .avp_vendor = 10415, .avp_name = "Network-Request-Support"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Packet-Filter-Information"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Packet-Filter-Operation"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Subsession-Enforcement-Info"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "IP-CAN-Type"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "RAT-Type"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Termination-Cause"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "User-Equipment-Info"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "QoS-Negotiation"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "QoS-Upgrade"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "3GPP-SGSN-MCC-MNC"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "3GPP-SGSN-Address"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "3GPP-SGSN-Ipv6-Address"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "RAI"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "3GPP-User-Location-Info"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "3GPP-MS-TimeZone"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 5535, .avp_name = "3GPP2-BSID"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Event-Trigger"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Multiple-BBERF-Action"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "User-CSG-Information"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Proxy-Info"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Route-Record"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules(rules, cmd);
+	  }
+	  /* CC-Answer */
+	  {
+		struct dict_object* cmd;
+		CHECK_dict_search( DICT_COMMAND, CMD_BY_NAME, "CC-Answer", &cmd)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 0, .avp_name = "Session-Id"}, RULE_FIXED_HEAD, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "DRMP"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Auth-Application-Id"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-Host"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-Realm"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Result-Code"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Experimental-Result"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "CC-Request-Type"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "CC-Request-Number"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Supported-Features"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "OC-Supported-Features"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "OC-OLR"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "QoS-Rule-Install"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "QoS-Rule-Remove"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "QoS-Information"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Bearer-Control-Mode"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Event-Trigger"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Charging-Information"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Subsession-Decision-Info"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "CSG-Information-Reporting"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "AN-GW-Address"}, RULE_OPTIONAL, 0, 2 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-State-Id"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Error-Message"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Error-Reporting-Host"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Failed-AVP"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Proxy-Info"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Route-Record"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Load"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules(rules, cmd);
+	  }
+	  /* Re-Authorization-Request */
+	  {
+		struct dict_object* cmd;
+		CHECK_dict_search( DICT_COMMAND, CMD_BY_NAME, "Re-Authorization-Request", &cmd)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 0, .avp_name = "Session-Id"}, RULE_FIXED_HEAD, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "DRMP"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Auth-Application-Id"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-Host"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-Realm"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Destination-Realm"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Destination-Host"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Re-Auth-Request-Type"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-State-Id"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "OC-Supported-Features"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "QoS-Rule-Install"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "QoS-Rule-Remove"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "QoS-Information"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Event-Trigger"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Subsession-Decision-Info"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "AN-GW-Address"}, RULE_OPTIONAL, 0, 2 },
+			{ { .avp_vendor = 10415, .avp_name = "Session-Release-Cause"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "HeNB-Local-IP-Address"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "UE-Local-IP-Address"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "UDP-Source-Port"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Proxy-Info"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Called-Station-Id"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Route-Record"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules(rules, cmd);
+	  }
+	  /* Re-Authorization-Answer */
+	  {
+		struct dict_object* cmd;
+		CHECK_dict_search( DICT_COMMAND, CMD_BY_NAME, "Re-Authorization-Answer", &cmd)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 0, .avp_name = "Session-Id"}, RULE_FIXED_HEAD, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "DRMP"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-Host"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-Realm"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Result-Code"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Experimental-Result"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-State-Id"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Framed-IP-Address"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Framed-IPv6-Prefix"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "IP-CAN-Type"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "RAT-Type"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "3GPP-SGSN-MCC-MNC"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "3GPP-SGSN-Address"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "3GPP-SGSN-Ipv6-Address"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "RAI"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "3GPP-User-Location-Info"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "3GPP-MS-TimeZone"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 5535, .avp_name = "3GPP2-BSID"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "OC-Supported-Features"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "OC-OLR"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "QoS-Information"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "QoS-Rule-Report"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "AN-GW-Address"}, RULE_OPTIONAL, 0, 2 },
+			{ { .avp_vendor = 10415, .avp_name = "Subsession-Enforcement-Info"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "User-CSG-Information"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Error-Message"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Error-Reporting-Host"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Failed-AVP"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Proxy-Info"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Load"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules(rules, cmd);
+	  }
+	  /* Trigger-Establishment-Request */
+	  {
+		struct dict_object* cmd;
+		CHECK_dict_search( DICT_COMMAND, CMD_BY_NAME, "Trigger-Establishment-Request", &cmd)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 0, .avp_name = "Session-Id"}, RULE_FIXED_HEAD, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "DRMP"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Auth-Application-Id"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-Host"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-Realm"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Destination-Realm"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Destination-Host"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Auth-Session-State"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-State-Id"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Subscription-Id"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "OC-Supported-Features"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Called-Station-Id"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "UE-Local-IP-Address"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "HeNB-Local-IP-Address"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "DRA-Binding"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "UDP-Source-Port"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Proxy-Info"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Route-Record"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules(rules, cmd);
+	  }
+	  /* Trigger-Establishment-Answer */
+	  {
+		struct dict_object* cmd;
+		CHECK_dict_search( DICT_COMMAND, CMD_BY_NAME, "Trigger-Establishment-Answer", &cmd)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 0, .avp_name = "Session-Id"}, RULE_FIXED_HEAD, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "DRMP"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-Host"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-Realm"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Result-Code"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Experimental-Result"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-State-Id"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "DRA-Deployment"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "OC-Supported-Features"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "OC-OLR"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Error-Message"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Error-Reporting-Host"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Failed-AVP"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Proxy-Info"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Load"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules(rules, cmd);
+	  }
+
+   }
+
+   LOG_D( "Extension 'Dictionary definitions for S9 (e10)' initialized");
+   return 0;
+}
+
+int dict_entry(char * conffile)
+{
+	dict_s9_load_defs(conffile);
+	return dict_s9_load_rules(conffile);
+}
+
+const char* dict_s9_proto_ver(char * conffile) {
+	return s9_proto_ver;
+}
+
+const double dict_s9_gen_ts(char * conffile) {
+	return s9_gen_date;
+}
+
+EXTENSION_ENTRY2("dict_s9", dict_s9_load_defs, dict_s9_load_rules, "dict_ts32299_avps", "dict_ts29212_avps", "dict_ts29215_avps", "dict_ts29273_avps", "dict_ts29214_avps", "dict_ts29272_avps", "dict_ts29229_avps", "dict_ts29061_avps", "dict_rfc4006bis_avps", "dict_draftload_avps", "dict_rfc7683_avps", "dict_rfc7155_avps", "dict_etsi283034_avps", "dict_3gpp2_avps", "dict_rfc7944_avps");
+
+
+
diff --git a/extensions/dict_SGd/CMakeLists.txt b/extensions/dict_SGd/CMakeLists.txt
new file mode 100644
index 0000000..3bc5901
--- /dev/null
+++ b/extensions/dict_SGd/CMakeLists.txt
@@ -0,0 +1,16 @@
+# The dict_SGd extension
+PROJECT("dict_SGd library generated by FdGen " C)
+
+# Compile as a module
+FD_ADD_EXTENSION(dict_SGd dict_SGd.c)
+
+
+####
+## INSTALL section ##
+
+INSTALL(TARGETS dict_SGd
+	LIBRARY DESTINATION ${INSTALL_EXTENSIONS_SUFFIX}
+COMPONENT freeDiameter-dictionary-SGD)
+
+
+
diff --git a/extensions/dict_SGd/SGd.did b/extensions/dict_SGd/SGd.did
new file mode 100644
index 0000000..3ffdde6
--- /dev/null
+++ b/extensions/dict_SGd/SGd.did
@@ -0,0 +1,39 @@
+dict_S6c
+dict_rfc6942_avps
+dict_ts29468_avps
+dict_ts29154_avps
+dict_ts29214_avps
+dict_ts29215_avps
+dict_ts29217_avps
+dict_3gpp2_avps
+dict_ts29343_avps
+dict_ts29338_avps
+dict_ts29128_avps
+dict_ts29344_avps
+dict_ts29345_avps
+dict_ts32299_avps
+dict_rfc6734_avps
+dict_rfc5778_avps
+dict_rfc5580_avps
+dict_rfc4072_avps
+dict_ts29273_avps
+dict_rfc5777_avps
+dict_rfc4006bis_avps
+dict_ts29212_avps
+dict_ts29061_avps
+dict_rfc5447_avps
+dict_ts29272_avps
+dict_ts29173_avps
+dict_ts29337_avps
+dict_etsi283034_avps
+dict_rfc4590_avps
+dict_rfc4004_avps
+dict_rfc7155_avps
+dict_ts29229_avps
+dict_rfc7683_avps
+dict_draftload_avps
+dict_ts29329_avps
+dict_ts29368_avps
+dict_ts29336_avps
+dict_rfc7944_avps
+dict_SGd
diff --git a/extensions/dict_SGd/dict_SGd.c b/extensions/dict_SGd/dict_SGd.c
new file mode 100644
index 0000000..77928ad
--- /dev/null
+++ b/extensions/dict_SGd/dict_SGd.c
@@ -0,0 +1,385 @@
+/*
+* Copyright (c) 2017 Sprint
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*    http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+/****************
+ Generated By: fdtool enhancements to diafuzzer
+ License: same as freeDiameter
+****************/
+
+
+/* 
+ * Dictionary definitions of objects specified in SGd (e10).
+ */
+#include <freeDiameter/extension.h>
+
+#define PROTO_VER "e10"
+#define GEN_DATE  1506697222.84
+
+const char *sgd_proto_ver = PROTO_VER;
+const double sgd_gen_date = GEN_DATE;
+
+/* The content of this file follows the same structure as dict_base_proto.c */
+
+#define CHECK_dict_new( _type, _data, _parent, _ref )                                     \
+{                                                                                         \
+    int _ret = fd_dict_new( fd_g_config->cnf_dict, (_type), (_data), (_parent), (_ref) ); \
+    if ( _ret != 0 && _ret != EEXIST )                                                    \
+       return _ret;                                                                       \
+}
+
+#define CHECK_dict_search( _type, _criteria, _what, _result )		\
+    CHECK_FCT(  fd_dict_search( fd_g_config->cnf_dict, (_type), (_criteria), (_what), (_result), ENOENT) );
+
+struct local_rules_definition {
+    struct dict_avp_request avp_vendor_plus_name;
+    enum rule_position	position;
+    int 			min;
+    int			max;
+};
+
+#define RULE_ORDER( _position ) ((((_position) == RULE_FIXED_HEAD) || ((_position) == RULE_FIXED_TAIL)) ? 1 : 0 )
+
+/* Attention! This version of the macro uses AVP_BY_NAME_AND_VENDOR, in contrast to most other copies! */
+#define PARSE_loc_rules( _rulearray, _parent) {                                                         \
+        int __ar;                                                                                       \
+        for (__ar=0; __ar < sizeof(_rulearray) / sizeof((_rulearray)[0]); __ar++) {                     \
+                struct dict_rule_data __data = { NULL,                                                  \
+                        (_rulearray)[__ar].position,                                                    \
+                        0,                                                                              \
+                        (_rulearray)[__ar].min,                                                         \
+                        (_rulearray)[__ar].max};                                                        \
+                __data.rule_order = RULE_ORDER(__data.rule_position);                                   \
+                CHECK_FCT(  fd_dict_search(                                                             \
+                        fd_g_config->cnf_dict,                                                          \
+                        DICT_AVP,                                                                       \
+                        AVP_BY_NAME_AND_VENDOR,                                                         \
+                        &(_rulearray)[__ar].avp_vendor_plus_name,                                       \
+                        &__data.rule_avp, 0 ) );                                                        \
+                if ( !__data.rule_avp ) {                                                               \
+                        TRACE_DEBUG(INFO, "AVP Not found: '%s'", (_rulearray)[__ar].avp_vendor_plus_name.avp_name);             \
+                        return ENOENT;                                                                  \
+                }                                                                                       \
+                {                                                                                       \
+                         int _ret = fd_dict_new( fd_g_config->cnf_dict, DICT_RULE, &(__data), (_parent), NULL ); \
+                         if ( _ret != 0 && _ret != EEXIST )      {                                      \
+                                TRACE_DEBUG(INFO, "Error on rule with AVP '%s'",                        \
+                                            (_rulearray)[__ar].avp_vendor_plus_name.avp_name);          \
+                                return EINVAL;                                                          \
+                         }                                                                              \
+                }                                                                                       \
+        }                                                                                               \
+}
+
+#define CHECK_vendor_new( _data ) { \
+        struct dict_object * vendor_found; \
+        if (fd_dict_search(fd_g_config->cnf_dict,DICT_VENDOR,VENDOR_BY_ID,&_data.vendor_id,&vendor_found,ENOENT) == ENOENT) { \
+                CHECK_FCT(fd_dict_new(fd_g_config->cnf_dict, DICT_VENDOR, &_data, NULL, NULL)); \
+        } \
+}
+
+#define enumval_def_u32( _val_, _str_ )		\
+    { _str_, 		{ .u32 = _val_ }}
+
+#define enumval_def_os( _len_, _val_, _str_ )				\
+    { _str_, 		{ .os = { .data = (unsigned char *)_val_, .len = _len_ }}}
+
+
+static int dict_sgd_load_defs(char * conffile)
+{
+   TRACE_ENTRY("%p", conffile);
+	struct dict_object * app_id16777312;
+	struct dict_object * app_id16777313;
+
+	/* Application Section */
+	{
+	  {
+			struct dict_object * vendor;
+			CHECK_dict_search(DICT_VENDOR, VENDOR_BY_NAME, "3GPP", &vendor)
+			struct dict_application_data data = { 16777312, "SGd-app16777312" };
+			CHECK_dict_new( DICT_APPLICATION, &data, vendor, &app_id16777312)
+	  }
+	  {
+			struct dict_object * vendor;
+			CHECK_dict_search(DICT_VENDOR, VENDOR_BY_NAME, "3GPP", &vendor)
+			struct dict_application_data data = { 16777313, "SGd" };
+			CHECK_dict_new( DICT_APPLICATION, &data, vendor, &app_id16777313)
+	  }
+	  /* Result codes */
+	  {
+			struct dict_object *type;
+			CHECK_dict_search(DICT_TYPE, TYPE_BY_NAME, "Enumerated(Result-Code)",&type);
+			struct dict_enumval_data        t_1 = { "General", { .u32=1 }};
+			struct dict_enumval_data        t_2 = { "Permanent_Failures", { .u32=3 }};
+			struct dict_enumval_data        t_3 = { "Transient_Failures", { .u32=4 }};
+
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_3, type, NULL);
+
+	  }
+	}
+
+
+   /* AVP section */
+   {
+		struct dict_object * Address_type;
+		struct dict_object * UTF8String_type;
+		struct dict_object * DiameterIdentity_type;
+		struct dict_object * DiameterURI_type;
+		struct dict_object * Time_type;
+		struct dict_object * IPFilterRule_type;
+
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "Address", &Address_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "UTF8String", &UTF8String_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "DiameterIdentity", &DiameterIdentity_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "DiameterURI", &DiameterURI_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "Time", &Time_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "IPFilterRule", &IPFilterRule_type);
+
+	
+   }
+
+   /* Commands section */
+   {
+		/* MO-Forward-Short-Message-Request */
+		{
+			struct dict_object* cmd;
+			struct dict_cmd_data data = {
+				8388645,	/* Code */
+				"MO-Forward-Short-Message-Request",	/* Name */
+				CMD_FLAG_REQUEST | CMD_FLAG_ERROR,	/* Fixed flags */
+				CMD_FLAG_REQUEST | CMD_FLAG_PROXIABLE,	/* Fixed flag values */
+			};
+
+			CHECK_dict_new( DICT_COMMAND, &data , app_id16777313, &cmd)
+		}
+		/* MO-Forward-Short-Message-Answer */
+		{
+			struct dict_object* cmd;
+			struct dict_cmd_data data = {
+				8388645,	/* Code */
+				"MO-Forward-Short-Message-Answer",	/* Name */
+				CMD_FLAG_REQUEST,	/* Fixed flags */
+				CMD_FLAG_PROXIABLE,	/* Fixed flag values */
+			};
+
+			CHECK_dict_new( DICT_COMMAND, &data , app_id16777313, &cmd)
+		}
+		/* MT-Forward-Short-Message-Request */
+		{
+			struct dict_object* cmd;
+			struct dict_cmd_data data = {
+				8388646,	/* Code */
+				"MT-Forward-Short-Message-Request",	/* Name */
+				CMD_FLAG_REQUEST | CMD_FLAG_ERROR,	/* Fixed flags */
+				CMD_FLAG_REQUEST | CMD_FLAG_PROXIABLE,	/* Fixed flag values */
+			};
+
+			CHECK_dict_new( DICT_COMMAND, &data , app_id16777313, &cmd)
+		}
+		/* MT-Forward-Short-Message-Answer */
+		{
+			struct dict_object* cmd;
+			struct dict_cmd_data data = {
+				8388646,	/* Code */
+				"MT-Forward-Short-Message-Answer",	/* Name */
+				CMD_FLAG_REQUEST,	/* Fixed flags */
+				CMD_FLAG_PROXIABLE,	/* Fixed flag values */
+			};
+
+			CHECK_dict_new( DICT_COMMAND, &data , app_id16777313, &cmd)
+		}
+
+   }
+
+   return 0;
+}
+
+static int dict_sgd_load_rules(char * conffile)
+{
+   /* Grouped AVP section */
+   {
+
+   }	
+
+   /* Commands section */
+   {
+	  /* MO-Forward-Short-Message-Request */
+	  {
+		struct dict_object* cmd;
+		CHECK_dict_search( DICT_COMMAND, CMD_BY_NAME, "MO-Forward-Short-Message-Request", &cmd)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 0, .avp_name = "Session-Id"}, RULE_FIXED_HEAD, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "DRMP"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Vendor-Specific-Application-Id"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Auth-Session-State"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-Host"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-Realm"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Destination-Host"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Destination-Realm"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "SC-Address"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "OFR-Flags"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Supported-Features"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "User-Identifier"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "SM-RP-UI"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "SMSMI-Correlation-ID"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "SM-Delivery-Outcome"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Proxy-Info"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Route-Record"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules(rules, cmd);
+	  }
+	  /* MO-Forward-Short-Message-Answer */
+	  {
+		struct dict_object* cmd;
+		CHECK_dict_search( DICT_COMMAND, CMD_BY_NAME, "MO-Forward-Short-Message-Answer", &cmd)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 0, .avp_name = "Session-Id"}, RULE_FIXED_HEAD, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "DRMP"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Vendor-Specific-Application-Id"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Result-Code"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Experimental-Result"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Auth-Session-State"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-Host"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-Realm"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Supported-Features"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules(rules, cmd);
+	  }
+	  /* MT-Forward-Short-Message-Request */
+	  {
+		struct dict_object* cmd;
+		CHECK_dict_search( DICT_COMMAND, CMD_BY_NAME, "MT-Forward-Short-Message-Request", &cmd)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 0, .avp_name = "Session-Id"}, RULE_FIXED_HEAD, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "DRMP"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Vendor-Specific-Application-Id"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Auth-Session-State"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-Host"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-Realm"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Destination-Host"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Destination-Realm"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "User-Name"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Supported-Features"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "SMSMI-Correlation-ID"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "SC-Address"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "SM-RP-UI"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "MME-Number-for-MT-SMS"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "SGSN-Number"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "TFR-Flags"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "SM-Delivery-Timer"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "SM-Delivery-Start-Time"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Maximum-Retransmission-Time"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "SMS-GMSC-Address"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Proxy-Info"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Route-Record"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules(rules, cmd);
+	  }
+	  /* MT-Forward-Short-Message-Answer */
+	  {
+		struct dict_object* cmd;
+		CHECK_dict_search( DICT_COMMAND, CMD_BY_NAME, "MT-Forward-Short-Message-Answer", &cmd)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 0, .avp_name = "Session-Id"}, RULE_FIXED_HEAD, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "DRMP"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Vendor-Specific-Application-Id"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Result-Code"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Experimental-Result"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Auth-Session-State"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-Host"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-Realm"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Supported-Features"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Absent-User-Diagnostic-SM"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules(rules, cmd);
+	  }
+	  /* Alert-Service-Centre-Request */
+	  {
+		struct dict_object* cmd;
+		CHECK_dict_search( DICT_COMMAND, CMD_BY_NAME, "Alert-Service-Centre-Request", &cmd)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 0, .avp_name = "Session-Id"}, RULE_FIXED_HEAD, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "DRMP"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Vendor-Specific-Application-Id"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Auth-Session-State"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-Host"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-Realm"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Destination-Host"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Destination-Realm"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "SC-Address"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "User-Identifier"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "SMSMI-Correlation-ID"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Maximum-UE-Availability-Time"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "SMS-GMSC-Alert-Event"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Serving-Node"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Supported-Features"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Proxy-Info"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Route-Record"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules(rules, cmd);
+	  }
+	  /* Alert-Service-Centre-Answer */
+	  {
+		struct dict_object* cmd;
+		CHECK_dict_search( DICT_COMMAND, CMD_BY_NAME, "Alert-Service-Centre-Answer", &cmd)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 0, .avp_name = "Session-Id"}, RULE_FIXED_HEAD, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "DRMP"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Vendor-Specific-Application-Id"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Result-Code"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Experimental-Result"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Auth-Session-State"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-Host"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-Realm"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Supported-Features"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Failed-AVP"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Proxy-Info"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Route-Record"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules(rules, cmd);
+	  }
+
+   }
+
+   LOG_D( "Extension 'Dictionary definitions for SGd (e10)' initialized");
+   return 0;
+}
+
+int dict_entry(char * conffile)
+{
+	dict_sgd_load_defs(conffile);
+	return dict_sgd_load_rules(conffile);
+}
+
+const char* dict_sgd_proto_ver(char * conffile) {
+	return sgd_proto_ver;
+}
+
+const double dict_sgd_gen_ts(char * conffile) {
+	return sgd_gen_date;
+}
+
+EXTENSION_ENTRY2("dict_sgd", dict_sgd_load_defs, dict_sgd_load_rules, "dict_S6c", "dict_ts29338_avps", "dict_ts29272_avps", "dict_ts29336_avps", "dict_ts29173_avps", "dict_ts29329_avps", "dict_ts29229_avps", "dict_rfc7944_avps");
+
+
+
diff --git a/extensions/dict_SLh/CMakeLists.txt b/extensions/dict_SLh/CMakeLists.txt
new file mode 100644
index 0000000..a9d18b1
--- /dev/null
+++ b/extensions/dict_SLh/CMakeLists.txt
@@ -0,0 +1,16 @@
+# The dict_SLh extension
+PROJECT("dict_SLh library generated by FdGen " C)
+
+# Compile as a module
+FD_ADD_EXTENSION(dict_SLh dict_SLh.c)
+
+
+####
+## INSTALL section ##
+
+INSTALL(TARGETS dict_SLh
+	LIBRARY DESTINATION ${INSTALL_EXTENSIONS_SUFFIX}
+COMPONENT freeDiameter-dictionary-SLH)
+
+
+
diff --git a/extensions/dict_SLh/SLh.did b/extensions/dict_SLh/SLh.did
new file mode 100644
index 0000000..204faff
--- /dev/null
+++ b/extensions/dict_SLh/SLh.did
@@ -0,0 +1,38 @@
+dict_rfc6942_avps
+dict_rfc6734_avps
+dict_rfc5580_avps
+dict_ts29468_avps
+dict_ts29154_avps
+dict_ts29214_avps
+dict_ts29215_avps
+dict_ts29217_avps
+dict_3gpp2_avps
+dict_ts29343_avps
+dict_ts29128_avps
+dict_ts29344_avps
+dict_ts29345_avps
+dict_ts32299_avps
+dict_rfc5778_avps
+dict_ts29338_avps
+dict_ts29173_avps
+dict_ts29337_avps
+dict_etsi283034_avps
+dict_rfc4590_avps
+dict_ts29229_avps
+dict_draftload_avps
+dict_ts29329_avps
+dict_ts29368_avps
+dict_ts29336_avps
+dict_ts29061_avps
+dict_ts29272_avps
+dict_rfc7683_avps
+dict_rfc7944_avps
+dict_rfc5777_avps
+dict_rfc4006bis_avps
+dict_ts29212_avps
+dict_rfc7155_avps
+dict_rfc4072_avps
+dict_rfc4004_avps
+dict_rfc5447_avps
+dict_ts29273_avps
+dict_SLh
diff --git a/extensions/dict_SLh/dict_SLh.c b/extensions/dict_SLh/dict_SLh.c
new file mode 100644
index 0000000..edd54bb
--- /dev/null
+++ b/extensions/dict_SLh/dict_SLh.c
@@ -0,0 +1,250 @@
+/*
+* Copyright (c) 2017 Sprint
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*    http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+/****************
+ Generated By: fdtool enhancements to diafuzzer
+ License: same as freeDiameter
+****************/
+
+
+/* 
+ * Dictionary definitions of objects specified in SLh (e00).
+ */
+#include <freeDiameter/extension.h>
+
+#define PROTO_VER "e00"
+#define GEN_DATE  1506697215.67
+
+const char *slh_proto_ver = PROTO_VER;
+const double slh_gen_date = GEN_DATE;
+
+/* The content of this file follows the same structure as dict_base_proto.c */
+
+#define CHECK_dict_new( _type, _data, _parent, _ref )                                     \
+{                                                                                         \
+    int _ret = fd_dict_new( fd_g_config->cnf_dict, (_type), (_data), (_parent), (_ref) ); \
+    if ( _ret != 0 && _ret != EEXIST )                                                    \
+       return _ret;                                                                       \
+}
+
+#define CHECK_dict_search( _type, _criteria, _what, _result )		\
+    CHECK_FCT(  fd_dict_search( fd_g_config->cnf_dict, (_type), (_criteria), (_what), (_result), ENOENT) );
+
+struct local_rules_definition {
+    struct dict_avp_request avp_vendor_plus_name;
+    enum rule_position	position;
+    int 			min;
+    int			max;
+};
+
+#define RULE_ORDER( _position ) ((((_position) == RULE_FIXED_HEAD) || ((_position) == RULE_FIXED_TAIL)) ? 1 : 0 )
+
+/* Attention! This version of the macro uses AVP_BY_NAME_AND_VENDOR, in contrast to most other copies! */
+#define PARSE_loc_rules( _rulearray, _parent) {                                                         \
+        int __ar;                                                                                       \
+        for (__ar=0; __ar < sizeof(_rulearray) / sizeof((_rulearray)[0]); __ar++) {                     \
+                struct dict_rule_data __data = { NULL,                                                  \
+                        (_rulearray)[__ar].position,                                                    \
+                        0,                                                                              \
+                        (_rulearray)[__ar].min,                                                         \
+                        (_rulearray)[__ar].max};                                                        \
+                __data.rule_order = RULE_ORDER(__data.rule_position);                                   \
+                CHECK_FCT(  fd_dict_search(                                                             \
+                        fd_g_config->cnf_dict,                                                          \
+                        DICT_AVP,                                                                       \
+                        AVP_BY_NAME_AND_VENDOR,                                                         \
+                        &(_rulearray)[__ar].avp_vendor_plus_name,                                       \
+                        &__data.rule_avp, 0 ) );                                                        \
+                if ( !__data.rule_avp ) {                                                               \
+                        TRACE_DEBUG(INFO, "AVP Not found: '%s'", (_rulearray)[__ar].avp_vendor_plus_name.avp_name);             \
+                        return ENOENT;                                                                  \
+                }                                                                                       \
+                {                                                                                       \
+                         int _ret = fd_dict_new( fd_g_config->cnf_dict, DICT_RULE, &(__data), (_parent), NULL ); \
+                         if ( _ret != 0 && _ret != EEXIST )      {                                      \
+                                TRACE_DEBUG(INFO, "Error on rule with AVP '%s'",                        \
+                                            (_rulearray)[__ar].avp_vendor_plus_name.avp_name);          \
+                                return EINVAL;                                                          \
+                         }                                                                              \
+                }                                                                                       \
+        }                                                                                               \
+}
+
+#define CHECK_vendor_new( _data ) { \
+        struct dict_object * vendor_found; \
+        if (fd_dict_search(fd_g_config->cnf_dict,DICT_VENDOR,VENDOR_BY_ID,&_data.vendor_id,&vendor_found,ENOENT) == ENOENT) { \
+                CHECK_FCT(fd_dict_new(fd_g_config->cnf_dict, DICT_VENDOR, &_data, NULL, NULL)); \
+        } \
+}
+
+#define enumval_def_u32( _val_, _str_ )		\
+    { _str_, 		{ .u32 = _val_ }}
+
+#define enumval_def_os( _len_, _val_, _str_ )				\
+    { _str_, 		{ .os = { .data = (unsigned char *)_val_, .len = _len_ }}}
+
+
+static int dict_slh_load_defs(char * conffile)
+{
+   TRACE_ENTRY("%p", conffile);
+	struct dict_object * app_id16777291;
+
+	/* Application Section */
+	{
+	  {
+			struct dict_object * vendor;
+			CHECK_dict_search(DICT_VENDOR, VENDOR_BY_NAME, "3GPP", &vendor)
+			struct dict_application_data data = { 16777291, "SLh" };
+			CHECK_dict_new( DICT_APPLICATION, &data, vendor, &app_id16777291)
+	  }
+	}
+
+
+   /* AVP section */
+   {
+		struct dict_object * Address_type;
+		struct dict_object * UTF8String_type;
+		struct dict_object * DiameterIdentity_type;
+		struct dict_object * DiameterURI_type;
+		struct dict_object * Time_type;
+		struct dict_object * IPFilterRule_type;
+
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "Address", &Address_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "UTF8String", &UTF8String_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "DiameterIdentity", &DiameterIdentity_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "DiameterURI", &DiameterURI_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "Time", &Time_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "IPFilterRule", &IPFilterRule_type);
+
+	
+   }
+
+   /* Commands section */
+   {
+		/* LCS-Routing-Info-Request */
+		{
+			struct dict_object* cmd;
+			struct dict_cmd_data data = {
+				8388622,	/* Code */
+				"LCS-Routing-Info-Request",	/* Name */
+				CMD_FLAG_REQUEST | CMD_FLAG_ERROR,	/* Fixed flags */
+				CMD_FLAG_REQUEST | CMD_FLAG_PROXIABLE,	/* Fixed flag values */
+			};
+
+			CHECK_dict_new( DICT_COMMAND, &data , app_id16777291, &cmd)
+		}
+		/* LCS-Routing-Info-Answer */
+		{
+			struct dict_object* cmd;
+			struct dict_cmd_data data = {
+				8388622,	/* Code */
+				"LCS-Routing-Info-Answer",	/* Name */
+				CMD_FLAG_REQUEST,	/* Fixed flags */
+				CMD_FLAG_PROXIABLE,	/* Fixed flag values */
+			};
+
+			CHECK_dict_new( DICT_COMMAND, &data , app_id16777291, &cmd)
+		}
+
+   }
+
+   return 0;
+}
+
+static int dict_slh_load_rules(char * conffile)
+{
+   /* Grouped AVP section */
+   {
+
+   }	
+
+   /* Commands section */
+   {
+	  /* LCS-Routing-Info-Request */
+	  {
+		struct dict_object* cmd;
+		CHECK_dict_search( DICT_COMMAND, CMD_BY_NAME, "LCS-Routing-Info-Request", &cmd)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 0, .avp_name = "Session-Id"}, RULE_FIXED_HEAD, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Vendor-Specific-Application-Id"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Auth-Session-State"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-Host"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-Realm"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Destination-Host"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Destination-Realm"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "User-Name"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "MSISDN"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "GMLC-Number"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Supported-Features"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Proxy-Info"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Route-Record"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules(rules, cmd);
+	  }
+	  /* LCS-Routing-Info-Answer */
+	  {
+		struct dict_object* cmd;
+		CHECK_dict_search( DICT_COMMAND, CMD_BY_NAME, "LCS-Routing-Info-Answer", &cmd)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 0, .avp_name = "Session-Id"}, RULE_FIXED_HEAD, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Vendor-Specific-Application-Id"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Result-Code"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Experimental-Result"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Auth-Session-State"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-Host"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-Realm"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Supported-Features"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "User-Name"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "MSISDN"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "LMSI"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Serving-Node"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Additional-Serving-Node"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "GMLC-Address"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "PPR-Address"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "RIA-Flags"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Failed-AVP"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Proxy-Info"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Route-Record"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules(rules, cmd);
+	  }
+
+   }
+
+   LOG_D( "Extension 'Dictionary definitions for SLh (e00)' initialized");
+   return 0;
+}
+
+int dict_entry(char * conffile)
+{
+	dict_slh_load_defs(conffile);
+	return dict_slh_load_rules(conffile);
+}
+
+const char* dict_slh_proto_ver(char * conffile) {
+	return slh_proto_ver;
+}
+
+const double dict_slh_gen_ts(char * conffile) {
+	return slh_gen_date;
+}
+
+EXTENSION_ENTRY2("dict_slh", dict_slh_load_defs, dict_slh_load_rules, "dict_ts29272_avps", "dict_ts29173_avps", "dict_ts29273_avps", "dict_ts29329_avps", "dict_ts29229_avps");
+
+
+
diff --git a/extensions/dict_Sd/CMakeLists.txt b/extensions/dict_Sd/CMakeLists.txt
new file mode 100644
index 0000000..3fd2ef0
--- /dev/null
+++ b/extensions/dict_Sd/CMakeLists.txt
@@ -0,0 +1,16 @@
+# The dict_Sd extension
+PROJECT("dict_Sd library generated by FdGen " C)
+
+# Compile as a module
+FD_ADD_EXTENSION(dict_Sd dict_Sd.c)
+
+
+####
+## INSTALL section ##
+
+INSTALL(TARGETS dict_Sd
+	LIBRARY DESTINATION ${INSTALL_EXTENSIONS_SUFFIX}
+COMPONENT freeDiameter-dictionary-SD)
+
+
+
diff --git a/extensions/dict_Sd/Sd.did b/extensions/dict_Sd/Sd.did
new file mode 100644
index 0000000..0f6f67d
--- /dev/null
+++ b/extensions/dict_Sd/Sd.did
@@ -0,0 +1,39 @@
+dict_rfc6942_avps
+dict_ts29468_avps
+dict_ts29154_avps
+dict_ts29214_avps
+dict_ts29215_avps
+dict_ts29217_avps
+dict_3gpp2_avps
+dict_ts29343_avps
+dict_ts29338_avps
+dict_ts29128_avps
+dict_ts29344_avps
+dict_ts29345_avps
+dict_ts32299_avps
+dict_rfc6734_avps
+dict_rfc5778_avps
+dict_rfc5580_avps
+dict_rfc4072_avps
+dict_ts29273_avps
+dict_ts29173_avps
+dict_ts29337_avps
+dict_etsi283034_avps
+dict_rfc4590_avps
+dict_ts29229_avps
+dict_draftload_avps
+dict_ts29329_avps
+dict_ts29368_avps
+dict_ts29336_avps
+dict_ts29061_avps
+dict_rfc5447_avps
+dict_ts29272_avps
+dict_rfc7683_avps
+dict_rfc7944_avps
+dict_ts29212_avps
+dict_CreditControl
+dict_rfc4004_avps
+dict_rfc7155_avps
+dict_rfc5777_avps
+dict_rfc4006bis_avps
+dict_Sd
diff --git a/extensions/dict_Sd/dict_Sd.c b/extensions/dict_Sd/dict_Sd.c
new file mode 100644
index 0000000..c5dd8eb
--- /dev/null
+++ b/extensions/dict_Sd/dict_Sd.c
@@ -0,0 +1,432 @@
+/*
+* Copyright (c) 2017 Sprint
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*    http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+/****************
+ Generated By: fdtool enhancements to diafuzzer
+ License: same as freeDiameter
+****************/
+
+
+/* 
+ * Dictionary definitions of objects specified in Sd (e30).
+ */
+#include <freeDiameter/extension.h>
+
+#define PROTO_VER "e30"
+#define GEN_DATE  1506697212.17
+
+const char *sd_proto_ver = PROTO_VER;
+const double sd_gen_date = GEN_DATE;
+
+/* The content of this file follows the same structure as dict_base_proto.c */
+
+#define CHECK_dict_new( _type, _data, _parent, _ref )                                     \
+{                                                                                         \
+    int _ret = fd_dict_new( fd_g_config->cnf_dict, (_type), (_data), (_parent), (_ref) ); \
+    if ( _ret != 0 && _ret != EEXIST )                                                    \
+       return _ret;                                                                       \
+}
+
+#define CHECK_dict_search( _type, _criteria, _what, _result )		\
+    CHECK_FCT(  fd_dict_search( fd_g_config->cnf_dict, (_type), (_criteria), (_what), (_result), ENOENT) );
+
+struct local_rules_definition {
+    struct dict_avp_request avp_vendor_plus_name;
+    enum rule_position	position;
+    int 			min;
+    int			max;
+};
+
+#define RULE_ORDER( _position ) ((((_position) == RULE_FIXED_HEAD) || ((_position) == RULE_FIXED_TAIL)) ? 1 : 0 )
+
+/* Attention! This version of the macro uses AVP_BY_NAME_AND_VENDOR, in contrast to most other copies! */
+#define PARSE_loc_rules( _rulearray, _parent) {                                                         \
+        int __ar;                                                                                       \
+        for (__ar=0; __ar < sizeof(_rulearray) / sizeof((_rulearray)[0]); __ar++) {                     \
+                struct dict_rule_data __data = { NULL,                                                  \
+                        (_rulearray)[__ar].position,                                                    \
+                        0,                                                                              \
+                        (_rulearray)[__ar].min,                                                         \
+                        (_rulearray)[__ar].max};                                                        \
+                __data.rule_order = RULE_ORDER(__data.rule_position);                                   \
+                CHECK_FCT(  fd_dict_search(                                                             \
+                        fd_g_config->cnf_dict,                                                          \
+                        DICT_AVP,                                                                       \
+                        AVP_BY_NAME_AND_VENDOR,                                                         \
+                        &(_rulearray)[__ar].avp_vendor_plus_name,                                       \
+                        &__data.rule_avp, 0 ) );                                                        \
+                if ( !__data.rule_avp ) {                                                               \
+                        TRACE_DEBUG(INFO, "AVP Not found: '%s'", (_rulearray)[__ar].avp_vendor_plus_name.avp_name);             \
+                        return ENOENT;                                                                  \
+                }                                                                                       \
+                {                                                                                       \
+                         int _ret = fd_dict_new( fd_g_config->cnf_dict, DICT_RULE, &(__data), (_parent), NULL ); \
+                         if ( _ret != 0 && _ret != EEXIST )      {                                      \
+                                TRACE_DEBUG(INFO, "Error on rule with AVP '%s'",                        \
+                                            (_rulearray)[__ar].avp_vendor_plus_name.avp_name);          \
+                                return EINVAL;                                                          \
+                         }                                                                              \
+                }                                                                                       \
+        }                                                                                               \
+}
+
+#define CHECK_vendor_new( _data ) { \
+        struct dict_object * vendor_found; \
+        if (fd_dict_search(fd_g_config->cnf_dict,DICT_VENDOR,VENDOR_BY_ID,&_data.vendor_id,&vendor_found,ENOENT) == ENOENT) { \
+                CHECK_FCT(fd_dict_new(fd_g_config->cnf_dict, DICT_VENDOR, &_data, NULL, NULL)); \
+        } \
+}
+
+#define enumval_def_u32( _val_, _str_ )		\
+    { _str_, 		{ .u32 = _val_ }}
+
+#define enumval_def_os( _len_, _val_, _str_ )				\
+    { _str_, 		{ .os = { .data = (unsigned char *)_val_, .len = _len_ }}}
+
+
+static int dict_sd_load_defs(char * conffile)
+{
+   TRACE_ENTRY("%p", conffile);
+	struct dict_object * app_id16777303;
+
+	/* Application Section */
+	{
+	  {
+			struct dict_object * vendor;
+			CHECK_dict_search(DICT_VENDOR, VENDOR_BY_NAME, "3GPP", &vendor)
+			struct dict_application_data data = { 16777303, "Sd" };
+			CHECK_dict_new( DICT_APPLICATION, &data, vendor, &app_id16777303)
+	  }
+	  /* Result codes */
+	  {
+			struct dict_object *type;
+			CHECK_dict_search(DICT_TYPE, TYPE_BY_NAME, "Enumerated(Result-Code)",&type);
+			struct dict_enumval_data        t_1 = { "PCEF_Initiated_IP_CAN_Session_Modification", { .u32=1 }};
+			struct dict_enumval_data        t_2 = { "PCRF_Initiated_IP_CAN_Session_Modification", { .u32=2 }};
+			struct dict_enumval_data        t_3 = { "IP_CAN_Session_Termination", { .u32=3 }};
+			struct dict_enumval_data        t_4 = { "IP_CAN_Session_Modification", { .u32=4 }};
+			struct dict_enumval_data        t_5 = { "ADC_rule", { .u32=5 }};
+			struct dict_enumval_data        t_6 = { "Subscriber_Identifier", { .u32=6 }};
+			struct dict_enumval_data        t_7 = { "Default_QoS_control", { .u32=7 }};
+
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_3, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_4, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_5, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_6, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_7, type, NULL);
+
+	  }
+	}
+
+
+   /* AVP section */
+   {
+		struct dict_object * Address_type;
+		struct dict_object * UTF8String_type;
+		struct dict_object * DiameterIdentity_type;
+		struct dict_object * DiameterURI_type;
+		struct dict_object * Time_type;
+		struct dict_object * IPFilterRule_type;
+
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "Address", &Address_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "UTF8String", &UTF8String_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "DiameterIdentity", &DiameterIdentity_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "DiameterURI", &DiameterURI_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "Time", &Time_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "IPFilterRule", &IPFilterRule_type);
+
+	
+   }
+
+   /* Commands section */
+   {
+		/* TS-Request */
+		{
+			struct dict_object* cmd;
+			struct dict_cmd_data data = {
+				8388637,	/* Code */
+				"TS-Request",	/* Name */
+				CMD_FLAG_REQUEST | CMD_FLAG_ERROR,	/* Fixed flags */
+				CMD_FLAG_REQUEST | CMD_FLAG_PROXIABLE,	/* Fixed flag values */
+			};
+
+			CHECK_dict_new( DICT_COMMAND, &data , app_id16777303, &cmd)
+		}
+		/* TS-Answer */
+		{
+			struct dict_object* cmd;
+			struct dict_cmd_data data = {
+				8388637,	/* Code */
+				"TS-Answer",	/* Name */
+				CMD_FLAG_REQUEST,	/* Fixed flags */
+				CMD_FLAG_PROXIABLE,	/* Fixed flag values */
+			};
+
+			CHECK_dict_new( DICT_COMMAND, &data , app_id16777303, &cmd)
+		}
+
+   }
+
+   return 0;
+}
+
+static int dict_sd_load_rules(char * conffile)
+{
+   /* Grouped AVP section */
+   {
+
+   }	
+
+   /* Commands section */
+   {
+	  /* TS-Request */
+	  {
+		struct dict_object* cmd;
+		CHECK_dict_search( DICT_COMMAND, CMD_BY_NAME, "TS-Request", &cmd)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 0, .avp_name = "Session-Id"}, RULE_FIXED_HEAD, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "DRMP"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Vendor-Specific-Application-Id"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-Host"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-Realm"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Destination-Realm"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Destination-Host"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-State-Id"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "OC-Supported-Features"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Subscription-Id"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Supported-Features"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Framed-IP-Address"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Framed-IPv6-Prefix"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "IP-CAN-Type"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "RAT-Type"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "AN-Trusted"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "User-Equipment-Info"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "QoS-Information"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "AN-GW-Address"}, RULE_OPTIONAL, 0, 2 },
+			{ { .avp_vendor = 10415, .avp_name = "3GPP-SGSN-Address"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "3GPP-SGSN-Ipv6-Address"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "3GPP-GGSN-Address"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "3GPP-GGSN-Ipv6-Address"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "3GPP-Selection-Mode"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Dynamic-Address-Flag"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Dynamic-Address-Flag-Extension"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "PDN-Connection-Charging-ID"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "3GPP-SGSN-MCC-MNC"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "RAI"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "3GPP-User-Location-Info"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Fixed-User-Location-Info"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "User-CSG-Information"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "TWAN-Identifier"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "3GPP-MS-TimeZone"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "3GPP-Charging-Characteristics"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Called-Station-Id"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Charging-Information"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Online"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Offline"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "ADC-Rule-Install"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Revalidation-Time"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Usage-Monitoring-Information"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "CSG-Information-Reporting"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Event-Trigger"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Presence-Reporting-Area-Information"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 13019, .avp_name = "Logical-Access-Id"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 13019, .avp_name = "Physical-Access-Id"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 5535, .avp_name = "3GPP2-BSID"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Proxy-Info"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Route-Record"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules(rules, cmd);
+	  }
+	  /* TS-Answer */
+	  {
+		struct dict_object* cmd;
+		CHECK_dict_search( DICT_COMMAND, CMD_BY_NAME, "TS-Answer", &cmd)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 0, .avp_name = "Session-Id"}, RULE_FIXED_HEAD, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "DRMP"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Vendor-Specific-Application-Id"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-Host"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-Realm"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Result-Code"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Experimental-Result"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-State-Id"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "OC-Supported-Features"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "OC-OLR"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Supported-Features"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "ADC-Rule-Report"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Event-Report-Indication"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Error-Message"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Error-Reporting-Host"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Failed-AVP"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Proxy-Info"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Route-Record"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Load"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules(rules, cmd);
+	  }
+	  /* Credit-Control-Request */
+	  {
+		struct dict_object* cmd;
+		CHECK_dict_search( DICT_COMMAND, CMD_BY_NAME, "Credit-Control-Request", &cmd)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 0, .avp_name = "Session-Id"}, RULE_FIXED_HEAD, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "DRMP"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Auth-Application-Id"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-Host"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-Realm"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Destination-Realm"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "OC-Supported-Features"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "CC-Request-Type"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "CC-Request-Number"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Credit-Management-Status"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Destination-Host"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-State-Id"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Framed-IP-Address"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Framed-IPv6-Prefix"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "ADC-Rule-Report"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Application-Detection-Information"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Event-Trigger"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Event-Report-Indication"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Usage-Monitoring-Information"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Proxy-Info"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Route-Record"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Supported-Features"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules(rules, cmd);
+	  }
+	  /* Credit-Control-Answer */
+	  {
+		struct dict_object* cmd;
+		CHECK_dict_search( DICT_COMMAND, CMD_BY_NAME, "Credit-Control-Answer", &cmd)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 0, .avp_name = "Session-Id"}, RULE_FIXED_HEAD, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "DRMP"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Auth-Application-Id"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-Host"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-Realm"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Result-Code"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Experimental-Result"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "CC-Request-Type"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "CC-Request-Number"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "OC-Supported-Features"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "OC-OLR"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Framed-IPv6-Prefix"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "QoS-Information"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Event-Trigger"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Event-Report-Indication"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-State-Id"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Redirect-Host"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Redirect-Host-Usage"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Redirect-Max-Cache-Time"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "ADC-Rule-Remove"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "ADC-Rule-Install"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Revalidation-Time"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Usage-Monitoring-Information"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Error-Message"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Error-Reporting-Host"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Failed-AVP"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Proxy-Info"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Route-Record"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Supported-Features"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Load"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules(rules, cmd);
+	  }
+	  /* Re-Auth-Request */
+	  {
+		struct dict_object* cmd;
+		CHECK_dict_search( DICT_COMMAND, CMD_BY_NAME, "Re-Auth-Request", &cmd)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 0, .avp_name = "Session-Id"}, RULE_FIXED_HEAD, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "DRMP"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Auth-Application-Id"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-Host"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-Realm"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Destination-Realm"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Destination-Host"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Re-Auth-Request-Type"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Session-Release-Cause"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-State-Id"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "OC-Supported-Features"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "QoS-Information"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Event-Trigger"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Event-Report-Indication"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "ADC-Rule-Remove"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "ADC-Rule-Install"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Revalidation-Time"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Usage-Monitoring-Information"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Proxy-Info"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Route-Record"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules(rules, cmd);
+	  }
+	  /* Re-Auth-Answer */
+	  {
+		struct dict_object* cmd;
+		CHECK_dict_search( DICT_COMMAND, CMD_BY_NAME, "Re-Auth-Answer", &cmd)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 0, .avp_name = "Session-Id"}, RULE_FIXED_HEAD, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "DRMP"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-Host"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-Realm"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Result-Code"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Experimental-Result"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-State-Id"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "OC-Supported-Features"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "OC-OLR"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "ADC-Rule-Report"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Event-Report-Indication"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Error-Message"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Error-Reporting-Host"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Failed-AVP"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Proxy-Info"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Load"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules(rules, cmd);
+	  }
+
+   }
+
+   LOG_D( "Extension 'Dictionary definitions for Sd (e30)' initialized");
+   return 0;
+}
+
+int dict_entry(char * conffile)
+{
+	dict_sd_load_defs(conffile);
+	return dict_sd_load_rules(conffile);
+}
+
+const char* dict_sd_proto_ver(char * conffile) {
+	return sd_proto_ver;
+}
+
+const double dict_sd_gen_ts(char * conffile) {
+	return sd_gen_date;
+}
+
+EXTENSION_ENTRY2("dict_sd", dict_sd_load_defs, dict_sd_load_rules, "dict_ts32299_avps", "dict_ts29212_avps", "dict_ts29273_avps", "dict_ts29214_avps", "dict_ts29272_avps", "dict_ts29229_avps", "dict_ts29061_avps", "dict_CreditControl", "dict_rfc4006bis_avps", "dict_draftload_avps", "dict_rfc7683_avps", "dict_rfc7155_avps", "dict_etsi283034_avps", "dict_3gpp2_avps", "dict_rfc7944_avps");
+
+
+
diff --git a/extensions/dict_Sh/CMakeLists.txt b/extensions/dict_Sh/CMakeLists.txt
new file mode 100644
index 0000000..765e6cb
--- /dev/null
+++ b/extensions/dict_Sh/CMakeLists.txt
@@ -0,0 +1,16 @@
+# The dict_Sh extension
+PROJECT("dict_Sh library generated by FdGen " C)
+
+# Compile as a module
+FD_ADD_EXTENSION(dict_Sh dict_Sh.c)
+
+
+####
+## INSTALL section ##
+
+INSTALL(TARGETS dict_Sh
+	LIBRARY DESTINATION ${INSTALL_EXTENSIONS_SUFFIX}
+COMPONENT freeDiameter-dictionary-SH)
+
+
+
diff --git a/extensions/dict_Sh/Sh.did b/extensions/dict_Sh/Sh.did
new file mode 100644
index 0000000..0e2b2ac
--- /dev/null
+++ b/extensions/dict_Sh/Sh.did
@@ -0,0 +1,10 @@
+dict_etsi283034_avps
+dict_rfc4590_avps
+dict_rfc4004_avps
+dict_rfc7155_avps
+dict_ts29229_avps
+dict_rfc7683_avps
+dict_ts29329_avps
+dict_draftload_avps
+dict_rfc7944_avps
+dict_Sh
diff --git a/extensions/dict_Sh/dict_Sh.c b/extensions/dict_Sh/dict_Sh.c
new file mode 100644
index 0000000..287de2b
--- /dev/null
+++ b/extensions/dict_Sh/dict_Sh.c
@@ -0,0 +1,516 @@
+/*
+* Copyright (c) 2017 Sprint
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*    http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+/****************
+ Generated By: fdtool enhancements to diafuzzer
+ License: same as freeDiameter
+****************/
+
+
+/* 
+ * Dictionary definitions of objects specified in Sh (e20).
+ */
+#include <freeDiameter/extension.h>
+
+#define PROTO_VER "e20"
+#define GEN_DATE  1506697212.31
+
+const char *sh_proto_ver = PROTO_VER;
+const double sh_gen_date = GEN_DATE;
+
+/* The content of this file follows the same structure as dict_base_proto.c */
+
+#define CHECK_dict_new( _type, _data, _parent, _ref )                                     \
+{                                                                                         \
+    int _ret = fd_dict_new( fd_g_config->cnf_dict, (_type), (_data), (_parent), (_ref) ); \
+    if ( _ret != 0 && _ret != EEXIST )                                                    \
+       return _ret;                                                                       \
+}
+
+#define CHECK_dict_search( _type, _criteria, _what, _result )		\
+    CHECK_FCT(  fd_dict_search( fd_g_config->cnf_dict, (_type), (_criteria), (_what), (_result), ENOENT) );
+
+struct local_rules_definition {
+    struct dict_avp_request avp_vendor_plus_name;
+    enum rule_position	position;
+    int 			min;
+    int			max;
+};
+
+#define RULE_ORDER( _position ) ((((_position) == RULE_FIXED_HEAD) || ((_position) == RULE_FIXED_TAIL)) ? 1 : 0 )
+
+/* Attention! This version of the macro uses AVP_BY_NAME_AND_VENDOR, in contrast to most other copies! */
+#define PARSE_loc_rules( _rulearray, _parent) {                                                         \
+        int __ar;                                                                                       \
+        for (__ar=0; __ar < sizeof(_rulearray) / sizeof((_rulearray)[0]); __ar++) {                     \
+                struct dict_rule_data __data = { NULL,                                                  \
+                        (_rulearray)[__ar].position,                                                    \
+                        0,                                                                              \
+                        (_rulearray)[__ar].min,                                                         \
+                        (_rulearray)[__ar].max};                                                        \
+                __data.rule_order = RULE_ORDER(__data.rule_position);                                   \
+                CHECK_FCT(  fd_dict_search(                                                             \
+                        fd_g_config->cnf_dict,                                                          \
+                        DICT_AVP,                                                                       \
+                        AVP_BY_NAME_AND_VENDOR,                                                         \
+                        &(_rulearray)[__ar].avp_vendor_plus_name,                                       \
+                        &__data.rule_avp, 0 ) );                                                        \
+                if ( !__data.rule_avp ) {                                                               \
+                        TRACE_DEBUG(INFO, "AVP Not found: '%s'", (_rulearray)[__ar].avp_vendor_plus_name.avp_name);             \
+                        return ENOENT;                                                                  \
+                }                                                                                       \
+                {                                                                                       \
+                         int _ret = fd_dict_new( fd_g_config->cnf_dict, DICT_RULE, &(__data), (_parent), NULL ); \
+                         if ( _ret != 0 && _ret != EEXIST )      {                                      \
+                                TRACE_DEBUG(INFO, "Error on rule with AVP '%s'",                        \
+                                            (_rulearray)[__ar].avp_vendor_plus_name.avp_name);          \
+                                return EINVAL;                                                          \
+                         }                                                                              \
+                }                                                                                       \
+        }                                                                                               \
+}
+
+#define CHECK_vendor_new( _data ) { \
+        struct dict_object * vendor_found; \
+        if (fd_dict_search(fd_g_config->cnf_dict,DICT_VENDOR,VENDOR_BY_ID,&_data.vendor_id,&vendor_found,ENOENT) == ENOENT) { \
+                CHECK_FCT(fd_dict_new(fd_g_config->cnf_dict, DICT_VENDOR, &_data, NULL, NULL)); \
+        } \
+}
+
+#define enumval_def_u32( _val_, _str_ )		\
+    { _str_, 		{ .u32 = _val_ }}
+
+#define enumval_def_os( _len_, _val_, _str_ )				\
+    { _str_, 		{ .os = { .data = (unsigned char *)_val_, .len = _len_ }}}
+
+
+static int dict_sh_load_defs(char * conffile)
+{
+   TRACE_ENTRY("%p", conffile);
+	struct dict_object * app_id16777217;
+
+	/* Application Section */
+	{
+	  {
+			struct dict_object * vendor;
+			CHECK_dict_search(DICT_VENDOR, VENDOR_BY_NAME, "3GPP", &vendor)
+			struct dict_application_data data = { 16777217, "Sh" };
+			CHECK_dict_new( DICT_APPLICATION, &data, vendor, &app_id16777217)
+	  }
+	  /* Result codes */
+	  {
+			struct dict_object *type;
+			CHECK_dict_search(DICT_TYPE, TYPE_BY_NAME, "Enumerated(Result-Code)",&type);
+			struct dict_enumval_data        t_1 = { "used_in_Sh", { .u32=1 }};
+			struct dict_enumval_data        t_2 = { "Command_Code_values", { .u32=3 }};
+			struct dict_enumval_data        t_3 = { "Application_ID_value", { .u32=4 }};
+			struct dict_enumval_data        t_4 = { "Special_Requirements", { .u32=7 }};
+
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_3, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_4, type, NULL);
+
+	  }
+	}
+
+
+   /* AVP section */
+   {
+		struct dict_object * Address_type;
+		struct dict_object * UTF8String_type;
+		struct dict_object * DiameterIdentity_type;
+		struct dict_object * DiameterURI_type;
+		struct dict_object * Time_type;
+		struct dict_object * IPFilterRule_type;
+
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "Address", &Address_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "UTF8String", &UTF8String_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "DiameterIdentity", &DiameterIdentity_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "DiameterURI", &DiameterURI_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "Time", &Time_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "IPFilterRule", &IPFilterRule_type);
+
+	
+   }
+
+   /* Commands section */
+   {
+		/* User-Data-Request */
+		{
+			struct dict_object* cmd;
+			struct dict_cmd_data data = {
+				306,	/* Code */
+				"User-Data-Request",	/* Name */
+				CMD_FLAG_REQUEST | CMD_FLAG_ERROR,	/* Fixed flags */
+				CMD_FLAG_REQUEST | CMD_FLAG_PROXIABLE,	/* Fixed flag values */
+			};
+
+			CHECK_dict_new( DICT_COMMAND, &data , app_id16777217, &cmd)
+		}
+		/* User-Data-Answer */
+		{
+			struct dict_object* cmd;
+			struct dict_cmd_data data = {
+				306,	/* Code */
+				"User-Data-Answer",	/* Name */
+				CMD_FLAG_REQUEST,	/* Fixed flags */
+				CMD_FLAG_PROXIABLE,	/* Fixed flag values */
+			};
+
+			CHECK_dict_new( DICT_COMMAND, &data , app_id16777217, &cmd)
+		}
+		/* Profile-Update-Request */
+		{
+			struct dict_object* cmd;
+			struct dict_cmd_data data = {
+				307,	/* Code */
+				"Profile-Update-Request",	/* Name */
+				CMD_FLAG_REQUEST | CMD_FLAG_ERROR,	/* Fixed flags */
+				CMD_FLAG_REQUEST | CMD_FLAG_PROXIABLE,	/* Fixed flag values */
+			};
+
+			CHECK_dict_new( DICT_COMMAND, &data , app_id16777217, &cmd)
+		}
+		/* Profile-Update-Answer */
+		{
+			struct dict_object* cmd;
+			struct dict_cmd_data data = {
+				307,	/* Code */
+				"Profile-Update-Answer",	/* Name */
+				CMD_FLAG_REQUEST,	/* Fixed flags */
+				CMD_FLAG_PROXIABLE,	/* Fixed flag values */
+			};
+
+			CHECK_dict_new( DICT_COMMAND, &data , app_id16777217, &cmd)
+		}
+		/* Subscribe-Notifications-Request */
+		{
+			struct dict_object* cmd;
+			struct dict_cmd_data data = {
+				308,	/* Code */
+				"Subscribe-Notifications-Request",	/* Name */
+				CMD_FLAG_REQUEST | CMD_FLAG_ERROR,	/* Fixed flags */
+				CMD_FLAG_REQUEST | CMD_FLAG_PROXIABLE,	/* Fixed flag values */
+			};
+
+			CHECK_dict_new( DICT_COMMAND, &data , app_id16777217, &cmd)
+		}
+		/* Subscribe-Notifications-Answer */
+		{
+			struct dict_object* cmd;
+			struct dict_cmd_data data = {
+				308,	/* Code */
+				"Subscribe-Notifications-Answer",	/* Name */
+				CMD_FLAG_REQUEST,	/* Fixed flags */
+				CMD_FLAG_PROXIABLE,	/* Fixed flag values */
+			};
+
+			CHECK_dict_new( DICT_COMMAND, &data , app_id16777217, &cmd)
+		}
+		/* Push-Notification-Request */
+		{
+			struct dict_object* cmd;
+			struct dict_cmd_data data = {
+				309,	/* Code */
+				"Push-Notification-Request",	/* Name */
+				CMD_FLAG_REQUEST | CMD_FLAG_ERROR,	/* Fixed flags */
+				CMD_FLAG_REQUEST | CMD_FLAG_PROXIABLE,	/* Fixed flag values */
+			};
+
+			CHECK_dict_new( DICT_COMMAND, &data , app_id16777217, &cmd)
+		}
+		/* Push-Notification-Answer */
+		{
+			struct dict_object* cmd;
+			struct dict_cmd_data data = {
+				309,	/* Code */
+				"Push-Notification-Answer",	/* Name */
+				CMD_FLAG_REQUEST,	/* Fixed flags */
+				CMD_FLAG_PROXIABLE,	/* Fixed flag values */
+			};
+
+			CHECK_dict_new( DICT_COMMAND, &data , app_id16777217, &cmd)
+		}
+
+   }
+
+   return 0;
+}
+
+static int dict_sh_load_rules(char * conffile)
+{
+   /* Grouped AVP section */
+   {
+
+   }	
+
+   /* Commands section */
+   {
+	  /* User-Data-Request */
+	  {
+		struct dict_object* cmd;
+		CHECK_dict_search( DICT_COMMAND, CMD_BY_NAME, "User-Data-Request", &cmd)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 0, .avp_name = "Session-Id"}, RULE_FIXED_HEAD, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "DRMP"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Vendor-Specific-Application-Id"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Auth-Session-State"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-Host"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-Realm"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Destination-Host"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Destination-Realm"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Supported-Features"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "User-Identity"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Wildcarded-Public-Identity"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Wildcarded-IMPU"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Server-Name"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Service-Indication"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Data-Reference"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Identity-Set"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Requested-Domain"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Current-Location"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "DSAI-Tag"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Session-Priority"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "User-Name"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Requested-Nodes"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Serving-Node-Indication"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Pre-paging-Supported"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Local-Time-Zone-Indication"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "UDR-Flags"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Call-Reference-Info"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "OC-Supported-Features"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Proxy-Info"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Route-Record"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules(rules, cmd);
+	  }
+	  /* User-Data-Answer */
+	  {
+		struct dict_object* cmd;
+		CHECK_dict_search( DICT_COMMAND, CMD_BY_NAME, "User-Data-Answer", &cmd)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 0, .avp_name = "Session-Id"}, RULE_FIXED_HEAD, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "DRMP"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Vendor-Specific-Application-Id"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Result-Code"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Experimental-Result"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Auth-Session-State"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-Host"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-Realm"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Supported-Features"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Wildcarded-Public-Identity"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Wildcarded-IMPU"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "User-Data"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "OC-Supported-Features"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "OC-OLR"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Load"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Failed-AVP"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Proxy-Info"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Route-Record"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules(rules, cmd);
+	  }
+	  /* Profile-Update-Request */
+	  {
+		struct dict_object* cmd;
+		CHECK_dict_search( DICT_COMMAND, CMD_BY_NAME, "Profile-Update-Request", &cmd)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 0, .avp_name = "Session-Id"}, RULE_FIXED_HEAD, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "DRMP"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Vendor-Specific-Application-Id"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Auth-Session-State"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-Host"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-Realm"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Destination-Host"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Destination-Realm"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Supported-Features"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "User-Identity"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Wildcarded-Public-Identity"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Wildcarded-IMPU"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "User-Name"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Data-Reference"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "User-Data"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "OC-Supported-Features"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Proxy-Info"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Route-Record"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules(rules, cmd);
+	  }
+	  /* Profile-Update-Answer */
+	  {
+		struct dict_object* cmd;
+		CHECK_dict_search( DICT_COMMAND, CMD_BY_NAME, "Profile-Update-Answer", &cmd)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 0, .avp_name = "Session-Id"}, RULE_FIXED_HEAD, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "DRMP"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Vendor-Specific-Application-Id"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Result-Code"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Experimental-Result"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Auth-Session-State"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-Host"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-Realm"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Wildcarded-Public-Identity"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Wildcarded-IMPU"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Repository-Data-ID"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Data-Reference"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Supported-Features"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "OC-Supported-Features"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "OC-OLR"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Load"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Failed-AVP"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Proxy-Info"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Route-Record"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules(rules, cmd);
+	  }
+	  /* Subscribe-Notifications-Request */
+	  {
+		struct dict_object* cmd;
+		CHECK_dict_search( DICT_COMMAND, CMD_BY_NAME, "Subscribe-Notifications-Request", &cmd)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 0, .avp_name = "Session-Id"}, RULE_FIXED_HEAD, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "DRMP"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Vendor-Specific-Application-Id"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Auth-Session-State"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-Host"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-Realm"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Destination-Host"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Destination-Realm"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Supported-Features"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "User-Identity"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Wildcarded-Public-Identity"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Wildcarded-IMPU"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Service-Indication"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Send-Data-Indication"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Server-Name"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Subs-Req-Type"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Data-Reference"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Identity-Set"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Expiry-Time"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "DSAI-Tag"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "One-Time-Notification"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "User-Name"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "OC-Supported-Features"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Proxy-Info"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Route-Record"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules(rules, cmd);
+	  }
+	  /* Subscribe-Notifications-Answer */
+	  {
+		struct dict_object* cmd;
+		CHECK_dict_search( DICT_COMMAND, CMD_BY_NAME, "Subscribe-Notifications-Answer", &cmd)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 0, .avp_name = "Session-Id"}, RULE_FIXED_HEAD, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "DRMP"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Vendor-Specific-Application-Id"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Auth-Session-State"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Result-Code"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Experimental-Result"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-Host"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-Realm"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Wildcarded-Public-Identity"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Wildcarded-IMPU"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Supported-Features"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "User-Data"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Expiry-Time"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "OC-Supported-Features"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "OC-OLR"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Load"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Failed-AVP"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Proxy-Info"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Route-Record"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules(rules, cmd);
+	  }
+	  /* Push-Notification-Request */
+	  {
+		struct dict_object* cmd;
+		CHECK_dict_search( DICT_COMMAND, CMD_BY_NAME, "Push-Notification-Request", &cmd)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 0, .avp_name = "Session-Id"}, RULE_FIXED_HEAD, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "DRMP"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Vendor-Specific-Application-Id"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Auth-Session-State"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-Host"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-Realm"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Destination-Host"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Destination-Realm"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Supported-Features"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "User-Identity"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Wildcarded-Public-Identity"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Wildcarded-IMPU"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "User-Name"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "User-Data"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Proxy-Info"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Route-Record"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules(rules, cmd);
+	  }
+	  /* Push-Notification-Answer */
+	  {
+		struct dict_object* cmd;
+		CHECK_dict_search( DICT_COMMAND, CMD_BY_NAME, "Push-Notification-Answer", &cmd)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 0, .avp_name = "Session-Id"}, RULE_FIXED_HEAD, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "DRMP"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Vendor-Specific-Application-Id"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Result-Code"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Experimental-Result"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Auth-Session-State"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-Host"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-Realm"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Supported-Features"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Failed-AVP"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Proxy-Info"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Route-Record"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules(rules, cmd);
+	  }
+
+   }
+
+   LOG_D( "Extension 'Dictionary definitions for Sh (e20)' initialized");
+   return 0;
+}
+
+int dict_entry(char * conffile)
+{
+	dict_sh_load_defs(conffile);
+	return dict_sh_load_rules(conffile);
+}
+
+const char* dict_sh_proto_ver(char * conffile) {
+	return sh_proto_ver;
+}
+
+const double dict_sh_gen_ts(char * conffile) {
+	return sh_gen_date;
+}
+
+EXTENSION_ENTRY2("dict_sh", dict_sh_load_defs, dict_sh_load_rules, "dict_ts29329_avps", "dict_ts29229_avps", "dict_draftload_avps", "dict_rfc7683_avps", "dict_rfc7944_avps");
+
+
+
diff --git a/extensions/dict_T4/CMakeLists.txt b/extensions/dict_T4/CMakeLists.txt
new file mode 100644
index 0000000..813b8bf
--- /dev/null
+++ b/extensions/dict_T4/CMakeLists.txt
@@ -0,0 +1,16 @@
+# The dict_T4 extension
+PROJECT("dict_T4 library generated by FdGen " C)
+
+# Compile as a module
+FD_ADD_EXTENSION(dict_T4 dict_T4.c)
+
+
+####
+## INSTALL section ##
+
+INSTALL(TARGETS dict_T4
+	LIBRARY DESTINATION ${INSTALL_EXTENSIONS_SUFFIX}
+COMPONENT freeDiameter-dictionary-dict_T4)
+
+
+
diff --git a/extensions/dict_T4/T4.did b/extensions/dict_T4/T4.did
new file mode 100644
index 0000000..2ad7fcb
--- /dev/null
+++ b/extensions/dict_T4/T4.did
@@ -0,0 +1,38 @@
+dict_rfc6942_avps
+dict_ts29468_avps
+dict_ts29154_avps
+dict_ts29214_avps
+dict_ts29215_avps
+dict_ts29217_avps
+dict_3gpp2_avps
+dict_ts29337_avps
+dict_ts29343_avps
+dict_ts29338_avps
+dict_ts29128_avps
+dict_ts29344_avps
+dict_ts29345_avps
+dict_ts29173_avps
+dict_ts32299_avps
+dict_rfc6734_avps
+dict_rfc5580_avps
+dict_rfc4072_avps
+dict_ts29273_avps
+dict_rfc4006bis_avps
+dict_ts29212_avps
+dict_ts29061_avps
+dict_ts29272_avps
+dict_rfc5447_avps
+dict_rfc5778_avps
+dict_rfc5777_avps
+dict_ts29336_avps
+dict_etsi283034_avps
+dict_rfc4590_avps
+dict_rfc4004_avps
+dict_rfc7155_avps
+dict_ts29229_avps
+dict_rfc7683_avps
+dict_draftload_avps
+dict_rfc7944_avps
+dict_ts29329_avps
+dict_ts29368_avps
+dict_T4
diff --git a/extensions/dict_T4/dict_T4.c b/extensions/dict_T4/dict_T4.c
new file mode 100644
index 0000000..e02df57
--- /dev/null
+++ b/extensions/dict_T4/dict_T4.c
@@ -0,0 +1,338 @@
+/*
+* Copyright (c) 2017 Sprint
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*    http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+/****************
+ Generated By: fdtool enhancements to diafuzzer
+ License: same as freeDiameter
+****************/
+
+
+/* 
+ * Dictionary definitions of objects specified in T4 (e00).
+ */
+#include <freeDiameter/extension.h>
+
+#define PROTO_VER "e00"
+#define GEN_DATE  1506697219.31
+
+const char *t4_proto_ver = PROTO_VER;
+const double t4_gen_date = GEN_DATE;
+
+/* The content of this file follows the same structure as dict_base_proto.c */
+
+#define CHECK_dict_new( _type, _data, _parent, _ref )                                     \
+{                                                                                         \
+    int _ret = fd_dict_new( fd_g_config->cnf_dict, (_type), (_data), (_parent), (_ref) ); \
+    if ( _ret != 0 && _ret != EEXIST )                                                    \
+       return _ret;                                                                       \
+}
+
+#define CHECK_dict_search( _type, _criteria, _what, _result )		\
+    CHECK_FCT(  fd_dict_search( fd_g_config->cnf_dict, (_type), (_criteria), (_what), (_result), ENOENT) );
+
+struct local_rules_definition {
+    struct dict_avp_request avp_vendor_plus_name;
+    enum rule_position	position;
+    int 			min;
+    int			max;
+};
+
+#define RULE_ORDER( _position ) ((((_position) == RULE_FIXED_HEAD) || ((_position) == RULE_FIXED_TAIL)) ? 1 : 0 )
+
+/* Attention! This version of the macro uses AVP_BY_NAME_AND_VENDOR, in contrast to most other copies! */
+#define PARSE_loc_rules( _rulearray, _parent) {                                                         \
+        int __ar;                                                                                       \
+        for (__ar=0; __ar < sizeof(_rulearray) / sizeof((_rulearray)[0]); __ar++) {                     \
+                struct dict_rule_data __data = { NULL,                                                  \
+                        (_rulearray)[__ar].position,                                                    \
+                        0,                                                                              \
+                        (_rulearray)[__ar].min,                                                         \
+                        (_rulearray)[__ar].max};                                                        \
+                __data.rule_order = RULE_ORDER(__data.rule_position);                                   \
+                CHECK_FCT(  fd_dict_search(                                                             \
+                        fd_g_config->cnf_dict,                                                          \
+                        DICT_AVP,                                                                       \
+                        AVP_BY_NAME_AND_VENDOR,                                                         \
+                        &(_rulearray)[__ar].avp_vendor_plus_name,                                       \
+                        &__data.rule_avp, 0 ) );                                                        \
+                if ( !__data.rule_avp ) {                                                               \
+                        TRACE_DEBUG(INFO, "AVP Not found: '%s'", (_rulearray)[__ar].avp_vendor_plus_name.avp_name);             \
+                        return ENOENT;                                                                  \
+                }                                                                                       \
+                {                                                                                       \
+                         int _ret = fd_dict_new( fd_g_config->cnf_dict, DICT_RULE, &(__data), (_parent), NULL ); \
+                         if ( _ret != 0 && _ret != EEXIST )      {                                      \
+                                TRACE_DEBUG(INFO, "Error on rule with AVP '%s'",                        \
+                                            (_rulearray)[__ar].avp_vendor_plus_name.avp_name);          \
+                                return EINVAL;                                                          \
+                         }                                                                              \
+                }                                                                                       \
+        }                                                                                               \
+}
+
+#define CHECK_vendor_new( _data ) { \
+        struct dict_object * vendor_found; \
+        if (fd_dict_search(fd_g_config->cnf_dict,DICT_VENDOR,VENDOR_BY_ID,&_data.vendor_id,&vendor_found,ENOENT) == ENOENT) { \
+                CHECK_FCT(fd_dict_new(fd_g_config->cnf_dict, DICT_VENDOR, &_data, NULL, NULL)); \
+        } \
+}
+
+#define enumval_def_u32( _val_, _str_ )		\
+    { _str_, 		{ .u32 = _val_ }}
+
+#define enumval_def_os( _len_, _val_, _str_ )				\
+    { _str_, 		{ .os = { .data = (unsigned char *)_val_, .len = _len_ }}}
+
+
+static int dict_t4_load_defs(char * conffile)
+{
+   TRACE_ENTRY("%p", conffile);
+	struct dict_object * app_id16777311;
+
+	/* Application Section */
+	{
+	  {
+			struct dict_object * vendor;
+			CHECK_dict_search(DICT_VENDOR, VENDOR_BY_NAME, "3GPP", &vendor)
+			struct dict_application_data data = { 16777311, "T4" };
+			CHECK_dict_new( DICT_APPLICATION, &data, vendor, &app_id16777311)
+	  }
+	  /* Result codes */
+	  {
+			struct dict_object *type;
+			CHECK_dict_search(DICT_TYPE, TYPE_BY_NAME, "Enumerated(Result-Code)",&type);
+			struct dict_enumval_data        t_1 = { "General", { .u32=1 }};
+			struct dict_enumval_data        t_2 = { "SMS_SC_and_MTC_IWF_behaviour", { .u32=2 }};
+			struct dict_enumval_data        t_3 = { "Permanent_Failures", { .u32=3 }};
+			struct dict_enumval_data        t_4 = { "Void", { .u32=4 }};
+
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_3, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_4, type, NULL);
+
+	  }
+	}
+
+
+   /* AVP section */
+   {
+		struct dict_object * Address_type;
+		struct dict_object * UTF8String_type;
+		struct dict_object * DiameterIdentity_type;
+		struct dict_object * DiameterURI_type;
+		struct dict_object * Time_type;
+		struct dict_object * IPFilterRule_type;
+
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "Address", &Address_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "UTF8String", &UTF8String_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "DiameterIdentity", &DiameterIdentity_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "DiameterURI", &DiameterURI_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "Time", &Time_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "IPFilterRule", &IPFilterRule_type);
+
+	
+   }
+
+   /* Commands section */
+   {
+		/* Device-Trigger-Request */
+		{
+			struct dict_object* cmd;
+			struct dict_cmd_data data = {
+				8388643,	/* Code */
+				"Device-Trigger-Request",	/* Name */
+				CMD_FLAG_REQUEST | CMD_FLAG_ERROR,	/* Fixed flags */
+				CMD_FLAG_REQUEST | CMD_FLAG_PROXIABLE,	/* Fixed flag values */
+			};
+
+			CHECK_dict_new( DICT_COMMAND, &data , app_id16777311, &cmd)
+		}
+		/* Device-Trigger-Answer */
+		{
+			struct dict_object* cmd;
+			struct dict_cmd_data data = {
+				8388643,	/* Code */
+				"Device-Trigger-Answer",	/* Name */
+				CMD_FLAG_REQUEST,	/* Fixed flags */
+				CMD_FLAG_PROXIABLE,	/* Fixed flag values */
+			};
+
+			CHECK_dict_new( DICT_COMMAND, &data , app_id16777311, &cmd)
+		}
+		/* Delivery-Report-Request */
+		{
+			struct dict_object* cmd;
+			struct dict_cmd_data data = {
+				8388644,	/* Code */
+				"Delivery-Report-Request",	/* Name */
+				CMD_FLAG_REQUEST | CMD_FLAG_ERROR,	/* Fixed flags */
+				CMD_FLAG_REQUEST | CMD_FLAG_PROXIABLE,	/* Fixed flag values */
+			};
+
+			CHECK_dict_new( DICT_COMMAND, &data , app_id16777311, &cmd)
+		}
+		/* Delivery-Report-Answer */
+		{
+			struct dict_object* cmd;
+			struct dict_cmd_data data = {
+				8388644,	/* Code */
+				"Delivery-Report-Answer",	/* Name */
+				CMD_FLAG_REQUEST,	/* Fixed flags */
+				CMD_FLAG_PROXIABLE,	/* Fixed flag values */
+			};
+
+			CHECK_dict_new( DICT_COMMAND, &data , app_id16777311, &cmd)
+		}
+
+   }
+
+   return 0;
+}
+
+static int dict_t4_load_rules(char * conffile)
+{
+   /* Grouped AVP section */
+   {
+
+   }	
+
+   /* Commands section */
+   {
+	  /* Device-Trigger-Request */
+	  {
+		struct dict_object* cmd;
+		CHECK_dict_search( DICT_COMMAND, CMD_BY_NAME, "Device-Trigger-Request", &cmd)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 0, .avp_name = "Session-Id"}, RULE_FIXED_HEAD, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "DRMP"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Auth-Session-State"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-Host"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-Realm"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Destination-Host"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Destination-Realm"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "User-Identifier"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "SM-RP-SMEA"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Payload"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Serving-Node"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Additional-Serving-Node"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Reference-Number"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Validity-Time"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Priority-Indication"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Application-Port-Identifier"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Old-Reference-Number"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Trigger-Action"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Supported-Features"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Proxy-Info"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Route-Record"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules(rules, cmd);
+	  }
+	  /* Device-Trigger-Answer */
+	  {
+		struct dict_object* cmd;
+		CHECK_dict_search( DICT_COMMAND, CMD_BY_NAME, "Device-Trigger-Answer", &cmd)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 0, .avp_name = "Session-Id"}, RULE_FIXED_HEAD, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "DRMP"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Vendor-Specific-Application-Id"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Result-Code"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Experimental-Result"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "MTC-Error-Diagnostic"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Auth-Session-State"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-Host"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-Realm"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Old-Reference-Number"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Trigger-Action"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Supported-Features"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Failed-AVP"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Proxy-Info"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Route-Record"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules(rules, cmd);
+	  }
+	  /* Delivery-Report-Request */
+	  {
+		struct dict_object* cmd;
+		CHECK_dict_search( DICT_COMMAND, CMD_BY_NAME, "Delivery-Report-Request", &cmd)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 0, .avp_name = "Session-Id"}, RULE_FIXED_HEAD, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "DRMP"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Auth-Session-State"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-Host"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-Realm"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Destination-Host"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Destination-Realm"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "User-Identifier"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "SM-RP-SMEA"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "SM-Delivery-Outcome-T4"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Absent-Subscriber-Diagnostic-T4"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Reference-Number"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Supported-Features"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Proxy-Info"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Route-Record"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules(rules, cmd);
+	  }
+	  /* Delivery-Report-Answer */
+	  {
+		struct dict_object* cmd;
+		CHECK_dict_search( DICT_COMMAND, CMD_BY_NAME, "Delivery-Report-Answer", &cmd)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 0, .avp_name = "Session-Id"}, RULE_FIXED_HEAD, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "DRMP"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Vendor-Specific-Application-Id"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Result-Code"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Experimental-Result"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Auth-Session-State"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-Host"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-Realm"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Supported-Features"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Failed-AVP"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Proxy-Info"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Route-Record"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules(rules, cmd);
+	  }
+
+   }
+
+   LOG_D( "Extension 'Dictionary definitions for T4 (e00)' initialized");
+   return 0;
+}
+
+int dict_entry(char * conffile)
+{
+	dict_t4_load_defs(conffile);
+	return dict_t4_load_rules(conffile);
+}
+
+const char* dict_t4_proto_ver(char * conffile) {
+	return t4_proto_ver;
+}
+
+const double dict_t4_gen_ts(char * conffile) {
+	return t4_gen_date;
+}
+
+EXTENSION_ENTRY2("dict_t4", dict_t4_load_defs, dict_t4_load_rules, "dict_ts29337_avps", "dict_ts29336_avps", "dict_ts29338_avps", "dict_ts29272_avps", "dict_ts29368_avps", "dict_ts29173_avps", "dict_ts29229_avps", "dict_ts29329_avps", "dict_rfc4006bis_avps", "dict_rfc7155_avps", "dict_rfc7944_avps");
+
+
+
diff --git a/extensions/dict_T6aT6bT7/CMakeLists.txt b/extensions/dict_T6aT6bT7/CMakeLists.txt
new file mode 100644
index 0000000..eb55e44
--- /dev/null
+++ b/extensions/dict_T6aT6bT7/CMakeLists.txt
@@ -0,0 +1,16 @@
+# The dict_T6aT6bT7 extension
+PROJECT("dict_T6aT6bT7 library generated by FdGen " C)
+
+# Compile as a module
+FD_ADD_EXTENSION(dict_T6aT6bT7 dict_T6aT6bT7.c)
+
+
+####
+## INSTALL section ##
+
+INSTALL(TARGETS dict_T6aT6bT7
+	LIBRARY DESTINATION ${INSTALL_EXTENSIONS_SUFFIX}
+COMPONENT freeDiameter-dictionary-T6AT6BT7)
+
+
+
diff --git a/extensions/dict_T6aT6bT7/T6aT6bT7.did b/extensions/dict_T6aT6bT7/T6aT6bT7.did
new file mode 100644
index 0000000..ca39ad5
--- /dev/null
+++ b/extensions/dict_T6aT6bT7/T6aT6bT7.did
@@ -0,0 +1,38 @@
+dict_rfc6942_avps
+dict_ts29468_avps
+dict_ts29154_avps
+dict_ts29214_avps
+dict_ts29215_avps
+dict_ts29217_avps
+dict_3gpp2_avps
+dict_ts29343_avps
+dict_ts29338_avps
+dict_ts29128_avps
+dict_ts29344_avps
+dict_ts29345_avps
+dict_ts32299_avps
+dict_rfc6734_avps
+dict_rfc5778_avps
+dict_rfc5580_avps
+dict_rfc4072_avps
+dict_ts29273_avps
+dict_ts29173_avps
+dict_ts29337_avps
+dict_etsi283034_avps
+dict_rfc4590_avps
+dict_ts29229_avps
+dict_draftload_avps
+dict_ts29329_avps
+dict_ts29368_avps
+dict_ts29336_avps
+dict_ts29061_avps
+dict_rfc5447_avps
+dict_ts29272_avps
+dict_rfc7683_avps
+dict_rfc7944_avps
+dict_rfc5777_avps
+dict_rfc4006bis_avps
+dict_rfc4004_avps
+dict_rfc7155_avps
+dict_ts29212_avps
+dict_T6aT6bT7
diff --git a/extensions/dict_T6aT6bT7/dict_T6aT6bT7.c b/extensions/dict_T6aT6bT7/dict_T6aT6bT7.c
new file mode 100644
index 0000000..e137a4a
--- /dev/null
+++ b/extensions/dict_T6aT6bT7/dict_T6aT6bT7.c
@@ -0,0 +1,485 @@
+/*
+* Copyright (c) 2017 Sprint
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*    http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+/****************
+ Generated By: fdtool enhancements to diafuzzer
+ License: same as freeDiameter
+****************/
+
+
+/* 
+ * Dictionary definitions of objects specified in T6aT6bT7 (e20).
+ */
+#include <freeDiameter/extension.h>
+
+#define PROTO_VER "e20"
+#define GEN_DATE  1506697230.23
+
+const char *t6at6bt7_proto_ver = PROTO_VER;
+const double t6at6bt7_gen_date = GEN_DATE;
+
+/* The content of this file follows the same structure as dict_base_proto.c */
+
+#define CHECK_dict_new( _type, _data, _parent, _ref )                                     \
+{                                                                                         \
+    int _ret = fd_dict_new( fd_g_config->cnf_dict, (_type), (_data), (_parent), (_ref) ); \
+    if ( _ret != 0 && _ret != EEXIST )                                                    \
+       return _ret;                                                                       \
+}
+
+#define CHECK_dict_search( _type, _criteria, _what, _result )		\
+    CHECK_FCT(  fd_dict_search( fd_g_config->cnf_dict, (_type), (_criteria), (_what), (_result), ENOENT) );
+
+struct local_rules_definition {
+    struct dict_avp_request avp_vendor_plus_name;
+    enum rule_position	position;
+    int 			min;
+    int			max;
+};
+
+#define RULE_ORDER( _position ) ((((_position) == RULE_FIXED_HEAD) || ((_position) == RULE_FIXED_TAIL)) ? 1 : 0 )
+
+/* Attention! This version of the macro uses AVP_BY_NAME_AND_VENDOR, in contrast to most other copies! */
+#define PARSE_loc_rules( _rulearray, _parent) {                                                         \
+        int __ar;                                                                                       \
+        for (__ar=0; __ar < sizeof(_rulearray) / sizeof((_rulearray)[0]); __ar++) {                     \
+                struct dict_rule_data __data = { NULL,                                                  \
+                        (_rulearray)[__ar].position,                                                    \
+                        0,                                                                              \
+                        (_rulearray)[__ar].min,                                                         \
+                        (_rulearray)[__ar].max};                                                        \
+                __data.rule_order = RULE_ORDER(__data.rule_position);                                   \
+                CHECK_FCT(  fd_dict_search(                                                             \
+                        fd_g_config->cnf_dict,                                                          \
+                        DICT_AVP,                                                                       \
+                        AVP_BY_NAME_AND_VENDOR,                                                         \
+                        &(_rulearray)[__ar].avp_vendor_plus_name,                                       \
+                        &__data.rule_avp, 0 ) );                                                        \
+                if ( !__data.rule_avp ) {                                                               \
+                        TRACE_DEBUG(INFO, "AVP Not found: '%s'", (_rulearray)[__ar].avp_vendor_plus_name.avp_name);             \
+                        return ENOENT;                                                                  \
+                }                                                                                       \
+                {                                                                                       \
+                         int _ret = fd_dict_new( fd_g_config->cnf_dict, DICT_RULE, &(__data), (_parent), NULL ); \
+                         if ( _ret != 0 && _ret != EEXIST )      {                                      \
+                                TRACE_DEBUG(INFO, "Error on rule with AVP '%s'",                        \
+                                            (_rulearray)[__ar].avp_vendor_plus_name.avp_name);          \
+                                return EINVAL;                                                          \
+                         }                                                                              \
+                }                                                                                       \
+        }                                                                                               \
+}
+
+#define CHECK_vendor_new( _data ) { \
+        struct dict_object * vendor_found; \
+        if (fd_dict_search(fd_g_config->cnf_dict,DICT_VENDOR,VENDOR_BY_ID,&_data.vendor_id,&vendor_found,ENOENT) == ENOENT) { \
+                CHECK_FCT(fd_dict_new(fd_g_config->cnf_dict, DICT_VENDOR, &_data, NULL, NULL)); \
+        } \
+}
+
+#define enumval_def_u32( _val_, _str_ )		\
+    { _str_, 		{ .u32 = _val_ }}
+
+#define enumval_def_os( _len_, _val_, _str_ )				\
+    { _str_, 		{ .os = { .data = (unsigned char *)_val_, .len = _len_ }}}
+
+
+static int dict_t6at6bt7_load_defs(char * conffile)
+{
+   TRACE_ENTRY("%p", conffile);
+	struct dict_object * app_id16777346;
+
+	/* Application Section */
+	{
+	  {
+			struct dict_object * vendor;
+			CHECK_dict_search(DICT_VENDOR, VENDOR_BY_NAME, "3GPP", &vendor)
+			struct dict_application_data data = { 16777346, "T6aT6bT7" };
+			CHECK_dict_new( DICT_APPLICATION, &data, vendor, &app_id16777346)
+	  }
+	}
+
+
+   /* AVP section */
+   {
+		struct dict_object * Address_type;
+		struct dict_object * UTF8String_type;
+		struct dict_object * DiameterIdentity_type;
+		struct dict_object * DiameterURI_type;
+		struct dict_object * Time_type;
+		struct dict_object * IPFilterRule_type;
+
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "Address", &Address_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "UTF8String", &UTF8String_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "DiameterIdentity", &DiameterIdentity_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "DiameterURI", &DiameterURI_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "Time", &Time_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "IPFilterRule", &IPFilterRule_type);
+
+	
+   }
+
+   /* Commands section */
+   {
+		/* Connection-Management-Request */
+		{
+			struct dict_object* cmd;
+			struct dict_cmd_data data = {
+				8388732,	/* Code */
+				"Connection-Management-Request",	/* Name */
+				CMD_FLAG_REQUEST | CMD_FLAG_ERROR,	/* Fixed flags */
+				CMD_FLAG_REQUEST | CMD_FLAG_PROXIABLE,	/* Fixed flag values */
+			};
+
+			CHECK_dict_new( DICT_COMMAND, &data , app_id16777346, &cmd)
+		}
+		/* Connection-Management-Answer */
+		{
+			struct dict_object* cmd;
+			struct dict_cmd_data data = {
+				8388732,	/* Code */
+				"Connection-Management-Answer",	/* Name */
+				CMD_FLAG_REQUEST,	/* Fixed flags */
+				CMD_FLAG_PROXIABLE,	/* Fixed flag values */
+			};
+
+			CHECK_dict_new( DICT_COMMAND, &data , app_id16777346, &cmd)
+		}
+		/* MO-Data-Request */
+		{
+			struct dict_object* cmd;
+			struct dict_cmd_data data = {
+				8388733,	/* Code */
+				"MO-Data-Request",	/* Name */
+				CMD_FLAG_REQUEST | CMD_FLAG_ERROR,	/* Fixed flags */
+				CMD_FLAG_REQUEST | CMD_FLAG_PROXIABLE,	/* Fixed flag values */
+			};
+
+			CHECK_dict_new( DICT_COMMAND, &data , app_id16777346, &cmd)
+		}
+		/* MO-Data-Answer */
+		{
+			struct dict_object* cmd;
+			struct dict_cmd_data data = {
+				8388733,	/* Code */
+				"MO-Data-Answer",	/* Name */
+				CMD_FLAG_REQUEST,	/* Fixed flags */
+				CMD_FLAG_PROXIABLE,	/* Fixed flag values */
+			};
+
+			CHECK_dict_new( DICT_COMMAND, &data , app_id16777346, &cmd)
+		}
+		/* MT-Data-Request */
+		{
+			struct dict_object* cmd;
+			struct dict_cmd_data data = {
+				8388734,	/* Code */
+				"MT-Data-Request",	/* Name */
+				CMD_FLAG_REQUEST | CMD_FLAG_ERROR,	/* Fixed flags */
+				CMD_FLAG_REQUEST | CMD_FLAG_PROXIABLE,	/* Fixed flag values */
+			};
+
+			CHECK_dict_new( DICT_COMMAND, &data , app_id16777346, &cmd)
+		}
+		/* MT-Data-Answer */
+		{
+			struct dict_object* cmd;
+			struct dict_cmd_data data = {
+				8388734,	/* Code */
+				"MT-Data-Answer",	/* Name */
+				CMD_FLAG_REQUEST,	/* Fixed flags */
+				CMD_FLAG_PROXIABLE,	/* Fixed flag values */
+			};
+
+			CHECK_dict_new( DICT_COMMAND, &data , app_id16777346, &cmd)
+		}
+
+   }
+
+   return 0;
+}
+
+static int dict_t6at6bt7_load_rules(char * conffile)
+{
+   /* Grouped AVP section */
+   {
+
+   }	
+
+   /* Commands section */
+   {
+	  /* Configuration-Information-Request */
+	  {
+		struct dict_object* cmd;
+		CHECK_dict_search( DICT_COMMAND, CMD_BY_NAME, "Configuration-Information-Request", &cmd)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 0, .avp_name = "Session-Id"}, RULE_FIXED_HEAD, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "DRMP"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Auth-Session-State"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-Host"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-Realm"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Destination-Host"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Destination-Realm"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Supported-Features"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Monitoring-Event-Configuration"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Proxy-Info"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Route-Record"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules(rules, cmd);
+	  }
+	  /* Configuration-Information-Answer */
+	  {
+		struct dict_object* cmd;
+		CHECK_dict_search( DICT_COMMAND, CMD_BY_NAME, "Configuration-Information-Answer", &cmd)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 0, .avp_name = "Session-Id"}, RULE_FIXED_HEAD, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "DRMP"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Result-Code"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Experimental-Result"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Auth-Session-State"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-Host"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-Realm"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Supported-Features"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Monitoring-Event-Report"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Monitoring-Event-Config-Status"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Failed-AVP"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Proxy-Info"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Route-Record"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules(rules, cmd);
+	  }
+	  /* Reporting-Information-Request */
+	  {
+		struct dict_object* cmd;
+		CHECK_dict_search( DICT_COMMAND, CMD_BY_NAME, "Reporting-Information-Request", &cmd)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 0, .avp_name = "Session-Id"}, RULE_FIXED_HEAD, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "DRMP"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Auth-Session-State"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-Host"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-Realm"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Destination-Host"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Destination-Realm"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "OC-Supported-Features"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Supported-Features"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Monitoring-Event-Report"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules(rules, cmd);
+	  }
+	  /* Reporting-Information-Answer */
+	  {
+		struct dict_object* cmd;
+		CHECK_dict_search( DICT_COMMAND, CMD_BY_NAME, "Reporting-Information-Answer", &cmd)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 0, .avp_name = "Session-Id"}, RULE_FIXED_HEAD, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "DRMP"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Result-Code"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Experimental-Result"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Auth-Session-State"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-Host"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-Realm"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "OC-Supported-Features"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "OC-OLR"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Load"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Supported-Features"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Failed-AVP"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Proxy-Info"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Route-Record"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules(rules, cmd);
+	  }
+	  /* Connection-Management-Request */
+	  {
+		struct dict_object* cmd;
+		CHECK_dict_search( DICT_COMMAND, CMD_BY_NAME, "Connection-Management-Request", &cmd)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 0, .avp_name = "Session-Id"}, RULE_FIXED_HEAD, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "User-Identifier"}, RULE_FIXED_HEAD, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Bearer-Identifier"}, RULE_FIXED_HEAD, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "DRMP"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Auth-Session-State"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-Host"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-Realm"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Destination-Host"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Destination-Realm"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "OC-Supported-Features"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "CMR-Flags"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Maximum-UE-Availability-Time"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Supported-Features"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Connection-Action"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Service-Selection"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Serving-PLMN-Rate-Control"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Extended-PCO"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "3GPP-Charging-Characteristics"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "RAT-Type"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Terminal-Information"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Visited-PLMN-Id"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Proxy-Info"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Route-Record"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules(rules, cmd);
+	  }
+	  /* Connection-Management-Answer */
+	  {
+		struct dict_object* cmd;
+		CHECK_dict_search( DICT_COMMAND, CMD_BY_NAME, "Connection-Management-Answer", &cmd)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 0, .avp_name = "Session-Id"}, RULE_FIXED_HEAD, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "DRMP"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Result-Code"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Experimental-Result"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Auth-Session-State"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-Host"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-Realm"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "OC-Supported-Features"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "OC-OLR"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Load"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Supported-Features"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "PDN-Connection-Charging-ID"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Extended-PCO"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Failed-AVP"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Proxy-Info"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Route-Record"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules(rules, cmd);
+	  }
+	  /* MO-Data-Request */
+	  {
+		struct dict_object* cmd;
+		CHECK_dict_search( DICT_COMMAND, CMD_BY_NAME, "MO-Data-Request", &cmd)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 0, .avp_name = "Session-Id"}, RULE_FIXED_HEAD, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "User-Identifier"}, RULE_FIXED_HEAD, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Bearer-Identifier"}, RULE_FIXED_HEAD, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "DRMP"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Auth-Session-State"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-Host"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-Realm"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Destination-Host"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Destination-Realm"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "OC-Supported-Features"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Supported-Features"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Non-IP-Data"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Proxy-Info"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Route-Record"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "RRC-Cause-Counter"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules(rules, cmd);
+	  }
+	  /* MO-Data-Answer */
+	  {
+		struct dict_object* cmd;
+		CHECK_dict_search( DICT_COMMAND, CMD_BY_NAME, "MO-Data-Answer", &cmd)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 0, .avp_name = "Session-Id"}, RULE_FIXED_HEAD, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "DRMP"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Result-Code"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Experimental-Result"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Auth-Session-State"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-Host"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-Realm"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "OC-Supported-Features"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "OC-OLR"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Load"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Supported-Features"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Failed-AVP"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Proxy-Info"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Route-Record"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules(rules, cmd);
+	  }
+	  /* MT-Data-Request */
+	  {
+		struct dict_object* cmd;
+		CHECK_dict_search( DICT_COMMAND, CMD_BY_NAME, "MT-Data-Request", &cmd)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 0, .avp_name = "Session-Id"}, RULE_FIXED_HEAD, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "User-Identifier"}, RULE_FIXED_HEAD, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Bearer-Identifier"}, RULE_FIXED_HEAD, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "DRMP"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Auth-Session-State"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-Host"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-Realm"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Destination-Host"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Destination-Realm"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "OC-Supported-Features"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Supported-Features"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Non-IP-Data"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "SCEF-Wait-Time"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Maximum-Retransmission-Time"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Proxy-Info"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Route-Record"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules(rules, cmd);
+	  }
+	  /* MT-Data-Answer */
+	  {
+		struct dict_object* cmd;
+		CHECK_dict_search( DICT_COMMAND, CMD_BY_NAME, "MT-Data-Answer", &cmd)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 0, .avp_name = "Session-Id"}, RULE_FIXED_HEAD, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "DRMP"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Result-Code"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Experimental-Result"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Auth-Session-State"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-Host"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-Realm"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "OC-Supported-Features"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "OC-OLR"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Load"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Requested-Retransmission-Time"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Supported-Features"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Failed-AVP"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Proxy-Info"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Route-Record"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules(rules, cmd);
+	  }
+
+   }
+
+   LOG_D( "Extension 'Dictionary definitions for T6aT6bT7 (e20)' initialized");
+   return 0;
+}
+
+int dict_entry(char * conffile)
+{
+	dict_t6at6bt7_load_defs(conffile);
+	return dict_t6at6bt7_load_rules(conffile);
+}
+
+const char* dict_t6at6bt7_proto_ver(char * conffile) {
+	return t6at6bt7_proto_ver;
+}
+
+const double dict_t6at6bt7_gen_ts(char * conffile) {
+	return t6at6bt7_gen_date;
+}
+
+EXTENSION_ENTRY2("dict_t6at6bt7", dict_t6at6bt7_load_defs, dict_t6at6bt7_load_rules, "dict_ts32299_avps", "dict_ts29272_avps", "dict_ts29128_avps", "dict_S6t", "dict_ts29336_avps", "dict_ts29212_avps", "dict_ts29217_avps", "dict_ts29338_avps", "dict_ts29229_avps", "dict_ts29061_avps", "dict_draftload_avps", "dict_rfc7683_avps", "dict_rfc5778_avps", "dict_rfc7944_avps");
+
+
+
diff --git a/extensions/dict_Tsp/CMakeLists.txt b/extensions/dict_Tsp/CMakeLists.txt
new file mode 100644
index 0000000..44eda5b
--- /dev/null
+++ b/extensions/dict_Tsp/CMakeLists.txt
@@ -0,0 +1,16 @@
+# The dict_Tsp extension
+PROJECT("dict_Tsp library generated by FdGen " C)
+
+# Compile as a module
+FD_ADD_EXTENSION(dict_Tsp dict_Tsp.c)
+
+
+####
+## INSTALL section ##
+
+INSTALL(TARGETS dict_Tsp
+	LIBRARY DESTINATION ${INSTALL_EXTENSIONS_SUFFIX}
+COMPONENT freeDiameter-dictionary-TSP)
+
+
+
diff --git a/extensions/dict_Tsp/Tsp.did b/extensions/dict_Tsp/Tsp.did
new file mode 100644
index 0000000..75b325f
--- /dev/null
+++ b/extensions/dict_Tsp/Tsp.did
@@ -0,0 +1,38 @@
+dict_rfc6942_avps
+dict_ts29468_avps
+dict_ts29154_avps
+dict_ts29214_avps
+dict_ts29215_avps
+dict_ts29217_avps
+dict_3gpp2_avps
+dict_ts29337_avps
+dict_ts29343_avps
+dict_ts29338_avps
+dict_ts29128_avps
+dict_ts29344_avps
+dict_ts29345_avps
+dict_ts29173_avps
+dict_ts32299_avps
+dict_rfc6734_avps
+dict_rfc5580_avps
+dict_rfc4072_avps
+dict_ts29273_avps
+dict_rfc4006bis_avps
+dict_ts29212_avps
+dict_ts29061_avps
+dict_ts29272_avps
+dict_rfc5447_avps
+dict_rfc5778_avps
+dict_rfc5777_avps
+dict_ts29336_avps
+dict_etsi283034_avps
+dict_rfc4590_avps
+dict_rfc4004_avps
+dict_rfc7155_avps
+dict_ts29229_avps
+dict_rfc7683_avps
+dict_draftload_avps
+dict_rfc7944_avps
+dict_ts29329_avps
+dict_ts29368_avps
+dict_Tsp
diff --git a/extensions/dict_Tsp/dict_Tsp.c b/extensions/dict_Tsp/dict_Tsp.c
new file mode 100644
index 0000000..d1eed0f
--- /dev/null
+++ b/extensions/dict_Tsp/dict_Tsp.c
@@ -0,0 +1,334 @@
+/*
+* Copyright (c) 2017 Sprint
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*    http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+/****************
+ Generated By: fdtool enhancements to diafuzzer
+ License: same as freeDiameter
+****************/
+
+
+/* 
+ * Dictionary definitions of objects specified in Tsp (e10).
+ */
+#include <freeDiameter/extension.h>
+
+#define PROTO_VER "e10"
+#define GEN_DATE  1506697226.2
+
+const char *tsp_proto_ver = PROTO_VER;
+const double tsp_gen_date = GEN_DATE;
+
+/* The content of this file follows the same structure as dict_base_proto.c */
+
+#define CHECK_dict_new( _type, _data, _parent, _ref )                                     \
+{                                                                                         \
+    int _ret = fd_dict_new( fd_g_config->cnf_dict, (_type), (_data), (_parent), (_ref) ); \
+    if ( _ret != 0 && _ret != EEXIST )                                                    \
+       return _ret;                                                                       \
+}
+
+#define CHECK_dict_search( _type, _criteria, _what, _result )		\
+    CHECK_FCT(  fd_dict_search( fd_g_config->cnf_dict, (_type), (_criteria), (_what), (_result), ENOENT) );
+
+struct local_rules_definition {
+    struct dict_avp_request avp_vendor_plus_name;
+    enum rule_position	position;
+    int 			min;
+    int			max;
+};
+
+#define RULE_ORDER( _position ) ((((_position) == RULE_FIXED_HEAD) || ((_position) == RULE_FIXED_TAIL)) ? 1 : 0 )
+
+/* Attention! This version of the macro uses AVP_BY_NAME_AND_VENDOR, in contrast to most other copies! */
+#define PARSE_loc_rules( _rulearray, _parent) {                                                         \
+        int __ar;                                                                                       \
+        for (__ar=0; __ar < sizeof(_rulearray) / sizeof((_rulearray)[0]); __ar++) {                     \
+                struct dict_rule_data __data = { NULL,                                                  \
+                        (_rulearray)[__ar].position,                                                    \
+                        0,                                                                              \
+                        (_rulearray)[__ar].min,                                                         \
+                        (_rulearray)[__ar].max};                                                        \
+                __data.rule_order = RULE_ORDER(__data.rule_position);                                   \
+                CHECK_FCT(  fd_dict_search(                                                             \
+                        fd_g_config->cnf_dict,                                                          \
+                        DICT_AVP,                                                                       \
+                        AVP_BY_NAME_AND_VENDOR,                                                         \
+                        &(_rulearray)[__ar].avp_vendor_plus_name,                                       \
+                        &__data.rule_avp, 0 ) );                                                        \
+                if ( !__data.rule_avp ) {                                                               \
+                        TRACE_DEBUG(INFO, "AVP Not found: '%s'", (_rulearray)[__ar].avp_vendor_plus_name.avp_name);             \
+                        return ENOENT;                                                                  \
+                }                                                                                       \
+                {                                                                                       \
+                         int _ret = fd_dict_new( fd_g_config->cnf_dict, DICT_RULE, &(__data), (_parent), NULL ); \
+                         if ( _ret != 0 && _ret != EEXIST )      {                                      \
+                                TRACE_DEBUG(INFO, "Error on rule with AVP '%s'",                        \
+                                            (_rulearray)[__ar].avp_vendor_plus_name.avp_name);          \
+                                return EINVAL;                                                          \
+                         }                                                                              \
+                }                                                                                       \
+        }                                                                                               \
+}
+
+#define CHECK_vendor_new( _data ) { \
+        struct dict_object * vendor_found; \
+        if (fd_dict_search(fd_g_config->cnf_dict,DICT_VENDOR,VENDOR_BY_ID,&_data.vendor_id,&vendor_found,ENOENT) == ENOENT) { \
+                CHECK_FCT(fd_dict_new(fd_g_config->cnf_dict, DICT_VENDOR, &_data, NULL, NULL)); \
+        } \
+}
+
+#define enumval_def_u32( _val_, _str_ )		\
+    { _str_, 		{ .u32 = _val_ }}
+
+#define enumval_def_os( _len_, _val_, _str_ )				\
+    { _str_, 		{ .os = { .data = (unsigned char *)_val_, .len = _len_ }}}
+
+
+static int dict_tsp_load_defs(char * conffile)
+{
+   TRACE_ENTRY("%p", conffile);
+	struct dict_object * app_id16777309;
+
+	/* Application Section */
+	{
+	  {
+			struct dict_object * vendor;
+			CHECK_dict_search(DICT_VENDOR, VENDOR_BY_NAME, "3GPP", &vendor)
+			struct dict_application_data data = { 16777309, "Tsp" };
+			CHECK_dict_new( DICT_APPLICATION, &data, vendor, &app_id16777309)
+	  }
+	  /* Result codes */
+	  {
+			struct dict_object *type;
+			CHECK_dict_search(DICT_TYPE, TYPE_BY_NAME, "Enumerated(Result-Code)",&type);
+			struct dict_enumval_data        t_1 = { "General", { .u32=1 }};
+			struct dict_enumval_data        t_2 = { "SCS_behaviour", { .u32=2 }};
+			struct dict_enumval_data        t_3 = { "MTC_IWF_behaviour", { .u32=3 }};
+			struct dict_enumval_data        t_4 = { "Replace_Failure", { .u32=4 }};
+			struct dict_enumval_data        t_5 = { "Delivery_of_a_MSISDN_less_MO_SMS", { .u32=9 }};
+
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_3, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_4, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_5, type, NULL);
+
+	  }
+	}
+
+
+   /* AVP section */
+   {
+		struct dict_object * Address_type;
+		struct dict_object * UTF8String_type;
+		struct dict_object * DiameterIdentity_type;
+		struct dict_object * DiameterURI_type;
+		struct dict_object * Time_type;
+		struct dict_object * IPFilterRule_type;
+
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "Address", &Address_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "UTF8String", &UTF8String_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "DiameterIdentity", &DiameterIdentity_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "DiameterURI", &DiameterURI_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "Time", &Time_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "IPFilterRule", &IPFilterRule_type);
+
+	
+   }
+
+   /* Commands section */
+   {
+		/* Device-Action-Request */
+		{
+			struct dict_object* cmd;
+			struct dict_cmd_data data = {
+				8388639,	/* Code */
+				"Device-Action-Request",	/* Name */
+				CMD_FLAG_REQUEST | CMD_FLAG_ERROR,	/* Fixed flags */
+				CMD_FLAG_REQUEST | CMD_FLAG_PROXIABLE,	/* Fixed flag values */
+			};
+
+			CHECK_dict_new( DICT_COMMAND, &data , app_id16777309, &cmd)
+		}
+		/* Device-Action-Answer */
+		{
+			struct dict_object* cmd;
+			struct dict_cmd_data data = {
+				8388639,	/* Code */
+				"Device-Action-Answer",	/* Name */
+				CMD_FLAG_REQUEST,	/* Fixed flags */
+				CMD_FLAG_PROXIABLE,	/* Fixed flag values */
+			};
+
+			CHECK_dict_new( DICT_COMMAND, &data , app_id16777309, &cmd)
+		}
+		/* Device-Notification-Request */
+		{
+			struct dict_object* cmd;
+			struct dict_cmd_data data = {
+				8388640,	/* Code */
+				"Device-Notification-Request",	/* Name */
+				CMD_FLAG_REQUEST | CMD_FLAG_ERROR,	/* Fixed flags */
+				CMD_FLAG_REQUEST | CMD_FLAG_PROXIABLE,	/* Fixed flag values */
+			};
+
+			CHECK_dict_new( DICT_COMMAND, &data , app_id16777309, &cmd)
+		}
+		/* Device-Notification-Answer */
+		{
+			struct dict_object* cmd;
+			struct dict_cmd_data data = {
+				8388640,	/* Code */
+				"Device-Notification-Answer",	/* Name */
+				CMD_FLAG_REQUEST,	/* Fixed flags */
+				CMD_FLAG_PROXIABLE,	/* Fixed flag values */
+			};
+
+			CHECK_dict_new( DICT_COMMAND, &data , app_id16777309, &cmd)
+		}
+
+   }
+
+   return 0;
+}
+
+static int dict_tsp_load_rules(char * conffile)
+{
+   /* Grouped AVP section */
+   {
+
+   }	
+
+   /* Commands section */
+   {
+	  /* Device-Action-Request */
+	  {
+		struct dict_object* cmd;
+		CHECK_dict_search( DICT_COMMAND, CMD_BY_NAME, "Device-Action-Request", &cmd)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 0, .avp_name = "Session-Id"}, RULE_FIXED_HEAD, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Auth-Application-Id"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Auth-Session-State"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-Host"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-Realm"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Destination-Realm"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Destination-Host"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-State-Id"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Device-Action"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Proxy-Info"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Route-Record"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Supported-Features"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules(rules, cmd);
+	  }
+	  /* Device-Action-Answer */
+	  {
+		struct dict_object* cmd;
+		CHECK_dict_search( DICT_COMMAND, CMD_BY_NAME, "Device-Action-Answer", &cmd)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 0, .avp_name = "Session-Id"}, RULE_FIXED_HEAD, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Auth-Application-Id"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Auth-Session-State"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-Host"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-Realm"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Result-Code"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Experimental-Result"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Error-Message"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Error-Reporting-Host"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Failed-AVP"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-State-Id"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Device-Notification"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Redirect-Host"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Redirect-Host-Usage"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Redirect-Max-Cache-Time"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Proxy-Info"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Supported-Features"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Feature-Supported-In-Final-Target"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Load"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules(rules, cmd);
+	  }
+	  /* Device-Notification-Request */
+	  {
+		struct dict_object* cmd;
+		CHECK_dict_search( DICT_COMMAND, CMD_BY_NAME, "Device-Notification-Request", &cmd)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 0, .avp_name = "Session-Id"}, RULE_FIXED_HEAD, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Auth-Application-Id"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Auth-Session-State"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-Host"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-Realm"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Destination-Realm"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Destination-Host"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-State-Id"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Device-Notification"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Proxy-Info"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Route-Record"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules(rules, cmd);
+	  }
+	  /* Device-Notification-Answer */
+	  {
+		struct dict_object* cmd;
+		CHECK_dict_search( DICT_COMMAND, CMD_BY_NAME, "Device-Notification-Answer", &cmd)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 0, .avp_name = "Session-Id"}, RULE_FIXED_HEAD, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Auth-Application-Id"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Auth-Session-State"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-Host"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-Realm"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Result-Code"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Experimental-Result"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-State-Id"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Error-Message"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Error-Reporting-Host"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Redirect-Host"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Redirect-Host-Usage"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Redirect-Max-Cache-Time"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Failed-AVP"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Proxy-Info"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules(rules, cmd);
+	  }
+
+   }
+
+   LOG_D( "Extension 'Dictionary definitions for Tsp (e10)' initialized");
+   return 0;
+}
+
+int dict_entry(char * conffile)
+{
+	dict_tsp_load_defs(conffile);
+	return dict_tsp_load_rules(conffile);
+}
+
+const char* dict_tsp_proto_ver(char * conffile) {
+	return tsp_proto_ver;
+}
+
+const double dict_tsp_gen_ts(char * conffile) {
+	return tsp_gen_date;
+}
+
+EXTENSION_ENTRY2("dict_tsp", dict_tsp_load_defs, dict_tsp_load_rules, "dict_ts29368_avps", "dict_ts29337_avps", "dict_ts29336_avps", "dict_ts29338_avps", "dict_ts29329_avps", "dict_ts29229_avps", "dict_draftload_avps", "dict_rfc4006bis_avps");
+
+
+
diff --git a/extensions/dict_dcca/CMakeLists.txt b/extensions/dict_dcca/CMakeLists.txt
new file mode 100644
index 0000000..62ab6b9
--- /dev/null
+++ b/extensions/dict_dcca/CMakeLists.txt
@@ -0,0 +1,13 @@
+# The dict_dcca extension
+PROJECT("Diameter DCCA (Diameter Credit Control Application ) dictionary definitions" C)
+
+# Compile as a module
+FD_ADD_EXTENSION(dict_dcca dict_dcca.c)
+
+
+####
+## INSTALL section ##
+
+INSTALL(TARGETS dict_dcca
+	LIBRARY DESTINATION ${INSTALL_EXTENSIONS_SUFFIX}
+	COMPONENT freeDiameter-dictionary-rfc4006)
diff --git a/extensions/dict_dcca/dict_dcca.c b/extensions/dict_dcca/dict_dcca.c
new file mode 100644
index 0000000..5d94603
--- /dev/null
+++ b/extensions/dict_dcca/dict_dcca.c
@@ -0,0 +1,1487 @@
+/****************
+ Contributed by: Konstantin Chekushin <koch@lmt.lv> and Thomas Klausner <tk@giga.or.at>
+ License: same as freeDiameter
+****************/
+
+
+/* 
+ * Dictionary definitions of objects specified in DCCA (rfc4006).
+ */
+#include <freeDiameter/extension.h>
+
+
+/* The content of this file follows the same structure as dict_base_proto.c */
+
+#define CHECK_dict_new( _type, _data, _parent, _ref )			\
+    CHECK_FCT(  fd_dict_new( fd_g_config->cnf_dict, (_type), (_data), (_parent), (_ref))  );
+
+#define CHECK_dict_search( _type, _criteria, _what, _result )		\
+    CHECK_FCT(  fd_dict_search( fd_g_config->cnf_dict, (_type), (_criteria), (_what), (_result), ENOENT) );
+
+struct local_rules_definition {
+    char 			*avp_name;
+    enum rule_position	position;
+    int 			min;
+    int			max;
+};
+
+#define RULE_ORDER( _position ) ((((_position) == RULE_FIXED_HEAD) || ((_position) == RULE_FIXED_TAIL)) ? 1 : 0 )
+
+#define PARSE_loc_rules( _rulearray, _parent) {				\
+	int __ar;							\
+	for (__ar=0; __ar < sizeof(_rulearray) / sizeof((_rulearray)[0]); __ar++) { \
+	    struct dict_rule_data __data = { NULL,			\
+					     (_rulearray)[__ar].position, \
+					     0,				\
+					     (_rulearray)[__ar].min,	\
+					     (_rulearray)[__ar].max};	\
+	    __data.rule_order = RULE_ORDER(__data.rule_position);	\
+	    CHECK_FCT(  fd_dict_search(					\
+			    fd_g_config->cnf_dict,			\
+			    DICT_AVP,					\
+			    AVP_BY_NAME,				\
+			    (_rulearray)[__ar].avp_name,		\
+			    &__data.rule_avp, 0 ) );			\
+	    if ( !__data.rule_avp ) {					\
+		TRACE_DEBUG(INFO, "AVP Not found: '%s'", (_rulearray)[__ar].avp_name );	\
+		return ENOENT;						\
+	    }								\
+	    CHECK_FCT_DO( fd_dict_new( fd_g_config->cnf_dict, DICT_RULE, &__data, _parent, NULL), \
+			  {						\
+			      TRACE_DEBUG(INFO, "Error on rule with AVP '%s'", \
+					  (_rulearray)[__ar].avp_name ); \
+			      return EINVAL;				\
+			  } );						\
+	}								\
+    }
+
+#define enumval_def_u32( _val_, _str_ )		\
+    { _str_, 		{ .u32 = _val_ }}
+
+#define enumval_def_os( _len_, _val_, _str_ )				\
+    { _str_, 		{ .os = { .data = (unsigned char *)_val_, .len = _len_ }}}
+
+
+static int dict_dcca_entry(char * conffile)
+{
+    struct dict_object * dcca;
+    TRACE_ENTRY("%p", conffile);		
+	
+    /* Applications section */
+    {
+	/* DCCA */
+	{
+	    struct dict_application_data data = {        4, "Diameter Credit Control Application" 			};
+	    CHECK_dict_new( DICT_APPLICATION, &data, NULL, &dcca);
+	}                                
+    }
+	
+    /* Result codes */
+    {
+        struct dict_object *ResultCodeType;
+        CHECK_dict_search(DICT_TYPE, TYPE_BY_NAME, "Enumerated(Result-Code)", &ResultCodeType);
+
+        {
+            struct dict_enumval_data error_code = {"END_USER_SERVICE_DENIED",
+						   { .u32 = 4010}};
+            CHECK_dict_new(DICT_ENUMVAL, &error_code, ResultCodeType, NULL);
+        }
+        {
+            struct dict_enumval_data error_code = {"CREDIT_CONTROL_NOT_APPLICABLE",
+						   { .u32 = 4011}};
+            CHECK_dict_new(DICT_ENUMVAL, &error_code, ResultCodeType, NULL);
+        }
+        {
+            struct dict_enumval_data error_code = {"CREDIT_LIMIT_REACHED",
+						   { .u32 = 4012}};
+            CHECK_dict_new(DICT_ENUMVAL, &error_code, ResultCodeType, NULL);
+        }
+        {
+            struct dict_enumval_data error_code = {"USER_UNKNOWN",
+						   { .u32 = 5030}};
+            CHECK_dict_new(DICT_ENUMVAL, &error_code, ResultCodeType, NULL);
+        }
+        {
+            struct dict_enumval_data error_code = {"RATING_FAILED",
+						   { .u32 = 5031}};
+            CHECK_dict_new(DICT_ENUMVAL, &error_code, ResultCodeType, NULL);
+        }
+
+    }
+
+
+	
+    /* AVP section */
+    {
+	struct dict_object * Address_type;
+	struct dict_object * UTF8String_type;
+	struct dict_object * DiameterIdentity_type;
+	struct dict_object * DiameterURI_type;
+	struct dict_object * Time_type;
+	struct dict_object * IPFilterRule_type;
+
+	CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "Address", &Address_type);
+	CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "UTF8String", &UTF8String_type);
+	CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "DiameterIdentity", &DiameterIdentity_type);
+	CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "DiameterURI", &DiameterURI_type);
+	CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "Time", &Time_type);
+	CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "IPFilterRule", &IPFilterRule_type);
+                
+                
+	/* CC-Correlation-Id */
+	{
+	    /* 
+	       OctetString. 
+	    */
+	    struct dict_avp_data    data = { 
+		411,                                    /* Code */
+		0,                                      /* Vendor */
+		"CC-Correlation-Id",                    /* Name */
+		AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,   /* Fixed flags */
+		AVP_FLAG_MANDATORY,                     /* Fixed flag values */
+		AVP_TYPE_OCTETSTRING                    /* base type of data */
+	    };
+
+	    CHECK_dict_new( DICT_AVP, &data , NULL, NULL);
+	}
+                
+	/* CC-Input-Octets */
+	{
+	    /* 
+	       Unsigned64. 
+	    */
+	    struct dict_avp_data data = { 
+		412,                                    /* Code */
+		0,                                      /* Vendor */
+		"CC-Input-Octets",                      /* Name */
+		AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,   /* Fixed flags */
+		AVP_FLAG_MANDATORY,                     /* Fixed flag values */
+		AVP_TYPE_UNSIGNED64                     /* base type of data */
+	    };
+	    CHECK_dict_new( DICT_AVP, &data , NULL, NULL);
+	}
+                
+	/* CC-Output-Octets */
+	{
+	    /* 
+	       Unsigned64. 
+	    */
+	    struct dict_avp_data data = { 
+		414,                                    /* Code */
+		0,                                      /* Vendor */
+		"CC-Output-Octets",                     /* Name */
+		AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,   /* Fixed flags */
+		AVP_FLAG_MANDATORY,                     /* Fixed flag values */
+		AVP_TYPE_UNSIGNED64                     /* base type of data */
+	    };
+	    CHECK_dict_new( DICT_AVP, &data , NULL, NULL);
+	}
+                
+	/* CC-Request-Number */
+	{
+	    /* 
+	       Unsigned32. 
+	    */
+	    struct dict_avp_data data = { 
+		415,                                    /* Code */
+		0,                                      /* Vendor */
+		"CC-Request-Number",                    /* Name */
+		AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,   /* Fixed flags */
+		AVP_FLAG_MANDATORY,                     /* Fixed flag values */
+		AVP_TYPE_UNSIGNED32                     /* base type of data */
+	    };
+	    CHECK_dict_new( DICT_AVP, &data , NULL, NULL);
+	}
+
+	/* CC-Request-Type */
+	{
+	    /* 
+	       Enumerated. 
+	    */
+
+	    struct dict_object              *type;
+	    struct dict_type_data           tdata = { AVP_TYPE_INTEGER32, "Enumerated(CC-Request-Type)", NULL, NULL, NULL };
+	    struct dict_enumval_data        t_1 = { "INITIAL_REQUEST", { .i32 = 1 }};
+	    struct dict_enumval_data        t_2 = { "UPDATE_REQUEST", { .i32 = 2 }};
+	    struct dict_enumval_data        t_3 = { "TERMINATION_REQUEST", { .i32 = 3 }};
+	    struct dict_enumval_data        t_4 = { "EVENT_REQUEST", { .i32 = 4 }};
+                  
+
+	    struct dict_avp_data    data = { 
+		416,                                    /* Code */
+		0,                                      /* Vendor */
+		"CC-Request-Type",                      /* Name */
+		AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,   /* Fixed flags */
+		AVP_FLAG_MANDATORY,                     /* Fixed flag values */
+		AVP_TYPE_INTEGER32                      /* base type of data */
+	    };
+	    /* Create the Enumerated type, and then the AVP */
+	    CHECK_dict_new( DICT_TYPE, &tdata , NULL, &type);
+	    CHECK_dict_new( DICT_ENUMVAL, &t_1 , type, NULL);
+	    CHECK_dict_new( DICT_ENUMVAL, &t_2 , type, NULL);
+	    CHECK_dict_new( DICT_ENUMVAL, &t_3 , type, NULL);
+	    CHECK_dict_new( DICT_ENUMVAL, &t_4 , type, NULL);
+	    CHECK_dict_new( DICT_AVP, &data , type, NULL);
+	}
+                
+
+	/* CC-Service-Specific-Units */
+	{
+	    /* 
+	       Unsigned64. 
+	    */
+	    struct dict_avp_data data = { 
+		417,                                    /* Code */
+		0,                                      /* Vendor */
+		"CC-Service-Specific-Units",            /* Name */
+		AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,   /* Fixed flags */
+		AVP_FLAG_MANDATORY,                     /* Fixed flag values */
+		AVP_TYPE_UNSIGNED64                     /* base type of data */
+	    };
+	    CHECK_dict_new( DICT_AVP, &data , NULL, NULL);
+	}
+   
+	/* CC-Session-Failover */
+	{
+	    /* 
+	       Enumerated. 
+	    */
+
+	    struct dict_object              *type;
+	    struct dict_type_data           tdata = { AVP_TYPE_INTEGER32, "Enumerated(CC-Session-Failover)" , NULL, NULL, NULL };
+	    struct dict_enumval_data        t_1 = { "FAILOVER_NOT_SUPPORTED", { .i32 = 0 }};
+	    struct dict_enumval_data        t_2 = { "FAILOVER_SUPPORTED", { .i32 = 1 }};
+                  
+
+	    struct dict_avp_data    data = { 
+		418,                                    /* Code */
+		0,                                      /* Vendor */
+		"CC-Session-Failover",                  /* Name */
+		AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,   /* Fixed flags */
+		AVP_FLAG_MANDATORY,                     /* Fixed flag values */
+		AVP_TYPE_INTEGER32                      /* base type of data */
+	    };
+	    /* Create the Enumerated type, and then the AVP */
+	    CHECK_dict_new( DICT_TYPE, &tdata , NULL, &type);
+	    CHECK_dict_new( DICT_ENUMVAL, &t_1 , type, NULL);                  
+	    CHECK_dict_new( DICT_ENUMVAL, &t_2 , type, NULL);
+	    CHECK_dict_new( DICT_AVP, &data , type, NULL);
+	}
+                
+	/* CC-Sub-Session-Id */
+	{
+	    /* 
+	       Unsigned64. 
+	    */
+	    struct dict_avp_data data = { 
+		419,                                    /* Code */
+		0,                                      /* Vendor */
+		"CC-Sub-Session-Id",                    /* Name */
+		AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,   /* Fixed flags */
+		AVP_FLAG_MANDATORY,                     /* Fixed flag values */
+		AVP_TYPE_UNSIGNED64                     /* base type of data */
+	    };
+	    CHECK_dict_new( DICT_AVP, &data , NULL, NULL);
+	}
+                
+	/* CC-Time */
+	{
+	    /* 
+	       Unsigned32. 
+	    */
+	    struct dict_avp_data data = { 
+		420,                                    /* Code */
+		0,                                      /* Vendor */
+		"CC-Time",                              /* Name */
+		AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,   /* Fixed flags */
+		AVP_FLAG_MANDATORY,                     /* Fixed flag values */
+		AVP_TYPE_UNSIGNED32                     /* base type of data */
+	    };
+	    CHECK_dict_new( DICT_AVP, &data , NULL, NULL);
+	}
+                                     
+	/* CC-Total-Octets */
+	{
+	    /* 
+	       Unsigned64. 
+	    */
+	    struct dict_avp_data data = { 
+		421,                                    /* Code */
+		0,                                      /* Vendor */
+		"CC-Total-Octets",                      /* Name */
+		AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,   /* Fixed flags */
+		AVP_FLAG_MANDATORY,                     /* Fixed flag values */
+		AVP_TYPE_UNSIGNED64                     /* base type of data */
+	    };
+	    CHECK_dict_new( DICT_AVP, &data , NULL, NULL);
+	}
+                
+	/* CC-Unit-Type */
+	{
+	    /* 
+	       Enumerated. 
+	    */
+
+	    struct dict_object              *type;
+	    struct dict_type_data           tdata = { AVP_TYPE_INTEGER32, "Enumerated(CC-Unit-Type)" , NULL, NULL, NULL };
+	    struct dict_enumval_data        t_1 = { "TIME", { .i32 = 0 }};
+	    struct dict_enumval_data        t_2 = { "MONEY", { .i32 = 1 }};
+	    struct dict_enumval_data        t_3 = { "TOTAL-OCTETS", { .i32 = 2 }};
+	    struct dict_enumval_data        t_4 = { "INPUT-OCTETS", { .i32 = 3 }};
+	    struct dict_enumval_data        t_5 = { "OUTPUT-OCTETS", { .i32 = 4 }};
+	    struct dict_enumval_data        t_6 = { "SERVICE-SPECIFIC-UNITS", { .i32 = 5 }};
+                  
+
+	    struct dict_avp_data    data = { 
+		454,                                    /* Code */
+		0,                                      /* Vendor */
+		"CC-Unit-Type",                         /* Name */
+		AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,   /* Fixed flags */
+		AVP_FLAG_MANDATORY,                     /* Fixed flag values */
+		AVP_TYPE_INTEGER32                      /* base type of data */
+	    };
+	    /* Create the Enumerated type, and then the AVP */
+	    CHECK_dict_new( DICT_TYPE, &tdata , NULL, &type);
+	    CHECK_dict_new( DICT_ENUMVAL, &t_1 , type, NULL);   
+	    CHECK_dict_new( DICT_ENUMVAL, &t_2 , type, NULL); 
+	    CHECK_dict_new( DICT_ENUMVAL, &t_3 , type, NULL); 
+	    CHECK_dict_new( DICT_ENUMVAL, &t_4 , type, NULL); 
+	    CHECK_dict_new( DICT_ENUMVAL, &t_5 , type, NULL); 
+	    CHECK_dict_new( DICT_ENUMVAL, &t_6 , type, NULL); 
+	    CHECK_dict_new( DICT_AVP, &data , type, NULL);
+	}
+
+	/* Check-Balance-Result */
+	{
+	    /* 
+	       Enumerated. 
+	    */
+
+	    struct dict_object              *type;
+	    struct dict_type_data           tdata = { AVP_TYPE_INTEGER32, "Enumerated(Check-Balance-Result)" , NULL, NULL, NULL };
+	    struct dict_enumval_data        t_1 = { "ENOUGH_CREDIT", { .i32 = 0 }};
+	    struct dict_enumval_data        t_2 = { "NO_CREDIT", { .i32 = 1 }};
+                  
+
+	    struct dict_avp_data    data = { 
+		422,                                    /* Code */
+		0,                                      /* Vendor */
+		"Check-Balance-Result",                 /* Name */
+		AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,   /* Fixed flags */
+		AVP_FLAG_MANDATORY,                     /* Fixed flag values */
+		AVP_TYPE_INTEGER32                      /* base type of data */
+	    };
+	    /* Create the Enumerated type, and then the AVP */
+	    CHECK_dict_new( DICT_TYPE, &tdata , NULL, &type);
+	    CHECK_dict_new( DICT_ENUMVAL, &t_1 , type, NULL);  
+	    CHECK_dict_new( DICT_ENUMVAL, &t_2 , type, NULL); 
+	    CHECK_dict_new( DICT_AVP, &data , type, NULL);
+	}
+                
+	/* Cost-Unit */
+	{
+	    /* 
+	       UTF8String. 
+	    */
+	    struct dict_avp_data    data = { 
+		424,                                    /* Code */
+		0,                                      /* Vendor */
+		"Cost-Unit",                            /* Name */
+		AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,   /* Fixed flags */
+		AVP_FLAG_MANDATORY,                     /* Fixed flag values */
+		AVP_TYPE_OCTETSTRING                    /* base type of data */
+	    };
+	    CHECK_dict_new( DICT_AVP, &data , UTF8String_type, NULL);
+	} 
+                
+	/* Credit-Control */
+	{
+	    /* 
+	       Enumerated. 
+	    */
+
+	    struct dict_object              *type;
+	    struct dict_type_data           tdata = { AVP_TYPE_INTEGER32, "Enumerated(Credit-Control)" , NULL, NULL, NULL };
+	    struct dict_enumval_data        t_1 = { "CREDIT_AUTHORIZATION", { .i32 = 0 }};
+	    struct dict_enumval_data        t_2 = { "RE_AUTHORIZATION", { .i32 = 1 }};
+                  
+	    struct dict_avp_data    data = { 
+		426,                                    /* Code */
+		0,                                      /* Vendor */
+		"Credit-Control",                       /* Name */
+		AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,   /* Fixed flags */
+		AVP_FLAG_MANDATORY,                     /* Fixed flag values */
+		AVP_TYPE_INTEGER32                      /* base type of data */
+	    };
+	    /* Create the Enumerated type, and then the AVP */
+	    CHECK_dict_new( DICT_TYPE, &tdata , NULL, &type);
+	    CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL); 
+	    CHECK_dict_new( DICT_ENUMVAL, &t_2, type, NULL);
+	    CHECK_dict_new( DICT_AVP, &data , type, NULL);
+	}
+   
+	/* Credit-Control-Failure-Handling */
+	{
+	    /* 
+	       Enumerated. 
+	    */
+
+	    struct dict_object              *type;
+	    struct dict_type_data           tdata = { AVP_TYPE_INTEGER32, "Enumerated(Credit-Control-Failure-Handling)" , NULL, NULL, NULL };
+	    struct dict_enumval_data        t_1 = { "TERMINATE", { .i32 = 0 }};
+	    struct dict_enumval_data        t_2 = { "CONTINUE", { .i32 = 1 }};
+	    struct dict_enumval_data        t_3 = { "RETRY_AND_TERMINATE", { .i32 = 2 }};
+                  
+	    struct dict_avp_data    data = { 
+		427,                                    /* Code */
+		0,                                      /* Vendor */
+		"Credit-Control-Failure-Handling",      /* Name */
+		AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,   /* Fixed flags */
+		AVP_FLAG_MANDATORY,                     /* Fixed flag values */
+		AVP_TYPE_INTEGER32                      /* base type of data */
+	    };
+	    /* Create the Enumerated type, and then the AVP */
+	    CHECK_dict_new( DICT_TYPE, &tdata , NULL, &type);
+	    CHECK_dict_new( DICT_ENUMVAL, &t_1 , type, NULL);   
+	    CHECK_dict_new( DICT_ENUMVAL, &t_2 , type, NULL);
+	    CHECK_dict_new( DICT_ENUMVAL, &t_3 , type, NULL);
+	    CHECK_dict_new( DICT_AVP, &data , type, NULL);
+	}
+
+	/* Currency-Code */
+	{
+	    /* 
+	       Unsigned32. 
+	    */
+	    struct dict_avp_data data = { 
+		425,                                    /* Code */
+		0,                                      /* Vendor */
+		"Currency-Code",                        /* Name */
+		AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,   /* Fixed flags */
+		AVP_FLAG_MANDATORY,                     /* Fixed flag values */
+		AVP_TYPE_UNSIGNED32                     /* base type of data */
+	    };
+	    CHECK_dict_new( DICT_AVP, &data , NULL, NULL);
+	}
+
+	/* Direct-Debiting-Failure-Handling */
+	{
+	    /* 
+	       Enumerated. 
+	    */
+
+	    struct dict_object              *type;
+	    struct dict_type_data           tdata = { AVP_TYPE_INTEGER32, "Enumerated(Direct-Debiting-Failure-Handling)" , NULL, NULL, NULL };
+	    struct dict_enumval_data        t_1 = { "TERMINATE_OR_BUFFER", { .i32 = 0 }};
+	    struct dict_enumval_data        t_2 = { "CONTINUE", { .i32 = 1 }};
+                  
+	    struct dict_avp_data    data = { 
+		428,                                    /* Code */
+		0,                                      /* Vendor */
+		"Direct-Debiting-Failure-Handling",     /* Name */
+		AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,   /* Fixed flags */
+		AVP_FLAG_MANDATORY,                     /* Fixed flag values */
+		AVP_TYPE_INTEGER32                      /* base type of data */
+	    };
+	    /* Create the Enumerated type, and then the AVP */
+	    CHECK_dict_new( DICT_TYPE, &tdata , NULL, &type);
+	    CHECK_dict_new( DICT_ENUMVAL, &t_1 , type, NULL); 
+	    CHECK_dict_new( DICT_ENUMVAL, &t_2 , type, NULL);
+	    CHECK_dict_new( DICT_AVP, &data , type, NULL);
+	}
+
+	/* Exponent */
+	{
+	    /* 
+	       Integer32. 
+	    */
+	    struct dict_avp_data data = { 
+		429,                                    /* Code */
+		0,                                      /* Vendor */
+		"Exponent",                             /* Name */
+		AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,   /* Fixed flags */
+		AVP_FLAG_MANDATORY,                     /* Fixed flag values */
+		AVP_TYPE_INTEGER32                      /* base type of data */
+	    };
+	    CHECK_dict_new( DICT_AVP, &data , NULL, NULL);
+	}
+                
+	/* Final-Unit-Action */
+	{
+	    /* 
+	       Enumerated. 
+	    */
+
+	    struct dict_object              *type;
+	    struct dict_type_data           tdata = { AVP_TYPE_INTEGER32, "Enumerated(Final-Unit-Action)" , NULL, NULL, NULL };
+	    struct dict_enumval_data        t_1 = { "TERMINATE", { .i32 = 0 }};
+	    struct dict_enumval_data        t_2 = { "REDIRECT", { .i32 = 1 }};
+	    struct dict_enumval_data        t_3 = { "RESTRICT_ACCESS", { .i32 = 2 }};
+                  
+	    struct dict_avp_data    data = { 
+		449,                                    /* Code */
+		0,                                      /* Vendor */
+		"Final-Unit-Action",                    /* Name */
+		AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,   /* Fixed flags */
+		AVP_FLAG_MANDATORY,                     /* Fixed flag values */
+		AVP_TYPE_INTEGER32                      /* base type of data */
+	    };
+	    /* Create the Enumerated type, and then the AVP */
+	    CHECK_dict_new( DICT_TYPE, &tdata , NULL, &type);
+	    CHECK_dict_new( DICT_ENUMVAL, &t_1 , type, NULL);  
+	    CHECK_dict_new( DICT_ENUMVAL, &t_2 , type, NULL); 
+	    CHECK_dict_new( DICT_ENUMVAL, &t_3 , type, NULL); 
+	    CHECK_dict_new( DICT_AVP, &data , type, NULL);
+	}
+
+	/* G-S-U-Pool-Identifier */
+	{
+	    /* 
+	       Unsigned32. 
+	    */
+	    struct dict_avp_data data = { 
+		453,                                    /* Code */
+		0,                                      /* Vendor */
+		"G-S-U-Pool-Identifier",                /* Name */
+		AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,   /* Fixed flags */
+		AVP_FLAG_MANDATORY,                     /* Fixed flag values */
+		AVP_TYPE_UNSIGNED32                     /* base type of data */
+	    };
+	    CHECK_dict_new( DICT_AVP, &data , NULL, NULL);
+	}
+                
+	/* Multiple-Services-Indicator */
+	{
+	    /* 
+	       Enumerated. 
+	    */
+
+	    struct dict_object              *type;
+	    struct dict_type_data           tdata = { AVP_TYPE_INTEGER32, "Enumerated(Multiple-Services-Indicator)" , NULL, NULL, NULL };
+	    struct dict_enumval_data        t_1 = { "MULTIPLE_SERVICES_NOT_SUPPORTED", { .i32 = 0 }};
+	    struct dict_enumval_data        t_2 = { "MULTIPLE_SERVICES_SUPPORTED", { .i32 = 1 }};
+                  
+	    struct dict_avp_data    data = { 
+		455,                                    /* Code */
+		0,                                      /* Vendor */
+		"Multiple-Services-Indicator",          /* Name */
+		AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,   /* Fixed flags */
+		AVP_FLAG_MANDATORY,                     /* Fixed flag values */
+		AVP_TYPE_INTEGER32                      /* base type of data */
+	    };
+	    /* Create the Enumerated type, and then the AVP */
+	    CHECK_dict_new( DICT_TYPE, &tdata , NULL, &type);
+	    CHECK_dict_new( DICT_ENUMVAL, &t_1 , type, NULL); 
+	    CHECK_dict_new( DICT_ENUMVAL, &t_2 , type, NULL);
+	    CHECK_dict_new( DICT_AVP, &data , type, NULL);
+	}
+                
+	/* Rating-Group */
+	{
+	    /* 
+	       Unsigned32. 
+	    */
+	    struct dict_avp_data data = { 
+		432,                                    /* Code */
+		0,                                      /* Vendor */
+		"Rating-Group",                         /* Name */
+		AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,   /* Fixed flags */
+		AVP_FLAG_MANDATORY,                     /* Fixed flag values */
+		AVP_TYPE_UNSIGNED32                     /* base type of data */
+	    };
+	    CHECK_dict_new( DICT_AVP, &data , NULL, NULL);
+	}
+                                      
+	/* Redirect-Address-Type */
+	{
+	    /* 
+	       Enumerated. 
+	    */
+
+	    struct dict_object              *type;
+	    struct dict_type_data           tdata = { AVP_TYPE_INTEGER32, "Enumerated(Redirect-Address-Type)" , NULL, NULL, NULL };
+	    struct dict_enumval_data        t_1 = { "IPV4_ADDRESS", { .i32 = 0 }};
+	    struct dict_enumval_data        t_2 = { "IPV6_ADDRESS", { .i32 = 1 }};
+	    struct dict_enumval_data        t_3 = { "URL", { .i32 = 2 }};
+	    struct dict_enumval_data        t_4 = { "SIP_URI", { .i32 = 3 }};
+                  
+	    struct dict_avp_data    data = { 
+		433,                                    /* Code */
+		0,                                      /* Vendor */
+		"Redirect-Address-Type",                /* Name */
+		AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,   /* Fixed flags */
+		AVP_FLAG_MANDATORY,                     /* Fixed flag values */
+		AVP_TYPE_INTEGER32                      /* base type of data */
+	    };
+	    /* Create the Enumerated type, and then the AVP */
+	    CHECK_dict_new( DICT_TYPE, &tdata , NULL, &type);
+	    CHECK_dict_new( DICT_ENUMVAL, &t_1 , type, NULL);  
+	    CHECK_dict_new( DICT_ENUMVAL, &t_2 , type, NULL); 
+	    CHECK_dict_new( DICT_ENUMVAL, &t_3 , type, NULL); 
+	    CHECK_dict_new( DICT_ENUMVAL, &t_4 , type, NULL); 
+	    CHECK_dict_new( DICT_AVP, &data , type, NULL);
+	}           
+
+	/* Redirect-Server-Address */
+	{
+	    /* 
+	       UTF8String. 
+	    */
+	    struct dict_avp_data    data = { 
+		435,                                    /* Code */
+		0,                                      /* Vendor */
+		"Redirect-Server-Address",              /* Name */
+		AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,   /* Fixed flags */
+		AVP_FLAG_MANDATORY,                     /* Fixed flag values */
+		AVP_TYPE_OCTETSTRING                    /* base type of data */
+	    };
+	    CHECK_dict_new( DICT_AVP, &data , UTF8String_type, NULL);
+	}
+                
+	/* Requested-Action */
+	{
+	    /* 
+	       Enumerated. 
+	    */
+
+	    struct dict_object              *type;
+	    struct dict_type_data           tdata = { AVP_TYPE_INTEGER32, "Enumerated(Requested-Action)" , NULL, NULL, NULL };
+	    struct dict_enumval_data        t_1 = { "DIRECT_DEBITING", { .i32 = 0 }};
+	    struct dict_enumval_data        t_2 = { "REFUND_ACCOUNT", { .i32 = 1 }};
+	    struct dict_enumval_data        t_3 = { "CHECK_BALANCE", { .i32 = 2 }};
+	    struct dict_enumval_data        t_4 = { "PRICE_ENQUIRY", { .i32 = 3 }};
+                  
+	    struct dict_avp_data    data = { 
+		436,                                    /* Code */
+		0,                                      /* Vendor */
+		"Requested-Action",                     /* Name */
+		AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,   /* Fixed flags */
+		AVP_FLAG_MANDATORY,                     /* Fixed flag values */
+		AVP_TYPE_INTEGER32                      /* base type of data */
+	    };
+	    /* Create the Enumerated type, and then the AVP */
+	    CHECK_dict_new( DICT_TYPE, &tdata , NULL, &type);
+	    CHECK_dict_new( DICT_ENUMVAL, &t_1 , type, NULL); 
+	    CHECK_dict_new( DICT_ENUMVAL, &t_2 , type, NULL);
+	    CHECK_dict_new( DICT_ENUMVAL, &t_3 , type, NULL);
+	    CHECK_dict_new( DICT_ENUMVAL, &t_4 , type, NULL);
+	    CHECK_dict_new( DICT_AVP, &data , type, NULL);
+	}
+                                    
+	/* Restriction-Filter-Rule */
+	{
+	    /* 
+	       IPFiltrRule. 
+	    */
+	    struct dict_avp_data    data = { 
+		438,                                    /* Code */
+		0,                                      /* Vendor */
+		"Restriction-Filter-Rule",              /* Name */
+		AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,   /* Fixed flags */
+		AVP_FLAG_MANDATORY,                     /* Fixed flag values */
+		AVP_TYPE_OCTETSTRING                    /* base type of data */
+	    };
+	    CHECK_dict_new( DICT_AVP, &data , IPFilterRule_type, NULL);
+	}
+	/*Service-Context-Id  */
+	{
+	    /* 
+	       UTF8String. 
+	    */
+	    struct dict_avp_data    data = { 
+		461,                                    /* Code */
+		0,                                      /* Vendor */
+		"Service-Context-Id",                   /* Name */
+		AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,   /* Fixed flags */
+		AVP_FLAG_MANDATORY,                     /* Fixed flag values */
+		AVP_TYPE_OCTETSTRING                    /* base type of data */
+	    };
+	    CHECK_dict_new( DICT_AVP, &data , UTF8String_type, NULL);
+	}
+
+	/* Service-Identifier */
+	{
+	    /* 
+	       Unsigned32. 
+	    */
+	    struct dict_avp_data data = { 
+		439,                                    /* Code */
+		0,                                      /* Vendor */
+		"Service-Identifier",                   /* Name */
+		AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,   /* Fixed flags */
+		AVP_FLAG_MANDATORY,                     /* Fixed flag values */
+		AVP_TYPE_UNSIGNED32                     /* base type of data */
+	    };
+	    CHECK_dict_new( DICT_AVP, &data , NULL, NULL);
+	}                       
+                               
+	/* Service-Parameter-Type */
+	{
+	    /* 
+	       Unsigned32. 
+	    */
+	    struct dict_avp_data data = { 
+		441,                                    /* Code */
+		0,                                      /* Vendor */
+		"Service-Parameter-Type",               /* Name */
+		AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,   /* Fixed flags */
+		AVP_FLAG_MANDATORY,                     /* Fixed flag values */
+		AVP_TYPE_UNSIGNED32                     /* base type of data */
+	    };
+	    CHECK_dict_new( DICT_AVP, &data , NULL, NULL);
+	}
+                
+	/* Service-Parameter-Value */
+	{
+	    /* 
+	       OctetString. 
+	    */
+	    struct dict_avp_data data = { 
+		442,                                    /* Code */
+		0,                                      /* Vendor */
+		"Service-Parameter-Value",              /* Name */
+		AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,   /* Fixed flags */
+		AVP_FLAG_MANDATORY,                     /* Fixed flag values */
+		AVP_TYPE_OCTETSTRING                    /* base type of data */
+	    };
+	    CHECK_dict_new( DICT_AVP, &data , NULL, NULL);
+	}
+
+	/* Subscription-Id-Data */
+	{
+	    /* 
+	       UTF8String. 
+	    */
+	    struct dict_avp_data    data = { 
+		444,                                    /* Code */
+		0,                                      /* Vendor */
+		"Subscription-Id-Data",                 /* Name */
+		AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,   /* Fixed flags */
+		AVP_FLAG_MANDATORY,                     /* Fixed flag values */
+		AVP_TYPE_OCTETSTRING                    /* base type of data */
+	    };
+	    CHECK_dict_new( DICT_AVP, &data , UTF8String_type, NULL);
+	}            
+    
+	/* Subscription-Id-Type */
+	{
+	    /* 
+	       Enumerated. 
+	    */
+
+	    struct dict_object              *type;
+	    struct dict_type_data           tdata = { AVP_TYPE_INTEGER32, "Enumerated(Subscription-Id-Type)" , NULL, NULL, NULL };
+	    struct dict_enumval_data        t_1 = { "END_USER_E164", { .i32 = 0 }};
+	    struct dict_enumval_data        t_2 = { "END_USER_IMSI", { .i32 = 1 }};
+	    struct dict_enumval_data        t_3 = { "END_USER_SIP_URI", { .i32 = 2 }};
+	    struct dict_enumval_data        t_4 = { "END_USER_NAI", { .i32 = 3 }};
+                  
+	    struct dict_avp_data    data = { 
+		450,                                    /* Code */
+		0,                                      /* Vendor */
+		"Subscription-Id-Type",                 /* Name */
+		AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,   /* Fixed flags */
+		AVP_FLAG_MANDATORY,                     /* Fixed flag values */
+		AVP_TYPE_INTEGER32                      /* base type of data */
+	    };
+	    /* Create the Enumerated type, and then the AVP */
+	    CHECK_dict_new( DICT_TYPE, &tdata , NULL, &type);
+	    CHECK_dict_new( DICT_ENUMVAL, &t_1 , type, NULL); 
+	    CHECK_dict_new( DICT_ENUMVAL, &t_2 , type, NULL);
+	    CHECK_dict_new( DICT_ENUMVAL, &t_3 , type, NULL);
+	    CHECK_dict_new( DICT_ENUMVAL, &t_4 , type, NULL);
+	    CHECK_dict_new( DICT_AVP, &data , type, NULL);
+	}
+                
+	/* Tariff-Change-Usage */
+	{
+	    /* 
+	       Enumerated. 
+	    */
+
+	    struct dict_object              *type;
+	    struct dict_type_data           tdata = { AVP_TYPE_INTEGER32, "Enumerated(Tariff-Change-Usage)" , NULL, NULL, NULL };
+	    struct dict_enumval_data        t_1 = { "UNIT_BEFORE_TARIFF_CHANGE", { .i32 = 0 }};
+	    struct dict_enumval_data        t_2 = { "UNIT_AFTER_TARIFF_CHANGE", { .i32 = 1 }};
+	    struct dict_enumval_data        t_3 = { "UNIT_INDETERMINATE", { .i32 = 2 }};
+                  
+	    struct dict_avp_data    data = { 
+		452,                                    /* Code */
+		0,                                      /* Vendor */
+		"Tariff-Change-Usage",                  /* Name */
+		AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,   /* Fixed flags */
+		AVP_FLAG_MANDATORY,                     /* Fixed flag values */
+		AVP_TYPE_INTEGER32                      /* base type of data */
+	    };
+	    /* Create the Enumerated type, and then the AVP */
+	    CHECK_dict_new( DICT_TYPE, &tdata , NULL, &type);
+	    CHECK_dict_new( DICT_ENUMVAL, &t_1 , type, NULL); 
+	    CHECK_dict_new( DICT_ENUMVAL, &t_2 , type, NULL);
+	    CHECK_dict_new( DICT_ENUMVAL, &t_3 , type, NULL);
+	    CHECK_dict_new( DICT_AVP, &data , type, NULL);
+	}
+                
+	/* Tariff-Time-Change */
+	{
+	    /*
+	      Time. 
+	    */
+	    struct dict_avp_data data = { 
+		451,                                    /* Code */
+		0,                                      /* Vendor */
+		"Tariff-Time-Change",                   /* Name */
+		AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,   /* Fixed flags */
+		AVP_FLAG_MANDATORY,                     /* Fixed flag values */
+		AVP_TYPE_OCTETSTRING                    /* base type of data */
+	    };
+	    CHECK_dict_new( DICT_AVP, &data , Time_type, NULL);
+	}
+
+	/* User-Equipment-Info-Type */
+	{
+	    /* 
+	       Enumerated. 
+	    */
+
+	    struct dict_object              *type;
+	    struct dict_type_data           tdata = { AVP_TYPE_INTEGER32, "Enumerated(User-Equipment-Info-Type)" , NULL, NULL, NULL };
+	    struct dict_enumval_data        t_1 = { "IMEISV", { .i32 = 0 }};
+	    struct dict_enumval_data        t_2 = { "MAC", { .i32 = 1 }};
+	    struct dict_enumval_data        t_3 = { "EUI64", { .i32 = 2 }};
+                  
+	    struct dict_avp_data    data = { 
+		459,                                    /* Code */
+		0,                                      /* Vendor */
+		"User-Equipment-Info-Type",             /* Name */
+		AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,   /* Fixed flags */
+		AVP_FLAG_MANDATORY,                     /* Fixed flag values */
+		AVP_TYPE_INTEGER32                      /* base type of data */
+	    };
+	    /* Create the Enumerated type, and then the AVP */
+	    CHECK_dict_new( DICT_TYPE, &tdata , NULL, &type);
+	    CHECK_dict_new( DICT_ENUMVAL, &t_1 , type, NULL);
+	    CHECK_dict_new( DICT_ENUMVAL, &t_2 , type, NULL);
+	    CHECK_dict_new( DICT_ENUMVAL, &t_3 , type, NULL);
+	    CHECK_dict_new( DICT_AVP, &data , type, NULL);
+	}                           
+   
+	/* User-Equipment-Info-Value */
+	{
+	    /* 
+	       OctetString. 
+	    */
+	    struct dict_avp_data data = { 
+		460,                                    /* Code */
+		0,                                      /* Vendor */
+		"User-Equipment-Info-Value",            /* Name */
+		AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,   /* Fixed flags */
+		AVP_FLAG_MANDATORY,                     /* Fixed flag values */
+		AVP_TYPE_OCTETSTRING                    /* base type of data */
+	    };
+	    CHECK_dict_new( DICT_AVP, &data , NULL, NULL);
+	}
+
+	/* Value-Digits */
+	{
+	    /* 
+	       Integer64. 
+	    */
+	    struct dict_avp_data data = { 
+		447,                                    /* Code */
+		0,                                      /* Vendor */
+		"Value-Digits",                         /* Name */
+		AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,   /* Fixed flags */
+		AVP_FLAG_MANDATORY,                     /* Fixed flag values */
+		AVP_TYPE_INTEGER64                      /* base type of data */
+	    };
+	    CHECK_dict_new( DICT_AVP, &data , NULL, NULL);
+	}                         
+                 
+	/* Validity-Time */
+	{
+	    /* 
+	       Unsigned32. 
+	    */
+	    struct dict_avp_data data = { 
+		448,                                    /* Code */
+		0,                                      /* Vendor */
+		"Validity-Time",                        /* Name */
+		AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,   /* Fixed flags */
+		AVP_FLAG_MANDATORY,                     /* Fixed flag values */
+		AVP_TYPE_UNSIGNED32                     /* base type of data */
+	    };
+	    CHECK_dict_new( DICT_AVP, &data , NULL, NULL);
+	}
+
+
+	/* Grouped AVPs below since they have dependencies on types above */
+
+	/* Redirect-Server */
+	{
+	    /*
+	      Grouped
+	    */
+	    struct dict_object * avp;
+	    struct dict_avp_data data = {
+		434,                                    /* Code */
+		0,                                      /* Vendor */
+		"Redirect-Server",                      /* Name */
+		AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,   /* Fixed flags */
+		AVP_FLAG_MANDATORY,                     /* Fixed flag values */
+		AVP_TYPE_GROUPED                        /* base type of data */
+	    };
+	    struct local_rules_definition rules[] = {
+		{  "Redirect-Address-Type",	RULE_REQUIRED,	-1, 1 },
+		{  "Redirect-Server-Address",	RULE_REQUIRED,	-1, 1 }
+	    };
+	    CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+	    PARSE_loc_rules( rules, avp );
+	}
+
+	/* Service-Parameter-Info */
+	{
+	    /*
+	      Grouped
+	    */
+	    struct dict_object * avp;
+	    struct dict_avp_data data = {
+		440,                                    /* Code */
+		0,                                      /* Vendor */
+		"Service-Parameter-Info",               /* Name */
+		AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,   /* Fixed flags */
+		AVP_FLAG_MANDATORY,                     /* Fixed flag values */
+		AVP_TYPE_GROUPED                        /* base type of data */
+	    };
+	    struct local_rules_definition rules[] = {
+		{  "Service-Parameter-Type",	RULE_REQUIRED,	-1, 1 },
+		{  "Service-Parameter-Value",	RULE_REQUIRED,	-1, 1 }
+	    };
+	    CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+	    PARSE_loc_rules( rules, avp );
+	}                        
+
+	/* Subscription-Id */
+	{
+	    /*
+	      Grouped
+	    */
+	    struct dict_object * avp;
+	    struct dict_avp_data data = {
+		443,                                    /* Code */
+		0,                                      /* Vendor */
+		"Subscription-Id",                      /* Name */
+		AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,   /* Fixed flags */
+		AVP_FLAG_MANDATORY,                     /* Fixed flag values */
+		AVP_TYPE_GROUPED                        /* base type of data */
+	    };
+	    struct local_rules_definition rules[] = {
+		{  "Subscription-Id-Type",	RULE_REQUIRED,	-1, 1 },
+		{  "Subscription-Id-Data",	RULE_REQUIRED,	-1, 1 }
+	    };
+	    CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+	    PARSE_loc_rules( rules, avp );
+	}
+                                     
+	/* Unit-Value */
+	{
+	    /*
+	      Grouped
+	    */
+	    struct dict_object * avp;
+	    struct dict_avp_data data = {
+		445,                                    /* Code */
+		0,                                      /* Vendor */
+		"Unit-Value",                           /* Name */
+		AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,   /* Fixed flags */
+		AVP_FLAG_MANDATORY,                     /* Fixed flag values */
+		AVP_TYPE_GROUPED                        /* base type of data */
+	    };
+	    struct local_rules_definition rules[] = {
+		{  "Value-Digits",	RULE_REQUIRED,	-1, 1 },
+		{  "Exponent",		RULE_OPTIONAL,	-1, 1 }
+	    };
+	    CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+	    PARSE_loc_rules( rules, avp );
+	}
+
+	/* User-Equipment-Info */
+	{
+	    /*
+	      Grouped
+	    */
+	    struct dict_object * avp;
+	    struct dict_avp_data data = {
+		458,                                    /* Code */
+		0,                                      /* Vendor */
+		"User-Equipment-Info",                  /* Name */
+		AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,   /* Fixed flags */
+		AVP_FLAG_MANDATORY,                     /* Fixed flag values */
+		AVP_TYPE_GROUPED                        /* base type of data */
+	    };
+	    struct local_rules_definition rules[] = {
+		{  "User-Equipment-Info-Type",	RULE_REQUIRED,	-1, 1 },
+		{  "User-Equipment-Info-Value",	RULE_REQUIRED,	-1, 1 }
+	    };
+	    CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+	    PARSE_loc_rules( rules, avp );
+	}
+
+	/* grouped AVPs using grouped AVPs */ 
+
+	/* CC-Money */
+	{
+	    /*
+	      Grouped
+	    */
+	    struct dict_object * avp;
+	    struct dict_avp_data data = {
+		413,                                    /* Code */
+		0,                                      /* Vendor */
+		"CC-Money",                             /* Name */
+		AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,   /* Fixed flags */
+		AVP_FLAG_MANDATORY,                     /* Fixed flag values */
+		AVP_TYPE_GROUPED                        /* base type of data */
+	    };
+	    struct local_rules_definition rules[] = {
+		{  "Unit-Value",	RULE_REQUIRED,	-1, 1 },
+		{  "Currency-Code",	RULE_OPTIONAL,	-1, 1 }
+	    };
+	    CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+	    PARSE_loc_rules( rules, avp );
+	}
+
+	/* Cost-Information */
+	{
+	    /*
+	      Grouped
+	    */
+	    struct dict_object * avp;
+	    struct dict_avp_data data = {
+		423,                                    /* Code */
+		0,                                      /* Vendor */
+		"Cost-Information",                     /* Name */
+		AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,   /* Fixed flags */
+		AVP_FLAG_MANDATORY,                     /* Fixed flag values */
+		AVP_TYPE_GROUPED                        /* base type of data */
+	    };
+	    struct local_rules_definition rules[] = {
+		{  "Unit-Value",	RULE_REQUIRED,	-1, 1 },
+		{  "Currency-Code",	RULE_REQUIRED,	-1, 1 },
+		{  "Cost-Unit",		RULE_OPTIONAL,	-1, 1 }
+	    };
+	    CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+	    PARSE_loc_rules( rules, avp );
+	}
+
+	/* Final-Unit-Indication */
+	{
+	    /*
+	      Grouped
+	    */
+	    struct dict_object * avp;
+	    struct dict_avp_data data = {
+		430,                                    /* Code */
+		0,                                      /* Vendor */
+		"Final-Unit-Indication",                /* Name */
+		AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,   /* Fixed flags */
+		AVP_FLAG_MANDATORY,                     /* Fixed flag values */
+		AVP_TYPE_GROUPED                        /* base type of data */
+	    };
+	    struct local_rules_definition rules[] = {
+		{  "Final-Unit-Action",		RULE_REQUIRED,	-1, 1 },
+		{  "Restriction-Filter-Rule",	RULE_OPTIONAL,	-1, -1 },
+		{  "Filter-Id",			RULE_OPTIONAL,	-1, -1 },
+		{  "Redirect-Server",		RULE_OPTIONAL,	-1, 1 },
+	    };
+	    CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+	    PARSE_loc_rules( rules, avp );
+	}
+                
+	/* Granted-Service-Unit */
+	{
+	    /*
+	      Grouped
+	    */
+	    struct dict_object * avp;
+	    struct dict_avp_data data = {
+		431,                                    /* Code */
+		0,                                      /* Vendor */
+		"Granted-Service-Unit",                 /* Name */
+		AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,   /* Fixed flags */
+		AVP_FLAG_MANDATORY,                     /* Fixed flag values */
+		AVP_TYPE_GROUPED                        /* base type of data */
+	    };
+	    struct local_rules_definition rules[] = {
+		{  "Tariff-Time-Change",	RULE_OPTIONAL,	-1, 1 },
+		{  "CC-Time",	       		RULE_OPTIONAL,	-1, 1 },
+		{  "CC-Money",			RULE_OPTIONAL,	-1, 1 },
+		{  "CC-Total-Octets",		RULE_OPTIONAL,	-1, 1 },
+		{  "CC-Input-Octets",		RULE_OPTIONAL,	-1, 1 },
+		{  "CC-Output-Octets",		RULE_OPTIONAL,	-1, 1 },
+		{  "CC-Service-Specific-Units",	RULE_OPTIONAL,	-1, 1 }
+		/* plus any additional AVPs { "AVP", RULE_OPTIONAL, -1, -1 } */
+	    };
+	    CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+	    PARSE_loc_rules( rules, avp );
+	}
+
+	/* G-S-U-Pool-Reference */
+	{
+	    /*
+	      Grouped
+	    */
+	    struct dict_object * avp;
+	    struct dict_avp_data data = {
+		457,                                    /* Code */
+		0,                                      /* Vendor */
+		"G-S-U-Pool-Reference",                 /* Name */
+		AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,   /* Fixed flags */
+		AVP_FLAG_MANDATORY,                     /* Fixed flag values */
+		AVP_TYPE_GROUPED                        /* base type of data */
+	    };
+	    struct local_rules_definition rules[] = {
+		{  "G-S-U-Pool-Identifier",	RULE_REQUIRED,	-1, 1 },
+		{  "CC-Unit-Type",		RULE_REQUIRED,	-1, 1 },
+		{  "Unit-Value",		RULE_REQUIRED,	-1, 1 }
+	    };
+	    CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+	    PARSE_loc_rules( rules, avp );
+	}                     
+
+	/* Requested-Service-Unit */
+	{
+	    /*
+	      Grouped
+	    */
+	    struct dict_object * avp;
+	    struct dict_avp_data data = {
+		437,                                    /* Code */
+		0,                                      /* Vendor */
+		"Requested-Service-Unit",               /* Name */
+		AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,   /* Fixed flags */
+		AVP_FLAG_MANDATORY,                     /* Fixed flag values */
+		AVP_TYPE_GROUPED                        /* base type of data */
+	    };
+	    struct local_rules_definition rules[] = {
+		{  "CC-Time",	       		RULE_OPTIONAL,	-1, 1 },
+		{  "CC-Money",			RULE_OPTIONAL,	-1, 1 },
+		{  "CC-Total-Octets",		RULE_OPTIONAL,	-1, 1 },
+		{  "CC-Input-Octets",		RULE_OPTIONAL,	-1, 1 },
+		{  "CC-Output-Octets",		RULE_OPTIONAL,	-1, 1 },
+		{  "CC-Service-Specific-Units",	RULE_OPTIONAL,	-1, 1 }
+		/* plus any additional AVPs { "AVP", RULE_OPTIONAL, -1, -1 } */
+	    };
+	    CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+	    PARSE_loc_rules( rules, avp );
+	}
+
+	/* Used-Service-Unit */
+	{
+	    /*
+	      Grouped
+	    */
+	    struct dict_object * avp;
+	    struct dict_avp_data data = {
+		446,                                    /* Code */
+		0,                                      /* Vendor */
+		"Used-Service-Unit",                    /* Name */
+		AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,   /* Fixed flags */
+		AVP_FLAG_MANDATORY,                     /* Fixed flag values */
+		AVP_TYPE_GROUPED                        /* base type of data */
+	    };
+	    struct local_rules_definition rules[] = {
+		{  "Tariff-Change-Usage",	RULE_OPTIONAL,	-1, 1 },
+		{  "CC-Time",	       		RULE_OPTIONAL,	-1, 1 },
+		{  "CC-Money",			RULE_OPTIONAL,	-1, 1 },
+		{  "CC-Total-Octets",		RULE_OPTIONAL,	-1, 1 },
+		{  "CC-Input-Octets",		RULE_OPTIONAL,	-1, 1 },
+		{  "CC-Output-Octets",		RULE_OPTIONAL,	-1, 1 },
+		{  "CC-Service-Specific-Units",	RULE_OPTIONAL,	-1, 1 }
+		/* plus any additional AVPs { "AVP", RULE_OPTIONAL, -1, -1 } */
+	    };
+	    CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+	    PARSE_loc_rules( rules, avp );
+	}
+
+	/* at least three levels of grouping */
+	/* Multiple-Services-Credit-Control */
+	{
+	    /*
+	      Grouped
+	    */
+	    struct dict_object * avp;
+	    struct dict_avp_data data = {
+		456,                                    /* Code */
+		0,                                      /* Vendor */
+		"Multiple-Services-Credit-Control",     /* Name */
+		AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,   /* Fixed flags */
+		AVP_FLAG_MANDATORY,                     /* Fixed flag values */
+		AVP_TYPE_GROUPED                        /* base type of data */
+	    };
+	    struct local_rules_definition rules[] = {
+		{  "Granted-Service-Unit",	RULE_OPTIONAL,	-1, 1 },
+		{  "Requested-Service-Unit",	RULE_OPTIONAL,	-1, 1 },
+		{  "Used-Service-Unit",		RULE_OPTIONAL,	-1, -1 },
+		{  "Tariff-Change-Usage",	RULE_OPTIONAL,	-1, 1 },
+		{  "Service-Identifier",	RULE_OPTIONAL,	-1, -1 },
+		{  "Rating-Group",		RULE_OPTIONAL,	-1, 1 },
+		{  "G-S-U-Pool-Reference",	RULE_OPTIONAL,	-1, -1 },
+		{  "Validity-Time",		RULE_OPTIONAL,	-1, 1 },
+		{  "Result-Code",		RULE_OPTIONAL,	-1, 1 },
+		{  "Final-Unit-Indication",	RULE_OPTIONAL,	-1, 1 }
+		/* plus any additional AVPs { "AVP", RULE_OPTIONAL, -1, -1 } */
+	    };
+	    CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+	    PARSE_loc_rules( rules, avp );
+	}
+                
+
+    }
+
+
+    /* Commands section */
+    {
+	/* Credit-Control-Request (CCR) Command */
+	{
+	    /*
+	      From RFC 4006:
+
+	      3.1.  Credit-Control-Request (CCR) Command
+		  
+	      The Credit-Control-Request message (CCR) is indicated by the
+	      command-code field being set to 272 and the 'R' bit being set in the
+	      Command Flags field.  It is used between the Diameter credit-control
+	      client and the credit-control server to request credit authorization
+	      for a given service.
+		  
+	      The Auth-Application-Id MUST be set to the value 4, indicating the
+	      Diameter credit-control application.
+		  
+	      Message Format
+		  
+	      <Credit-Control-Request> ::= < Diameter Header: 272, REQ, PXY >
+			 	          < Session-Id >
+			 	          { Origin-Host }
+			 	          { Origin-Realm }
+			 	          { Destination-Realm }
+			 	          { Auth-Application-Id }
+			 	          { Service-Context-Id }
+			 	          { CC-Request-Type }
+			 	          { CC-Request-Number }
+			 	          [ Destination-Host ]
+			 	          [ User-Name ]
+			 	          [ CC-Sub-Session-Id ]
+			 	          [ Acct-Multi-Session-Id ]
+			 	          [ Origin-State-Id ]
+			 	          [ Event-Timestamp ]
+			 	         *[ Subscription-Id ]
+			 	          [ Service-Identifier ]
+			 	          [ Termination-Cause ]
+			 	          [ Requested-Service-Unit ]
+			 	          [ Requested-Action ]
+			 	         *[ Used-Service-Unit ]
+			 	          [ Multiple-Services-Indicator ]
+			 	         *[ Multiple-Services-Credit-Control ]
+			 	         *[ Service-Parameter-Info ]
+			 	          [ CC-Correlation-Id ]
+			 	          [ User-Equipment-Info ]
+			 	         *[ Proxy-Info ]
+			 	         *[ Route-Record ]
+			 	         *[ AVP ]
+			 	          		  
+	      10.1.  Credit-Control AVP Table
+		  
+	      The table in this section is used to represent which credit-control
+	      applications specific AVPs defined in this document are to be present
+	      in the credit-control messages.
+		  
+	      +-----------+
+	      |  Command  |
+	      |   Code    |
+	      |-----+-----+
+	      Attribute Name                | CCR | CCA |
+	      ------------------------------|-----+-----+
+	      Acct-Multi-Session-Id         | 0-1 | 0-1 |
+	      Auth-Application-Id           | 1   | 1   |
+	      CC-Correlation-Id             | 0-1 | 0   |
+	      CC-Session-Failover           | 0   | 0-1 |
+	      CC-Request-Number             | 1   | 1   |
+	      CC-Request-Type               | 1   | 1   |
+	      CC-Sub-Session-Id             | 0-1 | 0-1 |
+	      Check-Balance-Result          | 0   | 0-1 |
+	      Cost-Information              | 0   | 0-1 |
+	      Credit-Control-Failure-       | 0   | 0-1 |
+	      Handling                      |     |     |
+	      Destination-Host              | 0-1 | 0   |
+	      Destination-Realm             | 1   | 0   |
+	      Direct-Debiting-Failure-      | 0   | 0-1 |
+	      Handling                      |     |     |
+	      Event-Timestamp               | 0-1 | 0-1 |
+	      Failed-AVP                    | 0   | 0+  |
+	      Final-Unit-Indication         | 0   | 0-1 |
+	      Granted-Service-Unit          | 0   | 0-1 |
+	      Multiple-Services-Credit-     | 0+  | 0+  |
+	      Control                       |     |     |
+	      Multiple-Services-Indicator   | 0-1 | 0   |
+	      Origin-Host                   | 1   | 1   |
+	      Origin-Realm                  | 1   | 1   |
+	      Origin-State-Id               | 0-1 | 0-1 |
+	      Proxy-Info                    | 0+  | 0+  |
+	      Redirect-Host                 | 0   | 0+  |
+	      Redirect-Host-Usage           | 0   | 0-1 |
+	      Redirect-Max-Cache-Time       | 0   | 0-1 |
+	      Requested-Action              | 0-1 | 0   |
+	      Requested-Service-Unit        | 0-1 | 0   |
+	      Route-Record                  | 0+  | 0+  |
+	      Result-Code                   | 0   | 1   |
+	      Service-Context-Id            | 1   | 0   |
+	      Service-Identifier            | 0-1 | 0   |
+	      Service-Parameter-Info        | 0+  | 0   |
+	      Session-Id                    | 1   | 1   |
+	      Subscription-Id               | 0+  | 0   |
+	      Termination-Cause             | 0-1 | 0   |
+	      User-Equipment-Info           | 0-1 | 0   |
+	      Used-Service-Unit             | 0+  | 0   |
+	      User-Name                     | 0-1 | 0-1 |
+	      Validity-Time                 | 0   | 0-1 |
+	      ------------------------------|-----+-----+
+		  
+
+	    */
+	    struct dict_object * cmd;
+	    struct dict_cmd_data data = { 
+		272, 					/* Code */
+		"Credit-Control-Request", 		/* Name */
+		CMD_FLAG_REQUEST | CMD_FLAG_PROXIABLE, 	/* Fixed flags */
+		CMD_FLAG_REQUEST | CMD_FLAG_PROXIABLE 			/* Fixed flag values */
+	    };
+	    struct local_rules_definition rules[] = 
+		{ 	 
+		    { "Session-Id", RULE_FIXED_HEAD, -1, 1 },
+		    { "Origin-Host", RULE_REQUIRED, -1, 1 },
+		    { "Origin-Realm", RULE_REQUIRED, -1, 1 },
+		    { "Destination-Realm", RULE_REQUIRED, -1, 1 },
+		    { "Auth-Application-Id", RULE_REQUIRED, -1, 1 },
+		    { "Service-Context-Id", RULE_REQUIRED, -1, 1 },
+		    { "CC-Request-Type", RULE_REQUIRED, -1, 1 },
+		    { "CC-Request-Number", RULE_REQUIRED, -1, 1 },
+		    { "Destination-Host", RULE_OPTIONAL, -1, 1 },
+		    { "User-Name", RULE_OPTIONAL, -1, 1 },
+		    { "CC-Sub-Session-Id", RULE_OPTIONAL, -1, 1 },
+		    { "Acct-Multi-Session-Id", RULE_OPTIONAL, -1, 1 },
+		    { "Origin-State-Id", RULE_OPTIONAL, -1, 1 },
+		    { "Event-Timestamp", RULE_OPTIONAL, -1, 1 },
+		    { "Subscription-Id", RULE_OPTIONAL, -1, -1 },
+		    { "Service-Identifier", RULE_OPTIONAL, -1, 1 },
+		    { "Termination-Cause", RULE_OPTIONAL, -1, 1 },
+		    { "Requested-Service-Unit", RULE_OPTIONAL, -1, 1 },
+		    { "Requested-Action", RULE_OPTIONAL, -1, 1 },
+		    { "Used-Service-Unit", RULE_OPTIONAL, -1, -1 },
+		    { "Multiple-Services-Indicator", RULE_OPTIONAL, -1, 1 },
+		    { "Multiple-Services-Credit-Control", RULE_OPTIONAL, -1, -1 },
+		    { "Service-Parameter-Info", RULE_OPTIONAL, -1, -1 },
+		    { "CC-Correlation-Id", RULE_OPTIONAL, -1, 1 },
+		    { "User-Equipment-Info", RULE_OPTIONAL, -1, 1 },
+		    { "Proxy-Info", RULE_OPTIONAL, -1, -1 },
+		    { "Route-Record", RULE_OPTIONAL, -1, -1 }
+		    /* plus any additional AVPs { "AVP", RULE_OPTIONAL, -1, -1 } */
+		};
+
+	    CHECK_dict_new( DICT_COMMAND, &data, dcca, &cmd);
+	    PARSE_loc_rules( rules, cmd );
+	}
+
+	/* Credit-Control-Answer (CCA) Command */
+	{
+	    /*
+	      From RFC 4006:
+	      3.2.  Credit-Control-Answer (CCA) Command
+		  
+	      The Credit-Control-Answer message (CCA) is indicated by the command-
+	      code field being set to 272 and the 'R' bit being cleared in the
+	      Command Flags field.  It is used between the credit-control server
+	      and the Diameter credit-control client to acknowledge a Credit-
+	      Control-Request command.
+		  
+	      Message Format
+		  
+	      <Credit-Control-Answer> ::= < Diameter Header: 272, PXY >
+			 	          < Session-Id >
+			 	          { Result-Code }
+			 	          { Origin-Host }
+			 	          { Origin-Realm }
+			 	          { Auth-Application-Id }
+			 	          { CC-Request-Type }
+			 	          { CC-Request-Number }
+			 	          [ User-Name ]
+			 	          [ CC-Session-Failover ]
+			 	          [ CC-Sub-Session-Id ]
+			 	          [ Acct-Multi-Session-Id ]
+			 	          [ Origin-State-Id ]
+			 	          [ Event-Timestamp ]
+			 	          [ Granted-Service-Unit ]
+			 	         *[ Multiple-Services-Credit-Control ]
+			 	          [ Cost-Information]
+			 	          [ Final-Unit-Indication ]
+			 	          [ Check-Balance-Result ]
+			 	          [ Credit-Control-Failure-Handling ]
+			 	          [ Direct-Debiting-Failure-Handling ]
+			 	          [ Validity-Time]
+			 	         *[ Redirect-Host]
+			 	          [ Redirect-Host-Usage ]
+			 	          [ Redirect-Max-Cache-Time ]
+			 	         *[ Proxy-Info ]
+			 	         *[ Route-Record ]
+			 	         *[ Failed-AVP ]
+			 	         *[ AVP ]
+			 	          		  
+	      */
+	    struct dict_object * cmd;
+	    struct dict_cmd_data data = { 
+		272, 					/* Code */
+		"Credit-Control-Answer", 		/* Name */
+		CMD_FLAG_REQUEST | CMD_FLAG_PROXIABLE | CMD_FLAG_ERROR,	/* Fixed flags */
+		CMD_FLAG_PROXIABLE 			/* Fixed flag values */
+	    };
+	    struct local_rules_definition rules[] = 
+		{ 	 
+		    { "Session-Id", RULE_FIXED_HEAD, -1, 1 },
+		    { "Result-Code", RULE_REQUIRED, -1, 1 },
+		    { "Origin-Host", RULE_REQUIRED, -1, 1 },
+		    { "Origin-Realm", RULE_REQUIRED, -1, 1 },
+		    { "Auth-Application-Id", RULE_REQUIRED, -1, 1 },
+		    { "CC-Request-Type", RULE_REQUIRED, -1, 1 },
+		    { "CC-Request-Number", RULE_REQUIRED, -1, 1 },
+		    { "User-Name", RULE_OPTIONAL, -1, 1 },
+		    { "CC-Session-Failover", RULE_OPTIONAL, -1, 1 },
+		    { "CC-Sub-Session-Id", RULE_OPTIONAL, -1, 1 },
+		    { "Acct-Multi-Session-Id", RULE_OPTIONAL, -1, 1 },
+		    { "Origin-State-Id", RULE_OPTIONAL, -1, 1 },
+		    { "Event-Timestamp", RULE_OPTIONAL, -1, 1 },
+		    { "Granted-Service-Unit", RULE_OPTIONAL, -1, 1 },
+		    { "Multiple-Services-Credit-Control", RULE_OPTIONAL, -1, -1 },
+		    { "Cost-Information", RULE_OPTIONAL, -1, 1 },
+		    { "Final-Unit-Indication", RULE_OPTIONAL, -1, 1 },
+		    { "Check-Balance-Result", RULE_OPTIONAL, -1, 1 },
+		    { "Credit-Control-Failure-Handling", RULE_OPTIONAL, -1, 1 },
+		    { "Direct-Debiting-Failure-Handling", RULE_OPTIONAL, -1, 1 },
+		    { "Validity-Time", RULE_OPTIONAL, -1, 1 },
+		    { "Redirect-Host", RULE_OPTIONAL, -1, -1 },
+		    { "Redirect-Host-Usage", RULE_OPTIONAL, -1, 1 },
+		    { "Redirect-Max-Cache-Time", RULE_OPTIONAL, -1, 1 },
+		    { "Proxy-Info", RULE_OPTIONAL, -1, -1 },
+		    { "Route-Record", RULE_OPTIONAL, -1, -1 },
+		    { "Failed-AVP", RULE_OPTIONAL, -1, -1 }
+		    /* plus any additional AVPs { "AVP", RULE_OPTIONAL, -1, -1 } */
+		};
+
+	    CHECK_dict_new( DICT_COMMAND, &data, dcca, &cmd);
+	    PARSE_loc_rules( rules, cmd );
+	}
+    }
+    LOG_D( "Extension 'Dictionary definitions for DCCA (rfc4006)' initialized");
+    return 0;
+}
+
+/* needs dict_nasreq for Filter-Id */
+EXTENSION_ENTRY("dict_dcca", dict_dcca_entry, "dict_nasreq");
diff --git a/extensions/dict_dcca_3gpp/CMakeLists.txt b/extensions/dict_dcca_3gpp/CMakeLists.txt
new file mode 100644
index 0000000..7105c15
--- /dev/null
+++ b/extensions/dict_dcca_3gpp/CMakeLists.txt
@@ -0,0 +1,13 @@
+# The dict_dcca_3gpp extension
+PROJECT("Diameter DCCA (Diameter Credit Control Application) 3GPP dictionary definitions" C)
+
+# Compile as a module
+FD_ADD_EXTENSION(dict_dcca_3gpp dict_dcca_3gpp.c)
+
+
+####
+## INSTALL section ##
+
+INSTALL(TARGETS dict_dcca_3gpp
+	LIBRARY DESTINATION ${INSTALL_EXTENSIONS_SUFFIX}
+	COMPONENT freeDiameter-dictionary-rfc4006-extension-3gpp)
diff --git a/extensions/dict_dcca_3gpp/dict_dcca_3gpp.c b/extensions/dict_dcca_3gpp/dict_dcca_3gpp.c
new file mode 100644
index 0000000..dd79be4
--- /dev/null
+++ b/extensions/dict_dcca_3gpp/dict_dcca_3gpp.c
@@ -0,0 +1,10929 @@
+/*********************************************************************************************************
+ * Software License Agreement (BSD License)                                                               *
+ * Author: Thomas Klausner <tk@giga.or.at>                                                                *
+ *                                                                                                        *
+ * Copyright (c) 2013, Thomas Klausner                                                                    *
+ * All rights reserved.                                                                                   *
+ *                                                                                                        *
+ * Written under contract by nfotex IT GmbH, http://nfotex.com/                                           *
+ *                                                                                                        *
+ * Redistribution and use of this software in source and binary forms, with or without modification, are  *
+ * permitted provided that the following conditions are met:                                              *
+ *                                                                                                        *
+ * * Redistributions of source code must retain the above                                                 *
+ *   copyright notice, this list of conditions and the                                                    *
+ *   following disclaimer.                                                                                *
+ *                                                                                                        *
+ * * Redistributions in binary form must reproduce the above                                              *
+ *   copyright notice, this list of conditions and the                                                    *
+ *   following disclaimer in the documentation and/or other                                               *
+ *   materials provided with the distribution.                                                            *
+ *                                                                                                        *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED *
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR *
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT     *
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS    *
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR *
+ * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF   *
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.                                                             *
+ *********************************************************************************************************/
+
+/* 
+ * Dictionary definitions for objects specified for DCCA by 3GPP.
+ *
+ * This extensions contains a lot of AVPs from various 3GPP standards
+ * documents, and some rules for the grouped AVPs described therein.
+ *
+ * This extension does not contain ALL AVPs described by 3GPP, but
+ * quite a big number of them.
+ *
+ * When extending the AVPs, please edit dict_dcca_3gpp.org instead and
+ * create pastable code with contrib/tools/org_to_fd.pl.
+ *
+ * Some points of consideration:
+ * 1. This dictionary could be split up per document.
+ *
+ * + pro: you can only load the AVPs/Rules you're interested in ->
+ * smaller memory size
+ *
+ * - con: the documents use AVPs from each other A LOT, so setting the
+ * dependencies correctly will be annoying
+ *
+ * - con: you need to load all of them as extensions
+ *
+ * 2. This dictionary contains ONE AVP in the "3GPP2" vendor space,
+ * since I found it wasteful to write a separate dictionary just for
+ * one AVP. Also, it is defined in a 3GPP document.
+ *
+ * 3. While there are quite a number of rules here already, many more
+ * are missing. I've only added rules for those grouped AVPs or
+ * commands in which I was concretely interested so far; many more
+ * will need to be added to make this complete.
+ *
+ * That being said, I hope this will be useful for you.
+ *
+ */
+
+
+/*
+ * Some comments on the 3GPP Standards documents themselves:
+ *
+ * 1. It would be good if 29.061 was reviewed to check for each AVP if
+ * it is Mandatory or not. The data currently in the document does not
+ * match what was in the previous version of the freeDiameter
+ * extension (the one that existedbefore I rewrote it) or what I saw
+ * so far. IIRC, even the table and the document contradict each
+ * other. The AVP table is also missing an entry for
+ * "External-Identifier", 28.
+ *
+ * 2. 29.140 has conflicting AVP names with other documents:
+ *   - Sequence-Number is also in 32.329
+ *   - Recipient-Address is also in 32.299
+ *   - Status is also in 32.299
+ *
+ * 3. 29.229 has name conflict with 29.329 about User-Data (different
+ * AVP code 702, instead of 606) -- the weird thing is, the latter
+ * uses some AVPs from the former, but not this one.
+*/
+#include <freeDiameter/extension.h>
+
+
+/* The content of this file follows the same structure as dict_base_proto.c */
+
+#define CHECK_dict_new( _type, _data, _parent, _ref )	\
+	CHECK_FCT(  fd_dict_new( fd_g_config->cnf_dict, (_type), (_data), (_parent), (_ref))  );
+
+#define CHECK_dict_search( _type, _criteria, _what, _result )	\
+	CHECK_FCT(  fd_dict_search( fd_g_config->cnf_dict, (_type), (_criteria), (_what), (_result), ENOENT) );
+
+struct local_rules_definition {
+	struct dict_avp_request avp_vendor_plus_name;
+	enum rule_position	position;
+	int 			min;
+	int			max;
+};
+
+#define RULE_ORDER( _position ) ((((_position) == RULE_FIXED_HEAD) || ((_position) == RULE_FIXED_TAIL)) ? 1 : 0 )
+
+/* Attention! This version of the macro uses AVP_BY_NAME_AND_VENDOR, in contrast to most other copies! */
+#define PARSE_loc_rules( _rulearray, _parent) {								\
+	int __ar;											\
+	for (__ar=0; __ar < sizeof(_rulearray) / sizeof((_rulearray)[0]); __ar++) {			\
+		struct dict_rule_data __data = { NULL, 							\
+			(_rulearray)[__ar].position,							\
+			0, 										\
+			(_rulearray)[__ar].min,								\
+			(_rulearray)[__ar].max};							\
+		__data.rule_order = RULE_ORDER(__data.rule_position);					\
+		CHECK_FCT(  fd_dict_search( 								\
+			fd_g_config->cnf_dict,								\
+			DICT_AVP, 									\
+			AVP_BY_NAME_AND_VENDOR, 							\
+			&(_rulearray)[__ar].avp_vendor_plus_name,					\
+			&__data.rule_avp, 0 ) );							\
+		if ( !__data.rule_avp ) {								\
+			TRACE_DEBUG(INFO, "AVP Not found: '%s'", (_rulearray)[__ar].avp_vendor_plus_name.avp_name);		\
+			return ENOENT;									\
+		}											\
+		CHECK_FCT_DO( fd_dict_new( fd_g_config->cnf_dict, DICT_RULE, &__data, _parent, NULL),	\
+			{							        		\
+				TRACE_DEBUG(INFO, "Error on rule with AVP '%s'",      			\
+					    (_rulearray)[__ar].avp_vendor_plus_name.avp_name);		\
+				return EINVAL;					      			\
+			} );							      			\
+	}									      			\
+}
+
+#define enumval_def_u32( _val_, _str_ ) \
+		{ _str_, 		{ .u32 = _val_ }}
+
+#define enumval_def_os( _len_, _val_, _str_ ) \
+		{ _str_, 		{ .os = { .data = (unsigned char *)_val_, .len = _len_ }}}
+
+
+static int dict_dcca_3gpp_entry(char * conffile)
+{
+	/* Applications section */
+	{		
+                /* Create the vendors */
+                {
+                        struct dict_vendor_data vendor_data = { 10415, "3GPP" };
+                        CHECK_FCT(fd_dict_new(fd_g_config->cnf_dict, DICT_VENDOR, &vendor_data, NULL, NULL));
+                }
+                {
+                        struct dict_vendor_data vendor_data = { 5535, "3GPP2" };
+                        CHECK_FCT(fd_dict_new(fd_g_config->cnf_dict, DICT_VENDOR, &vendor_data, NULL, NULL));
+                }
+
+	}
+	
+
+	struct dict_object * Address_type;
+	struct dict_object * DiameterIdentity_type;
+	struct dict_object * DiameterURI_type;
+	struct dict_object * IPFilterRule_type;
+	struct dict_object * Time_type;
+	struct dict_object * UTF8String_type;
+
+	CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "Address", &Address_type);
+	CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "DiameterIdentity", &DiameterIdentity_type);
+	CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "DiameterURI", &DiameterURI_type);
+	CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "IPFilterRule", &IPFilterRule_type);
+	CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "Time", &Time_type);
+	CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "UTF8String", &UTF8String_type);
+	
+
+	/* The following is created automatically. Do not modify. */
+	/* Changes will be lost during the next update. Modify the source org file instead. */
+
+	/* 3GPP 29.061-c00 (12.0.0 2012.12.20)                          */
+	/* 3GPP 29.061 is not very clear and self-inconsistent about M  */
+	/* for this reason, other sources are assumed more trustworthy  */
+	/* M inconsistently specified                                   */
+	/* 3GPP-IMSI */
+	{
+		struct dict_avp_data data = {
+			1,	/* Code */
+			10415,	/* Vendor */
+			"3GPP-IMSI",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, UTF8String_type, NULL);
+	};
+
+	/* 29.061 says OctetString; dumps say UInt32; manually changed  */
+	/* 29.061 says MUST NOT M; dumps say MUST                       */
+	/* 3GPP-Charging-Id */
+	{
+		struct dict_avp_data data = {
+			2,	/* Code */
+			10415,	/* Vendor */
+			"3GPP-Charging-Id",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_UNSIGNED32	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* 29.061 says MUST NOT M; dumps say MUST                       */
+	/* 3GPP-PDP-Type */
+	{
+		struct dict_avp_data data = {
+			3,	/* Code */
+			10415,	/* Vendor */
+			"3GPP-PDP-Type",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_INTEGER32	/* base type of data */
+		};
+		struct dict_object		*type;
+		struct dict_type_data	 tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(3GPP-PDP-Type)", NULL, NULL, NULL };
+		CHECK_dict_new(DICT_TYPE, &tdata, NULL, &type);
+		CHECK_dict_new(DICT_AVP, &data, type, NULL);
+	};
+
+	/* 3GPP-CG-Address */
+	{
+		struct dict_avp_data data = {
+			4,	/* Code */
+			10415,	/* Vendor */
+			"3GPP-CG-Address",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* 29.061 says MUST NOT M; old contrib/3gpp says MUST           */
+	/* 3GPP-GPRS-Negotiated-QoS-Profile */
+	{
+		struct dict_avp_data data = {
+			5,	/* Code */
+			10415,	/* Vendor */
+			"3GPP-GPRS-Negotiated-QoS-Profile",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, UTF8String_type, NULL);
+	};
+
+	/* M inconsistently specified; old contrib/3gg says MUST NOT    */
+	/* 3GPP-SGSN-Address */
+	{
+		struct dict_avp_data data = {
+			6,	/* Code */
+			10415,	/* Vendor */
+			"3GPP-SGSN-Address",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* 3GPP-GGSN-Address */
+	{
+		struct dict_avp_data data = {
+			7,	/* Code */
+			10415,	/* Vendor */
+			"3GPP-GGSN-Address",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* 29.061 says MUST NOT M; dumps say MUST                       */
+	/* 3GPP-IMSI-MCC-MNC */
+	{
+		struct dict_avp_data data = {
+			8,	/* Code */
+			10415,	/* Vendor */
+			"3GPP-IMSI-MCC-MNC",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, UTF8String_type, NULL);
+	};
+
+	/* 29.061 says MUST NOT M; old contrib/3gpp says MUST           */
+	/* 3GPP-GGSN-MCC-MNC */
+	{
+		struct dict_avp_data data = {
+			9,	/* Code */
+			10415,	/* Vendor */
+			"3GPP-GGSN-MCC-MNC",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, UTF8String_type, NULL);
+	};
+
+	/* 29.061 says MUST NOT M; old contrib/3gpp says MUST           */
+	/* 3GPP-NSAPI */
+	{
+		struct dict_avp_data data = {
+			10,	/* Code */
+			10415,	/* Vendor */
+			"3GPP-NSAPI",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* added manually, missing in AVP table                         */
+	/* 3GPP-Session-Stop-Indicator */
+	{
+		struct dict_avp_data data = {
+			11,	/* Code */
+			10415,	/* Vendor */
+			"3GPP-Session-Stop-Indicator",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* 29.061 says MUST NOT M; old contrib/3gpp says MUST           */
+	/* 3GPP-Selection-Mode */
+	{
+		struct dict_avp_data data = {
+			12,	/* Code */
+			10415,	/* Vendor */
+			"3GPP-Selection-Mode",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, UTF8String_type, NULL);
+	};
+
+	/* 29.061 says MUST NOT M; old contrib/3gpp says MUST           */
+	/* 3GPP-Charging-Characteristics */
+	{
+		struct dict_avp_data data = {
+			13,	/* Code */
+			10415,	/* Vendor */
+			"3GPP-Charging-Characteristics",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, UTF8String_type, NULL);
+	};
+
+	/* 29.061 says MUST NOT M; old contrib/3gpp says MUST           */
+	/* 3GPP-CG-IPv6-Address */
+	{
+		struct dict_avp_data data = {
+			14,	/* Code */
+			10415,	/* Vendor */
+			"3GPP-CG-IPv6-Address",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* M inconsistently specified                                   */
+	/* 29.061 says MUST NOT M; old contrib/3gpp says MUST           */
+	/* 3GPP-SGSN-IPv6-Address */
+	{
+		struct dict_avp_data data = {
+			15,	/* Code */
+			10415,	/* Vendor */
+			"3GPP-SGSN-IPv6-Address",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* 29.061 says MUST NOT M; old contrib/3gpp says MUST           */
+	/* 3GPP-GGSN-IPv6-Address */
+	{
+		struct dict_avp_data data = {
+			16,	/* Code */
+			10415,	/* Vendor */
+			"3GPP-GGSN-IPv6-Address",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* 29.061 says MUST NOT M; old contrib/3gpp says MUST           */
+	/* 3GPP-IPv6-DNS-Servers */
+	{
+		struct dict_avp_data data = {
+			17,	/* Code */
+			10415,	/* Vendor */
+			"3GPP-IPv6-DNS-Servers",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* 29.061 says MUST NOT M; old contrib/3gpp says MUST           */
+	/* 3GPP-SGSN-MCC-MNC */
+	{
+		struct dict_avp_data data = {
+			18,	/* Code */
+			10415,	/* Vendor */
+			"3GPP-SGSN-MCC-MNC",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, UTF8String_type, NULL);
+	};
+
+	/* M inconsistently specified                                   */
+	/* 3GPP-IMEISV */
+	{
+		struct dict_avp_data data = {
+			20,	/* Code */
+			10415,	/* Vendor */
+			"3GPP-IMEISV",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* M inconsistently specified                                   */
+	/* 3GPP-RAT-Type */
+	{
+		struct dict_avp_data data = {
+			21,	/* Code */
+			10415,	/* Vendor */
+			"3GPP-RAT-Type",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* M inconsistently specified                                   */
+	/* 3GPP-User-Location-Info */
+	{
+		struct dict_avp_data data = {
+			22,	/* Code */
+			10415,	/* Vendor */
+			"3GPP-User-Location-Info",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* M inconsistently specified                                   */
+	/* 3GPP-MS-TimeZone */
+	{
+		struct dict_avp_data data = {
+			23,	/* Code */
+			10415,	/* Vendor */
+			"3GPP-MS-TimeZone",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* 3GPP-CAMEL-Charging-Info */
+	{
+		struct dict_avp_data data = {
+			24,	/* Code */
+			10415,	/* Vendor */
+			"3GPP-CAMEL-Charging-Info",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* 3GPP-Packet-Filter */
+	{
+		struct dict_avp_data data = {
+			25,	/* Code */
+			10415,	/* Vendor */
+			"3GPP-Packet-Filter",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* 3GPP-Negotiated-DSCP */
+	{
+		struct dict_avp_data data = {
+			26,	/* Code */
+			10415,	/* Vendor */
+			"3GPP-Negotiated-DSCP",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* 3GPP-Allocate-IP-Type */
+	{
+		struct dict_avp_data data = {
+			27,	/* Code */
+			10415,	/* Vendor */
+			"3GPP-Allocate-IP-Type",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* added manually, missing in AVP table                         */
+	/* External-Identifier */
+	{
+		struct dict_avp_data data = {
+			28,	/* Code */
+			10415,	/* Vendor */
+			"External-Identifier",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* TMGI */
+	{
+		struct dict_avp_data data = {
+			900,	/* Code */
+			10415,	/* Vendor */
+			"TMGI",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* Required-MBMS-Bearer-Capabilities */
+	{
+		struct dict_avp_data data = {
+			901,	/* Code */
+			10415,	/* Vendor */
+			"Required-MBMS-Bearer-Capabilities",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, UTF8String_type, NULL);
+	};
+
+	/* MBMS-StartStop-Indication */
+	{
+		struct dict_avp_data data = {
+			902,	/* Code */
+			10415,	/* Vendor */
+			"MBMS-StartStop-Indication",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_INTEGER32	/* base type of data */
+		};
+		struct dict_object		*type;
+		struct dict_type_data	 tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(MBMS-StartStop-Indication)", NULL, NULL, NULL };
+		CHECK_dict_new(DICT_TYPE, &tdata, NULL, &type);
+		CHECK_dict_new(DICT_AVP, &data, type, NULL);
+	};
+
+	/* MBMS-Service-Area */
+	{
+		struct dict_avp_data data = {
+			903,	/* Code */
+			10415,	/* Vendor */
+			"MBMS-Service-Area",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* MBMS-Session-Duration */
+	{
+		struct dict_avp_data data = {
+			904,	/* Code */
+			10415,	/* Vendor */
+			"MBMS-Session-Duration",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* Alternative-APN */
+	{
+		struct dict_avp_data data = {
+			905,	/* Code */
+			10415,	/* Vendor */
+			"Alternative-APN",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, UTF8String_type, NULL);
+	};
+
+	/* MBMS-Service-Type */
+	{
+		struct dict_avp_data data = {
+			906,	/* Code */
+			10415,	/* Vendor */
+			"MBMS-Service-Type",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_INTEGER32	/* base type of data */
+		};
+		struct dict_object		*type;
+		struct dict_type_data	 tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(MBMS-Service-Type)", NULL, NULL, NULL };
+		CHECK_dict_new(DICT_TYPE, &tdata, NULL, &type);
+		CHECK_dict_new(DICT_AVP, &data, type, NULL);
+	};
+
+	/* MBMS-2G-3G-Indicator */
+	{
+		struct dict_avp_data data = {
+			907,	/* Code */
+			10415,	/* Vendor */
+			"MBMS-2G-3G-Indicator",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_INTEGER32	/* base type of data */
+		};
+		struct dict_object		*type;
+		struct dict_type_data	 tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(MBMS-2G-3G-Indicator)", NULL, NULL, NULL };
+		CHECK_dict_new(DICT_TYPE, &tdata, NULL, &type);
+		CHECK_dict_new(DICT_AVP, &data, type, NULL);
+	};
+
+	/* MBMS-Session-Identity */
+	{
+		struct dict_avp_data data = {
+			908,	/* Code */
+			10415,	/* Vendor */
+			"MBMS-Session-Identity",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* RAI */
+	{
+		struct dict_avp_data data = {
+			909,	/* Code */
+			10415,	/* Vendor */
+			"RAI",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, UTF8String_type, NULL);
+	};
+
+	/* Additional-MBMS-Trace-Info */
+	{
+		struct dict_avp_data data = {
+			910,	/* Code */
+			10415,	/* Vendor */
+			"Additional-MBMS-Trace-Info",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* MBMS-Time-To-Data-Transfer */
+	{
+		struct dict_avp_data data = {
+			911,	/* Code */
+			10415,	/* Vendor */
+			"MBMS-Time-To-Data-Transfer",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* MBMS-Session-Repetition-Number */
+	{
+		struct dict_avp_data data = {
+			912,	/* Code */
+			10415,	/* Vendor */
+			"MBMS-Session-Repetition-Number",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* MBMS-Required-QoS */
+	{
+		struct dict_avp_data data = {
+			913,	/* Code */
+			10415,	/* Vendor */
+			"MBMS-Required-QoS",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, UTF8String_type, NULL);
+	};
+
+	/* MBMS-Counting-Information */
+	{
+		struct dict_avp_data data = {
+			914,	/* Code */
+			10415,	/* Vendor */
+			"MBMS-Counting-Information",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_INTEGER32	/* base type of data */
+		};
+		struct dict_object		*type;
+		struct dict_type_data	 tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(MBMS-Counting-Information)", NULL, NULL, NULL };
+		CHECK_dict_new(DICT_TYPE, &tdata, NULL, &type);
+		CHECK_dict_new(DICT_AVP, &data, type, NULL);
+	};
+
+	/* MBMS-User-Data-Mode-Indication */
+	{
+		struct dict_avp_data data = {
+			915,	/* Code */
+			10415,	/* Vendor */
+			"MBMS-User-Data-Mode-Indication",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_INTEGER32	/* base type of data */
+		};
+		struct dict_object		*type;
+		struct dict_type_data	 tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(MBMS-User-Data-Mode-Indication)", NULL, NULL, NULL };
+		CHECK_dict_new(DICT_TYPE, &tdata, NULL, &type);
+		CHECK_dict_new(DICT_AVP, &data, type, NULL);
+	};
+
+	/* MBMS-GGSN-Address */
+	{
+		struct dict_avp_data data = {
+			916,	/* Code */
+			10415,	/* Vendor */
+			"MBMS-GGSN-Address",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* MBMS-GGSN-IPv6-Address */
+	{
+		struct dict_avp_data data = {
+			917,	/* Code */
+			10415,	/* Vendor */
+			"MBMS-GGSN-IPv6-Address",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* MBMS-BMSC-SSM-IP-Address */
+	{
+		struct dict_avp_data data = {
+			918,	/* Code */
+			10415,	/* Vendor */
+			"MBMS-BMSC-SSM-IP-Address",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* MBMS-BMSC-SSM-IPv6-Address */
+	{
+		struct dict_avp_data data = {
+			919,	/* Code */
+			10415,	/* Vendor */
+			"MBMS-BMSC-SSM-IPv6-Address",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* MBMS-Flow-Identifier */
+	{
+		struct dict_avp_data data = {
+			920,	/* Code */
+			10415,	/* Vendor */
+			"MBMS-Flow-Identifier",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* CN-IP-Multicast-Distribution */
+	{
+		struct dict_avp_data data = {
+			921,	/* Code */
+			10415,	/* Vendor */
+			"CN-IP-Multicast-Distribution",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_INTEGER32	/* base type of data */
+		};
+		struct dict_object		*type;
+		struct dict_type_data	 tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(CN-IP-Multicast-Distribution)", NULL, NULL, NULL };
+		CHECK_dict_new(DICT_TYPE, &tdata, NULL, &type);
+		CHECK_dict_new(DICT_AVP, &data, type, NULL);
+	};
+
+	/* MBMS-HC-Indicator */
+	{
+		struct dict_avp_data data = {
+			922,	/* Code */
+			10415,	/* Vendor */
+			"MBMS-HC-Indicator",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_INTEGER32	/* base type of data */
+		};
+		struct dict_object		*type;
+		struct dict_type_data	 tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(MBMS-HC-Indicator)", NULL, NULL, NULL };
+		CHECK_dict_new(DICT_TYPE, &tdata, NULL, &type);
+		CHECK_dict_new(DICT_AVP, &data, type, NULL);
+	};
+
+	/* 3GPP 29.140-700 (7.0.0 2007.07.05)                           */
+	/* Served-User-Identity */
+	{
+		struct dict_avp_data data = {
+			1100,	/* Code */
+			10415,	/* Vendor */
+			"Served-User-Identity",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_GROUPED	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* reuses: MSISDN                                               */
+	/* VASP-ID */
+	{
+		struct dict_avp_data data = {
+			1101,	/* Code */
+			10415,	/* Vendor */
+			"VASP-ID",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, UTF8String_type, NULL);
+	};
+
+	/* VAS-ID */
+	{
+		struct dict_avp_data data = {
+			1102,	/* Code */
+			10415,	/* Vendor */
+			"VAS-ID",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, UTF8String_type, NULL);
+	};
+
+	/* Trigger-Event */
+	{
+		struct dict_avp_data data = {
+			1103,	/* Code */
+			10415,	/* Vendor */
+			"Trigger-Event",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_INTEGER32	/* base type of data */
+		};
+		struct dict_object		*type;
+		struct dict_type_data	 tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Trigger-Event)", NULL, NULL, NULL };
+		CHECK_dict_new(DICT_TYPE, &tdata, NULL, &type);
+		CHECK_dict_new(DICT_AVP, &data, type, NULL);
+	};
+
+	/* reuses: 3GPP-IMSI                                            */
+	/* Sender-Address */
+	{
+		struct dict_avp_data data = {
+			1104,	/* Code */
+			10415,	/* Vendor */
+			"Sender-Address",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, UTF8String_type, NULL);
+	};
+
+	/* Initial-Recipient-Address */
+	{
+		struct dict_avp_data data = {
+			1105,	/* Code */
+			10415,	/* Vendor */
+			"Initial-Recipient-Address",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_GROUPED	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* Result-Recipient-Address */
+	{
+		struct dict_avp_data data = {
+			1106,	/* Code */
+			10415,	/* Vendor */
+			"Result-Recipient-Address",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_GROUPED	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* conflicts with one in (more common) 32.329                   */
+	/* Sequence-Number-29.140 */
+	{
+		struct dict_avp_data data = {
+			1107,	/* Code */
+			10415,	/* Vendor */
+			"Sequence-Number-29.140",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_UNSIGNED32	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* conflicts with one in (more common) 32.299                   */
+	/* Recipient-Address-29.140 */
+	{
+		struct dict_avp_data data = {
+			1108,	/* Code */
+			10415,	/* Vendor */
+			"Recipient-Address-29.140",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, UTF8String_type, NULL);
+	};
+
+	/* Routeing-Address */
+	{
+		struct dict_avp_data data = {
+			1109,	/* Code */
+			10415,	/* Vendor */
+			"Routeing-Address",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, UTF8String_type, NULL);
+	};
+
+	/* Originating-Interface */
+	{
+		struct dict_avp_data data = {
+			1110,	/* Code */
+			10415,	/* Vendor */
+			"Originating-Interface",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_INTEGER32	/* base type of data */
+		};
+		struct dict_object		*type;
+		struct dict_type_data	 tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Originating-Interface)", NULL, NULL, NULL };
+		CHECK_dict_new(DICT_TYPE, &tdata, NULL, &type);
+		CHECK_dict_new(DICT_AVP, &data, type, NULL);
+	};
+
+	/* Delivery-Report */
+	{
+		struct dict_avp_data data = {
+			1111,	/* Code */
+			10415,	/* Vendor */
+			"Delivery-Report",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_INTEGER32	/* base type of data */
+		};
+		struct dict_object		*type;
+		struct dict_type_data	 tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Delivery-Report)", NULL, NULL, NULL };
+		CHECK_dict_new(DICT_TYPE, &tdata, NULL, &type);
+		CHECK_dict_new(DICT_AVP, &data, type, NULL);
+	};
+
+	/* Read-Reply */
+	{
+		struct dict_avp_data data = {
+			1112,	/* Code */
+			10415,	/* Vendor */
+			"Read-Reply",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_INTEGER32	/* base type of data */
+		};
+		struct dict_object		*type;
+		struct dict_type_data	 tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Read-Reply)", NULL, NULL, NULL };
+		CHECK_dict_new(DICT_TYPE, &tdata, NULL, &type);
+		CHECK_dict_new(DICT_AVP, &data, type, NULL);
+	};
+
+	/* Sender-Visibility */
+	{
+		struct dict_avp_data data = {
+			1113,	/* Code */
+			10415,	/* Vendor */
+			"Sender-Visibility",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_INTEGER32	/* base type of data */
+		};
+		struct dict_object		*type;
+		struct dict_type_data	 tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Sender-Visibility)", NULL, NULL, NULL };
+		CHECK_dict_new(DICT_TYPE, &tdata, NULL, &type);
+		CHECK_dict_new(DICT_AVP, &data, type, NULL);
+	};
+
+	/* Service-Key */
+	{
+		struct dict_avp_data data = {
+			1114,	/* Code */
+			10415,	/* Vendor */
+			"Service-Key",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, UTF8String_type, NULL);
+	};
+
+	/* Billing-Information */
+	{
+		struct dict_avp_data data = {
+			1115,	/* Code */
+			10415,	/* Vendor */
+			"Billing-Information",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, UTF8String_type, NULL);
+	};
+
+	/* conflicts with one in (more common) 32.299                   */
+	/* Status-29.140 */
+	{
+		struct dict_avp_data data = {
+			1116,	/* Code */
+			10415,	/* Vendor */
+			"Status-29.140",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_GROUPED	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* Status-Code */
+	{
+		struct dict_avp_data data = {
+			1117,	/* Code */
+			10415,	/* Vendor */
+			"Status-Code",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, UTF8String_type, NULL);
+	};
+
+	/* Status-Text */
+	{
+		struct dict_avp_data data = {
+			1118,	/* Code */
+			10415,	/* Vendor */
+			"Status-Text",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, UTF8String_type, NULL);
+	};
+
+	/* Routeing-Address-Resolution */
+	{
+		struct dict_avp_data data = {
+			1119,	/* Code */
+			10415,	/* Vendor */
+			"Routeing-Address-Resolution",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_INTEGER32	/* base type of data */
+		};
+		struct dict_object		*type;
+		struct dict_type_data	 tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Routeing-Address-Resolution)", NULL, NULL, NULL };
+		CHECK_dict_new(DICT_TYPE, &tdata, NULL, &type);
+		CHECK_dict_new(DICT_AVP, &data, type, NULL);
+	};
+
+	/* 3GPP 29.173-c00 (12.0.0 2013.03.13)                          */
+	/* LMSI */
+	{
+		struct dict_avp_data data = {
+			2400,	/* Code */
+			10415,	/* Vendor */
+			"LMSI",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* Serving-Node */
+	{
+		struct dict_avp_data data = {
+			2401,	/* Code */
+			10415,	/* Vendor */
+			"Serving-Node",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_GROUPED	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* MME-Name */
+	{
+		struct dict_avp_data data = {
+			2402,	/* Code */
+			10415,	/* Vendor */
+			"MME-Name",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, DiameterIdentity_type, NULL);
+	};
+
+	/* MSC-Number */
+	{
+		struct dict_avp_data data = {
+			2403,	/* Code */
+			10415,	/* Vendor */
+			"MSC-Number",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* LCS-Capabilities-Sets */
+	{
+		struct dict_avp_data data = {
+			2404,	/* Code */
+			10415,	/* Vendor */
+			"LCS-Capabilities-Sets",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_UNSIGNED32	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* GMLC-Address */
+	{
+		struct dict_avp_data data = {
+			2405,	/* Code */
+			10415,	/* Vendor */
+			"GMLC-Address",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, Address_type, NULL);
+	};
+
+	/* Additional-Serving-Node */
+	{
+		struct dict_avp_data data = {
+			2406,	/* Code */
+			10415,	/* Vendor */
+			"Additional-Serving-Node",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_GROUPED	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* PPR-Address */
+	{
+		struct dict_avp_data data = {
+			2407,	/* Code */
+			10415,	/* Vendor */
+			"PPR-Address",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, Address_type, NULL);
+	};
+
+	/* MME-Realm */
+	{
+		struct dict_avp_data data = {
+			2408,	/* Code */
+			10415,	/* Vendor */
+			"MME-Realm",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, DiameterIdentity_type, NULL);
+	};
+
+	/* SGSN-Name */
+	{
+		struct dict_avp_data data = {
+			2409,	/* Code */
+			10415,	/* Vendor */
+			"SGSN-Name",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, DiameterIdentity_type, NULL);
+	};
+
+	/* SGSN-Realm */
+	{
+		struct dict_avp_data data = {
+			2410,	/* Code */
+			10415,	/* Vendor */
+			"SGSN-Realm",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, DiameterIdentity_type, NULL);
+	};
+
+	/* 3GPP 29.210-670 (6.7.0 2006-12-18)                           */
+	/* PDP-Session-Operation */
+	{
+		struct dict_avp_data data = {
+			1015,	/* Code */
+			10415,	/* Vendor */
+			"PDP-Session-Operation",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_INTEGER32	/* base type of data */
+		};
+		struct dict_object		*type;
+		struct dict_type_data	 tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(PDP-Session-Operation)", NULL, NULL, NULL };
+		CHECK_dict_new(DICT_TYPE, &tdata, NULL, &type);
+		CHECK_dict_new(DICT_AVP, &data, type, NULL);
+	};
+
+	/* 3GPP 29.212-c00 (12.0.0 2013.03.15)                          */
+	/* Gx-specific                                                  */
+	/* ADC-Revalidation-Time */
+	{
+		struct dict_avp_data data = {
+			2801,	/* Code */
+			10415,	/* Vendor */
+			"ADC-Revalidation-Time",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, Time_type, NULL);
+	};
+
+	/* ADC-Rule-Install */
+	{
+		struct dict_avp_data data = {
+			1092,	/* Code */
+			10415,	/* Vendor */
+			"ADC-Rule-Install",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR,	/* Fixed flag values */
+			AVP_TYPE_GROUPED	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* ADC-Rule-Remove */
+	{
+		struct dict_avp_data data = {
+			1093,	/* Code */
+			10415,	/* Vendor */
+			"ADC-Rule-Remove",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR,	/* Fixed flag values */
+			AVP_TYPE_GROUPED	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* ADC-Rule-Definition */
+	{
+		struct dict_avp_data data = {
+			1094,	/* Code */
+			10415,	/* Vendor */
+			"ADC-Rule-Definition",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR,	/* Fixed flag values */
+			AVP_TYPE_GROUPED	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* ADC-Rule-Base-Name */
+	{
+		struct dict_avp_data data = {
+			1095,	/* Code */
+			10415,	/* Vendor */
+			"ADC-Rule-Base-Name",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, UTF8String_type, NULL);
+	};
+
+	/* ADC-Rule-Name */
+	{
+		struct dict_avp_data data = {
+			1096,	/* Code */
+			10415,	/* Vendor */
+			"ADC-Rule-Name",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* ADC-Rule-Report */
+	{
+		struct dict_avp_data data = {
+			1097,	/* Code */
+			10415,	/* Vendor */
+			"ADC-Rule-Report",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR,	/* Fixed flag values */
+			AVP_TYPE_GROUPED	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* Application-Detection-Information */
+	{
+		struct dict_avp_data data = {
+			1098,	/* Code */
+			10415,	/* Vendor */
+			"Application-Detection-Information",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR,	/* Fixed flag values */
+			AVP_TYPE_GROUPED	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* Access-Network-Charging-Identifier-Gx */
+	{
+		struct dict_avp_data data = {
+			1022,	/* Code */
+			10415,	/* Vendor */
+			"Access-Network-Charging-Identifier-Gx",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_GROUPED	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* Allocation-Retention-Priority */
+	{
+		struct dict_avp_data data = {
+			1034,	/* Code */
+			10415,	/* Vendor */
+			"Allocation-Retention-Priority",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR,	/* Fixed flag values */
+			AVP_TYPE_GROUPED	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* AN-GW-Address */
+	{
+		struct dict_avp_data data = {
+			1050,	/* Code */
+			10415,	/* Vendor */
+			"AN-GW-Address",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, Address_type, NULL);
+	};
+
+	/* APN-Aggregate-Max-Bitrate-DL */
+	{
+		struct dict_avp_data data = {
+			1040,	/* Code */
+			10415,	/* Vendor */
+			"APN-Aggregate-Max-Bitrate-DL",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR,	/* Fixed flag values */
+			AVP_TYPE_UNSIGNED32	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* APN-Aggregate-Max-Bitrate-UL */
+	{
+		struct dict_avp_data data = {
+			1041,	/* Code */
+			10415,	/* Vendor */
+			"APN-Aggregate-Max-Bitrate-UL",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR,	/* Fixed flag values */
+			AVP_TYPE_UNSIGNED32	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* Bearer-Control-Mode */
+	{
+		struct dict_avp_data data = {
+			1023,	/* Code */
+			10415,	/* Vendor */
+			"Bearer-Control-Mode",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_INTEGER32	/* base type of data */
+		};
+		struct dict_object		*type;
+		struct dict_type_data	 tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Bearer-Control-Mode)", NULL, NULL, NULL };
+		CHECK_dict_new(DICT_TYPE, &tdata, NULL, &type);
+		CHECK_dict_new(DICT_AVP, &data, type, NULL);
+	};
+
+	/* Bearer-Identifier */
+	{
+		struct dict_avp_data data = {
+			1020,	/* Code */
+			10415,	/* Vendor */
+			"Bearer-Identifier",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* Bearer-Operation */
+	{
+		struct dict_avp_data data = {
+			1021,	/* Code */
+			10415,	/* Vendor */
+			"Bearer-Operation",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_INTEGER32	/* base type of data */
+		};
+		struct dict_object		*type;
+		struct dict_type_data	 tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Bearer-Operation)", NULL, NULL, NULL };
+		CHECK_dict_new(DICT_TYPE, &tdata, NULL, &type);
+		CHECK_dict_new(DICT_AVP, &data, type, NULL);
+	};
+
+	/* Bearer-Usage */
+	{
+		struct dict_avp_data data = {
+			1000,	/* Code */
+			10415,	/* Vendor */
+			"Bearer-Usage",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_INTEGER32	/* base type of data */
+		};
+		struct dict_object		*type;
+		struct dict_type_data	 tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Bearer-Usage)", NULL, NULL, NULL };
+		CHECK_dict_new(DICT_TYPE, &tdata, NULL, &type);
+		CHECK_dict_new(DICT_AVP, &data, type, NULL);
+	};
+
+	/* Charging-Rule-Install */
+	{
+		struct dict_avp_data data = {
+			1001,	/* Code */
+			10415,	/* Vendor */
+			"Charging-Rule-Install",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_GROUPED	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* Charging-Rule-Remove */
+	{
+		struct dict_avp_data data = {
+			1002,	/* Code */
+			10415,	/* Vendor */
+			"Charging-Rule-Remove",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_GROUPED	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* Charging-Rule-Definition */
+	{
+		struct dict_avp_data data = {
+			1003,	/* Code */
+			10415,	/* Vendor */
+			"Charging-Rule-Definition",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_GROUPED	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* Charging-Rule-Base-Name */
+	{
+		struct dict_avp_data data = {
+			1004,	/* Code */
+			10415,	/* Vendor */
+			"Charging-Rule-Base-Name",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, UTF8String_type, NULL);
+	};
+
+	/* Charging-Rule-Name */
+	{
+		struct dict_avp_data data = {
+			1005,	/* Code */
+			10415,	/* Vendor */
+			"Charging-Rule-Name",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* Charging-Rule-Report */
+	{
+		struct dict_avp_data data = {
+			1018,	/* Code */
+			10415,	/* Vendor */
+			"Charging-Rule-Report",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_GROUPED	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* Charging-Correlation-Indicator */
+	{
+		struct dict_avp_data data = {
+			1073,	/* Code */
+			10415,	/* Vendor */
+			"Charging-Correlation-Indicator",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR,	/* Fixed flag values */
+			AVP_TYPE_INTEGER32	/* base type of data */
+		};
+		struct dict_object		*type;
+		struct dict_type_data	 tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Charging-Correlation-Indicator)", NULL, NULL, NULL };
+		CHECK_dict_new(DICT_TYPE, &tdata, NULL, &type);
+		CHECK_dict_new(DICT_AVP, &data, type, NULL);
+	};
+
+	/* CoA-IP-Address */
+	{
+		struct dict_avp_data data = {
+			1035,	/* Code */
+			10415,	/* Vendor */
+			"CoA-IP-Address",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, Address_type, NULL);
+	};
+
+	/* CoA-Information */
+	{
+		struct dict_avp_data data = {
+			1039,	/* Code */
+			10415,	/* Vendor */
+			"CoA-Information",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR,	/* Fixed flag values */
+			AVP_TYPE_GROUPED	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* CSG-Information-Reporting */
+	{
+		struct dict_avp_data data = {
+			1071,	/* Code */
+			10415,	/* Vendor */
+			"CSG-Information-Reporting",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR,	/* Fixed flag values */
+			AVP_TYPE_INTEGER32	/* base type of data */
+		};
+		struct dict_object		*type;
+		struct dict_type_data	 tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(CSG-Information-Reporting)", NULL, NULL, NULL };
+		CHECK_dict_new(DICT_TYPE, &tdata, NULL, &type);
+		CHECK_dict_new(DICT_AVP, &data, type, NULL);
+	};
+
+	/* Default-EPS-Bearer-QoS */
+	{
+		struct dict_avp_data data = {
+			1049,	/* Code */
+			10415,	/* Vendor */
+			"Default-EPS-Bearer-QoS",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR,	/* Fixed flag values */
+			AVP_TYPE_GROUPED	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* Event-Report-Indication */
+	{
+		struct dict_avp_data data = {
+			1033,	/* Code */
+			10415,	/* Vendor */
+			"Event-Report-Indication",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR,	/* Fixed flag values */
+			AVP_TYPE_GROUPED	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* Event-Trigger */
+	{
+		struct dict_avp_data data = {
+			1006,	/* Code */
+			10415,	/* Vendor */
+			"Event-Trigger",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_INTEGER32	/* base type of data */
+		};
+		struct dict_object		*type;
+		struct dict_type_data	 tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Event-Trigger)", NULL, NULL, NULL };
+		CHECK_dict_new(DICT_TYPE, &tdata, NULL, &type);
+		CHECK_dict_new(DICT_AVP, &data, type, NULL);
+	};
+
+	/* Flow-Direction */
+	{
+		struct dict_avp_data data = {
+			1080,	/* Code */
+			10415,	/* Vendor */
+			"Flow-Direction",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR,	/* Fixed flag values */
+			AVP_TYPE_INTEGER32	/* base type of data */
+		};
+		struct dict_object		*type;
+		struct dict_type_data	 tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Flow-Direction)", NULL, NULL, NULL };
+		CHECK_dict_new(DICT_TYPE, &tdata, NULL, &type);
+		CHECK_dict_new(DICT_AVP, &data, type, NULL);
+	};
+
+	/* Flow-Information */
+	{
+		struct dict_avp_data data = {
+			1058,	/* Code */
+			10415,	/* Vendor */
+			"Flow-Information",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR,	/* Fixed flag values */
+			AVP_TYPE_GROUPED	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* Flow-Label */
+	{
+		struct dict_avp_data data = {
+			1057,	/* Code */
+			10415,	/* Vendor */
+			"Flow-Label",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* IP-CAN-Type */
+	{
+		struct dict_avp_data data = {
+			1027,	/* Code */
+			10415,	/* Vendor */
+			"IP-CAN-Type",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_INTEGER32	/* base type of data */
+		};
+		struct dict_object		*type;
+		struct dict_type_data	 tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(IP-CAN-Type)", NULL, NULL, NULL };
+		CHECK_dict_new(DICT_TYPE, &tdata, NULL, &type);
+		CHECK_dict_new(DICT_AVP, &data, type, NULL);
+	};
+
+	/* Guaranteed-Bitrate-DL */
+	{
+		struct dict_avp_data data = {
+			1025,	/* Code */
+			10415,	/* Vendor */
+			"Guaranteed-Bitrate-DL",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_UNSIGNED32	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* Guaranteed-Bitrate-UL */
+	{
+		struct dict_avp_data data = {
+			1026,	/* Code */
+			10415,	/* Vendor */
+			"Guaranteed-Bitrate-UL",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_UNSIGNED32	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* HeNB-Local-IP-Address */
+	{
+		struct dict_avp_data data = {
+			2804,	/* Code */
+			10415,	/* Vendor */
+			"HeNB-Local-IP-Address",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, Address_type, NULL);
+	};
+
+	/* Metering-Method */
+	{
+		struct dict_avp_data data = {
+			1007,	/* Code */
+			10415,	/* Vendor */
+			"Metering-Method",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_INTEGER32	/* base type of data */
+		};
+		struct dict_object		*type;
+		struct dict_type_data	 tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Metering-Method)", NULL, NULL, NULL };
+		CHECK_dict_new(DICT_TYPE, &tdata, NULL, &type);
+		CHECK_dict_new(DICT_AVP, &data, type, NULL);
+	};
+
+	/* Monitoring-Key */
+	{
+		struct dict_avp_data data = {
+			1066,	/* Code */
+			10415,	/* Vendor */
+			"Monitoring-Key",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* Mute-Notification */
+	{
+		struct dict_avp_data data = {
+			2809,	/* Code */
+			10415,	/* Vendor */
+			"Mute-Notification",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR,	/* Fixed flag values */
+			AVP_TYPE_INTEGER32	/* base type of data */
+		};
+		struct dict_object		*type;
+		struct dict_type_data	 tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Mute-Notification)", NULL, NULL, NULL };
+		CHECK_dict_new(DICT_TYPE, &tdata, NULL, &type);
+		CHECK_dict_new(DICT_AVP, &data, type, NULL);
+	};
+
+	/* Monitoring-Time */
+	{
+		struct dict_avp_data data = {
+			2810,	/* Code */
+			10415,	/* Vendor */
+			"Monitoring-Time",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, Time_type, NULL);
+	};
+
+	/* Network-Request-Support */
+	{
+		struct dict_avp_data data = {
+			1024,	/* Code */
+			10415,	/* Vendor */
+			"Network-Request-Support",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_INTEGER32	/* base type of data */
+		};
+		struct dict_object		*type;
+		struct dict_type_data	 tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Network-Request-Support)", NULL, NULL, NULL };
+		CHECK_dict_new(DICT_TYPE, &tdata, NULL, &type);
+		CHECK_dict_new(DICT_AVP, &data, type, NULL);
+	};
+
+	/* Offline */
+	{
+		struct dict_avp_data data = {
+			1008,	/* Code */
+			10415,	/* Vendor */
+			"Offline",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_INTEGER32	/* base type of data */
+		};
+		struct dict_object		*type;
+		struct dict_type_data	 tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Offline)", NULL, NULL, NULL };
+		CHECK_dict_new(DICT_TYPE, &tdata, NULL, &type);
+		CHECK_dict_new(DICT_AVP, &data, type, NULL);
+	};
+
+	/* Online */
+	{
+		struct dict_avp_data data = {
+			1009,	/* Code */
+			10415,	/* Vendor */
+			"Online",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_INTEGER32	/* base type of data */
+		};
+		struct dict_object		*type;
+		struct dict_type_data	 tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Online)", NULL, NULL, NULL };
+		CHECK_dict_new(DICT_TYPE, &tdata, NULL, &type);
+		CHECK_dict_new(DICT_AVP, &data, type, NULL);
+	};
+
+	/* Packet-Filter-Content */
+	{
+		struct dict_avp_data data = {
+			1059,	/* Code */
+			10415,	/* Vendor */
+			"Packet-Filter-Content",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, IPFilterRule_type, NULL);
+	};
+
+	/* Packet-Filter-Identifier */
+	{
+		struct dict_avp_data data = {
+			1060,	/* Code */
+			10415,	/* Vendor */
+			"Packet-Filter-Identifier",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* Packet-Filter-Information */
+	{
+		struct dict_avp_data data = {
+			1061,	/* Code */
+			10415,	/* Vendor */
+			"Packet-Filter-Information",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR,	/* Fixed flag values */
+			AVP_TYPE_GROUPED	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* Packet-Filter-Operation */
+	{
+		struct dict_avp_data data = {
+			1062,	/* Code */
+			10415,	/* Vendor */
+			"Packet-Filter-Operation",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR,	/* Fixed flag values */
+			AVP_TYPE_INTEGER32	/* base type of data */
+		};
+		struct dict_object		*type;
+		struct dict_type_data	 tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Packet-Filter-Operation)", NULL, NULL, NULL };
+		CHECK_dict_new(DICT_TYPE, &tdata, NULL, &type);
+		CHECK_dict_new(DICT_AVP, &data, type, NULL);
+	};
+
+	/* Packet-Filter-Usage */
+	{
+		struct dict_avp_data data = {
+			1072,	/* Code */
+			10415,	/* Vendor */
+			"Packet-Filter-Usage",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR,	/* Fixed flag values */
+			AVP_TYPE_INTEGER32	/* base type of data */
+		};
+		struct dict_object		*type;
+		struct dict_type_data	 tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Packet-Filter-Usage)", NULL, NULL, NULL };
+		CHECK_dict_new(DICT_TYPE, &tdata, NULL, &type);
+		CHECK_dict_new(DICT_AVP, &data, type, NULL);
+	};
+
+	/* PDN-Connection-ID */
+	{
+		struct dict_avp_data data = {
+			1065,	/* Code */
+			10415,	/* Vendor */
+			"PDN-Connection-ID",	/* Name */
+			AVP_FLAG_VENDOR,	/* Fixed flags */
+			AVP_FLAG_VENDOR,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* Precedence */
+	{
+		struct dict_avp_data data = {
+			1010,	/* Code */
+			10415,	/* Vendor */
+			"Precedence",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_UNSIGNED32	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* Pre-emption-Capability */
+	{
+		struct dict_avp_data data = {
+			1047,	/* Code */
+			10415,	/* Vendor */
+			"Pre-emption-Capability",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR,	/* Fixed flag values */
+			AVP_TYPE_INTEGER32	/* base type of data */
+		};
+		struct dict_object		*type;
+		struct dict_type_data	 tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Pre-emption-Capability)", NULL, NULL, NULL };
+		CHECK_dict_new(DICT_TYPE, &tdata, NULL, &type);
+		CHECK_dict_new(DICT_AVP, &data, type, NULL);
+	};
+
+	/* Pre-emption-Vulnerability */
+	{
+		struct dict_avp_data data = {
+			1048,	/* Code */
+			10415,	/* Vendor */
+			"Pre-emption-Vulnerability",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR,	/* Fixed flag values */
+			AVP_TYPE_INTEGER32	/* base type of data */
+		};
+		struct dict_object		*type;
+		struct dict_type_data	 tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Pre-emption-Vulnerability)", NULL, NULL, NULL };
+		CHECK_dict_new(DICT_TYPE, &tdata, NULL, &type);
+		CHECK_dict_new(DICT_AVP, &data, type, NULL);
+	};
+
+	/* Priority-Level */
+	{
+		struct dict_avp_data data = {
+			1046,	/* Code */
+			10415,	/* Vendor */
+			"Priority-Level",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR,	/* Fixed flag values */
+			AVP_TYPE_UNSIGNED32	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* Redirect-Information */
+	{
+		struct dict_avp_data data = {
+			1085,	/* Code */
+			10415,	/* Vendor */
+			"Redirect-Information",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR,	/* Fixed flag values */
+			AVP_TYPE_GROUPED	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* Redirect-Support */
+	{
+		struct dict_avp_data data = {
+			1086,	/* Code */
+			10415,	/* Vendor */
+			"Redirect-Support",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR,	/* Fixed flag values */
+			AVP_TYPE_INTEGER32	/* base type of data */
+		};
+		struct dict_object		*type;
+		struct dict_type_data	 tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Redirect-Support)", NULL, NULL, NULL };
+		CHECK_dict_new(DICT_TYPE, &tdata, NULL, &type);
+		CHECK_dict_new(DICT_AVP, &data, type, NULL);
+	};
+
+	/* Reporting-Level */
+	{
+		struct dict_avp_data data = {
+			1011,	/* Code */
+			10415,	/* Vendor */
+			"Reporting-Level",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_INTEGER32	/* base type of data */
+		};
+		struct dict_object		*type;
+		struct dict_type_data	 tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Reporting-Level)", NULL, NULL, NULL };
+		CHECK_dict_new(DICT_TYPE, &tdata, NULL, &type);
+		CHECK_dict_new(DICT_AVP, &data, type, NULL);
+	};
+
+	/* Routing-Filter */
+	{
+		struct dict_avp_data data = {
+			1078,	/* Code */
+			10415,	/* Vendor */
+			"Routing-Filter",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR,	/* Fixed flag values */
+			AVP_TYPE_GROUPED	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* Routing-IP-Address */
+	{
+		struct dict_avp_data data = {
+			1079,	/* Code */
+			10415,	/* Vendor */
+			"Routing-IP-Address",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, Address_type, NULL);
+	};
+
+	/* Routing-Rule-Definition */
+	{
+		struct dict_avp_data data = {
+			1076,	/* Code */
+			10415,	/* Vendor */
+			"Routing-Rule-Definition",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR,	/* Fixed flag values */
+			AVP_TYPE_GROUPED	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* Routing-Rule-Identifier */
+	{
+		struct dict_avp_data data = {
+			1077,	/* Code */
+			10415,	/* Vendor */
+			"Routing-Rule-Identifier",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* Routing-Rule-Install */
+	{
+		struct dict_avp_data data = {
+			1081,	/* Code */
+			10415,	/* Vendor */
+			"Routing-Rule-Install",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR,	/* Fixed flag values */
+			AVP_TYPE_GROUPED	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* Routing-Rule-Remove */
+	{
+		struct dict_avp_data data = {
+			1075,	/* Code */
+			10415,	/* Vendor */
+			"Routing-Rule-Remove",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR,	/* Fixed flag values */
+			AVP_TYPE_GROUPED	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* PCC-Rule-Status */
+	{
+		struct dict_avp_data data = {
+			1019,	/* Code */
+			10415,	/* Vendor */
+			"PCC-Rule-Status",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_INTEGER32	/* base type of data */
+		};
+		struct dict_object		*type;
+		struct dict_type_data	 tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(PCC-Rule-Status)", NULL, NULL, NULL };
+		CHECK_dict_new(DICT_TYPE, &tdata, NULL, &type);
+		CHECK_dict_new(DICT_AVP, &data, type, NULL);
+	};
+
+	/* Session-Release-Cause */
+	{
+		struct dict_avp_data data = {
+			1045,	/* Code */
+			10415,	/* Vendor */
+			"Session-Release-Cause",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_INTEGER32	/* base type of data */
+		};
+		struct dict_object		*type;
+		struct dict_type_data	 tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Session-Release-Cause)", NULL, NULL, NULL };
+		CHECK_dict_new(DICT_TYPE, &tdata, NULL, &type);
+		CHECK_dict_new(DICT_AVP, &data, type, NULL);
+	};
+
+	/* TDF-Information */
+	{
+		struct dict_avp_data data = {
+			1087,	/* Code */
+			10415,	/* Vendor */
+			"TDF-Information",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR,	/* Fixed flag values */
+			AVP_TYPE_GROUPED	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* TDF-Application-Identifier */
+	{
+		struct dict_avp_data data = {
+			1088,	/* Code */
+			10415,	/* Vendor */
+			"TDF-Application-Identifier",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* TDF-Application-Instance-Identifier */
+	{
+		struct dict_avp_data data = {
+			2802,	/* Code */
+			10415,	/* Vendor */
+			"TDF-Application-Instance-Identifier",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* TDF-Destination-Host */
+	{
+		struct dict_avp_data data = {
+			1089,	/* Code */
+			10415,	/* Vendor */
+			"TDF-Destination-Host",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, DiameterIdentity_type, NULL);
+	};
+
+	/* TDF-Destination-Realm */
+	{
+		struct dict_avp_data data = {
+			1090,	/* Code */
+			10415,	/* Vendor */
+			"TDF-Destination-Realm",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, DiameterIdentity_type, NULL);
+	};
+
+	/* TDF-IP-Address */
+	{
+		struct dict_avp_data data = {
+			1091,	/* Code */
+			10415,	/* Vendor */
+			"TDF-IP-Address",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, Address_type, NULL);
+	};
+
+	/* QoS-Class-Identifier */
+	{
+		struct dict_avp_data data = {
+			1028,	/* Code */
+			10415,	/* Vendor */
+			"QoS-Class-Identifier",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_INTEGER32	/* base type of data */
+		};
+		struct dict_object		*type;
+		struct dict_type_data	 tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(QoS-Class-Identifier)", NULL, NULL, NULL };
+		CHECK_dict_new(DICT_TYPE, &tdata, NULL, &type);
+		CHECK_dict_new(DICT_AVP, &data, type, NULL);
+	};
+
+	/* QoS-Information */
+	{
+		struct dict_avp_data data = {
+			1016,	/* Code */
+			10415,	/* Vendor */
+			"QoS-Information",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_GROUPED	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* QoS-Negotiation */
+	{
+		struct dict_avp_data data = {
+			1029,	/* Code */
+			10415,	/* Vendor */
+			"QoS-Negotiation",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_INTEGER32	/* base type of data */
+		};
+		struct dict_object		*type;
+		struct dict_type_data	 tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(QoS-Negotiation)", NULL, NULL, NULL };
+		CHECK_dict_new(DICT_TYPE, &tdata, NULL, &type);
+		CHECK_dict_new(DICT_AVP, &data, type, NULL);
+	};
+
+	/* QoS-Upgrade */
+	{
+		struct dict_avp_data data = {
+			1030,	/* Code */
+			10415,	/* Vendor */
+			"QoS-Upgrade",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_INTEGER32	/* base type of data */
+		};
+		struct dict_object		*type;
+		struct dict_type_data	 tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(QoS-Upgrade)", NULL, NULL, NULL };
+		CHECK_dict_new(DICT_TYPE, &tdata, NULL, &type);
+		CHECK_dict_new(DICT_AVP, &data, type, NULL);
+	};
+
+	/* PS-to-CS-Session-Continuity */
+	{
+		struct dict_avp_data data = {
+			1099,	/* Code */
+			10415,	/* Vendor */
+			"PS-to-CS-Session-Continuity",	/* Name */
+			AVP_FLAG_VENDOR,	/* Fixed flags */
+			AVP_FLAG_VENDOR,	/* Fixed flag values */
+			AVP_TYPE_INTEGER32	/* base type of data */
+		};
+		struct dict_object		*type;
+		struct dict_type_data	 tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(PS-to-CS-Session-Continuity)", NULL, NULL, NULL };
+		CHECK_dict_new(DICT_TYPE, &tdata, NULL, &type);
+		CHECK_dict_new(DICT_AVP, &data, type, NULL);
+	};
+
+	/* Resource-Allocation-Notification */
+	{
+		struct dict_avp_data data = {
+			1063,	/* Code */
+			10415,	/* Vendor */
+			"Resource-Allocation-Notification",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR,	/* Fixed flag values */
+			AVP_TYPE_INTEGER32	/* base type of data */
+		};
+		struct dict_object		*type;
+		struct dict_type_data	 tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Resource-Allocation-Notification)", NULL, NULL, NULL };
+		CHECK_dict_new(DICT_TYPE, &tdata, NULL, &type);
+		CHECK_dict_new(DICT_AVP, &data, type, NULL);
+	};
+
+	/* Rule-Failure-Code */
+	{
+		struct dict_avp_data data = {
+			1031,	/* Code */
+			10415,	/* Vendor */
+			"Rule-Failure-Code",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_INTEGER32	/* base type of data */
+		};
+		struct dict_object		*type;
+		struct dict_type_data	 tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Rule-Failure-Code)", NULL, NULL, NULL };
+		CHECK_dict_new(DICT_TYPE, &tdata, NULL, &type);
+		CHECK_dict_new(DICT_AVP, &data, type, NULL);
+	};
+
+	/* Security-Parameter-Index */
+	{
+		struct dict_avp_data data = {
+			1056,	/* Code */
+			10415,	/* Vendor */
+			"Security-Parameter-Index",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* TFT-Filter */
+	{
+		struct dict_avp_data data = {
+			1012,	/* Code */
+			10415,	/* Vendor */
+			"TFT-Filter",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, IPFilterRule_type, NULL);
+	};
+
+	/* TFT-Packet-Filter-Information */
+	{
+		struct dict_avp_data data = {
+			1013,	/* Code */
+			10415,	/* Vendor */
+			"TFT-Packet-Filter-Information",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_GROUPED	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* ToS-Traffic-Class */
+	{
+		struct dict_avp_data data = {
+			1014,	/* Code */
+			10415,	/* Vendor */
+			"ToS-Traffic-Class",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* Tunnel-Header-Filter */
+	{
+		struct dict_avp_data data = {
+			1036,	/* Code */
+			10415,	/* Vendor */
+			"Tunnel-Header-Filter",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, IPFilterRule_type, NULL);
+	};
+
+	/* Tunnel-Header-Length */
+	{
+		struct dict_avp_data data = {
+			1037,	/* Code */
+			10415,	/* Vendor */
+			"Tunnel-Header-Length",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR,	/* Fixed flag values */
+			AVP_TYPE_UNSIGNED32	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* Tunnel-Information */
+	{
+		struct dict_avp_data data = {
+			1038,	/* Code */
+			10415,	/* Vendor */
+			"Tunnel-Information",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR,	/* Fixed flag values */
+			AVP_TYPE_GROUPED	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* RAT-Type */
+	{
+		struct dict_avp_data data = {
+			1032,	/* Code */
+			10415,	/* Vendor */
+			"RAT-Type",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR,	/* Fixed flag values */
+			AVP_TYPE_INTEGER32	/* base type of data */
+		};
+		struct dict_object		*type;
+		struct dict_type_data	 tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(RAT-Type)", NULL, NULL, NULL };
+		CHECK_dict_new(DICT_TYPE, &tdata, NULL, &type);
+		CHECK_dict_new(DICT_AVP, &data, type, NULL);
+	};
+
+	/* Revalidation-Time */
+	{
+		struct dict_avp_data data = {
+			1042,	/* Code */
+			10415,	/* Vendor */
+			"Revalidation-Time",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, Time_type, NULL);
+	};
+
+	/* Rule-Activation-Time */
+	{
+		struct dict_avp_data data = {
+			1043,	/* Code */
+			10415,	/* Vendor */
+			"Rule-Activation-Time",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, Time_type, NULL);
+	};
+
+	/* UDP-Source-Port */
+	{
+		struct dict_avp_data data = {
+			2806,	/* Code */
+			10415,	/* Vendor */
+			"UDP-Source-Port",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR,	/* Fixed flag values */
+			AVP_TYPE_UNSIGNED32	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* UE-Local-IP-Address */
+	{
+		struct dict_avp_data data = {
+			2805,	/* Code */
+			10415,	/* Vendor */
+			"UE-Local-IP-Address",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, Address_type, NULL);
+	};
+
+	/* Usage-Monitoring-Information */
+	{
+		struct dict_avp_data data = {
+			1067,	/* Code */
+			10415,	/* Vendor */
+			"Usage-Monitoring-Information",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR,	/* Fixed flag values */
+			AVP_TYPE_GROUPED	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* Rule-Deactivation-Time */
+	{
+		struct dict_avp_data data = {
+			1044,	/* Code */
+			10415,	/* Vendor */
+			"Rule-Deactivation-Time",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, Time_type, NULL);
+	};
+
+	/* Usage-Monitoring-Level */
+	{
+		struct dict_avp_data data = {
+			1068,	/* Code */
+			10415,	/* Vendor */
+			"Usage-Monitoring-Level",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR,	/* Fixed flag values */
+			AVP_TYPE_INTEGER32	/* base type of data */
+		};
+		struct dict_object		*type;
+		struct dict_type_data	 tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Usage-Monitoring-Level)", NULL, NULL, NULL };
+		CHECK_dict_new(DICT_TYPE, &tdata, NULL, &type);
+		CHECK_dict_new(DICT_AVP, &data, type, NULL);
+	};
+
+	/* Usage-Monitoring-Report */
+	{
+		struct dict_avp_data data = {
+			1069,	/* Code */
+			10415,	/* Vendor */
+			"Usage-Monitoring-Report",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR,	/* Fixed flag values */
+			AVP_TYPE_INTEGER32	/* base type of data */
+		};
+		struct dict_object		*type;
+		struct dict_type_data	 tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Usage-Monitoring-Report)", NULL, NULL, NULL };
+		CHECK_dict_new(DICT_TYPE, &tdata, NULL, &type);
+		CHECK_dict_new(DICT_AVP, &data, type, NULL);
+	};
+
+	/* Usage-Monitoring-Support */
+	{
+		struct dict_avp_data data = {
+			1070,	/* Code */
+			10415,	/* Vendor */
+			"Usage-Monitoring-Support",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR,	/* Fixed flag values */
+			AVP_TYPE_INTEGER32	/* base type of data */
+		};
+		struct dict_object		*type;
+		struct dict_type_data	 tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Usage-Monitoring-Support)", NULL, NULL, NULL };
+		CHECK_dict_new(DICT_TYPE, &tdata, NULL, &type);
+		CHECK_dict_new(DICT_AVP, &data, type, NULL);
+	};
+
+	/* Gxx-specific                                                 */
+	/* QoS-Rule-Install */
+	{
+		struct dict_avp_data data = {
+			1051,	/* Code */
+			10415,	/* Vendor */
+			"QoS-Rule-Install",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_GROUPED	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* QoS-Rule-Remove */
+	{
+		struct dict_avp_data data = {
+			1052,	/* Code */
+			10415,	/* Vendor */
+			"QoS-Rule-Remove",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_GROUPED	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* QoS-Rule-Definition */
+	{
+		struct dict_avp_data data = {
+			1053,	/* Code */
+			10415,	/* Vendor */
+			"QoS-Rule-Definition",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_GROUPED	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* QoS-Rule-Name */
+	{
+		struct dict_avp_data data = {
+			1054,	/* Code */
+			10415,	/* Vendor */
+			"QoS-Rule-Name",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* QoS-Rule-Base-Name */
+	{
+		struct dict_avp_data data = {
+			1074,	/* Code */
+			10415,	/* Vendor */
+			"QoS-Rule-Base-Name",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, UTF8String_type, NULL);
+	};
+
+	/* QoS-Rule-Report */
+	{
+		struct dict_avp_data data = {
+			1055,	/* Code */
+			10415,	/* Vendor */
+			"QoS-Rule-Report",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_GROUPED	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* Session-Linking-Indicator */
+	{
+		struct dict_avp_data data = {
+			1064,	/* Code */
+			10415,	/* Vendor */
+			"Session-Linking-Indicator",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_INTEGER32	/* base type of data */
+		};
+		struct dict_object		*type;
+		struct dict_type_data	 tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Session-Linking-Indicator)", NULL, NULL, NULL };
+		CHECK_dict_new(DICT_TYPE, &tdata, NULL, &type);
+		CHECK_dict_new(DICT_AVP, &data, type, NULL);
+	};
+
+	/* S15-specific                                                 */
+	/* CS-Service-Qos-Request-Identifier */
+	{
+		struct dict_avp_data data = {
+			2807,	/* Code */
+			10415,	/* Vendor */
+			"CS-Service-Qos-Request-Identifier",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* CS-Service-QoS-Request-Operation */
+	{
+		struct dict_avp_data data = {
+			2808,	/* Code */
+			10415,	/* Vendor */
+			"CS-Service-QoS-Request-Operation",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_INTEGER32	/* base type of data */
+		};
+		struct dict_object		*type;
+		struct dict_type_data	 tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(CS-Service-QoS-Request-Operation)", NULL, NULL, NULL };
+		CHECK_dict_new(DICT_TYPE, &tdata, NULL, &type);
+		CHECK_dict_new(DICT_AVP, &data, type, NULL);
+	};
+
+	/* 3GPP 29.214-b80 (11.8.0 2013.03.15)                          */
+	/* Abort-Cause */
+	{
+		struct dict_avp_data data = {
+			500,	/* Code */
+			10415,	/* Vendor */
+			"Abort-Cause",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_INTEGER32	/* base type of data */
+		};
+		struct dict_object		*type;
+		struct dict_type_data	 tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Abort-Cause)", NULL, NULL, NULL };
+		CHECK_dict_new(DICT_TYPE, &tdata, NULL, &type);
+		CHECK_dict_new(DICT_AVP, &data, type, NULL);
+	};
+
+	/* Access-Network-Charging-Address */
+	{
+		struct dict_avp_data data = {
+			501,	/* Code */
+			10415,	/* Vendor */
+			"Access-Network-Charging-Address",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, Address_type, NULL);
+	};
+
+	/* Access-Network-Charging-Identifier */
+	{
+		struct dict_avp_data data = {
+			502,	/* Code */
+			10415,	/* Vendor */
+			"Access-Network-Charging-Identifier",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_GROUPED	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* Access-Network-Charging-Identifier-Value */
+	{
+		struct dict_avp_data data = {
+			503,	/* Code */
+			10415,	/* Vendor */
+			"Access-Network-Charging-Identifier-Value",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* Acceptable-Service-Info */
+	{
+		struct dict_avp_data data = {
+			526,	/* Code */
+			10415,	/* Vendor */
+			"Acceptable-Service-Info",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_GROUPED	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* AF-Application-Identifier */
+	{
+		struct dict_avp_data data = {
+			504,	/* Code */
+			10415,	/* Vendor */
+			"AF-Application-Identifier",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* AF-Charging-Identifier */
+	{
+		struct dict_avp_data data = {
+			505,	/* Code */
+			10415,	/* Vendor */
+			"AF-Charging-Identifier",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* Application-Service-Provider-Identity */
+	{
+		struct dict_avp_data data = {
+			532,	/* Code */
+			10415,	/* Vendor */
+			"Application-Service-Provider-Identity",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, UTF8String_type, NULL);
+	};
+
+	/* Codec-Data */
+	{
+		struct dict_avp_data data = {
+			524,	/* Code */
+			10415,	/* Vendor */
+			"Codec-Data",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* Flow-Description */
+	{
+		struct dict_avp_data data = {
+			507,	/* Code */
+			10415,	/* Vendor */
+			"Flow-Description",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, IPFilterRule_type, NULL);
+	};
+
+	/* Flow-Number */
+	{
+		struct dict_avp_data data = {
+			509,	/* Code */
+			10415,	/* Vendor */
+			"Flow-Number",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_UNSIGNED32	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* Flows */
+	{
+		struct dict_avp_data data = {
+			510,	/* Code */
+			10415,	/* Vendor */
+			"Flows",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_GROUPED	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* Flow-Status */
+	{
+		struct dict_avp_data data = {
+			511,	/* Code */
+			10415,	/* Vendor */
+			"Flow-Status",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_INTEGER32	/* base type of data */
+		};
+		struct dict_object		*type;
+		struct dict_type_data	 tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Flow-Status)", NULL, NULL, NULL };
+		CHECK_dict_new(DICT_TYPE, &tdata, NULL, &type);
+		CHECK_dict_new(DICT_AVP, &data, type, NULL);
+	};
+
+	/* Flow-Usage */
+	{
+		struct dict_avp_data data = {
+			512,	/* Code */
+			10415,	/* Vendor */
+			"Flow-Usage",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_INTEGER32	/* base type of data */
+		};
+		struct dict_object		*type;
+		struct dict_type_data	 tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Flow-Usage)", NULL, NULL, NULL };
+		CHECK_dict_new(DICT_TYPE, &tdata, NULL, &type);
+		CHECK_dict_new(DICT_AVP, &data, type, NULL);
+	};
+
+	/* Service-URN */
+	{
+		struct dict_avp_data data = {
+			525,	/* Code */
+			10415,	/* Vendor */
+			"Service-URN",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* Specific-Action */
+	{
+		struct dict_avp_data data = {
+			513,	/* Code */
+			10415,	/* Vendor */
+			"Specific-Action",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_INTEGER32	/* base type of data */
+		};
+		struct dict_object		*type;
+		struct dict_type_data	 tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Specific-Action)", NULL, NULL, NULL };
+		CHECK_dict_new(DICT_TYPE, &tdata, NULL, &type);
+		CHECK_dict_new(DICT_AVP, &data, type, NULL);
+	};
+
+	/* Max-Requested-Bandwidth-DL */
+	{
+		struct dict_avp_data data = {
+			515,	/* Code */
+			10415,	/* Vendor */
+			"Max-Requested-Bandwidth-DL",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_UNSIGNED32	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* Max-Requested-Bandwidth-UL */
+	{
+		struct dict_avp_data data = {
+			516,	/* Code */
+			10415,	/* Vendor */
+			"Max-Requested-Bandwidth-UL",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_UNSIGNED32	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* Media-Component-Description */
+	{
+		struct dict_avp_data data = {
+			517,	/* Code */
+			10415,	/* Vendor */
+			"Media-Component-Description",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_GROUPED	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* Media-Component-Number */
+	{
+		struct dict_avp_data data = {
+			518,	/* Code */
+			10415,	/* Vendor */
+			"Media-Component-Number",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_UNSIGNED32	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* Media-Sub-Component */
+	{
+		struct dict_avp_data data = {
+			519,	/* Code */
+			10415,	/* Vendor */
+			"Media-Sub-Component",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_GROUPED	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* Media-Type */
+	{
+		struct dict_avp_data data = {
+			520,	/* Code */
+			10415,	/* Vendor */
+			"Media-Type",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_INTEGER32	/* base type of data */
+		};
+		struct dict_object		*type;
+		struct dict_type_data	 tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Media-Type)", NULL, NULL, NULL };
+		CHECK_dict_new(DICT_TYPE, &tdata, NULL, &type);
+		CHECK_dict_new(DICT_AVP, &data, type, NULL);
+	};
+
+	/* MPS-Identifier */
+	{
+		struct dict_avp_data data = {
+			528,	/* Code */
+			10415,	/* Vendor */
+			"MPS-Identifier",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* Min-Requested-Bandwidth-DL */
+	{
+		struct dict_avp_data data = {
+			534,	/* Code */
+			10415,	/* Vendor */
+			"Min-Requested-Bandwidth-DL",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR,	/* Fixed flag values */
+			AVP_TYPE_UNSIGNED32	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* Min-Requested-Bandwidth-UL */
+	{
+		struct dict_avp_data data = {
+			535,	/* Code */
+			10415,	/* Vendor */
+			"Min-Requested-Bandwidth-UL",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR,	/* Fixed flag values */
+			AVP_TYPE_UNSIGNED32	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* RR-Bandwidth */
+	{
+		struct dict_avp_data data = {
+			521,	/* Code */
+			10415,	/* Vendor */
+			"RR-Bandwidth",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_UNSIGNED32	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* RS-Bandwidth */
+	{
+		struct dict_avp_data data = {
+			522,	/* Code */
+			10415,	/* Vendor */
+			"RS-Bandwidth",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_UNSIGNED32	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* Service-Info-Status */
+	{
+		struct dict_avp_data data = {
+			527,	/* Code */
+			10415,	/* Vendor */
+			"Service-Info-Status",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_INTEGER32	/* base type of data */
+		};
+		struct dict_object		*type;
+		struct dict_type_data	 tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Service-Info-Status)", NULL, NULL, NULL };
+		CHECK_dict_new(DICT_TYPE, &tdata, NULL, &type);
+		CHECK_dict_new(DICT_AVP, &data, type, NULL);
+	};
+
+	/* SIP-Forking-Indication */
+	{
+		struct dict_avp_data data = {
+			523,	/* Code */
+			10415,	/* Vendor */
+			"SIP-Forking-Indication",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_INTEGER32	/* base type of data */
+		};
+		struct dict_object		*type;
+		struct dict_type_data	 tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(SIP-Forking-Indication)", NULL, NULL, NULL };
+		CHECK_dict_new(DICT_TYPE, &tdata, NULL, &type);
+		CHECK_dict_new(DICT_AVP, &data, type, NULL);
+	};
+
+	/* Sponsor-Identity */
+	{
+		struct dict_avp_data data = {
+			531,	/* Code */
+			10415,	/* Vendor */
+			"Sponsor-Identity",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, UTF8String_type, NULL);
+	};
+
+	/* Sponsored-Connectivity-Data */
+	{
+		struct dict_avp_data data = {
+			530,	/* Code */
+			10415,	/* Vendor */
+			"Sponsored-Connectivity-Data",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR,	/* Fixed flag values */
+			AVP_TYPE_GROUPED	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* AF-Signalling-Protocol */
+	{
+		struct dict_avp_data data = {
+			529,	/* Code */
+			10415,	/* Vendor */
+			"AF-Signalling-Protocol",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR,	/* Fixed flag values */
+			AVP_TYPE_INTEGER32	/* base type of data */
+		};
+		struct dict_object		*type;
+		struct dict_type_data	 tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(AF-Signalling-Protocol)", NULL, NULL, NULL };
+		CHECK_dict_new(DICT_TYPE, &tdata, NULL, &type);
+		CHECK_dict_new(DICT_AVP, &data, type, NULL);
+	};
+
+	/* Required-Access-Info */
+	{
+		struct dict_avp_data data = {
+			536,	/* Code */
+			10415,	/* Vendor */
+			"Required-Access-Info",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR,	/* Fixed flag values */
+			AVP_TYPE_INTEGER32	/* base type of data */
+		};
+		struct dict_object		*type;
+		struct dict_type_data	 tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Required-Access-Info)", NULL, NULL, NULL };
+		CHECK_dict_new(DICT_TYPE, &tdata, NULL, &type);
+		CHECK_dict_new(DICT_AVP, &data, type, NULL);
+	};
+
+	/* Rx-Request-Type */
+	{
+		struct dict_avp_data data = {
+			533,	/* Code */
+			10415,	/* Vendor */
+			"Rx-Request-Type",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR,	/* Fixed flag values */
+			AVP_TYPE_INTEGER32	/* base type of data */
+		};
+		struct dict_object		*type;
+		struct dict_type_data	 tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Rx-Request-Type)", NULL, NULL, NULL };
+		CHECK_dict_new(DICT_TYPE, &tdata, NULL, &type);
+		CHECK_dict_new(DICT_AVP, &data, type, NULL);
+	};
+
+	/* IP-Domain-Id */
+	{
+		struct dict_avp_data data = {
+			537,	/* Code */
+			10415,	/* Vendor */
+			"IP-Domain-Id",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* 3GPP 29.229-b20 (11.2.0 2012.12.21)                          */
+	/* Associated-Identities */
+	{
+		struct dict_avp_data data = {
+			632,	/* Code */
+			10415,	/* Vendor */
+			"Associated-Identities",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR,	/* Fixed flag values */
+			AVP_TYPE_GROUPED	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* Associated-Registered-Identities */
+	{
+		struct dict_avp_data data = {
+			647,	/* Code */
+			10415,	/* Vendor */
+			"Associated-Registered-Identities",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR,	/* Fixed flag values */
+			AVP_TYPE_GROUPED	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* Call-ID-SIP-Header */
+	{
+		struct dict_avp_data data = {
+			643,	/* Code */
+			10415,	/* Vendor */
+			"Call-ID-SIP-Header",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* Charging-Information */
+	{
+		struct dict_avp_data data = {
+			618,	/* Code */
+			10415,	/* Vendor */
+			"Charging-Information",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_GROUPED	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* Confidentiality-Key */
+	{
+		struct dict_avp_data data = {
+			625,	/* Code */
+			10415,	/* Vendor */
+			"Confidentiality-Key",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* Contact */
+	{
+		struct dict_avp_data data = {
+			641,	/* Code */
+			10415,	/* Vendor */
+			"Contact",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* Deregistration-Reason */
+	{
+		struct dict_avp_data data = {
+			615,	/* Code */
+			10415,	/* Vendor */
+			"Deregistration-Reason",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_GROUPED	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* Digest-Algorithm */
+	{
+		struct dict_avp_data data = {
+			111,	/* Code */
+			10415,	/* Vendor */
+			"Digest-Algorithm",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, UTF8String_type, NULL);
+	};
+
+	/* Digest-HA1 */
+	{
+		struct dict_avp_data data = {
+			121,	/* Code */
+			10415,	/* Vendor */
+			"Digest-HA1",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, UTF8String_type, NULL);
+	};
+
+	/* Digest-QoP */
+	{
+		struct dict_avp_data data = {
+			110,	/* Code */
+			10415,	/* Vendor */
+			"Digest-QoP",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, UTF8String_type, NULL);
+	};
+
+	/* Digest-Realm */
+	{
+		struct dict_avp_data data = {
+			104,	/* Code */
+			10415,	/* Vendor */
+			"Digest-Realm",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, UTF8String_type, NULL);
+	};
+
+	/* Feature-List */
+	{
+		struct dict_avp_data data = {
+			630,	/* Code */
+			10415,	/* Vendor */
+			"Feature-List",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR,	/* Fixed flag values */
+			AVP_TYPE_UNSIGNED32	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* Feature-List-ID */
+	{
+		struct dict_avp_data data = {
+			629,	/* Code */
+			10415,	/* Vendor */
+			"Feature-List-ID",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR,	/* Fixed flag values */
+			AVP_TYPE_UNSIGNED32	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* From-SIP-Header */
+	{
+		struct dict_avp_data data = {
+			644,	/* Code */
+			10415,	/* Vendor */
+			"From-SIP-Header",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* Identity-with-Emergency-Registration */
+	{
+		struct dict_avp_data data = {
+			651,	/* Code */
+			10415,	/* Vendor */
+			"Identity-with-Emergency-Registration",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR,	/* Fixed flag values */
+			AVP_TYPE_GROUPED	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* Integrity-Key */
+	{
+		struct dict_avp_data data = {
+			626,	/* Code */
+			10415,	/* Vendor */
+			"Integrity-Key",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* LIA-Flags */
+	{
+		struct dict_avp_data data = {
+			653,	/* Code */
+			10415,	/* Vendor */
+			"LIA-Flags",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR,	/* Fixed flag values */
+			AVP_TYPE_UNSIGNED32	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* Loose-Route-Indication */
+	{
+		struct dict_avp_data data = {
+			638,	/* Code */
+			10415,	/* Vendor */
+			"Loose-Route-Indication",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR,	/* Fixed flag values */
+			AVP_TYPE_INTEGER32	/* base type of data */
+		};
+		struct dict_object		*type;
+		struct dict_type_data	 tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Loose-Route-Indication)", NULL, NULL, NULL };
+		CHECK_dict_new(DICT_TYPE, &tdata, NULL, &type);
+		CHECK_dict_new(DICT_AVP, &data, type, NULL);
+	};
+
+	/* Mandatory-Capability */
+	{
+		struct dict_avp_data data = {
+			604,	/* Code */
+			10415,	/* Vendor */
+			"Mandatory-Capability",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_UNSIGNED32	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* Multiple-Registration-Indication */
+	{
+		struct dict_avp_data data = {
+			648,	/* Code */
+			10415,	/* Vendor */
+			"Multiple-Registration-Indication",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR,	/* Fixed flag values */
+			AVP_TYPE_INTEGER32	/* base type of data */
+		};
+		struct dict_object		*type;
+		struct dict_type_data	 tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Multiple-Registration-Indication)", NULL, NULL, NULL };
+		CHECK_dict_new(DICT_TYPE, &tdata, NULL, &type);
+		CHECK_dict_new(DICT_AVP, &data, type, NULL);
+	};
+
+	/* Optional-Capability */
+	{
+		struct dict_avp_data data = {
+			605,	/* Code */
+			10415,	/* Vendor */
+			"Optional-Capability",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_UNSIGNED32	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* Originating-Request */
+	{
+		struct dict_avp_data data = {
+			633,	/* Code */
+			10415,	/* Vendor */
+			"Originating-Request",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_INTEGER32	/* base type of data */
+		};
+		struct dict_object		*type;
+		struct dict_type_data	 tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Originating-Request)", NULL, NULL, NULL };
+		CHECK_dict_new(DICT_TYPE, &tdata, NULL, &type);
+		CHECK_dict_new(DICT_AVP, &data, type, NULL);
+	};
+
+	/* Path */
+	{
+		struct dict_avp_data data = {
+			640,	/* Code */
+			10415,	/* Vendor */
+			"Path",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* Primary-Charging-Collection-Function-Name */
+	{
+		struct dict_avp_data data = {
+			621,	/* Code */
+			10415,	/* Vendor */
+			"Primary-Charging-Collection-Function-Name",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, DiameterURI_type, NULL);
+	};
+
+	/* Primary-Event-Charging-Function-Name */
+	{
+		struct dict_avp_data data = {
+			619,	/* Code */
+			10415,	/* Vendor */
+			"Primary-Event-Charging-Function-Name",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, DiameterURI_type, NULL);
+	};
+
+	/* Priviledged-Sender-Indication */
+	{
+		struct dict_avp_data data = {
+			652,	/* Code */
+			10415,	/* Vendor */
+			"Priviledged-Sender-Indication",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR,	/* Fixed flag values */
+			AVP_TYPE_INTEGER32	/* base type of data */
+		};
+		struct dict_object		*type;
+		struct dict_type_data	 tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Priviledged-Sender-Indication)", NULL, NULL, NULL };
+		CHECK_dict_new(DICT_TYPE, &tdata, NULL, &type);
+		CHECK_dict_new(DICT_AVP, &data, type, NULL);
+	};
+
+	/* Public-Identity */
+	{
+		struct dict_avp_data data = {
+			601,	/* Code */
+			10415,	/* Vendor */
+			"Public-Identity",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, UTF8String_type, NULL);
+	};
+
+	/* Reason-Code */
+	{
+		struct dict_avp_data data = {
+			616,	/* Code */
+			10415,	/* Vendor */
+			"Reason-Code",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_INTEGER32	/* base type of data */
+		};
+		struct dict_object		*type;
+		struct dict_type_data	 tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Reason-Code)", NULL, NULL, NULL };
+		CHECK_dict_new(DICT_TYPE, &tdata, NULL, &type);
+		CHECK_dict_new(DICT_AVP, &data, type, NULL);
+	};
+
+	/* Reason-Info */
+	{
+		struct dict_avp_data data = {
+			617,	/* Code */
+			10415,	/* Vendor */
+			"Reason-Info",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, UTF8String_type, NULL);
+	};
+
+	/* Record-Route */
+	{
+		struct dict_avp_data data = {
+			646,	/* Code */
+			10415,	/* Vendor */
+			"Record-Route",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* Restoration-Info */
+	{
+		struct dict_avp_data data = {
+			649,	/* Code */
+			10415,	/* Vendor */
+			"Restoration-Info",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR,	/* Fixed flag values */
+			AVP_TYPE_GROUPED	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* SCSCF-Restoration-Info */
+	{
+		struct dict_avp_data data = {
+			639,	/* Code */
+			10415,	/* Vendor */
+			"SCSCF-Restoration-Info",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR,	/* Fixed flag values */
+			AVP_TYPE_GROUPED	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* SIP-Auth-Data-Item */
+	{
+		struct dict_avp_data data = {
+			612,	/* Code */
+			10415,	/* Vendor */
+			"SIP-Auth-Data-Item",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_GROUPED	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* SIP-Authenticate */
+	{
+		struct dict_avp_data data = {
+			609,	/* Code */
+			10415,	/* Vendor */
+			"SIP-Authenticate",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* SIP-Authentication-Context */
+	{
+		struct dict_avp_data data = {
+			611,	/* Code */
+			10415,	/* Vendor */
+			"SIP-Authentication-Context",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* SIP-Authentication-Scheme */
+	{
+		struct dict_avp_data data = {
+			608,	/* Code */
+			10415,	/* Vendor */
+			"SIP-Authentication-Scheme",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, UTF8String_type, NULL);
+	};
+
+	/* SIP-Authorization */
+	{
+		struct dict_avp_data data = {
+			610,	/* Code */
+			10415,	/* Vendor */
+			"SIP-Authorization",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* SIP-Digest-Authenticate */
+	{
+		struct dict_avp_data data = {
+			635,	/* Code */
+			10415,	/* Vendor */
+			"SIP-Digest-Authenticate",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR,	/* Fixed flag values */
+			AVP_TYPE_GROUPED	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* SIP-Item-Number */
+	{
+		struct dict_avp_data data = {
+			613,	/* Code */
+			10415,	/* Vendor */
+			"SIP-Item-Number",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_UNSIGNED32	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* SIP-Number-Auth-Items */
+	{
+		struct dict_avp_data data = {
+			607,	/* Code */
+			10415,	/* Vendor */
+			"SIP-Number-Auth-Items",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_UNSIGNED32	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* Secondary-Charging-Collection-Function-Name */
+	{
+		struct dict_avp_data data = {
+			622,	/* Code */
+			10415,	/* Vendor */
+			"Secondary-Charging-Collection-Function-Name",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, DiameterURI_type, NULL);
+	};
+
+	/* Secondary-Event-Charging-Function-Name */
+	{
+		struct dict_avp_data data = {
+			620,	/* Code */
+			10415,	/* Vendor */
+			"Secondary-Event-Charging-Function-Name",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, DiameterURI_type, NULL);
+	};
+
+	/* Server-Assignment-Type */
+	{
+		struct dict_avp_data data = {
+			614,	/* Code */
+			10415,	/* Vendor */
+			"Server-Assignment-Type",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_INTEGER32	/* base type of data */
+		};
+		struct dict_object		*type;
+		struct dict_type_data	 tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Server-Assignment-Type)", NULL, NULL, NULL };
+		CHECK_dict_new(DICT_TYPE, &tdata, NULL, &type);
+		CHECK_dict_new(DICT_AVP, &data, type, NULL);
+	};
+
+	/* Server-Capabilities */
+	{
+		struct dict_avp_data data = {
+			603,	/* Code */
+			10415,	/* Vendor */
+			"Server-Capabilities",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_GROUPED	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* Server-Name */
+	{
+		struct dict_avp_data data = {
+			602,	/* Code */
+			10415,	/* Vendor */
+			"Server-Name",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, UTF8String_type, NULL);
+	};
+
+	/* Session-Priority */
+	{
+		struct dict_avp_data data = {
+			650,	/* Code */
+			10415,	/* Vendor */
+			"Session-Priority",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR,	/* Fixed flag values */
+			AVP_TYPE_INTEGER32	/* base type of data */
+		};
+		struct dict_object		*type;
+		struct dict_type_data	 tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Session-Priority)", NULL, NULL, NULL };
+		CHECK_dict_new(DICT_TYPE, &tdata, NULL, &type);
+		CHECK_dict_new(DICT_AVP, &data, type, NULL);
+	};
+
+	/* Subscription-Info */
+	{
+		struct dict_avp_data data = {
+			642,	/* Code */
+			10415,	/* Vendor */
+			"Subscription-Info",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR,	/* Fixed flag values */
+			AVP_TYPE_GROUPED	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* Supported-Applications */
+	{
+		struct dict_avp_data data = {
+			631,	/* Code */
+			10415,	/* Vendor */
+			"Supported-Applications",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR,	/* Fixed flag values */
+			AVP_TYPE_GROUPED	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* Supported-Features */
+	{
+		struct dict_avp_data data = {
+			628,	/* Code */
+			10415,	/* Vendor */
+			"Supported-Features",	/* Name */
+			AVP_FLAG_VENDOR,	/* Fixed flags */
+			AVP_FLAG_VENDOR,	/* Fixed flag values */
+			AVP_TYPE_GROUPED	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* To-SIP-Header */
+	{
+		struct dict_avp_data data = {
+			645,	/* Code */
+			10415,	/* Vendor */
+			"To-SIP-Header",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* UAR-Flags */
+	{
+		struct dict_avp_data data = {
+			637,	/* Code */
+			10415,	/* Vendor */
+			"UAR-Flags",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR,	/* Fixed flag values */
+			AVP_TYPE_UNSIGNED32	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* User-Authorization-Type */
+	{
+		struct dict_avp_data data = {
+			623,	/* Code */
+			10415,	/* Vendor */
+			"User-Authorization-Type",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_INTEGER32	/* base type of data */
+		};
+		struct dict_object		*type;
+		struct dict_type_data	 tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(User-Authorization-Type)", NULL, NULL, NULL };
+		CHECK_dict_new(DICT_TYPE, &tdata, NULL, &type);
+		CHECK_dict_new(DICT_AVP, &data, type, NULL);
+	};
+
+	/* User-Data */
+	{
+		struct dict_avp_data data = {
+			606,	/* Code */
+			10415,	/* Vendor */
+			"User-Data",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* User-Data-Already-Available */
+	{
+		struct dict_avp_data data = {
+			624,	/* Code */
+			10415,	/* Vendor */
+			"User-Data-Already-Available",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_INTEGER32	/* base type of data */
+		};
+		struct dict_object		*type;
+		struct dict_type_data	 tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(User-Data-Already-Available)", NULL, NULL, NULL };
+		CHECK_dict_new(DICT_TYPE, &tdata, NULL, &type);
+		CHECK_dict_new(DICT_AVP, &data, type, NULL);
+	};
+
+	/* Visited-Network-Identifier */
+	{
+		struct dict_avp_data data = {
+			600,	/* Code */
+			10415,	/* Vendor */
+			"Visited-Network-Identifier",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* Wildcarded-Public-Identity */
+	{
+		struct dict_avp_data data = {
+			634,	/* Code */
+			10415,	/* Vendor */
+			"Wildcarded-Public-Identity",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, UTF8String_type, NULL);
+	};
+
+	/* 3GPP 32.299-b60 (11.6.0 2012.12.21)                          */
+	/* AF-Correlation-Information */
+	{
+		struct dict_avp_data data = {
+			1276,	/* Code */
+			10415,	/* Vendor */
+			"AF-Correlation-Information",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_GROUPED	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* Access-Network-Information */
+	{
+		struct dict_avp_data data = {
+			1263,	/* Code */
+			10415,	/* Vendor */
+			"Access-Network-Information",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* Access-Transfer-Information */
+	{
+		struct dict_avp_data data = {
+			2709,	/* Code */
+			10415,	/* Vendor */
+			"Access-Transfer-Information",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_GROUPED	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* Access-Transfer-Type */
+	{
+		struct dict_avp_data data = {
+			2710,	/* Code */
+			10415,	/* Vendor */
+			"Access-Transfer-Type",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_INTEGER32	/* base type of data */
+		};
+		struct dict_object		*type;
+		struct dict_type_data	 tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Access-Transfer-Type)", NULL, NULL, NULL };
+		CHECK_dict_new(DICT_TYPE, &tdata, NULL, &type);
+		CHECK_dict_new(DICT_AVP, &data, type, NULL);
+	};
+
+	/* Account-Expiration */
+	{
+		struct dict_avp_data data = {
+			2309,	/* Code */
+			10415,	/* Vendor */
+			"Account-Expiration",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, Time_type, NULL);
+	};
+
+	/* Accumulated-Cost */
+	{
+		struct dict_avp_data data = {
+			2052,	/* Code */
+			10415,	/* Vendor */
+			"Accumulated-Cost",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_GROUPED	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* Adaptations */
+	{
+		struct dict_avp_data data = {
+			1217,	/* Code */
+			10415,	/* Vendor */
+			"Adaptations",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_INTEGER32	/* base type of data */
+		};
+		struct dict_object		*type;
+		struct dict_type_data	 tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Adaptations)", NULL, NULL, NULL };
+		CHECK_dict_new(DICT_TYPE, &tdata, NULL, &type);
+		CHECK_dict_new(DICT_AVP, &data, type, NULL);
+	};
+
+	/* Additional-Content-Information */
+	{
+		struct dict_avp_data data = {
+			1207,	/* Code */
+			10415,	/* Vendor */
+			"Additional-Content-Information",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_GROUPED	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* Additional-Type-Information */
+	{
+		struct dict_avp_data data = {
+			1205,	/* Code */
+			10415,	/* Vendor */
+			"Additional-Type-Information",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, UTF8String_type, NULL);
+	};
+
+	/* Address-Data */
+	{
+		struct dict_avp_data data = {
+			897,	/* Code */
+			10415,	/* Vendor */
+			"Address-Data",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, UTF8String_type, NULL);
+	};
+
+	/* Address-Domain */
+	{
+		struct dict_avp_data data = {
+			898,	/* Code */
+			10415,	/* Vendor */
+			"Address-Domain",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_GROUPED	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* Address-Type */
+	{
+		struct dict_avp_data data = {
+			899,	/* Code */
+			10415,	/* Vendor */
+			"Address-Type",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_INTEGER32	/* base type of data */
+		};
+		struct dict_object		*type;
+		struct dict_type_data	 tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Address-Type)", NULL, NULL, NULL };
+		CHECK_dict_new(DICT_TYPE, &tdata, NULL, &type);
+		CHECK_dict_new(DICT_AVP, &data, type, NULL);
+	};
+
+	/* Addressee-Type */
+	{
+		struct dict_avp_data data = {
+			1208,	/* Code */
+			10415,	/* Vendor */
+			"Addressee-Type",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_INTEGER32	/* base type of data */
+		};
+		struct dict_object		*type;
+		struct dict_type_data	 tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Addressee-Type)", NULL, NULL, NULL };
+		CHECK_dict_new(DICT_TYPE, &tdata, NULL, &type);
+		CHECK_dict_new(DICT_AVP, &data, type, NULL);
+	};
+
+	/* Alternate-Charged-Party-Address */
+	{
+		struct dict_avp_data data = {
+			1280,	/* Code */
+			10415,	/* Vendor */
+			"Alternate-Charged-Party-Address",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, UTF8String_type, NULL);
+	};
+
+	/* AoC-Cost-Information */
+	{
+		struct dict_avp_data data = {
+			2053,	/* Code */
+			10415,	/* Vendor */
+			"AoC-Cost-Information",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_GROUPED	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* AoC-Format */
+	{
+		struct dict_avp_data data = {
+			2310,	/* Code */
+			10415,	/* Vendor */
+			"AoC-Format",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_INTEGER32	/* base type of data */
+		};
+		struct dict_object		*type;
+		struct dict_type_data	 tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(AoC-Format)", NULL, NULL, NULL };
+		CHECK_dict_new(DICT_TYPE, &tdata, NULL, &type);
+		CHECK_dict_new(DICT_AVP, &data, type, NULL);
+	};
+
+	/* AoC-Information */
+	{
+		struct dict_avp_data data = {
+			2054,	/* Code */
+			10415,	/* Vendor */
+			"AoC-Information",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_GROUPED	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* AoC-Request-Type */
+	{
+		struct dict_avp_data data = {
+			2055,	/* Code */
+			10415,	/* Vendor */
+			"AoC-Request-Type",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_INTEGER32	/* base type of data */
+		};
+		struct dict_object		*type;
+		struct dict_type_data	 tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(AoC-Request-Type)", NULL, NULL, NULL };
+		CHECK_dict_new(DICT_TYPE, &tdata, NULL, &type);
+		CHECK_dict_new(DICT_AVP, &data, type, NULL);
+	};
+
+	/* AoC-Service */
+	{
+		struct dict_avp_data data = {
+			2311,	/* Code */
+			10415,	/* Vendor */
+			"AoC-Service",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_GROUPED	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* AoC-Service-Obligatory-Type */
+	{
+		struct dict_avp_data data = {
+			2312,	/* Code */
+			10415,	/* Vendor */
+			"AoC-Service-Obligatory-Type",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_INTEGER32	/* base type of data */
+		};
+		struct dict_object		*type;
+		struct dict_type_data	 tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(AoC-Service-Obligatory-Type)", NULL, NULL, NULL };
+		CHECK_dict_new(DICT_TYPE, &tdata, NULL, &type);
+		CHECK_dict_new(DICT_AVP, &data, type, NULL);
+	};
+
+	/* AoC-Service-Type */
+	{
+		struct dict_avp_data data = {
+			2313,	/* Code */
+			10415,	/* Vendor */
+			"AoC-Service-Type",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_INTEGER32	/* base type of data */
+		};
+		struct dict_object		*type;
+		struct dict_type_data	 tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(AoC-Service-Type)", NULL, NULL, NULL };
+		CHECK_dict_new(DICT_TYPE, &tdata, NULL, &type);
+		CHECK_dict_new(DICT_AVP, &data, type, NULL);
+	};
+
+	/* AoC-Subscription-Information */
+	{
+		struct dict_avp_data data = {
+			2314,	/* Code */
+			10415,	/* Vendor */
+			"AoC-Subscription-Information",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_GROUPED	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* Applic-ID */
+	{
+		struct dict_avp_data data = {
+			1218,	/* Code */
+			10415,	/* Vendor */
+			"Applic-ID",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, UTF8String_type, NULL);
+	};
+
+	/* Application-Server */
+	{
+		struct dict_avp_data data = {
+			836,	/* Code */
+			10415,	/* Vendor */
+			"Application-Server",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, UTF8String_type, NULL);
+	};
+
+	/* Application-Server-Information */
+	{
+		struct dict_avp_data data = {
+			850,	/* Code */
+			10415,	/* Vendor */
+			"Application-Server-Information",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_GROUPED	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* Application-Provided-Called-Party-Address */
+	{
+		struct dict_avp_data data = {
+			837,	/* Code */
+			10415,	/* Vendor */
+			"Application-Provided-Called-Party-Address",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, UTF8String_type, NULL);
+	};
+
+	/* Associated-Party-Address */
+	{
+		struct dict_avp_data data = {
+			2035,	/* Code */
+			10415,	/* Vendor */
+			"Associated-Party-Address",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, UTF8String_type, NULL);
+	};
+
+	/* Associated-URI */
+	{
+		struct dict_avp_data data = {
+			856,	/* Code */
+			10415,	/* Vendor */
+			"Associated-URI",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, UTF8String_type, NULL);
+	};
+
+	/* Aux-Applic-Info */
+	{
+		struct dict_avp_data data = {
+			1219,	/* Code */
+			10415,	/* Vendor */
+			"Aux-Applic-Info",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, UTF8String_type, NULL);
+	};
+
+	/* Base-Time-Interval */
+	{
+		struct dict_avp_data data = {
+			1265,	/* Code */
+			10415,	/* Vendor */
+			"Base-Time-Interval",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_UNSIGNED32	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* Bearer-Service */
+	{
+		struct dict_avp_data data = {
+			854,	/* Code */
+			10415,	/* Vendor */
+			"Bearer-Service",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* CG-Address */
+	{
+		struct dict_avp_data data = {
+			846,	/* Code */
+			10415,	/* Vendor */
+			"CG-Address",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, Address_type, NULL);
+	};
+
+	/* CSG-Access-Mode */
+	{
+		struct dict_avp_data data = {
+			2317,	/* Code */
+			10415,	/* Vendor */
+			"CSG-Access-Mode",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_INTEGER32	/* base type of data */
+		};
+		struct dict_object		*type;
+		struct dict_type_data	 tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(CSG-Access-Mode)", NULL, NULL, NULL };
+		CHECK_dict_new(DICT_TYPE, &tdata, NULL, &type);
+		CHECK_dict_new(DICT_AVP, &data, type, NULL);
+	};
+
+	/* CSG-Membership-Indication */
+	{
+		struct dict_avp_data data = {
+			2318,	/* Code */
+			10415,	/* Vendor */
+			"CSG-Membership-Indication",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_INTEGER32	/* base type of data */
+		};
+		struct dict_object		*type;
+		struct dict_type_data	 tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(CSG-Membership-Indication)", NULL, NULL, NULL };
+		CHECK_dict_new(DICT_TYPE, &tdata, NULL, &type);
+		CHECK_dict_new(DICT_AVP, &data, type, NULL);
+	};
+
+	/* CUG-Information */
+	{
+		struct dict_avp_data data = {
+			2304,	/* Code */
+			10415,	/* Vendor */
+			"CUG-Information",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* Called-Asserted-Identity */
+	{
+		struct dict_avp_data data = {
+			1250,	/* Code */
+			10415,	/* Vendor */
+			"Called-Asserted-Identity",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, UTF8String_type, NULL);
+	};
+
+	/* Called-Party-Address */
+	{
+		struct dict_avp_data data = {
+			832,	/* Code */
+			10415,	/* Vendor */
+			"Called-Party-Address",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, UTF8String_type, NULL);
+	};
+
+	/* Calling-Party-Address */
+	{
+		struct dict_avp_data data = {
+			831,	/* Code */
+			10415,	/* Vendor */
+			"Calling-Party-Address",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, UTF8String_type, NULL);
+	};
+
+	/* Carrier-Select-Routing-Information */
+	{
+		struct dict_avp_data data = {
+			2023,	/* Code */
+			10415,	/* Vendor */
+			"Carrier-Select-Routing-Information",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, UTF8String_type, NULL);
+	};
+
+	/* Cause-Code */
+	{
+		struct dict_avp_data data = {
+			861,	/* Code */
+			10415,	/* Vendor */
+			"Cause-Code",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_INTEGER32	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* Change-Condition */
+	{
+		struct dict_avp_data data = {
+			2037,	/* Code */
+			10415,	/* Vendor */
+			"Change-Condition",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_INTEGER32	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* Change-Time */
+	{
+		struct dict_avp_data data = {
+			2038,	/* Code */
+			10415,	/* Vendor */
+			"Change-Time",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, Time_type, NULL);
+	};
+
+	/* Charge-Reason-Code */
+	{
+		struct dict_avp_data data = {
+			2118,	/* Code */
+			10415,	/* Vendor */
+			"Charge-Reason-Code",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_INTEGER32	/* base type of data */
+		};
+		struct dict_object		*type;
+		struct dict_type_data	 tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Charge-Reason-Code)", NULL, NULL, NULL };
+		CHECK_dict_new(DICT_TYPE, &tdata, NULL, &type);
+		CHECK_dict_new(DICT_AVP, &data, type, NULL);
+	};
+
+	/* Charged-Party */
+	{
+		struct dict_avp_data data = {
+			857,	/* Code */
+			10415,	/* Vendor */
+			"Charged-Party",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, UTF8String_type, NULL);
+	};
+
+	/* Charging-Characteristics-Selection-Mode */
+	{
+		struct dict_avp_data data = {
+			2066,	/* Code */
+			10415,	/* Vendor */
+			"Charging-Characteristics-Selection-Mode",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_INTEGER32	/* base type of data */
+		};
+		struct dict_object		*type;
+		struct dict_type_data	 tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Charging-Characteristics-Selection-Mode)", NULL, NULL, NULL };
+		CHECK_dict_new(DICT_TYPE, &tdata, NULL, &type);
+		CHECK_dict_new(DICT_AVP, &data, type, NULL);
+	};
+
+	/* Class-Identifier */
+	{
+		struct dict_avp_data data = {
+			1214,	/* Code */
+			10415,	/* Vendor */
+			"Class-Identifier",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_INTEGER32	/* base type of data */
+		};
+		struct dict_object		*type;
+		struct dict_type_data	 tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Class-Identifier)", NULL, NULL, NULL };
+		CHECK_dict_new(DICT_TYPE, &tdata, NULL, &type);
+		CHECK_dict_new(DICT_AVP, &data, type, NULL);
+	};
+
+	/* Client-Address */
+	{
+		struct dict_avp_data data = {
+			2018,	/* Code */
+			10415,	/* Vendor */
+			"Client-Address",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, Address_type, NULL);
+	};
+
+	/* Content-Class */
+	{
+		struct dict_avp_data data = {
+			1220,	/* Code */
+			10415,	/* Vendor */
+			"Content-Class",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_INTEGER32	/* base type of data */
+		};
+		struct dict_object		*type;
+		struct dict_type_data	 tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Content-Class)", NULL, NULL, NULL };
+		CHECK_dict_new(DICT_TYPE, &tdata, NULL, &type);
+		CHECK_dict_new(DICT_AVP, &data, type, NULL);
+	};
+
+	/* Content-Disposition */
+	{
+		struct dict_avp_data data = {
+			828,	/* Code */
+			10415,	/* Vendor */
+			"Content-Disposition",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, UTF8String_type, NULL);
+	};
+
+	/* Content-Length */
+	{
+		struct dict_avp_data data = {
+			827,	/* Code */
+			10415,	/* Vendor */
+			"Content-Length",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_UNSIGNED32	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* Content-Size */
+	{
+		struct dict_avp_data data = {
+			1206,	/* Code */
+			10415,	/* Vendor */
+			"Content-Size",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_UNSIGNED32	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* Content-Type */
+	{
+		struct dict_avp_data data = {
+			826,	/* Code */
+			10415,	/* Vendor */
+			"Content-Type",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, UTF8String_type, NULL);
+	};
+
+	/* Current-Tariff */
+	{
+		struct dict_avp_data data = {
+			2056,	/* Code */
+			10415,	/* Vendor */
+			"Current-Tariff",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_GROUPED	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* DRM-Content */
+	{
+		struct dict_avp_data data = {
+			1221,	/* Code */
+			10415,	/* Vendor */
+			"DRM-Content",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_INTEGER32	/* base type of data */
+		};
+		struct dict_object		*type;
+		struct dict_type_data	 tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(DRM-Content)", NULL, NULL, NULL };
+		CHECK_dict_new(DICT_TYPE, &tdata, NULL, &type);
+		CHECK_dict_new(DICT_AVP, &data, type, NULL);
+	};
+
+	/* Data-Coding-Scheme */
+	{
+		struct dict_avp_data data = {
+			2001,	/* Code */
+			10415,	/* Vendor */
+			"Data-Coding-Scheme",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_INTEGER32	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* Deferred-Location-Event-Type */
+	{
+		struct dict_avp_data data = {
+			1230,	/* Code */
+			10415,	/* Vendor */
+			"Deferred-Location-Event-Type",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, UTF8String_type, NULL);
+	};
+
+	/* Delivery-Report-Requested */
+	{
+		struct dict_avp_data data = {
+			1216,	/* Code */
+			10415,	/* Vendor */
+			"Delivery-Report-Requested",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_INTEGER32	/* base type of data */
+		};
+		struct dict_object		*type;
+		struct dict_type_data	 tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Delivery-Report-Requested)", NULL, NULL, NULL };
+		CHECK_dict_new(DICT_TYPE, &tdata, NULL, &type);
+		CHECK_dict_new(DICT_AVP, &data, type, NULL);
+	};
+
+	/* Destination-Interface */
+	{
+		struct dict_avp_data data = {
+			2002,	/* Code */
+			10415,	/* Vendor */
+			"Destination-Interface",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_GROUPED	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* Diagnostics */
+	{
+		struct dict_avp_data data = {
+			2039,	/* Code */
+			10415,	/* Vendor */
+			"Diagnostics",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_INTEGER32	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* Domain-Name */
+	{
+		struct dict_avp_data data = {
+			1200,	/* Code */
+			10415,	/* Vendor */
+			"Domain-Name",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, UTF8String_type, NULL);
+	};
+
+	/* Dynamic-Address-Flag */
+	{
+		struct dict_avp_data data = {
+			2051,	/* Code */
+			10415,	/* Vendor */
+			"Dynamic-Address-Flag",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_INTEGER32	/* base type of data */
+		};
+		struct dict_object		*type;
+		struct dict_type_data	 tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Dynamic-Address-Flag)", NULL, NULL, NULL };
+		CHECK_dict_new(DICT_TYPE, &tdata, NULL, &type);
+		CHECK_dict_new(DICT_AVP, &data, type, NULL);
+	};
+
+	/* Dynamic-Address-Flag-Extension */
+	{
+		struct dict_avp_data data = {
+			2068,	/* Code */
+			10415,	/* Vendor */
+			"Dynamic-Address-Flag-Extension",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_INTEGER32	/* base type of data */
+		};
+		struct dict_object		*type;
+		struct dict_type_data	 tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Dynamic-Address-Flag-Extension)", NULL, NULL, NULL };
+		CHECK_dict_new(DICT_TYPE, &tdata, NULL, &type);
+		CHECK_dict_new(DICT_AVP, &data, type, NULL);
+	};
+
+	/* Early-Media-Description */
+	{
+		struct dict_avp_data data = {
+			1272,	/* Code */
+			10415,	/* Vendor */
+			"Early-Media-Description",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_GROUPED	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* Envelope */
+	{
+		struct dict_avp_data data = {
+			1266,	/* Code */
+			10415,	/* Vendor */
+			"Envelope",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_GROUPED	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* Envelope-End-Time */
+	{
+		struct dict_avp_data data = {
+			1267,	/* Code */
+			10415,	/* Vendor */
+			"Envelope-End-Time",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, Time_type, NULL);
+	};
+
+	/* Envelope-Reporting */
+	{
+		struct dict_avp_data data = {
+			1268,	/* Code */
+			10415,	/* Vendor */
+			"Envelope-Reporting",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_INTEGER32	/* base type of data */
+		};
+		struct dict_object		*type;
+		struct dict_type_data	 tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Envelope-Reporting)", NULL, NULL, NULL };
+		CHECK_dict_new(DICT_TYPE, &tdata, NULL, &type);
+		CHECK_dict_new(DICT_AVP, &data, type, NULL);
+	};
+
+	/* Envelope-Start-Time */
+	{
+		struct dict_avp_data data = {
+			1269,	/* Code */
+			10415,	/* Vendor */
+			"Envelope-Start-Time",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, Time_type, NULL);
+	};
+
+	/* Event */
+	{
+		struct dict_avp_data data = {
+			825,	/* Code */
+			10415,	/* Vendor */
+			"Event",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, UTF8String_type, NULL);
+	};
+
+	/* Event-Charging-TimeStamp */
+	{
+		struct dict_avp_data data = {
+			1258,	/* Code */
+			10415,	/* Vendor */
+			"Event-Charging-TimeStamp",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, Time_type, NULL);
+	};
+
+	/* Event-Type */
+	{
+		struct dict_avp_data data = {
+			823,	/* Code */
+			10415,	/* Vendor */
+			"Event-Type",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_GROUPED	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* Expires */
+	{
+		struct dict_avp_data data = {
+			888,	/* Code */
+			10415,	/* Vendor */
+			"Expires",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_UNSIGNED32	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* File-Repair-Supported */
+	{
+		struct dict_avp_data data = {
+			1224,	/* Code */
+			10415,	/* Vendor */
+			"File-Repair-Supported",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_INTEGER32	/* base type of data */
+		};
+		struct dict_object		*type;
+		struct dict_type_data	 tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(File-Repair-Supported)", NULL, NULL, NULL };
+		CHECK_dict_new(DICT_TYPE, &tdata, NULL, &type);
+		CHECK_dict_new(DICT_AVP, &data, type, NULL);
+	};
+
+	/* From-Address */
+	{
+		struct dict_avp_data data = {
+			2708,	/* Code */
+			10415,	/* Vendor */
+			"From-Address",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, UTF8String_type, NULL);
+	};
+
+	/* GGSN-Address */
+	{
+		struct dict_avp_data data = {
+			847,	/* Code */
+			10415,	/* Vendor */
+			"GGSN-Address",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, Address_type, NULL);
+	};
+
+	/* IMS-Application-Reference-Identifier */
+	{
+		struct dict_avp_data data = {
+			2601,	/* Code */
+			10415,	/* Vendor */
+			"IMS-Application-Reference-Identifier",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, UTF8String_type, NULL);
+	};
+
+	/* IMS-Charging-Identifier */
+	{
+		struct dict_avp_data data = {
+			841,	/* Code */
+			10415,	/* Vendor */
+			"IMS-Charging-Identifier",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, UTF8String_type, NULL);
+	};
+
+	/* IMS-Communication-Service-Identifier */
+	{
+		struct dict_avp_data data = {
+			1281,	/* Code */
+			10415,	/* Vendor */
+			"IMS-Communication-Service-Identifier",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, UTF8String_type, NULL);
+	};
+
+	/* IMS-Emergency-Indicator */
+	{
+		struct dict_avp_data data = {
+			2322,	/* Code */
+			10415,	/* Vendor */
+			"IMS-Emergency-Indicator",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_INTEGER32	/* base type of data */
+		};
+		struct dict_object		*type;
+		struct dict_type_data	 tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(IMS-Emergency-Indicator)", NULL, NULL, NULL };
+		CHECK_dict_new(DICT_TYPE, &tdata, NULL, &type);
+		CHECK_dict_new(DICT_AVP, &data, type, NULL);
+	};
+
+	/* IMS-Information */
+	{
+		struct dict_avp_data data = {
+			876,	/* Code */
+			10415,	/* Vendor */
+			"IMS-Information",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_GROUPED	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* IMSI-Unauthenticated-Flag */
+	{
+		struct dict_avp_data data = {
+			2308,	/* Code */
+			10415,	/* Vendor */
+			"IMSI-Unauthenticated-Flag",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_INTEGER32	/* base type of data */
+		};
+		struct dict_object		*type;
+		struct dict_type_data	 tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(IMSI-Unauthenticated-Flag)", NULL, NULL, NULL };
+		CHECK_dict_new(DICT_TYPE, &tdata, NULL, &type);
+		CHECK_dict_new(DICT_AVP, &data, type, NULL);
+	};
+
+	/* IP-Realm-Default-Indication */
+	{
+		struct dict_avp_data data = {
+			2603,	/* Code */
+			10415,	/* Vendor */
+			"IP-Realm-Default-Indication",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_INTEGER32	/* base type of data */
+		};
+		struct dict_object		*type;
+		struct dict_type_data	 tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(IP-Realm-Default-Indication)", NULL, NULL, NULL };
+		CHECK_dict_new(DICT_TYPE, &tdata, NULL, &type);
+		CHECK_dict_new(DICT_AVP, &data, type, NULL);
+	};
+
+	/* Incoming-Trunk-Group-Id */
+	{
+		struct dict_avp_data data = {
+			852,	/* Code */
+			10415,	/* Vendor */
+			"Incoming-Trunk-Group-Id",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, UTF8String_type, NULL);
+	};
+
+	/* Incremental-Cost */
+	{
+		struct dict_avp_data data = {
+			2062,	/* Code */
+			10415,	/* Vendor */
+			"Incremental-Cost",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_GROUPED	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* Initial-IMS-Charging-Identifier */
+	{
+		struct dict_avp_data data = {
+			2321,	/* Code */
+			10415,	/* Vendor */
+			"Initial-IMS-Charging-Identifier",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, UTF8String_type, NULL);
+	};
+
+	/* Inter-Operator-Identifier */
+	{
+		struct dict_avp_data data = {
+			838,	/* Code */
+			10415,	/* Vendor */
+			"Inter-Operator-Identifier",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_GROUPED	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* Interface-Id */
+	{
+		struct dict_avp_data data = {
+			2003,	/* Code */
+			10415,	/* Vendor */
+			"Interface-Id",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, UTF8String_type, NULL);
+	};
+
+	/* Interface-Port */
+	{
+		struct dict_avp_data data = {
+			2004,	/* Code */
+			10415,	/* Vendor */
+			"Interface-Port",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, UTF8String_type, NULL);
+	};
+
+	/* Interface-Text */
+	{
+		struct dict_avp_data data = {
+			2005,	/* Code */
+			10415,	/* Vendor */
+			"Interface-Text",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, UTF8String_type, NULL);
+	};
+
+	/* Interface-Type */
+	{
+		struct dict_avp_data data = {
+			2006,	/* Code */
+			10415,	/* Vendor */
+			"Interface-Type",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_INTEGER32	/* base type of data */
+		};
+		struct dict_object		*type;
+		struct dict_type_data	 tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Interface-Type)", NULL, NULL, NULL };
+		CHECK_dict_new(DICT_TYPE, &tdata, NULL, &type);
+		CHECK_dict_new(DICT_AVP, &data, type, NULL);
+	};
+
+	/* LCS-APN */
+	{
+		struct dict_avp_data data = {
+			1231,	/* Code */
+			10415,	/* Vendor */
+			"LCS-APN",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, UTF8String_type, NULL);
+	};
+
+	/* LCS-Client-Dialed-By-MS */
+	{
+		struct dict_avp_data data = {
+			1233,	/* Code */
+			10415,	/* Vendor */
+			"LCS-Client-Dialed-By-MS",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, UTF8String_type, NULL);
+	};
+
+	/* LCS-Client-External-ID */
+	{
+		struct dict_avp_data data = {
+			1234,	/* Code */
+			10415,	/* Vendor */
+			"LCS-Client-External-ID",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, UTF8String_type, NULL);
+	};
+
+	/* LCS-Client-Id */
+	{
+		struct dict_avp_data data = {
+			1232,	/* Code */
+			10415,	/* Vendor */
+			"LCS-Client-Id",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_GROUPED	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* LCS-Client-Name */
+	{
+		struct dict_avp_data data = {
+			1235,	/* Code */
+			10415,	/* Vendor */
+			"LCS-Client-Name",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_GROUPED	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* LCS-Client-Type */
+	{
+		struct dict_avp_data data = {
+			1241,	/* Code */
+			10415,	/* Vendor */
+			"LCS-Client-Type",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_INTEGER32	/* base type of data */
+		};
+		struct dict_object		*type;
+		struct dict_type_data	 tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(LCS-Client-Type)", NULL, NULL, NULL };
+		CHECK_dict_new(DICT_TYPE, &tdata, NULL, &type);
+		CHECK_dict_new(DICT_AVP, &data, type, NULL);
+	};
+
+	/* LCS-Data-Coding-Scheme */
+	{
+		struct dict_avp_data data = {
+			1236,	/* Code */
+			10415,	/* Vendor */
+			"LCS-Data-Coding-Scheme",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, UTF8String_type, NULL);
+	};
+
+	/* LCS-Format-Indicator */
+	{
+		struct dict_avp_data data = {
+			1237,	/* Code */
+			10415,	/* Vendor */
+			"LCS-Format-Indicator",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_INTEGER32	/* base type of data */
+		};
+		struct dict_object		*type;
+		struct dict_type_data	 tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(LCS-Format-Indicator)", NULL, NULL, NULL };
+		CHECK_dict_new(DICT_TYPE, &tdata, NULL, &type);
+		CHECK_dict_new(DICT_AVP, &data, type, NULL);
+	};
+
+	/* LCS-Information */
+	{
+		struct dict_avp_data data = {
+			878,	/* Code */
+			10415,	/* Vendor */
+			"LCS-Information",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_GROUPED	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* LCS-Name-String */
+	{
+		struct dict_avp_data data = {
+			1238,	/* Code */
+			10415,	/* Vendor */
+			"LCS-Name-String",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, UTF8String_type, NULL);
+	};
+
+	/* LCS-Requestor-Id */
+	{
+		struct dict_avp_data data = {
+			1239,	/* Code */
+			10415,	/* Vendor */
+			"LCS-Requestor-Id",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_GROUPED	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* LCS-Requestor-Id-String */
+	{
+		struct dict_avp_data data = {
+			1240,	/* Code */
+			10415,	/* Vendor */
+			"LCS-Requestor-Id-String",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, UTF8String_type, NULL);
+	};
+
+	/* Local-GW-Inserted-Indication */
+	{
+		struct dict_avp_data data = {
+			2604,	/* Code */
+			10415,	/* Vendor */
+			"Local-GW-Inserted-Indication",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_INTEGER32	/* base type of data */
+		};
+		struct dict_object		*type;
+		struct dict_type_data	 tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Local-GW-Inserted-Indication)", NULL, NULL, NULL };
+		CHECK_dict_new(DICT_TYPE, &tdata, NULL, &type);
+		CHECK_dict_new(DICT_AVP, &data, type, NULL);
+	};
+
+	/* Local-Sequence-Number */
+	{
+		struct dict_avp_data data = {
+			2063,	/* Code */
+			10415,	/* Vendor */
+			"Local-Sequence-Number",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_UNSIGNED32	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* Location-Estimate */
+	{
+		struct dict_avp_data data = {
+			1242,	/* Code */
+			10415,	/* Vendor */
+			"Location-Estimate",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* Location-Estimate-Type */
+	{
+		struct dict_avp_data data = {
+			1243,	/* Code */
+			10415,	/* Vendor */
+			"Location-Estimate-Type",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_INTEGER32	/* base type of data */
+		};
+		struct dict_object		*type;
+		struct dict_type_data	 tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Location-Estimate-Type)", NULL, NULL, NULL };
+		CHECK_dict_new(DICT_TYPE, &tdata, NULL, &type);
+		CHECK_dict_new(DICT_AVP, &data, type, NULL);
+	};
+
+	/* Location-Type */
+	{
+		struct dict_avp_data data = {
+			1244,	/* Code */
+			10415,	/* Vendor */
+			"Location-Type",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_GROUPED	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* Low-Balance-Indication */
+	{
+		struct dict_avp_data data = {
+			2020,	/* Code */
+			10415,	/* Vendor */
+			"Low-Balance-Indication",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_INTEGER32	/* base type of data */
+		};
+		struct dict_object		*type;
+		struct dict_type_data	 tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Low-Balance-Indication)", NULL, NULL, NULL };
+		CHECK_dict_new(DICT_TYPE, &tdata, NULL, &type);
+		CHECK_dict_new(DICT_AVP, &data, type, NULL);
+	};
+
+	/* Low-Priority-Indicator */
+	{
+		struct dict_avp_data data = {
+			2602,	/* Code */
+			10415,	/* Vendor */
+			"Low-Priority-Indicator",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_INTEGER32	/* base type of data */
+		};
+		struct dict_object		*type;
+		struct dict_type_data	 tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Low-Priority-Indicator)", NULL, NULL, NULL };
+		CHECK_dict_new(DICT_TYPE, &tdata, NULL, &type);
+		CHECK_dict_new(DICT_AVP, &data, type, NULL);
+	};
+
+	/* MBMSGW-Address */
+	{
+		struct dict_avp_data data = {
+			2307,	/* Code */
+			10415,	/* Vendor */
+			"MBMSGW-Address",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, Address_type, NULL);
+	};
+
+	/* MBMS-Information */
+	{
+		struct dict_avp_data data = {
+			880,	/* Code */
+			10415,	/* Vendor */
+			"MBMS-Information",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_GROUPED	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* MBMS-User-Service-Type */
+	{
+		struct dict_avp_data data = {
+			1225,	/* Code */
+			10415,	/* Vendor */
+			"MBMS-User-Service-Type",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_INTEGER32	/* base type of data */
+		};
+		struct dict_object		*type;
+		struct dict_type_data	 tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(MBMS-User-Service-Type)", NULL, NULL, NULL };
+		CHECK_dict_new(DICT_TYPE, &tdata, NULL, &type);
+		CHECK_dict_new(DICT_AVP, &data, type, NULL);
+	};
+
+	/* MM-Content-Type */
+	{
+		struct dict_avp_data data = {
+			1203,	/* Code */
+			10415,	/* Vendor */
+			"MM-Content-Type",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_GROUPED	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* MMBox-Storage-Requested */
+	{
+		struct dict_avp_data data = {
+			1248,	/* Code */
+			10415,	/* Vendor */
+			"MMBox-Storage-Requested",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_INTEGER32	/* base type of data */
+		};
+		struct dict_object		*type;
+		struct dict_type_data	 tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(MMBox-Storage-Requested)", NULL, NULL, NULL };
+		CHECK_dict_new(DICT_TYPE, &tdata, NULL, &type);
+		CHECK_dict_new(DICT_AVP, &data, type, NULL);
+	};
+
+	/* MMS-Information */
+	{
+		struct dict_avp_data data = {
+			877,	/* Code */
+			10415,	/* Vendor */
+			"MMS-Information",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_GROUPED	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* MMTel-Information */
+	{
+		struct dict_avp_data data = {
+			2030,	/* Code */
+			10415,	/* Vendor */
+			"MMTel-Information",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_GROUPED	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* MMTel-SService-Type */
+	{
+		struct dict_avp_data data = {
+			2031,	/* Code */
+			10415,	/* Vendor */
+			"MMTel-SService-Type",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_UNSIGNED32	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* Media-Initiator-Flag */
+	{
+		struct dict_avp_data data = {
+			882,	/* Code */
+			10415,	/* Vendor */
+			"Media-Initiator-Flag",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_INTEGER32	/* base type of data */
+		};
+		struct dict_object		*type;
+		struct dict_type_data	 tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Media-Initiator-Flag)", NULL, NULL, NULL };
+		CHECK_dict_new(DICT_TYPE, &tdata, NULL, &type);
+		CHECK_dict_new(DICT_AVP, &data, type, NULL);
+	};
+
+	/* Media-Initiator-Party */
+	{
+		struct dict_avp_data data = {
+			1288,	/* Code */
+			10415,	/* Vendor */
+			"Media-Initiator-Party",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, UTF8String_type, NULL);
+	};
+
+	/* Message-Body */
+	{
+		struct dict_avp_data data = {
+			889,	/* Code */
+			10415,	/* Vendor */
+			"Message-Body",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_GROUPED	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* Message-Class */
+	{
+		struct dict_avp_data data = {
+			1213,	/* Code */
+			10415,	/* Vendor */
+			"Message-Class",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_GROUPED	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* Message-ID */
+	{
+		struct dict_avp_data data = {
+			1210,	/* Code */
+			10415,	/* Vendor */
+			"Message-ID",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, UTF8String_type, NULL);
+	};
+
+	/* Message-Size */
+	{
+		struct dict_avp_data data = {
+			1212,	/* Code */
+			10415,	/* Vendor */
+			"Message-Size",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_UNSIGNED32	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* Message-Type */
+	{
+		struct dict_avp_data data = {
+			1211,	/* Code */
+			10415,	/* Vendor */
+			"Message-Type",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_INTEGER32	/* base type of data */
+		};
+		struct dict_object		*type;
+		struct dict_type_data	 tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Message-Type)", NULL, NULL, NULL };
+		CHECK_dict_new(DICT_TYPE, &tdata, NULL, &type);
+		CHECK_dict_new(DICT_AVP, &data, type, NULL);
+	};
+
+	/* NNI-Information */
+	{
+		struct dict_avp_data data = {
+			2703,	/* Code */
+			10415,	/* Vendor */
+			"NNI-Information",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_GROUPED	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* NNI-Type */
+	{
+		struct dict_avp_data data = {
+			2704,	/* Code */
+			10415,	/* Vendor */
+			"NNI-Type",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_INTEGER32	/* base type of data */
+		};
+		struct dict_object		*type;
+		struct dict_type_data	 tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(NNI-Type)", NULL, NULL, NULL };
+		CHECK_dict_new(DICT_TYPE, &tdata, NULL, &type);
+		CHECK_dict_new(DICT_AVP, &data, type, NULL);
+	};
+
+	/* Neighbour-Node-Address */
+	{
+		struct dict_avp_data data = {
+			2705,	/* Code */
+			10415,	/* Vendor */
+			"Neighbour-Node-Address",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, Address_type, NULL);
+	};
+
+	/* Next-Tariff */
+	{
+		struct dict_avp_data data = {
+			2057,	/* Code */
+			10415,	/* Vendor */
+			"Next-Tariff",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_GROUPED	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* Node-Functionality */
+	{
+		struct dict_avp_data data = {
+			862,	/* Code */
+			10415,	/* Vendor */
+			"Node-Functionality",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_INTEGER32	/* base type of data */
+		};
+		struct dict_object		*type;
+		struct dict_type_data	 tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Node-Functionality)", NULL, NULL, NULL };
+		CHECK_dict_new(DICT_TYPE, &tdata, NULL, &type);
+		CHECK_dict_new(DICT_AVP, &data, type, NULL);
+	};
+
+	/* Node-Id */
+	{
+		struct dict_avp_data data = {
+			2064,	/* Code */
+			10415,	/* Vendor */
+			"Node-Id",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, UTF8String_type, NULL);
+	};
+
+	/* Number-Of-Diversions */
+	{
+		struct dict_avp_data data = {
+			2034,	/* Code */
+			10415,	/* Vendor */
+			"Number-Of-Diversions",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_UNSIGNED32	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* Number-Of-Messages-Sent */
+	{
+		struct dict_avp_data data = {
+			2019,	/* Code */
+			10415,	/* Vendor */
+			"Number-Of-Messages-Sent",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_UNSIGNED32	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* Number-Of-Participants */
+	{
+		struct dict_avp_data data = {
+			885,	/* Code */
+			10415,	/* Vendor */
+			"Number-Of-Participants",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_UNSIGNED32	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* Number-Of-Received-Talk-Bursts */
+	{
+		struct dict_avp_data data = {
+			1282,	/* Code */
+			10415,	/* Vendor */
+			"Number-Of-Received-Talk-Bursts",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_UNSIGNED32	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* Number-Of-Talk-Bursts */
+	{
+		struct dict_avp_data data = {
+			1283,	/* Code */
+			10415,	/* Vendor */
+			"Number-Of-Talk-Bursts",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_UNSIGNED32	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* Number-Portability-Routing-Information */
+	{
+		struct dict_avp_data data = {
+			2024,	/* Code */
+			10415,	/* Vendor */
+			"Number-Portability-Routing-Information",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, UTF8String_type, NULL);
+	};
+
+	/* Offline-Charging */
+	{
+		struct dict_avp_data data = {
+			1278,	/* Code */
+			10415,	/* Vendor */
+			"Offline-Charging",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_GROUPED	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* Online-Charging-Flag */
+	{
+		struct dict_avp_data data = {
+			2303,	/* Code */
+			10415,	/* Vendor */
+			"Online-Charging-Flag",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_INTEGER32	/* base type of data */
+		};
+		struct dict_object		*type;
+		struct dict_type_data	 tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Online-Charging-Flag)", NULL, NULL, NULL };
+		CHECK_dict_new(DICT_TYPE, &tdata, NULL, &type);
+		CHECK_dict_new(DICT_AVP, &data, type, NULL);
+	};
+
+	/* Originating-IOI */
+	{
+		struct dict_avp_data data = {
+			839,	/* Code */
+			10415,	/* Vendor */
+			"Originating-IOI",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, UTF8String_type, NULL);
+	};
+
+	/* Originator */
+	{
+		struct dict_avp_data data = {
+			864,	/* Code */
+			10415,	/* Vendor */
+			"Originator",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_INTEGER32	/* base type of data */
+		};
+		struct dict_object		*type;
+		struct dict_type_data	 tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Originator)", NULL, NULL, NULL };
+		CHECK_dict_new(DICT_TYPE, &tdata, NULL, &type);
+		CHECK_dict_new(DICT_AVP, &data, type, NULL);
+	};
+
+	/* Originator-Address */
+	{
+		struct dict_avp_data data = {
+			886,	/* Code */
+			10415,	/* Vendor */
+			"Originator-Address",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_GROUPED	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* Originator-Interface */
+	{
+		struct dict_avp_data data = {
+			2009,	/* Code */
+			10415,	/* Vendor */
+			"Originator-Interface",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_GROUPED	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* Originator-Received-Address */
+	{
+		struct dict_avp_data data = {
+			2027,	/* Code */
+			10415,	/* Vendor */
+			"Originator-Received-Address",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_GROUPED	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* Originator-SCCP-Address */
+	{
+		struct dict_avp_data data = {
+			2008,	/* Code */
+			10415,	/* Vendor */
+			"Originator-SCCP-Address",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, Address_type, NULL);
+	};
+
+	/* Outgoing-Session-Id */
+	{
+		struct dict_avp_data data = {
+			2320,	/* Code */
+			10415,	/* Vendor */
+			"Outgoing-Session-Id",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, UTF8String_type, NULL);
+	};
+
+	/* Outgoing-Trunk-Group-Id */
+	{
+		struct dict_avp_data data = {
+			853,	/* Code */
+			10415,	/* Vendor */
+			"Outgoing-Trunk-Group-Id",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, UTF8String_type, NULL);
+	};
+
+	/* PDG-Address */
+	{
+		struct dict_avp_data data = {
+			895,	/* Code */
+			10415,	/* Vendor */
+			"PDG-Address",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, Address_type, NULL);
+	};
+
+	/* PDG-Charging-Id */
+	{
+		struct dict_avp_data data = {
+			896,	/* Code */
+			10415,	/* Vendor */
+			"PDG-Charging-Id",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_UNSIGNED32	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* PDN-Connection-Charging-ID */
+	{
+		struct dict_avp_data data = {
+			2050,	/* Code */
+			10415,	/* Vendor */
+			"PDN-Connection-Charging-ID",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_UNSIGNED32	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* PDP-Address */
+	{
+		struct dict_avp_data data = {
+			1227,	/* Code */
+			10415,	/* Vendor */
+			"PDP-Address",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, Address_type, NULL);
+	};
+
+	/* PDP-Address-Prefix-Length */
+	{
+		struct dict_avp_data data = {
+			2606,	/* Code */
+			10415,	/* Vendor */
+			"PDP-Address-Prefix-Length",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_UNSIGNED32	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* PDP-Context-Type */
+	{
+		struct dict_avp_data data = {
+			1247,	/* Code */
+			10415,	/* Vendor */
+			"PDP-Context-Type",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_INTEGER32	/* base type of data */
+		};
+		struct dict_object		*type;
+		struct dict_type_data	 tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(PDP-Context-Type)", NULL, NULL, NULL };
+		CHECK_dict_new(DICT_TYPE, &tdata, NULL, &type);
+		CHECK_dict_new(DICT_AVP, &data, type, NULL);
+	};
+
+	/* PS-Append-Free-Format-Data */
+	{
+		struct dict_avp_data data = {
+			867,	/* Code */
+			10415,	/* Vendor */
+			"PS-Append-Free-Format-Data",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_INTEGER32	/* base type of data */
+		};
+		struct dict_object		*type;
+		struct dict_type_data	 tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(PS-Append-Free-Format-Data)", NULL, NULL, NULL };
+		CHECK_dict_new(DICT_TYPE, &tdata, NULL, &type);
+		CHECK_dict_new(DICT_AVP, &data, type, NULL);
+	};
+
+	/* PS-Free-Format-Data */
+	{
+		struct dict_avp_data data = {
+			866,	/* Code */
+			10415,	/* Vendor */
+			"PS-Free-Format-Data",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* PS-Furnish-Charging-Information */
+	{
+		struct dict_avp_data data = {
+			865,	/* Code */
+			10415,	/* Vendor */
+			"PS-Furnish-Charging-Information",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_GROUPED	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* PS-Information */
+	{
+		struct dict_avp_data data = {
+			874,	/* Code */
+			10415,	/* Vendor */
+			"PS-Information",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_GROUPED	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* Participant-Access-Priority */
+	{
+		struct dict_avp_data data = {
+			1259,	/* Code */
+			10415,	/* Vendor */
+			"Participant-Access-Priority",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_INTEGER32	/* base type of data */
+		};
+		struct dict_object		*type;
+		struct dict_type_data	 tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Participant-Access-Priority)", NULL, NULL, NULL };
+		CHECK_dict_new(DICT_TYPE, &tdata, NULL, &type);
+		CHECK_dict_new(DICT_AVP, &data, type, NULL);
+	};
+
+	/* Participant-Action-Type */
+	{
+		struct dict_avp_data data = {
+			2049,	/* Code */
+			10415,	/* Vendor */
+			"Participant-Action-Type",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_INTEGER32	/* base type of data */
+		};
+		struct dict_object		*type;
+		struct dict_type_data	 tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Participant-Action-Type)", NULL, NULL, NULL };
+		CHECK_dict_new(DICT_TYPE, &tdata, NULL, &type);
+		CHECK_dict_new(DICT_AVP, &data, type, NULL);
+	};
+
+	/* Participant-Group */
+	{
+		struct dict_avp_data data = {
+			1260,	/* Code */
+			10415,	/* Vendor */
+			"Participant-Group",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_GROUPED	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* Participants-Involved */
+	{
+		struct dict_avp_data data = {
+			887,	/* Code */
+			10415,	/* Vendor */
+			"Participants-Involved",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, UTF8String_type, NULL);
+	};
+
+	/* PoC-Change-Condition */
+	{
+		struct dict_avp_data data = {
+			1261,	/* Code */
+			10415,	/* Vendor */
+			"PoC-Change-Condition",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_INTEGER32	/* base type of data */
+		};
+		struct dict_object		*type;
+		struct dict_type_data	 tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(PoC-Change-Condition)", NULL, NULL, NULL };
+		CHECK_dict_new(DICT_TYPE, &tdata, NULL, &type);
+		CHECK_dict_new(DICT_AVP, &data, type, NULL);
+	};
+
+	/* PoC-Change-Time */
+	{
+		struct dict_avp_data data = {
+			1262,	/* Code */
+			10415,	/* Vendor */
+			"PoC-Change-Time",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, Time_type, NULL);
+	};
+
+	/* PoC-Controlling-Address */
+	{
+		struct dict_avp_data data = {
+			858,	/* Code */
+			10415,	/* Vendor */
+			"PoC-Controlling-Address",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, UTF8String_type, NULL);
+	};
+
+	/* PoC-Event-Type */
+	{
+		struct dict_avp_data data = {
+			2025,	/* Code */
+			10415,	/* Vendor */
+			"PoC-Event-Type",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_INTEGER32	/* base type of data */
+		};
+		struct dict_object		*type;
+		struct dict_type_data	 tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(PoC-Event-Type)", NULL, NULL, NULL };
+		CHECK_dict_new(DICT_TYPE, &tdata, NULL, &type);
+		CHECK_dict_new(DICT_AVP, &data, type, NULL);
+	};
+
+	/* PoC-Group-Name */
+	{
+		struct dict_avp_data data = {
+			859,	/* Code */
+			10415,	/* Vendor */
+			"PoC-Group-Name",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, UTF8String_type, NULL);
+	};
+
+	/* PoC-Information */
+	{
+		struct dict_avp_data data = {
+			879,	/* Code */
+			10415,	/* Vendor */
+			"PoC-Information",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_GROUPED	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* PoC-Server-Role */
+	{
+		struct dict_avp_data data = {
+			883,	/* Code */
+			10415,	/* Vendor */
+			"PoC-Server-Role",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_INTEGER32	/* base type of data */
+		};
+		struct dict_object		*type;
+		struct dict_type_data	 tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(PoC-Server-Role)", NULL, NULL, NULL };
+		CHECK_dict_new(DICT_TYPE, &tdata, NULL, &type);
+		CHECK_dict_new(DICT_AVP, &data, type, NULL);
+	};
+
+	/* PoC-Session-Id */
+	{
+		struct dict_avp_data data = {
+			1229,	/* Code */
+			10415,	/* Vendor */
+			"PoC-Session-Id",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, UTF8String_type, NULL);
+	};
+
+	/* PoC-Session-Initiation-type */
+	{
+		struct dict_avp_data data = {
+			1277,	/* Code */
+			10415,	/* Vendor */
+			"PoC-Session-Initiation-type",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_INTEGER32	/* base type of data */
+		};
+		struct dict_object		*type;
+		struct dict_type_data	 tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(PoC-Session-Initiation-type)", NULL, NULL, NULL };
+		CHECK_dict_new(DICT_TYPE, &tdata, NULL, &type);
+		CHECK_dict_new(DICT_AVP, &data, type, NULL);
+	};
+
+	/* PoC-Session-Type */
+	{
+		struct dict_avp_data data = {
+			884,	/* Code */
+			10415,	/* Vendor */
+			"PoC-Session-Type",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_INTEGER32	/* base type of data */
+		};
+		struct dict_object		*type;
+		struct dict_type_data	 tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(PoC-Session-Type)", NULL, NULL, NULL };
+		CHECK_dict_new(DICT_TYPE, &tdata, NULL, &type);
+		CHECK_dict_new(DICT_AVP, &data, type, NULL);
+	};
+
+	/* PoC-User-Role */
+	{
+		struct dict_avp_data data = {
+			1252,	/* Code */
+			10415,	/* Vendor */
+			"PoC-User-Role",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_GROUPED	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* PoC-User-Role-IDs */
+	{
+		struct dict_avp_data data = {
+			1253,	/* Code */
+			10415,	/* Vendor */
+			"PoC-User-Role-IDs",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, UTF8String_type, NULL);
+	};
+
+	/* PoC-User-Role-info-Units */
+	{
+		struct dict_avp_data data = {
+			1254,	/* Code */
+			10415,	/* Vendor */
+			"PoC-User-Role-info-Units",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_INTEGER32	/* base type of data */
+		};
+		struct dict_object		*type;
+		struct dict_type_data	 tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(PoC-User-Role-info-Units)", NULL, NULL, NULL };
+		CHECK_dict_new(DICT_TYPE, &tdata, NULL, &type);
+		CHECK_dict_new(DICT_AVP, &data, type, NULL);
+	};
+
+	/* Positioning-Data */
+	{
+		struct dict_avp_data data = {
+			1245,	/* Code */
+			10415,	/* Vendor */
+			"Positioning-Data",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, UTF8String_type, NULL);
+	};
+
+	/* Preferred-AoC-Currency */
+	{
+		struct dict_avp_data data = {
+			2315,	/* Code */
+			10415,	/* Vendor */
+			"Preferred-AoC-Currency",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_UNSIGNED32	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* Priority */
+	{
+		struct dict_avp_data data = {
+			1209,	/* Code */
+			10415,	/* Vendor */
+			"Priority",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_INTEGER32	/* base type of data */
+		};
+		struct dict_object		*type;
+		struct dict_type_data	 tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Priority)", NULL, NULL, NULL };
+		CHECK_dict_new(DICT_TYPE, &tdata, NULL, &type);
+		CHECK_dict_new(DICT_AVP, &data, type, NULL);
+	};
+
+	/* Quota-Consumption-Time */
+	{
+		struct dict_avp_data data = {
+			881,	/* Code */
+			10415,	/* Vendor */
+			"Quota-Consumption-Time",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_UNSIGNED32	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* Quota-Holding-Time */
+	{
+		struct dict_avp_data data = {
+			871,	/* Code */
+			10415,	/* Vendor */
+			"Quota-Holding-Time",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_UNSIGNED32	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* Rate-Element */
+	{
+		struct dict_avp_data data = {
+			2058,	/* Code */
+			10415,	/* Vendor */
+			"Rate-Element",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_GROUPED	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* Read-Reply-Report-Requested */
+	{
+		struct dict_avp_data data = {
+			1222,	/* Code */
+			10415,	/* Vendor */
+			"Read-Reply-Report-Requested",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_INTEGER32	/* base type of data */
+		};
+		struct dict_object		*type;
+		struct dict_type_data	 tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Read-Reply-Report-Requested)", NULL, NULL, NULL };
+		CHECK_dict_new(DICT_TYPE, &tdata, NULL, &type);
+		CHECK_dict_new(DICT_AVP, &data, type, NULL);
+	};
+
+	/* Real-Time-Tariff-Information */
+	{
+		struct dict_avp_data data = {
+			2305,	/* Code */
+			10415,	/* Vendor */
+			"Real-Time-Tariff-Information",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_GROUPED	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* Received-Talk-Burst-Time */
+	{
+		struct dict_avp_data data = {
+			1284,	/* Code */
+			10415,	/* Vendor */
+			"Received-Talk-Burst-Time",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_UNSIGNED32	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* Received-Talk-Burst-Volume */
+	{
+		struct dict_avp_data data = {
+			1285,	/* Code */
+			10415,	/* Vendor */
+			"Received-Talk-Burst-Volume",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_UNSIGNED32	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* Recipient-Address */
+	{
+		struct dict_avp_data data = {
+			1201,	/* Code */
+			10415,	/* Vendor */
+			"Recipient-Address",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_GROUPED	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* Recipient-Info */
+	{
+		struct dict_avp_data data = {
+			2026,	/* Code */
+			10415,	/* Vendor */
+			"Recipient-Info",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_GROUPED	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* Recipient-Received-Address */
+	{
+		struct dict_avp_data data = {
+			2028,	/* Code */
+			10415,	/* Vendor */
+			"Recipient-Received-Address",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_GROUPED	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* Recipient-SCCP-Address */
+	{
+		struct dict_avp_data data = {
+			2010,	/* Code */
+			10415,	/* Vendor */
+			"Recipient-SCCP-Address",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, Address_type, NULL);
+	};
+
+	/* Refund-Information */
+	{
+		struct dict_avp_data data = {
+			2022,	/* Code */
+			10415,	/* Vendor */
+			"Refund-Information",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* Relationship-Mode */
+	{
+		struct dict_avp_data data = {
+			2706,	/* Code */
+			10415,	/* Vendor */
+			"Relationship-Mode",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_INTEGER32	/* base type of data */
+		};
+		struct dict_object		*type;
+		struct dict_type_data	 tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Relationship-Mode)", NULL, NULL, NULL };
+		CHECK_dict_new(DICT_TYPE, &tdata, NULL, &type);
+		CHECK_dict_new(DICT_AVP, &data, type, NULL);
+	};
+
+	/* Remaining-Balance */
+	{
+		struct dict_avp_data data = {
+			2021,	/* Code */
+			10415,	/* Vendor */
+			"Remaining-Balance",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_GROUPED	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* Reply-Applic-ID */
+	{
+		struct dict_avp_data data = {
+			1223,	/* Code */
+			10415,	/* Vendor */
+			"Reply-Applic-ID",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, UTF8String_type, NULL);
+	};
+
+	/* Reply-Path-Requested */
+	{
+		struct dict_avp_data data = {
+			2011,	/* Code */
+			10415,	/* Vendor */
+			"Reply-Path-Requested",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_INTEGER32	/* base type of data */
+		};
+		struct dict_object		*type;
+		struct dict_type_data	 tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Reply-Path-Requested)", NULL, NULL, NULL };
+		CHECK_dict_new(DICT_TYPE, &tdata, NULL, &type);
+		CHECK_dict_new(DICT_AVP, &data, type, NULL);
+	};
+
+	/* Reporting-Reason */
+	{
+		struct dict_avp_data data = {
+			872,	/* Code */
+			10415,	/* Vendor */
+			"Reporting-Reason",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_INTEGER32	/* base type of data */
+		};
+		struct dict_object		*type;
+		struct dict_type_data	 tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Reporting-Reason)", NULL, NULL, NULL };
+		CHECK_dict_new(DICT_TYPE, &tdata, NULL, &type);
+		CHECK_dict_new(DICT_AVP, &data, type, NULL);
+	};
+
+	/* Requested-Party-Address */
+	{
+		struct dict_avp_data data = {
+			1251,	/* Code */
+			10415,	/* Vendor */
+			"Requested-Party-Address",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, UTF8String_type, NULL);
+	};
+
+	/* Role-Of-Node */
+	{
+		struct dict_avp_data data = {
+			829,	/* Code */
+			10415,	/* Vendor */
+			"Role-Of-Node",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_INTEGER32	/* base type of data */
+		};
+		struct dict_object		*type;
+		struct dict_type_data	 tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Role-Of-Node)", NULL, NULL, NULL };
+		CHECK_dict_new(DICT_TYPE, &tdata, NULL, &type);
+		CHECK_dict_new(DICT_AVP, &data, type, NULL);
+	};
+
+	/* SDP-Answer-Timestamp */
+	{
+		struct dict_avp_data data = {
+			1275,	/* Code */
+			10415,	/* Vendor */
+			"SDP-Answer-Timestamp",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, Time_type, NULL);
+	};
+
+	/* SDP-Media-Component */
+	{
+		struct dict_avp_data data = {
+			843,	/* Code */
+			10415,	/* Vendor */
+			"SDP-Media-Component",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_GROUPED	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* SDP-Media-Description */
+	{
+		struct dict_avp_data data = {
+			845,	/* Code */
+			10415,	/* Vendor */
+			"SDP-Media-Description",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, UTF8String_type, NULL);
+	};
+
+	/* SDP-Media-Name */
+	{
+		struct dict_avp_data data = {
+			844,	/* Code */
+			10415,	/* Vendor */
+			"SDP-Media-Name",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, UTF8String_type, NULL);
+	};
+
+	/* SDP-Offer-Timestamp */
+	{
+		struct dict_avp_data data = {
+			1274,	/* Code */
+			10415,	/* Vendor */
+			"SDP-Offer-Timestamp",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, Time_type, NULL);
+	};
+
+	/* SDP-Session-Description */
+	{
+		struct dict_avp_data data = {
+			842,	/* Code */
+			10415,	/* Vendor */
+			"SDP-Session-Description",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, UTF8String_type, NULL);
+	};
+
+	/* SDP-TimeStamps */
+	{
+		struct dict_avp_data data = {
+			1273,	/* Code */
+			10415,	/* Vendor */
+			"SDP-TimeStamps",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_GROUPED	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* SDP-Type */
+	{
+		struct dict_avp_data data = {
+			2036,	/* Code */
+			10415,	/* Vendor */
+			"SDP-Type",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_INTEGER32	/* base type of data */
+		};
+		struct dict_object		*type;
+		struct dict_type_data	 tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(SDP-Type)", NULL, NULL, NULL };
+		CHECK_dict_new(DICT_TYPE, &tdata, NULL, &type);
+		CHECK_dict_new(DICT_AVP, &data, type, NULL);
+	};
+
+	/* SGSN-Address */
+	{
+		struct dict_avp_data data = {
+			1228,	/* Code */
+			10415,	/* Vendor */
+			"SGSN-Address",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, Address_type, NULL);
+	};
+
+	/* SGW-Address */
+	{
+		struct dict_avp_data data = {
+			2067,	/* Code */
+			10415,	/* Vendor */
+			"SGW-Address",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, Address_type, NULL);
+	};
+
+	/* SGW-Change */
+	{
+		struct dict_avp_data data = {
+			2065,	/* Code */
+			10415,	/* Vendor */
+			"SGW-Change",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_INTEGER32	/* base type of data */
+		};
+		struct dict_object		*type;
+		struct dict_type_data	 tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(SGW-Change)", NULL, NULL, NULL };
+		CHECK_dict_new(DICT_TYPE, &tdata, NULL, &type);
+		CHECK_dict_new(DICT_AVP, &data, type, NULL);
+	};
+
+	/* SIP-Method */
+	{
+		struct dict_avp_data data = {
+			824,	/* Code */
+			10415,	/* Vendor */
+			"SIP-Method",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, UTF8String_type, NULL);
+	};
+
+	/* SIP-Request-Timestamp */
+	{
+		struct dict_avp_data data = {
+			834,	/* Code */
+			10415,	/* Vendor */
+			"SIP-Request-Timestamp",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, Time_type, NULL);
+	};
+
+	/* SIP-Request-Timestamp-Fraction */
+	{
+		struct dict_avp_data data = {
+			2301,	/* Code */
+			10415,	/* Vendor */
+			"SIP-Request-Timestamp-Fraction",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_UNSIGNED32	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* SIP-Response-Timestamp */
+	{
+		struct dict_avp_data data = {
+			835,	/* Code */
+			10415,	/* Vendor */
+			"SIP-Response-Timestamp",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, Time_type, NULL);
+	};
+
+	/* SIP-Response-Timestamp-Fraction */
+	{
+		struct dict_avp_data data = {
+			2302,	/* Code */
+			10415,	/* Vendor */
+			"SIP-Response-Timestamp-Fraction",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_UNSIGNED32	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* SM-Discharge-Time */
+	{
+		struct dict_avp_data data = {
+			2012,	/* Code */
+			10415,	/* Vendor */
+			"SM-Discharge-Time",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, Time_type, NULL);
+	};
+
+	/* SM-Message-Type */
+	{
+		struct dict_avp_data data = {
+			2007,	/* Code */
+			10415,	/* Vendor */
+			"SM-Message-Type",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_INTEGER32	/* base type of data */
+		};
+		struct dict_object		*type;
+		struct dict_type_data	 tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(SM-Message-Type)", NULL, NULL, NULL };
+		CHECK_dict_new(DICT_TYPE, &tdata, NULL, &type);
+		CHECK_dict_new(DICT_AVP, &data, type, NULL);
+	};
+
+	/* SM-Protocol-ID */
+	{
+		struct dict_avp_data data = {
+			2013,	/* Code */
+			10415,	/* Vendor */
+			"SM-Protocol-ID",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* SM-Service-Type */
+	{
+		struct dict_avp_data data = {
+			2029,	/* Code */
+			10415,	/* Vendor */
+			"SM-Service-Type",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_INTEGER32	/* base type of data */
+		};
+		struct dict_object		*type;
+		struct dict_type_data	 tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(SM-Service-Type)", NULL, NULL, NULL };
+		CHECK_dict_new(DICT_TYPE, &tdata, NULL, &type);
+		CHECK_dict_new(DICT_AVP, &data, type, NULL);
+	};
+
+	/* SM-Status */
+	{
+		struct dict_avp_data data = {
+			2014,	/* Code */
+			10415,	/* Vendor */
+			"SM-Status",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* SM-User-Data-Header */
+	{
+		struct dict_avp_data data = {
+			2015,	/* Code */
+			10415,	/* Vendor */
+			"SM-User-Data-Header",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* SMS-Information */
+	{
+		struct dict_avp_data data = {
+			2000,	/* Code */
+			10415,	/* Vendor */
+			"SMS-Information",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_GROUPED	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* SMS-Node */
+	{
+		struct dict_avp_data data = {
+			2016,	/* Code */
+			10415,	/* Vendor */
+			"SMS-Node",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_INTEGER32	/* base type of data */
+		};
+		struct dict_object		*type;
+		struct dict_type_data	 tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(SMS-Node)", NULL, NULL, NULL };
+		CHECK_dict_new(DICT_TYPE, &tdata, NULL, &type);
+		CHECK_dict_new(DICT_AVP, &data, type, NULL);
+	};
+
+	/* SMSC-Address */
+	{
+		struct dict_avp_data data = {
+			2017,	/* Code */
+			10415,	/* Vendor */
+			"SMSC-Address",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, Address_type, NULL);
+	};
+
+	/* Scale-Factor */
+	{
+		struct dict_avp_data data = {
+			2059,	/* Code */
+			10415,	/* Vendor */
+			"Scale-Factor",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_GROUPED	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* Served-Party-IP-Address */
+	{
+		struct dict_avp_data data = {
+			848,	/* Code */
+			10415,	/* Vendor */
+			"Served-Party-IP-Address",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, Address_type, NULL);
+	};
+
+	/* Service-Data-Container */
+	{
+		struct dict_avp_data data = {
+			2040,	/* Code */
+			10415,	/* Vendor */
+			"Service-Data-Container",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_GROUPED	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* Service-Id */
+	{
+		struct dict_avp_data data = {
+			855,	/* Code */
+			10415,	/* Vendor */
+			"Service-Id",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, UTF8String_type, NULL);
+	};
+
+	/* Service-Information */
+	{
+		struct dict_avp_data data = {
+			873,	/* Code */
+			10415,	/* Vendor */
+			"Service-Information",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_GROUPED	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* Service-Mode */
+	{
+		struct dict_avp_data data = {
+			2032,	/* Code */
+			10415,	/* Vendor */
+			"Service-Mode",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_UNSIGNED32	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* Service-Specific-Data */
+	{
+		struct dict_avp_data data = {
+			863,	/* Code */
+			10415,	/* Vendor */
+			"Service-Specific-Data",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, UTF8String_type, NULL);
+	};
+
+	/* Service-Specific-Info */
+	{
+		struct dict_avp_data data = {
+			1249,	/* Code */
+			10415,	/* Vendor */
+			"Service-Specific-Info",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_GROUPED	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* Service-Specific-Type */
+	{
+		struct dict_avp_data data = {
+			1257,	/* Code */
+			10415,	/* Vendor */
+			"Service-Specific-Type",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_UNSIGNED32	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* Serving-Node-Type */
+	{
+		struct dict_avp_data data = {
+			2047,	/* Code */
+			10415,	/* Vendor */
+			"Serving-Node-Type",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_INTEGER32	/* base type of data */
+		};
+		struct dict_object		*type;
+		struct dict_type_data	 tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Serving-Node-Type)", NULL, NULL, NULL };
+		CHECK_dict_new(DICT_TYPE, &tdata, NULL, &type);
+		CHECK_dict_new(DICT_AVP, &data, type, NULL);
+	};
+
+	/* Session-Direction */
+	{
+		struct dict_avp_data data = {
+			2707,	/* Code */
+			10415,	/* Vendor */
+			"Session-Direction",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_INTEGER32	/* base type of data */
+		};
+		struct dict_object		*type;
+		struct dict_type_data	 tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Session-Direction)", NULL, NULL, NULL };
+		CHECK_dict_new(DICT_TYPE, &tdata, NULL, &type);
+		CHECK_dict_new(DICT_AVP, &data, type, NULL);
+	};
+
+	/* Start-Time */
+	{
+		struct dict_avp_data data = {
+			2041,	/* Code */
+			10415,	/* Vendor */
+			"Start-Time",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, Time_type, NULL);
+	};
+
+	/* Status */
+	{
+		struct dict_avp_data data = {
+			2702,	/* Code */
+			10415,	/* Vendor */
+			"Status",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_INTEGER32	/* base type of data */
+		};
+		struct dict_object		*type;
+		struct dict_type_data	 tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Status)", NULL, NULL, NULL };
+		CHECK_dict_new(DICT_TYPE, &tdata, NULL, &type);
+		CHECK_dict_new(DICT_AVP, &data, type, NULL);
+	};
+
+	/* Stop-Time */
+	{
+		struct dict_avp_data data = {
+			2042,	/* Code */
+			10415,	/* Vendor */
+			"Stop-Time",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, Time_type, NULL);
+	};
+
+	/* Submission-Time */
+	{
+		struct dict_avp_data data = {
+			1202,	/* Code */
+			10415,	/* Vendor */
+			"Submission-Time",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, Time_type, NULL);
+	};
+
+	/* Subscriber-Role */
+	{
+		struct dict_avp_data data = {
+			2033,	/* Code */
+			10415,	/* Vendor */
+			"Subscriber-Role",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_INTEGER32	/* base type of data */
+		};
+		struct dict_object		*type;
+		struct dict_type_data	 tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Subscriber-Role)", NULL, NULL, NULL };
+		CHECK_dict_new(DICT_TYPE, &tdata, NULL, &type);
+		CHECK_dict_new(DICT_AVP, &data, type, NULL);
+	};
+
+	/* Supplementary-Service */
+	{
+		struct dict_avp_data data = {
+			2048,	/* Code */
+			10415,	/* Vendor */
+			"Supplementary-Service",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_GROUPED	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* Talk-Burst-Exchange */
+	{
+		struct dict_avp_data data = {
+			1255,	/* Code */
+			10415,	/* Vendor */
+			"Talk-Burst-Exchange",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_GROUPED	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* Talk-Burst-Time */
+	{
+		struct dict_avp_data data = {
+			1286,	/* Code */
+			10415,	/* Vendor */
+			"Talk-Burst-Time",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_UNSIGNED32	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* Talk-Burst-Volume */
+	{
+		struct dict_avp_data data = {
+			1287,	/* Code */
+			10415,	/* Vendor */
+			"Talk-Burst-Volume",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_UNSIGNED32	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* Tariff-Information */
+	{
+		struct dict_avp_data data = {
+			2060,	/* Code */
+			10415,	/* Vendor */
+			"Tariff-Information",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_GROUPED	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* Tariff-XML */
+	{
+		struct dict_avp_data data = {
+			2306,	/* Code */
+			10415,	/* Vendor */
+			"Tariff-XML",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, UTF8String_type, NULL);
+	};
+
+	/* Terminating-IOI */
+	{
+		struct dict_avp_data data = {
+			840,	/* Code */
+			10415,	/* Vendor */
+			"Terminating-IOI",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, UTF8String_type, NULL);
+	};
+
+	/* Time-First-Usage */
+	{
+		struct dict_avp_data data = {
+			2043,	/* Code */
+			10415,	/* Vendor */
+			"Time-First-Usage",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, Time_type, NULL);
+	};
+
+	/* Time-Last-Usage */
+	{
+		struct dict_avp_data data = {
+			2044,	/* Code */
+			10415,	/* Vendor */
+			"Time-Last-Usage",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, Time_type, NULL);
+	};
+
+	/* Time-Quota-Mechanism */
+	{
+		struct dict_avp_data data = {
+			1270,	/* Code */
+			10415,	/* Vendor */
+			"Time-Quota-Mechanism",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_GROUPED	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* Time-Quota-Threshold */
+	{
+		struct dict_avp_data data = {
+			868,	/* Code */
+			10415,	/* Vendor */
+			"Time-Quota-Threshold",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_UNSIGNED32	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* Time-Quota-Type */
+	{
+		struct dict_avp_data data = {
+			1271,	/* Code */
+			10415,	/* Vendor */
+			"Time-Quota-Type",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_INTEGER32	/* base type of data */
+		};
+		struct dict_object		*type;
+		struct dict_type_data	 tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Time-Quota-Type)", NULL, NULL, NULL };
+		CHECK_dict_new(DICT_TYPE, &tdata, NULL, &type);
+		CHECK_dict_new(DICT_AVP, &data, type, NULL);
+	};
+
+	/* Time-Stamps */
+	{
+		struct dict_avp_data data = {
+			833,	/* Code */
+			10415,	/* Vendor */
+			"Time-Stamps",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_GROUPED	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* Time-Usage */
+	{
+		struct dict_avp_data data = {
+			2045,	/* Code */
+			10415,	/* Vendor */
+			"Time-Usage",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_UNSIGNED32	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* Token-Text */
+	{
+		struct dict_avp_data data = {
+			1215,	/* Code */
+			10415,	/* Vendor */
+			"Token-Text",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, UTF8String_type, NULL);
+	};
+
+	/* Traffic-Data-Volumes */
+	{
+		struct dict_avp_data data = {
+			2046,	/* Code */
+			10415,	/* Vendor */
+			"Traffic-Data-Volumes",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_GROUPED	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* Transcoder-Inserted-Indication */
+	{
+		struct dict_avp_data data = {
+			2605,	/* Code */
+			10415,	/* Vendor */
+			"Transcoder-Inserted-Indication",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_INTEGER32	/* base type of data */
+		};
+		struct dict_object		*type;
+		struct dict_type_data	 tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Transcoder-Inserted-Indication)", NULL, NULL, NULL };
+		CHECK_dict_new(DICT_TYPE, &tdata, NULL, &type);
+		CHECK_dict_new(DICT_AVP, &data, type, NULL);
+	};
+
+	/* Transit-IOI-List */
+	{
+		struct dict_avp_data data = {
+			2701,	/* Code */
+			10415,	/* Vendor */
+			"Transit-IOI-List",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, UTF8String_type, NULL);
+	};
+
+	/* Trigger */
+	{
+		struct dict_avp_data data = {
+			1264,	/* Code */
+			10415,	/* Vendor */
+			"Trigger",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_GROUPED	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* Trigger-Type */
+	{
+		struct dict_avp_data data = {
+			870,	/* Code */
+			10415,	/* Vendor */
+			"Trigger-Type",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_INTEGER32	/* base type of data */
+		};
+		struct dict_object		*type;
+		struct dict_type_data	 tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Trigger-Type)", NULL, NULL, NULL };
+		CHECK_dict_new(DICT_TYPE, &tdata, NULL, &type);
+		CHECK_dict_new(DICT_AVP, &data, type, NULL);
+	};
+
+	/* Trunk-Group-Id */
+	{
+		struct dict_avp_data data = {
+			851,	/* Code */
+			10415,	/* Vendor */
+			"Trunk-Group-Id",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_GROUPED	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* Type-Number */
+	{
+		struct dict_avp_data data = {
+			1204,	/* Code */
+			10415,	/* Vendor */
+			"Type-Number",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_INTEGER32	/* base type of data */
+		};
+		struct dict_object		*type;
+		struct dict_type_data	 tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Type-Number)", NULL, NULL, NULL };
+		CHECK_dict_new(DICT_TYPE, &tdata, NULL, &type);
+		CHECK_dict_new(DICT_AVP, &data, type, NULL);
+	};
+
+	/* Unit-Cost */
+	{
+		struct dict_avp_data data = {
+			2061,	/* Code */
+			10415,	/* Vendor */
+			"Unit-Cost",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_GROUPED	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* Unit-Quota-Threshold */
+	{
+		struct dict_avp_data data = {
+			1226,	/* Code */
+			10415,	/* Vendor */
+			"Unit-Quota-Threshold",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_UNSIGNED32	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* User-CSG-Information */
+	{
+		struct dict_avp_data data = {
+			2319,	/* Code */
+			10415,	/* Vendor */
+			"User-CSG-Information",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_GROUPED	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* User-Participating-Type */
+	{
+		struct dict_avp_data data = {
+			1279,	/* Code */
+			10415,	/* Vendor */
+			"User-Participating-Type",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_INTEGER32	/* base type of data */
+		};
+		struct dict_object		*type;
+		struct dict_type_data	 tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(User-Participating-Type)", NULL, NULL, NULL };
+		CHECK_dict_new(DICT_TYPE, &tdata, NULL, &type);
+		CHECK_dict_new(DICT_AVP, &data, type, NULL);
+	};
+
+	/* User-Session-Id */
+	{
+		struct dict_avp_data data = {
+			830,	/* Code */
+			10415,	/* Vendor */
+			"User-Session-Id",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, UTF8String_type, NULL);
+	};
+
+	/* Volume-Quota-Threshold */
+	{
+		struct dict_avp_data data = {
+			869,	/* Code */
+			10415,	/* Vendor */
+			"Volume-Quota-Threshold",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_UNSIGNED32	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* WAG-Address */
+	{
+		struct dict_avp_data data = {
+			890,	/* Code */
+			10415,	/* Vendor */
+			"WAG-Address",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, Address_type, NULL);
+	};
+
+	/* WAG-PLMN-Id */
+	{
+		struct dict_avp_data data = {
+			891,	/* Code */
+			10415,	/* Vendor */
+			"WAG-PLMN-Id",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* WLAN-Information */
+	{
+		struct dict_avp_data data = {
+			875,	/* Code */
+			10415,	/* Vendor */
+			"WLAN-Information",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_GROUPED	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* WLAN-Radio-Container */
+	{
+		struct dict_avp_data data = {
+			892,	/* Code */
+			10415,	/* Vendor */
+			"WLAN-Radio-Container",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_GROUPED	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* WLAN-Session-Id */
+	{
+		struct dict_avp_data data = {
+			1246,	/* Code */
+			10415,	/* Vendor */
+			"WLAN-Session-Id",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, UTF8String_type, NULL);
+	};
+
+	/* WLAN-Technology */
+	{
+		struct dict_avp_data data = {
+			893,	/* Code */
+			10415,	/* Vendor */
+			"WLAN-Technology",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_UNSIGNED32	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* WLAN-UE-Local-IPAddress */
+	{
+		struct dict_avp_data data = {
+			894,	/* Code */
+			10415,	/* Vendor */
+			"WLAN-UE-Local-IPAddress",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, Address_type, NULL);
+	};
+
+	/* 3GPP 29.272-c00 (12.0.0 2013.03.13)                          */
+	/* Subscription-Data */
+	{
+		struct dict_avp_data data = {
+			1400,	/* Code */
+			10415,	/* Vendor */
+			"Subscription-Data",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_GROUPED	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* Terminal-Information */
+	{
+		struct dict_avp_data data = {
+			1401,	/* Code */
+			10415,	/* Vendor */
+			"Terminal-Information",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_GROUPED	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* IMEI */
+	{
+		struct dict_avp_data data = {
+			1402,	/* Code */
+			10415,	/* Vendor */
+			"IMEI",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, UTF8String_type, NULL);
+	};
+
+	/* Software-Version */
+	{
+		struct dict_avp_data data = {
+			1403,	/* Code */
+			10415,	/* Vendor */
+			"Software-Version",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, UTF8String_type, NULL);
+	};
+
+	/* QoS-Subscribed */
+	{
+		struct dict_avp_data data = {
+			1404,	/* Code */
+			10415,	/* Vendor */
+			"QoS-Subscribed",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* ULR-Flags */
+	{
+		struct dict_avp_data data = {
+			1405,	/* Code */
+			10415,	/* Vendor */
+			"ULR-Flags",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_UNSIGNED32	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* ULA-Flags */
+	{
+		struct dict_avp_data data = {
+			1406,	/* Code */
+			10415,	/* Vendor */
+			"ULA-Flags",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_UNSIGNED32	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* Visited-PLMN-Id */
+	{
+		struct dict_avp_data data = {
+			1407,	/* Code */
+			10415,	/* Vendor */
+			"Visited-PLMN-Id",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* Requested-EUTRAN-Authentication-Info */
+	{
+		struct dict_avp_data data = {
+			1408,	/* Code */
+			10415,	/* Vendor */
+			"Requested-EUTRAN-Authentication-Info",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_GROUPED	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* Requested-UTRAN-GERAN-Authentication-Info */
+	{
+		struct dict_avp_data data = {
+			1409,	/* Code */
+			10415,	/* Vendor */
+			"Requested-UTRAN-GERAN-Authentication-Info",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_GROUPED	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* Number-Of-Requested-Vectors */
+	{
+		struct dict_avp_data data = {
+			1410,	/* Code */
+			10415,	/* Vendor */
+			"Number-Of-Requested-Vectors",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_UNSIGNED32	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* Re-Synchronization-Info */
+	{
+		struct dict_avp_data data = {
+			1411,	/* Code */
+			10415,	/* Vendor */
+			"Re-Synchronization-Info",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* Immediate-Response-Preferred */
+	{
+		struct dict_avp_data data = {
+			1412,	/* Code */
+			10415,	/* Vendor */
+			"Immediate-Response-Preferred",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_UNSIGNED32	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* Authentication-Info */
+	{
+		struct dict_avp_data data = {
+			1413,	/* Code */
+			10415,	/* Vendor */
+			"Authentication-Info",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_GROUPED	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* E-UTRAN-Vector */
+	{
+		struct dict_avp_data data = {
+			1414,	/* Code */
+			10415,	/* Vendor */
+			"E-UTRAN-Vector",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_GROUPED	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* UTRAN-Vector */
+	{
+		struct dict_avp_data data = {
+			1415,	/* Code */
+			10415,	/* Vendor */
+			"UTRAN-Vector",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_GROUPED	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* GERAN-Vector */
+	{
+		struct dict_avp_data data = {
+			1416,	/* Code */
+			10415,	/* Vendor */
+			"GERAN-Vector",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_GROUPED	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* Network-Access-Mode */
+	{
+		struct dict_avp_data data = {
+			1417,	/* Code */
+			10415,	/* Vendor */
+			"Network-Access-Mode",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_INTEGER32	/* base type of data */
+		};
+		struct dict_object		*type;
+		struct dict_type_data	 tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Network-Access-Mode)", NULL, NULL, NULL };
+		CHECK_dict_new(DICT_TYPE, &tdata, NULL, &type);
+		CHECK_dict_new(DICT_AVP, &data, type, NULL);
+	};
+
+	/* HPLMN-ODB */
+	{
+		struct dict_avp_data data = {
+			1418,	/* Code */
+			10415,	/* Vendor */
+			"HPLMN-ODB",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_UNSIGNED32	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* Item-Number */
+	{
+		struct dict_avp_data data = {
+			1419,	/* Code */
+			10415,	/* Vendor */
+			"Item-Number",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_UNSIGNED32	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* Cancellation-Type */
+	{
+		struct dict_avp_data data = {
+			1420,	/* Code */
+			10415,	/* Vendor */
+			"Cancellation-Type",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_INTEGER32	/* base type of data */
+		};
+		struct dict_object		*type;
+		struct dict_type_data	 tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Cancellation-Type)", NULL, NULL, NULL };
+		CHECK_dict_new(DICT_TYPE, &tdata, NULL, &type);
+		CHECK_dict_new(DICT_AVP, &data, type, NULL);
+	};
+
+	/* DSR-Flags */
+	{
+		struct dict_avp_data data = {
+			1421,	/* Code */
+			10415,	/* Vendor */
+			"DSR-Flags",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_UNSIGNED32	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* DSA-Flags */
+	{
+		struct dict_avp_data data = {
+			1422,	/* Code */
+			10415,	/* Vendor */
+			"DSA-Flags",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_UNSIGNED32	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* Context-Identifier */
+	{
+		struct dict_avp_data data = {
+			1423,	/* Code */
+			10415,	/* Vendor */
+			"Context-Identifier",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_UNSIGNED32	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* Subscriber-Status */
+	{
+		struct dict_avp_data data = {
+			1424,	/* Code */
+			10415,	/* Vendor */
+			"Subscriber-Status",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_INTEGER32	/* base type of data */
+		};
+		struct dict_object		*type;
+		struct dict_type_data	 tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Subscriber-Status)", NULL, NULL, NULL };
+		CHECK_dict_new(DICT_TYPE, &tdata, NULL, &type);
+		CHECK_dict_new(DICT_AVP, &data, type, NULL);
+	};
+
+	/* Operator-Determined-Barring */
+	{
+		struct dict_avp_data data = {
+			1425,	/* Code */
+			10415,	/* Vendor */
+			"Operator-Determined-Barring",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_UNSIGNED32	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* Access-Restriction-Data */
+	{
+		struct dict_avp_data data = {
+			1426,	/* Code */
+			10415,	/* Vendor */
+			"Access-Restriction-Data",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_UNSIGNED32	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* APN-OI-Replacement */
+	{
+		struct dict_avp_data data = {
+			1427,	/* Code */
+			10415,	/* Vendor */
+			"APN-OI-Replacement",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, UTF8String_type, NULL);
+	};
+
+	/* All-APN-Configurations-Included-Indicator */
+	{
+		struct dict_avp_data data = {
+			1428,	/* Code */
+			10415,	/* Vendor */
+			"All-APN-Configurations-Included-Indicator",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_INTEGER32	/* base type of data */
+		};
+		struct dict_object		*type;
+		struct dict_type_data	 tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(All-APN-Configurations-Included-Indicator)", NULL, NULL, NULL };
+		CHECK_dict_new(DICT_TYPE, &tdata, NULL, &type);
+		CHECK_dict_new(DICT_AVP, &data, type, NULL);
+	};
+
+	/* APN-Configuration-Profile */
+	{
+		struct dict_avp_data data = {
+			1429,	/* Code */
+			10415,	/* Vendor */
+			"APN-Configuration-Profile",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_GROUPED	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* APN-Configuration */
+	{
+		struct dict_avp_data data = {
+			1430,	/* Code */
+			10415,	/* Vendor */
+			"APN-Configuration",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_GROUPED	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* EPS-Subscribed-QoS-Profile */
+	{
+		struct dict_avp_data data = {
+			1431,	/* Code */
+			10415,	/* Vendor */
+			"EPS-Subscribed-QoS-Profile",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_GROUPED	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* VPLMN-Dynamic-Address-Allowed */
+	{
+		struct dict_avp_data data = {
+			1432,	/* Code */
+			10415,	/* Vendor */
+			"VPLMN-Dynamic-Address-Allowed",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_INTEGER32	/* base type of data */
+		};
+		struct dict_object		*type;
+		struct dict_type_data	 tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(VPLMN-Dynamic-Address-Allowed)", NULL, NULL, NULL };
+		CHECK_dict_new(DICT_TYPE, &tdata, NULL, &type);
+		CHECK_dict_new(DICT_AVP, &data, type, NULL);
+	};
+
+	/* STN-SR */
+	{
+		struct dict_avp_data data = {
+			1433,	/* Code */
+			10415,	/* Vendor */
+			"STN-SR",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* Alert-Reason */
+	{
+		struct dict_avp_data data = {
+			1434,	/* Code */
+			10415,	/* Vendor */
+			"Alert-Reason",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_INTEGER32	/* base type of data */
+		};
+		struct dict_object		*type;
+		struct dict_type_data	 tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Alert-Reason)", NULL, NULL, NULL };
+		CHECK_dict_new(DICT_TYPE, &tdata, NULL, &type);
+		CHECK_dict_new(DICT_AVP, &data, type, NULL);
+	};
+
+	/* AMBR */
+	{
+		struct dict_avp_data data = {
+			1435,	/* Code */
+			10415,	/* Vendor */
+			"AMBR",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_GROUPED	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* CSG-Subscription-Data */
+	{
+		struct dict_avp_data data = {
+			1436,	/* Code */
+			10415,	/* Vendor */
+			"CSG-Subscription-Data",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_GROUPED	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* CSG-Id */
+	{
+		struct dict_avp_data data = {
+			1437,	/* Code */
+			10415,	/* Vendor */
+			"CSG-Id",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_UNSIGNED32	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* PDN-GW-Allocation-Type */
+	{
+		struct dict_avp_data data = {
+			1438,	/* Code */
+			10415,	/* Vendor */
+			"PDN-GW-Allocation-Type",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_INTEGER32	/* base type of data */
+		};
+		struct dict_object		*type;
+		struct dict_type_data	 tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(PDN-GW-Allocation-Type)", NULL, NULL, NULL };
+		CHECK_dict_new(DICT_TYPE, &tdata, NULL, &type);
+		CHECK_dict_new(DICT_AVP, &data, type, NULL);
+	};
+
+	/* Expiration-Date */
+	{
+		struct dict_avp_data data = {
+			1439,	/* Code */
+			10415,	/* Vendor */
+			"Expiration-Date",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, Time_type, NULL);
+	};
+
+	/* RAT-Frequency-Selection-Priority-ID */
+	{
+		struct dict_avp_data data = {
+			1440,	/* Code */
+			10415,	/* Vendor */
+			"RAT-Frequency-Selection-Priority-ID",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_UNSIGNED32	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* IDA-Flags */
+	{
+		struct dict_avp_data data = {
+			1441,	/* Code */
+			10415,	/* Vendor */
+			"IDA-Flags",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_UNSIGNED32	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* PUA-Flags */
+	{
+		struct dict_avp_data data = {
+			1442,	/* Code */
+			10415,	/* Vendor */
+			"PUA-Flags",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_UNSIGNED32	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* NOR-Flags */
+	{
+		struct dict_avp_data data = {
+			1443,	/* Code */
+			10415,	/* Vendor */
+			"NOR-Flags",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_UNSIGNED32	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* User-Id */
+	{
+		struct dict_avp_data data = {
+			1444,	/* Code */
+			10415,	/* Vendor */
+			"User-Id",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, UTF8String_type, NULL);
+	};
+
+	/* Equipment-Status */
+	{
+		struct dict_avp_data data = {
+			1445,	/* Code */
+			10415,	/* Vendor */
+			"Equipment-Status",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_INTEGER32	/* base type of data */
+		};
+		struct dict_object		*type;
+		struct dict_type_data	 tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Equipment-Status)", NULL, NULL, NULL };
+		CHECK_dict_new(DICT_TYPE, &tdata, NULL, &type);
+		CHECK_dict_new(DICT_AVP, &data, type, NULL);
+	};
+
+	/* Regional-Subscription-Zone-Code */
+	{
+		struct dict_avp_data data = {
+			1446,	/* Code */
+			10415,	/* Vendor */
+			"Regional-Subscription-Zone-Code",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* RAND */
+	{
+		struct dict_avp_data data = {
+			1447,	/* Code */
+			10415,	/* Vendor */
+			"RAND",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* XRES */
+	{
+		struct dict_avp_data data = {
+			1448,	/* Code */
+			10415,	/* Vendor */
+			"XRES",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* AUTN */
+	{
+		struct dict_avp_data data = {
+			1449,	/* Code */
+			10415,	/* Vendor */
+			"AUTN",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* KASME */
+	{
+		struct dict_avp_data data = {
+			1450,	/* Code */
+			10415,	/* Vendor */
+			"KASME",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* Trace-Collection-Entity */
+	{
+		struct dict_avp_data data = {
+			1452,	/* Code */
+			10415,	/* Vendor */
+			"Trace-Collection-Entity",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, Address_type, NULL);
+	};
+
+	/* Kc */
+	{
+		struct dict_avp_data data = {
+			1453,	/* Code */
+			10415,	/* Vendor */
+			"Kc",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* SRES */
+	{
+		struct dict_avp_data data = {
+			1454,	/* Code */
+			10415,	/* Vendor */
+			"SRES",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* PDN-Type */
+	{
+		struct dict_avp_data data = {
+			1456,	/* Code */
+			10415,	/* Vendor */
+			"PDN-Type",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_INTEGER32	/* base type of data */
+		};
+		struct dict_object		*type;
+		struct dict_type_data	 tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(PDN-Type)", NULL, NULL, NULL };
+		CHECK_dict_new(DICT_TYPE, &tdata, NULL, &type);
+		CHECK_dict_new(DICT_AVP, &data, type, NULL);
+	};
+
+	/* Roaming-Restricted-Due-To-Unsupported-Feature */
+	{
+		struct dict_avp_data data = {
+			1457,	/* Code */
+			10415,	/* Vendor */
+			"Roaming-Restricted-Due-To-Unsupported-Feature",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_INTEGER32	/* base type of data */
+		};
+		struct dict_object		*type;
+		struct dict_type_data	 tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Roaming-Restricted-Due-To-Unsupported-Feature)", NULL, NULL, NULL };
+		CHECK_dict_new(DICT_TYPE, &tdata, NULL, &type);
+		CHECK_dict_new(DICT_AVP, &data, type, NULL);
+	};
+
+	/* Trace-Data */
+	{
+		struct dict_avp_data data = {
+			1458,	/* Code */
+			10415,	/* Vendor */
+			"Trace-Data",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_GROUPED	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* Trace-Reference */
+	{
+		struct dict_avp_data data = {
+			1459,	/* Code */
+			10415,	/* Vendor */
+			"Trace-Reference",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* Trace-Depth */
+	{
+		struct dict_avp_data data = {
+			1462,	/* Code */
+			10415,	/* Vendor */
+			"Trace-Depth",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_INTEGER32	/* base type of data */
+		};
+		struct dict_object		*type;
+		struct dict_type_data	 tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Trace-Depth)", NULL, NULL, NULL };
+		CHECK_dict_new(DICT_TYPE, &tdata, NULL, &type);
+		CHECK_dict_new(DICT_AVP, &data, type, NULL);
+	};
+
+	/* Trace-NE-Type-List */
+	{
+		struct dict_avp_data data = {
+			1463,	/* Code */
+			10415,	/* Vendor */
+			"Trace-NE-Type-List",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* Trace-Interface-List */
+	{
+		struct dict_avp_data data = {
+			1464,	/* Code */
+			10415,	/* Vendor */
+			"Trace-Interface-List",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* Trace-Event-List */
+	{
+		struct dict_avp_data data = {
+			1465,	/* Code */
+			10415,	/* Vendor */
+			"Trace-Event-List",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* OMC-Id */
+	{
+		struct dict_avp_data data = {
+			1466,	/* Code */
+			10415,	/* Vendor */
+			"OMC-Id",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* GPRS-Subscription-Data */
+	{
+		struct dict_avp_data data = {
+			1467,	/* Code */
+			10415,	/* Vendor */
+			"GPRS-Subscription-Data",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_GROUPED	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* Complete-Data-List-Included-Indicator */
+	{
+		struct dict_avp_data data = {
+			1468,	/* Code */
+			10415,	/* Vendor */
+			"Complete-Data-List-Included-Indicator",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_INTEGER32	/* base type of data */
+		};
+		struct dict_object		*type;
+		struct dict_type_data	 tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Complete-Data-List-Included-Indicator)", NULL, NULL, NULL };
+		CHECK_dict_new(DICT_TYPE, &tdata, NULL, &type);
+		CHECK_dict_new(DICT_AVP, &data, type, NULL);
+	};
+
+	/* PDP-Context */
+	{
+		struct dict_avp_data data = {
+			1469,	/* Code */
+			10415,	/* Vendor */
+			"PDP-Context",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_GROUPED	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* PDP-Type */
+	{
+		struct dict_avp_data data = {
+			1470,	/* Code */
+			10415,	/* Vendor */
+			"PDP-Type",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* 3GPP2-MEID */
+	{
+		struct dict_avp_data data = {
+			1471,	/* Code */
+			10415,	/* Vendor */
+			"3GPP2-MEID",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* Specific-APN-Info */
+	{
+		struct dict_avp_data data = {
+			1472,	/* Code */
+			10415,	/* Vendor */
+			"Specific-APN-Info",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_GROUPED	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* LCS-Info */
+	{
+		struct dict_avp_data data = {
+			1473,	/* Code */
+			10415,	/* Vendor */
+			"LCS-Info",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_GROUPED	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* GMLC-Number */
+	{
+		struct dict_avp_data data = {
+			1474,	/* Code */
+			10415,	/* Vendor */
+			"GMLC-Number",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* LCS-PrivacyException */
+	{
+		struct dict_avp_data data = {
+			1475,	/* Code */
+			10415,	/* Vendor */
+			"LCS-PrivacyException",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_GROUPED	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* SS-Code */
+	{
+		struct dict_avp_data data = {
+			1476,	/* Code */
+			10415,	/* Vendor */
+			"SS-Code",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* SS-Status */
+	{
+		struct dict_avp_data data = {
+			1477,	/* Code */
+			10415,	/* Vendor */
+			"SS-Status",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_GROUPED	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* Notification-To-UE-User */
+	{
+		struct dict_avp_data data = {
+			1478,	/* Code */
+			10415,	/* Vendor */
+			"Notification-To-UE-User",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_INTEGER32	/* base type of data */
+		};
+		struct dict_object		*type;
+		struct dict_type_data	 tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Notification-To-UE-User)", NULL, NULL, NULL };
+		CHECK_dict_new(DICT_TYPE, &tdata, NULL, &type);
+		CHECK_dict_new(DICT_AVP, &data, type, NULL);
+	};
+
+	/* External-Client */
+	{
+		struct dict_avp_data data = {
+			1479,	/* Code */
+			10415,	/* Vendor */
+			"External-Client",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_GROUPED	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* Client-Identity */
+	{
+		struct dict_avp_data data = {
+			1480,	/* Code */
+			10415,	/* Vendor */
+			"Client-Identity",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* GMLC-Restriction */
+	{
+		struct dict_avp_data data = {
+			1481,	/* Code */
+			10415,	/* Vendor */
+			"GMLC-Restriction",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_INTEGER32	/* base type of data */
+		};
+		struct dict_object		*type;
+		struct dict_type_data	 tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(GMLC-Restriction)", NULL, NULL, NULL };
+		CHECK_dict_new(DICT_TYPE, &tdata, NULL, &type);
+		CHECK_dict_new(DICT_AVP, &data, type, NULL);
+	};
+
+	/* PLMN-Client */
+	{
+		struct dict_avp_data data = {
+			1482,	/* Code */
+			10415,	/* Vendor */
+			"PLMN-Client",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_INTEGER32	/* base type of data */
+		};
+		struct dict_object		*type;
+		struct dict_type_data	 tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(PLMN-Client)", NULL, NULL, NULL };
+		CHECK_dict_new(DICT_TYPE, &tdata, NULL, &type);
+		CHECK_dict_new(DICT_AVP, &data, type, NULL);
+	};
+
+	/* Service-Type */
+	{
+		struct dict_avp_data data = {
+			1483,	/* Code */
+			10415,	/* Vendor */
+			"Service-Type",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_GROUPED	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* ServiceTypeIdentity */
+	{
+		struct dict_avp_data data = {
+			1484,	/* Code */
+			10415,	/* Vendor */
+			"ServiceTypeIdentity",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_UNSIGNED32	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* MO-LR */
+	{
+		struct dict_avp_data data = {
+			1485,	/* Code */
+			10415,	/* Vendor */
+			"MO-LR",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_GROUPED	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* Teleservice-List */
+	{
+		struct dict_avp_data data = {
+			1486,	/* Code */
+			10415,	/* Vendor */
+			"Teleservice-List",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_GROUPED	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* TS-Code */
+	{
+		struct dict_avp_data data = {
+			1487,	/* Code */
+			10415,	/* Vendor */
+			"TS-Code",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* Call-Barring-Infor-List */
+	{
+		struct dict_avp_data data = {
+			1488,	/* Code */
+			10415,	/* Vendor */
+			"Call-Barring-Infor-List",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_GROUPED	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* SGSN-Number */
+	{
+		struct dict_avp_data data = {
+			1489,	/* Code */
+			10415,	/* Vendor */
+			"SGSN-Number",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* IDR-Flags */
+	{
+		struct dict_avp_data data = {
+			1490,	/* Code */
+			10415,	/* Vendor */
+			"IDR-Flags",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_UNSIGNED32	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* ICS-Indicator */
+	{
+		struct dict_avp_data data = {
+			1491,	/* Code */
+			10415,	/* Vendor */
+			"ICS-Indicator",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR,	/* Fixed flag values */
+			AVP_TYPE_INTEGER32	/* base type of data */
+		};
+		struct dict_object		*type;
+		struct dict_type_data	 tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(ICS-Indicator)", NULL, NULL, NULL };
+		CHECK_dict_new(DICT_TYPE, &tdata, NULL, &type);
+		CHECK_dict_new(DICT_AVP, &data, type, NULL);
+	};
+
+	/* IMS-Voice-Over-PS-Sessions-Supported */
+	{
+		struct dict_avp_data data = {
+			1492,	/* Code */
+			10415,	/* Vendor */
+			"IMS-Voice-Over-PS-Sessions-Supported",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR,	/* Fixed flag values */
+			AVP_TYPE_INTEGER32	/* base type of data */
+		};
+		struct dict_object		*type;
+		struct dict_type_data	 tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(IMS-Voice-Over-PS-Sessions-Supported)", NULL, NULL, NULL };
+		CHECK_dict_new(DICT_TYPE, &tdata, NULL, &type);
+		CHECK_dict_new(DICT_AVP, &data, type, NULL);
+	};
+
+	/* Homogeneous-Support-of-IMS-Voice-Over-PS-Sessions */
+	{
+		struct dict_avp_data data = {
+			1493,	/* Code */
+			10415,	/* Vendor */
+			"Homogeneous-Support-of-IMS-Voice-Over-PS-Sessions",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR,	/* Fixed flag values */
+			AVP_TYPE_INTEGER32	/* base type of data */
+		};
+		struct dict_object		*type;
+		struct dict_type_data	 tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Homogeneous-Support-of-IMS-Voice-Over-PS-Sessions)", NULL, NULL, NULL };
+		CHECK_dict_new(DICT_TYPE, &tdata, NULL, &type);
+		CHECK_dict_new(DICT_AVP, &data, type, NULL);
+	};
+
+	/* Last-UE-Activity-Time */
+	{
+		struct dict_avp_data data = {
+			1494,	/* Code */
+			10415,	/* Vendor */
+			"Last-UE-Activity-Time",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, Time_type, NULL);
+	};
+
+	/* EPS-User-State */
+	{
+		struct dict_avp_data data = {
+			1495,	/* Code */
+			10415,	/* Vendor */
+			"EPS-User-State",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR,	/* Fixed flag values */
+			AVP_TYPE_GROUPED	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* EPS-Location-Information */
+	{
+		struct dict_avp_data data = {
+			1496,	/* Code */
+			10415,	/* Vendor */
+			"EPS-Location-Information",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR,	/* Fixed flag values */
+			AVP_TYPE_GROUPED	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* MME-User-State */
+	{
+		struct dict_avp_data data = {
+			1497,	/* Code */
+			10415,	/* Vendor */
+			"MME-User-State",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR,	/* Fixed flag values */
+			AVP_TYPE_GROUPED	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* SGSN-User-State */
+	{
+		struct dict_avp_data data = {
+			1498,	/* Code */
+			10415,	/* Vendor */
+			"SGSN-User-State",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR,	/* Fixed flag values */
+			AVP_TYPE_GROUPED	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* User-State */
+	{
+		struct dict_avp_data data = {
+			1499,	/* Code */
+			10415,	/* Vendor */
+			"User-State",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR,	/* Fixed flag values */
+			AVP_TYPE_INTEGER32	/* base type of data */
+		};
+		struct dict_object		*type;
+		struct dict_type_data	 tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(User-State)", NULL, NULL, NULL };
+		CHECK_dict_new(DICT_TYPE, &tdata, NULL, &type);
+		CHECK_dict_new(DICT_AVP, &data, type, NULL);
+	};
+
+	/* MME-LocationInformation */
+	{
+		struct dict_avp_data data = {
+			1600,	/* Code */
+			10415,	/* Vendor */
+			"MME-LocationInformation",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR,	/* Fixed flag values */
+			AVP_TYPE_GROUPED	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* SGSN-Location-Information */
+	{
+		struct dict_avp_data data = {
+			1601,	/* Code */
+			10415,	/* Vendor */
+			"SGSN-Location-Information",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR,	/* Fixed flag values */
+			AVP_TYPE_GROUPED	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* E-UTRAN-Cell-Global-Identity */
+	{
+		struct dict_avp_data data = {
+			1602,	/* Code */
+			10415,	/* Vendor */
+			"E-UTRAN-Cell-Global-Identity",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* Tracking-Area-Identity */
+	{
+		struct dict_avp_data data = {
+			1603,	/* Code */
+			10415,	/* Vendor */
+			"Tracking-Area-Identity",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* Cell-Global-Identity */
+	{
+		struct dict_avp_data data = {
+			1604,	/* Code */
+			10415,	/* Vendor */
+			"Cell-Global-Identity",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* Routing-Area-Identity */
+	{
+		struct dict_avp_data data = {
+			1605,	/* Code */
+			10415,	/* Vendor */
+			"Routing-Area-Identity",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* Location-Area-Identity */
+	{
+		struct dict_avp_data data = {
+			1606,	/* Code */
+			10415,	/* Vendor */
+			"Location-Area-Identity",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* Service-Area-Identity */
+	{
+		struct dict_avp_data data = {
+			1607,	/* Code */
+			10415,	/* Vendor */
+			"Service-Area-Identity",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* Geographical-Information */
+	{
+		struct dict_avp_data data = {
+			1608,	/* Code */
+			10415,	/* Vendor */
+			"Geographical-Information",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* Geodetic-Information */
+	{
+		struct dict_avp_data data = {
+			1609,	/* Code */
+			10415,	/* Vendor */
+			"Geodetic-Information",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* Current-Location-Retrieved */
+	{
+		struct dict_avp_data data = {
+			1610,	/* Code */
+			10415,	/* Vendor */
+			"Current-Location-Retrieved",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR,	/* Fixed flag values */
+			AVP_TYPE_INTEGER32	/* base type of data */
+		};
+		struct dict_object		*type;
+		struct dict_type_data	 tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Current-Location-Retrieved)", NULL, NULL, NULL };
+		CHECK_dict_new(DICT_TYPE, &tdata, NULL, &type);
+		CHECK_dict_new(DICT_AVP, &data, type, NULL);
+	};
+
+	/* Age-Of-Location-Information */
+	{
+		struct dict_avp_data data = {
+			1611,	/* Code */
+			10415,	/* Vendor */
+			"Age-Of-Location-Information",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR,	/* Fixed flag values */
+			AVP_TYPE_UNSIGNED32	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* Active-APN */
+	{
+		struct dict_avp_data data = {
+			1612,	/* Code */
+			10415,	/* Vendor */
+			"Active-APN",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR,	/* Fixed flag values */
+			AVP_TYPE_GROUPED	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* Error-Diagnostic */
+	{
+		struct dict_avp_data data = {
+			1614,	/* Code */
+			10415,	/* Vendor */
+			"Error-Diagnostic",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR,	/* Fixed flag values */
+			AVP_TYPE_INTEGER32	/* base type of data */
+		};
+		struct dict_object		*type;
+		struct dict_type_data	 tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Error-Diagnostic)", NULL, NULL, NULL };
+		CHECK_dict_new(DICT_TYPE, &tdata, NULL, &type);
+		CHECK_dict_new(DICT_AVP, &data, type, NULL);
+	};
+
+	/* Ext-PDP-Address */
+	{
+		struct dict_avp_data data = {
+			1621,	/* Code */
+			10415,	/* Vendor */
+			"Ext-PDP-Address",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, Address_type, NULL);
+	};
+
+	/* UE-SRVCC-Capability */
+	{
+		struct dict_avp_data data = {
+			1615,	/* Code */
+			10415,	/* Vendor */
+			"UE-SRVCC-Capability",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR,	/* Fixed flag values */
+			AVP_TYPE_INTEGER32	/* base type of data */
+		};
+		struct dict_object		*type;
+		struct dict_type_data	 tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(UE-SRVCC-Capability)", NULL, NULL, NULL };
+		CHECK_dict_new(DICT_TYPE, &tdata, NULL, &type);
+		CHECK_dict_new(DICT_AVP, &data, type, NULL);
+	};
+
+	/* MPS-Priority */
+	{
+		struct dict_avp_data data = {
+			1616,	/* Code */
+			10415,	/* Vendor */
+			"MPS-Priority",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR,	/* Fixed flag values */
+			AVP_TYPE_UNSIGNED32	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* VPLMN-LIPA-Allowed */
+	{
+		struct dict_avp_data data = {
+			1617,	/* Code */
+			10415,	/* Vendor */
+			"VPLMN-LIPA-Allowed",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR,	/* Fixed flag values */
+			AVP_TYPE_INTEGER32	/* base type of data */
+		};
+		struct dict_object		*type;
+		struct dict_type_data	 tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(VPLMN-LIPA-Allowed)", NULL, NULL, NULL };
+		CHECK_dict_new(DICT_TYPE, &tdata, NULL, &type);
+		CHECK_dict_new(DICT_AVP, &data, type, NULL);
+	};
+
+	/* LIPA-Permission */
+	{
+		struct dict_avp_data data = {
+			1618,	/* Code */
+			10415,	/* Vendor */
+			"LIPA-Permission",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR,	/* Fixed flag values */
+			AVP_TYPE_INTEGER32	/* base type of data */
+		};
+		struct dict_object		*type;
+		struct dict_type_data	 tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(LIPA-Permission)", NULL, NULL, NULL };
+		CHECK_dict_new(DICT_TYPE, &tdata, NULL, &type);
+		CHECK_dict_new(DICT_AVP, &data, type, NULL);
+	};
+
+	/* Subscribed-Periodic-RAU-TAU-Timer */
+	{
+		struct dict_avp_data data = {
+			1619,	/* Code */
+			10415,	/* Vendor */
+			"Subscribed-Periodic-RAU-TAU-Timer",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR,	/* Fixed flag values */
+			AVP_TYPE_UNSIGNED32	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* Ext-PDP-Type */
+	{
+		struct dict_avp_data data = {
+			1620,	/* Code */
+			10415,	/* Vendor */
+			"Ext-PDP-Type",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* SIPTO-Permission */
+	{
+		struct dict_avp_data data = {
+			1613,	/* Code */
+			10415,	/* Vendor */
+			"SIPTO-Permission",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR,	/* Fixed flag values */
+			AVP_TYPE_INTEGER32	/* base type of data */
+		};
+		struct dict_object		*type;
+		struct dict_type_data	 tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(SIPTO-Permission)", NULL, NULL, NULL };
+		CHECK_dict_new(DICT_TYPE, &tdata, NULL, &type);
+		CHECK_dict_new(DICT_AVP, &data, type, NULL);
+	};
+
+	/* MDT-Configuration */
+	{
+		struct dict_avp_data data = {
+			1622,	/* Code */
+			10415,	/* Vendor */
+			"MDT-Configuration",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR,	/* Fixed flag values */
+			AVP_TYPE_GROUPED	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* Job-Type */
+	{
+		struct dict_avp_data data = {
+			1623,	/* Code */
+			10415,	/* Vendor */
+			"Job-Type",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR,	/* Fixed flag values */
+			AVP_TYPE_INTEGER32	/* base type of data */
+		};
+		struct dict_object		*type;
+		struct dict_type_data	 tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Job-Type)", NULL, NULL, NULL };
+		CHECK_dict_new(DICT_TYPE, &tdata, NULL, &type);
+		CHECK_dict_new(DICT_AVP, &data, type, NULL);
+	};
+
+	/* Area-Scope */
+	{
+		struct dict_avp_data data = {
+			1624,	/* Code */
+			10415,	/* Vendor */
+			"Area-Scope",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR,	/* Fixed flag values */
+			AVP_TYPE_GROUPED	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* List-Of-Measurements */
+	{
+		struct dict_avp_data data = {
+			1625,	/* Code */
+			10415,	/* Vendor */
+			"List-Of-Measurements",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR,	/* Fixed flag values */
+			AVP_TYPE_UNSIGNED32	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* Reporting-Trigger */
+	{
+		struct dict_avp_data data = {
+			1626,	/* Code */
+			10415,	/* Vendor */
+			"Reporting-Trigger",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR,	/* Fixed flag values */
+			AVP_TYPE_UNSIGNED32	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* Report-Interval */
+	{
+		struct dict_avp_data data = {
+			1627,	/* Code */
+			10415,	/* Vendor */
+			"Report-Interval",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR,	/* Fixed flag values */
+			AVP_TYPE_INTEGER32	/* base type of data */
+		};
+		struct dict_object		*type;
+		struct dict_type_data	 tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Report-Interval)", NULL, NULL, NULL };
+		CHECK_dict_new(DICT_TYPE, &tdata, NULL, &type);
+		CHECK_dict_new(DICT_AVP, &data, type, NULL);
+	};
+
+	/* Report-Amount */
+	{
+		struct dict_avp_data data = {
+			1628,	/* Code */
+			10415,	/* Vendor */
+			"Report-Amount",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR,	/* Fixed flag values */
+			AVP_TYPE_INTEGER32	/* base type of data */
+		};
+		struct dict_object		*type;
+		struct dict_type_data	 tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Report-Amount)", NULL, NULL, NULL };
+		CHECK_dict_new(DICT_TYPE, &tdata, NULL, &type);
+		CHECK_dict_new(DICT_AVP, &data, type, NULL);
+	};
+
+	/* Event-Threshold-RSRP */
+	{
+		struct dict_avp_data data = {
+			1629,	/* Code */
+			10415,	/* Vendor */
+			"Event-Threshold-RSRP",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR,	/* Fixed flag values */
+			AVP_TYPE_UNSIGNED32	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* Event-Threshold-RSRQ */
+	{
+		struct dict_avp_data data = {
+			1630,	/* Code */
+			10415,	/* Vendor */
+			"Event-Threshold-RSRQ",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR,	/* Fixed flag values */
+			AVP_TYPE_UNSIGNED32	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* Logging-Interval */
+	{
+		struct dict_avp_data data = {
+			1631,	/* Code */
+			10415,	/* Vendor */
+			"Logging-Interval",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR,	/* Fixed flag values */
+			AVP_TYPE_INTEGER32	/* base type of data */
+		};
+		struct dict_object		*type;
+		struct dict_type_data	 tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Logging-Interval)", NULL, NULL, NULL };
+		CHECK_dict_new(DICT_TYPE, &tdata, NULL, &type);
+		CHECK_dict_new(DICT_AVP, &data, type, NULL);
+	};
+
+	/* Logging-Duration */
+	{
+		struct dict_avp_data data = {
+			1632,	/* Code */
+			10415,	/* Vendor */
+			"Logging-Duration",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR,	/* Fixed flag values */
+			AVP_TYPE_INTEGER32	/* base type of data */
+		};
+		struct dict_object		*type;
+		struct dict_type_data	 tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Logging-Duration)", NULL, NULL, NULL };
+		CHECK_dict_new(DICT_TYPE, &tdata, NULL, &type);
+		CHECK_dict_new(DICT_AVP, &data, type, NULL);
+	};
+
+	/* Relay-Node-Indicator */
+	{
+		struct dict_avp_data data = {
+			1633,	/* Code */
+			10415,	/* Vendor */
+			"Relay-Node-Indicator",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR,	/* Fixed flag values */
+			AVP_TYPE_INTEGER32	/* base type of data */
+		};
+		struct dict_object		*type;
+		struct dict_type_data	 tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Relay-Node-Indicator)", NULL, NULL, NULL };
+		CHECK_dict_new(DICT_TYPE, &tdata, NULL, &type);
+		CHECK_dict_new(DICT_AVP, &data, type, NULL);
+	};
+
+	/* MDT-User-Consent */
+	{
+		struct dict_avp_data data = {
+			1634,	/* Code */
+			10415,	/* Vendor */
+			"MDT-User-Consent",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR,	/* Fixed flag values */
+			AVP_TYPE_INTEGER32	/* base type of data */
+		};
+		struct dict_object		*type;
+		struct dict_type_data	 tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(MDT-User-Consent)", NULL, NULL, NULL };
+		CHECK_dict_new(DICT_TYPE, &tdata, NULL, &type);
+		CHECK_dict_new(DICT_AVP, &data, type, NULL);
+	};
+
+	/* PUR-Flags */
+	{
+		struct dict_avp_data data = {
+			1635,	/* Code */
+			10415,	/* Vendor */
+			"PUR-Flags",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR,	/* Fixed flag values */
+			AVP_TYPE_UNSIGNED32	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* Subscribed-VSRVCC */
+	{
+		struct dict_avp_data data = {
+			1636,	/* Code */
+			10415,	/* Vendor */
+			"Subscribed-VSRVCC",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR,	/* Fixed flag values */
+			AVP_TYPE_INTEGER32	/* base type of data */
+		};
+		struct dict_object		*type;
+		struct dict_type_data	 tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Subscribed-VSRVCC)", NULL, NULL, NULL };
+		CHECK_dict_new(DICT_TYPE, &tdata, NULL, &type);
+		CHECK_dict_new(DICT_AVP, &data, type, NULL);
+	};
+
+	/* Equivalent-PLMN-List */
+	{
+		struct dict_avp_data data = {
+			1637,	/* Code */
+			10415,	/* Vendor */
+			"Equivalent-PLMN-List",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR,	/* Fixed flag values */
+			AVP_TYPE_GROUPED	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* CLR-Flags */
+	{
+		struct dict_avp_data data = {
+			1638,	/* Code */
+			10415,	/* Vendor */
+			"CLR-Flags",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR,	/* Fixed flag values */
+			AVP_TYPE_UNSIGNED32	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* UVR-Flags */
+	{
+		struct dict_avp_data data = {
+			1639,	/* Code */
+			10415,	/* Vendor */
+			"UVR-Flags",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_UNSIGNED32	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* UVA-Flags */
+	{
+		struct dict_avp_data data = {
+			1640,	/* Code */
+			10415,	/* Vendor */
+			"UVA-Flags",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_UNSIGNED32	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* VPLMN-CSG-Subscription-Data */
+	{
+		struct dict_avp_data data = {
+			1641,	/* Code */
+			10415,	/* Vendor */
+			"VPLMN-CSG-Subscription-Data",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_GROUPED	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* Time-Zone */
+	{
+		struct dict_avp_data data = {
+			1642,	/* Code */
+			10415,	/* Vendor */
+			"Time-Zone",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, UTF8String_type, NULL);
+	};
+
+	/* A-MSISDN */
+	{
+		struct dict_avp_data data = {
+			1643,	/* Code */
+			10415,	/* Vendor */
+			"A-MSISDN",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* MME-Number-for-MT-SMS */
+	{
+		struct dict_avp_data data = {
+			1645,	/* Code */
+			10415,	/* Vendor */
+			"MME-Number-for-MT-SMS",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* SMS-Register-Request */
+	{
+		struct dict_avp_data data = {
+			1648,	/* Code */
+			10415,	/* Vendor */
+			"SMS-Register-Request",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR,	/* Fixed flag values */
+			AVP_TYPE_INTEGER32	/* base type of data */
+		};
+		struct dict_object		*type;
+		struct dict_type_data	 tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(SMS-Register-Request)", NULL, NULL, NULL };
+		CHECK_dict_new(DICT_TYPE, &tdata, NULL, &type);
+		CHECK_dict_new(DICT_AVP, &data, type, NULL);
+	};
+
+	/* Local-Time-Zone */
+	{
+		struct dict_avp_data data = {
+			1649,	/* Code */
+			10415,	/* Vendor */
+			"Local-Time-Zone",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR,	/* Fixed flag values */
+			AVP_TYPE_GROUPED	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* Daylight-Saving-Time */
+	{
+		struct dict_avp_data data = {
+			1650,	/* Code */
+			10415,	/* Vendor */
+			"Daylight-Saving-Time",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR,	/* Fixed flag values */
+			AVP_TYPE_INTEGER32	/* base type of data */
+		};
+		struct dict_object		*type;
+		struct dict_type_data	 tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Daylight-Saving-Time)", NULL, NULL, NULL };
+		CHECK_dict_new(DICT_TYPE, &tdata, NULL, &type);
+		CHECK_dict_new(DICT_AVP, &data, type, NULL);
+	};
+
+	/* Subscription-Data-Flags */
+	{
+		struct dict_avp_data data = {
+			1654,	/* Code */
+			10415,	/* Vendor */
+			"Subscription-Data-Flags",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR,	/* Fixed flag values */
+			AVP_TYPE_UNSIGNED32	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* Measurement-Period-UMTS */
+	{
+		struct dict_avp_data data = {
+			1655,	/* Code */
+			10415,	/* Vendor */
+			"Measurement-Period-UMTS",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR,	/* Fixed flag values */
+			AVP_TYPE_INTEGER32	/* base type of data */
+		};
+		struct dict_object		*type;
+		struct dict_type_data	 tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Measurement-Period-UMTS)", NULL, NULL, NULL };
+		CHECK_dict_new(DICT_TYPE, &tdata, NULL, &type);
+		CHECK_dict_new(DICT_AVP, &data, type, NULL);
+	};
+
+	/* Measurement-Period-LTE */
+	{
+		struct dict_avp_data data = {
+			1656,	/* Code */
+			10415,	/* Vendor */
+			"Measurement-Period-LTE",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR,	/* Fixed flag values */
+			AVP_TYPE_INTEGER32	/* base type of data */
+		};
+		struct dict_object		*type;
+		struct dict_type_data	 tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Measurement-Period-LTE)", NULL, NULL, NULL };
+		CHECK_dict_new(DICT_TYPE, &tdata, NULL, &type);
+		CHECK_dict_new(DICT_AVP, &data, type, NULL);
+	};
+
+	/* Collection-Period-RRM-LTE */
+	{
+		struct dict_avp_data data = {
+			1657,	/* Code */
+			10415,	/* Vendor */
+			"Collection-Period-RRM-LTE",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR,	/* Fixed flag values */
+			AVP_TYPE_INTEGER32	/* base type of data */
+		};
+		struct dict_object		*type;
+		struct dict_type_data	 tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Collection-Period-RRM-LTE)", NULL, NULL, NULL };
+		CHECK_dict_new(DICT_TYPE, &tdata, NULL, &type);
+		CHECK_dict_new(DICT_AVP, &data, type, NULL);
+	};
+
+	/* Collection-Period-RRM-UMTS */
+	{
+		struct dict_avp_data data = {
+			1658,	/* Code */
+			10415,	/* Vendor */
+			"Collection-Period-RRM-UMTS",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR,	/* Fixed flag values */
+			AVP_TYPE_INTEGER32	/* base type of data */
+		};
+		struct dict_object		*type;
+		struct dict_type_data	 tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Collection-Period-RRM-UMTS)", NULL, NULL, NULL };
+		CHECK_dict_new(DICT_TYPE, &tdata, NULL, &type);
+		CHECK_dict_new(DICT_AVP, &data, type, NULL);
+	};
+
+	/* Positioning-Method */
+	{
+		struct dict_avp_data data = {
+			1659,	/* Code */
+			10415,	/* Vendor */
+			"Positioning-Method",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* Measurement-Quantity */
+	{
+		struct dict_avp_data data = {
+			1660,	/* Code */
+			10415,	/* Vendor */
+			"Measurement-Quantity",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* Event-Threshold-Event-1F */
+	{
+		struct dict_avp_data data = {
+			1661,	/* Code */
+			10415,	/* Vendor */
+			"Event-Threshold-Event-1F",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR,	/* Fixed flag values */
+			AVP_TYPE_INTEGER32	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* Event-Threshold-Event-1I */
+	{
+		struct dict_avp_data data = {
+			1662,	/* Code */
+			10415,	/* Vendor */
+			"Event-Threshold-Event-1I",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR,	/* Fixed flag values */
+			AVP_TYPE_INTEGER32	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* 3GPP 29.329-b50 (11.5.0 2012.12.21)                          */
+	/* User-Identity */
+	{
+		struct dict_avp_data data = {
+			700,	/* Code */
+			10415,	/* Vendor */
+			"User-Identity",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_GROUPED	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* MSISDN */
+	{
+		struct dict_avp_data data = {
+			701,	/* Code */
+			10415,	/* Vendor */
+			"MSISDN",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* Name conflict with 29.229 User-Data (606), renamed           */
+	/* User-Data-29.329 */
+	{
+		struct dict_avp_data data = {
+			702,	/* Code */
+			10415,	/* Vendor */
+			"User-Data-29.329",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* Data-Reference */
+	{
+		struct dict_avp_data data = {
+			703,	/* Code */
+			10415,	/* Vendor */
+			"Data-Reference",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_INTEGER32	/* base type of data */
+		};
+		struct dict_object		*type;
+		struct dict_type_data	 tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Data-Reference)", NULL, NULL, NULL };
+		CHECK_dict_new(DICT_TYPE, &tdata, NULL, &type);
+		CHECK_dict_new(DICT_AVP, &data, type, NULL);
+	};
+
+	/* Service-Indication */
+	{
+		struct dict_avp_data data = {
+			704,	/* Code */
+			10415,	/* Vendor */
+			"Service-Indication",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* Subs-Req-Type */
+	{
+		struct dict_avp_data data = {
+			705,	/* Code */
+			10415,	/* Vendor */
+			"Subs-Req-Type",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_INTEGER32	/* base type of data */
+		};
+		struct dict_object		*type;
+		struct dict_type_data	 tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Subs-Req-Type)", NULL, NULL, NULL };
+		CHECK_dict_new(DICT_TYPE, &tdata, NULL, &type);
+		CHECK_dict_new(DICT_AVP, &data, type, NULL);
+	};
+
+	/* Requested-Domain */
+	{
+		struct dict_avp_data data = {
+			706,	/* Code */
+			10415,	/* Vendor */
+			"Requested-Domain",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_INTEGER32	/* base type of data */
+		};
+		struct dict_object		*type;
+		struct dict_type_data	 tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Requested-Domain)", NULL, NULL, NULL };
+		CHECK_dict_new(DICT_TYPE, &tdata, NULL, &type);
+		CHECK_dict_new(DICT_AVP, &data, type, NULL);
+	};
+
+	/* Current-Location */
+	{
+		struct dict_avp_data data = {
+			707,	/* Code */
+			10415,	/* Vendor */
+			"Current-Location",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_INTEGER32	/* base type of data */
+		};
+		struct dict_object		*type;
+		struct dict_type_data	 tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Current-Location)", NULL, NULL, NULL };
+		CHECK_dict_new(DICT_TYPE, &tdata, NULL, &type);
+		CHECK_dict_new(DICT_AVP, &data, type, NULL);
+	};
+
+	/* Identity-Set */
+	{
+		struct dict_avp_data data = {
+			708,	/* Code */
+			10415,	/* Vendor */
+			"Identity-Set",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR,	/* Fixed flag values */
+			AVP_TYPE_INTEGER32	/* base type of data */
+		};
+		struct dict_object		*type;
+		struct dict_type_data	 tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Identity-Set)", NULL, NULL, NULL };
+		CHECK_dict_new(DICT_TYPE, &tdata, NULL, &type);
+		CHECK_dict_new(DICT_AVP, &data, type, NULL);
+	};
+
+	/* Expiry-Time */
+	{
+		struct dict_avp_data data = {
+			709,	/* Code */
+			10415,	/* Vendor */
+			"Expiry-Time",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, Time_type, NULL);
+	};
+
+	/* Send-Data-Indication */
+	{
+		struct dict_avp_data data = {
+			710,	/* Code */
+			10415,	/* Vendor */
+			"Send-Data-Indication",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR,	/* Fixed flag values */
+			AVP_TYPE_INTEGER32	/* base type of data */
+		};
+		struct dict_object		*type;
+		struct dict_type_data	 tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Send-Data-Indication)", NULL, NULL, NULL };
+		CHECK_dict_new(DICT_TYPE, &tdata, NULL, &type);
+		CHECK_dict_new(DICT_AVP, &data, type, NULL);
+	};
+
+	/* in 29.229                                                    */
+	/* Server-Name                                                  */
+	/* Supported-Features                                           */
+	/* Feature-List-ID                                              */
+	/* Feature-List                                                 */
+	/* Supported-Applications                                       */
+	/* Public-Identity                                              */
+	/* DSAI-Tag */
+	{
+		struct dict_avp_data data = {
+			711,	/* Code */
+			10415,	/* Vendor */
+			"DSAI-Tag",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* in 29.229                                                    */
+	/* Wildcarded-Public-Identity                                   */
+	/* Wildcarded-IMPU */
+	{
+		struct dict_avp_data data = {
+			636,	/* Code */
+			10415,	/* Vendor */
+			"Wildcarded-IMPU",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, UTF8String_type, NULL);
+	};
+
+	/* in 29.229                                                    */
+	/* Session-Priority                                             */
+	/* One-Time-Notification */
+	{
+		struct dict_avp_data data = {
+			712,	/* Code */
+			10415,	/* Vendor */
+			"One-Time-Notification",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR,	/* Fixed flag values */
+			AVP_TYPE_INTEGER32	/* base type of data */
+		};
+		struct dict_object		*type;
+		struct dict_type_data	 tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(One-Time-Notification)", NULL, NULL, NULL };
+		CHECK_dict_new(DICT_TYPE, &tdata, NULL, &type);
+		CHECK_dict_new(DICT_AVP, &data, type, NULL);
+	};
+
+	/* Requested-Nodes */
+	{
+		struct dict_avp_data data = {
+			713,	/* Code */
+			10415,	/* Vendor */
+			"Requested-Nodes",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR,	/* Fixed flag values */
+			AVP_TYPE_UNSIGNED32	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* Serving-Node-Indication */
+	{
+		struct dict_avp_data data = {
+			714,	/* Code */
+			10415,	/* Vendor */
+			"Serving-Node-Indication",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR,	/* Fixed flag values */
+			AVP_TYPE_INTEGER32	/* base type of data */
+		};
+		struct dict_object		*type;
+		struct dict_type_data	 tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Serving-Node-Indication)", NULL, NULL, NULL };
+		CHECK_dict_new(DICT_TYPE, &tdata, NULL, &type);
+		CHECK_dict_new(DICT_AVP, &data, type, NULL);
+	};
+
+	/* Repository-Data-ID */
+	{
+		struct dict_avp_data data = {
+			715,	/* Code */
+			10415,	/* Vendor */
+			"Repository-Data-ID",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR,	/* Fixed flag values */
+			AVP_TYPE_GROUPED	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* Sequence-Number */
+	{
+		struct dict_avp_data data = {
+			716,	/* Code */
+			10415,	/* Vendor */
+			"Sequence-Number",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR,	/* Fixed flag values */
+			AVP_TYPE_UNSIGNED32	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* UDR-Flags */
+	{
+		struct dict_avp_data data = {
+			719,	/* Code */
+			10415,	/* Vendor */
+			"UDR-Flags",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR,	/* Fixed flag values */
+			AVP_TYPE_UNSIGNED32	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* OMA DDS Charging_Data V1.0 20110201-A                        */
+	/* Application-Server-Id */
+	{
+		struct dict_avp_data data = {
+			2101,	/* Code */
+			10415,	/* Vendor */
+			"Application-Server-Id",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, UTF8String_type, NULL);
+	};
+
+	/* Application-Service-Type */
+	{
+		struct dict_avp_data data = {
+			2102,	/* Code */
+			10415,	/* Vendor */
+			"Application-Service-Type",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, UTF8String_type, NULL);
+	};
+
+	/* Application-Session-Id */
+	{
+		struct dict_avp_data data = {
+			2103,	/* Code */
+			10415,	/* Vendor */
+			"Application-Session-Id",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, UTF8String_type, NULL);
+	};
+
+	/* Content-ID */
+	{
+		struct dict_avp_data data = {
+			2116,	/* Code */
+			10415,	/* Vendor */
+			"Content-ID",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, UTF8String_type, NULL);
+	};
+
+	/* Content-provider-ID */
+	{
+		struct dict_avp_data data = {
+			2117,	/* Code */
+			10415,	/* Vendor */
+			"Content-provider-ID",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, UTF8String_type, NULL);
+	};
+
+	/* DCD-Information */
+	{
+		struct dict_avp_data data = {
+			2115,	/* Code */
+			10415,	/* Vendor */
+			"DCD-Information",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_GROUPED	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* Delivery-Status */
+	{
+		struct dict_avp_data data = {
+			2104,	/* Code */
+			10415,	/* Vendor */
+			"Delivery-Status",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, UTF8String_type, NULL);
+	};
+
+	/* IM-Information */
+	{
+		struct dict_avp_data data = {
+			2110,	/* Code */
+			10415,	/* Vendor */
+			"IM-Information",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_GROUPED	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* Number-Of-Messages-Successfully-Exploded */
+	{
+		struct dict_avp_data data = {
+			2111,	/* Code */
+			10415,	/* Vendor */
+			"Number-Of-Messages-Successfully-Exploded",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_UNSIGNED32	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* Number-Of-Messages-Successfully-Sent */
+	{
+		struct dict_avp_data data = {
+			2112,	/* Code */
+			10415,	/* Vendor */
+			"Number-Of-Messages-Successfully-Sent",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_UNSIGNED32	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* Service-Generic-Information */
+	{
+		struct dict_avp_data data = {
+			1256,	/* Code */
+			10415,	/* Vendor */
+			"Service-Generic-Information",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_GROUPED	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* Total-Number-Of-Messages-Exploded */
+	{
+		struct dict_avp_data data = {
+			2113,	/* Code */
+			10415,	/* Vendor */
+			"Total-Number-Of-Messages-Exploded",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_UNSIGNED32	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* Total-Number-Of-Messages-Sent */
+	{
+		struct dict_avp_data data = {
+			2114,	/* Code */
+			10415,	/* Vendor */
+			"Total-Number-Of-Messages-Sent",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_UNSIGNED32	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+
+
+
+	/*****************************************************/
+	/* end of generated data, rules below added manually */
+	/*****************************************************/
+
+
+	
+	/* 3GPP2-BSID */
+	{
+		struct dict_avp_data data = {
+			9010,	/* Code */
+			5535,	/* Vendor */
+			"3GPP2-BSID",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */ /* XXX: guessed */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* 29.212 */
+	
+	{
+		struct dict_object *rule_avp;
+		struct dict_avp_request vpa;
+		vpa.avp_vendor = 10415;
+		vpa.avp_name = "Allocation-Retention-Priority";
+		CHECK_dict_search(DICT_AVP, AVP_BY_NAME_AND_VENDOR, &vpa, &rule_avp);
+		struct local_rules_definition rules[] =
+			{
+				{ { .avp_vendor = 10415, .avp_name = "Priority-Level" }, RULE_REQUIRED, -1, 1 },
+				{ { .avp_vendor = 10415, .avp_name = "Pre-emption-Capability" }, RULE_OPTIONAL, -1, 1 },
+				{ { .avp_vendor = 10415, .avp_name = "Pre-emption-Vulnerability" }, RULE_OPTIONAL, -1, 1 },
+			};
+			PARSE_loc_rules(rules, rule_avp);
+        }
+
+	{
+		struct dict_object *rule_avp;
+		struct dict_avp_request vpa;
+		vpa.avp_vendor = 10415;
+		vpa.avp_name = "QoS-Information";
+		CHECK_dict_search(DICT_AVP, AVP_BY_NAME_AND_VENDOR, &vpa, &rule_avp);
+		struct local_rules_definition rules[] =
+			{
+				{ { .avp_vendor = 10415, .avp_name = "QoS-Class-Identifier" }, RULE_OPTIONAL, -1, 1 },
+				{ { .avp_vendor = 10415, .avp_name = "Max-Requested-Bandwidth-UL" }, RULE_OPTIONAL, -1, 1 },
+				{ { .avp_vendor = 10415, .avp_name = "Max-Requested-Bandwidth-DL" }, RULE_OPTIONAL, -1, 1 },
+				{ { .avp_vendor = 10415, .avp_name = "Guaranteed-Bitrate-UL" }, RULE_OPTIONAL, -1, 1 },
+				{ { .avp_vendor = 10415, .avp_name = "Guaranteed-Bitrate-DL" }, RULE_OPTIONAL, -1, 1 },
+				{ { .avp_vendor = 10415, .avp_name = "Bearer-Identifier" }, RULE_OPTIONAL, -1, 1 },
+				{ { .avp_vendor = 10415, .avp_name = "Allocation-Retention-Priority" }, RULE_OPTIONAL, -1, 1 },
+				{ { .avp_vendor = 10415, .avp_name = "APN-Aggregate-Max-Bitrate-UL" }, RULE_OPTIONAL, -1, 1 },
+				{ { .avp_vendor = 10415, .avp_name = "APN-Aggregate-Max-Bitrate-DL" }, RULE_OPTIONAL, -1, 1 },
+			};
+			PARSE_loc_rules(rules, rule_avp);
+        }
+
+	/* 32.299 */
+
+	{
+		/* additional allowed AVPs */
+		struct dict_object *ccr;
+		CHECK_dict_search(DICT_COMMAND, CMD_BY_NAME, "Credit-Control-Request", &ccr);
+		struct local_rules_definition rules[] = 
+			{
+				{ { .avp_vendor = 10415, .avp_name = "AoC-Request-Type"}, RULE_OPTIONAL, -1, 1 },
+				{ { .avp_vendor = 10415, .avp_name = "Service-Information"}, RULE_OPTIONAL, -1, 1 },
+			};
+		PARSE_loc_rules(rules, ccr);
+        }
+
+	{
+		/* additional allowed AVPs */
+		struct dict_object *ccr;
+		CHECK_dict_search(DICT_COMMAND, CMD_BY_NAME, "Credit-Control-Answer", &ccr);
+		struct local_rules_definition rules[] = 
+			{
+				{ { .avp_vendor = 10415, .avp_name = "Low-Balance-Indication"}, RULE_OPTIONAL, -1, 1 },
+				{ { .avp_vendor = 10415, .avp_name = "Remaining-Balance"}, RULE_OPTIONAL, -1, 1 },
+				{ { .avp_vendor = 10415, .avp_name = "Service-Information"}, RULE_OPTIONAL, -1, 1 },
+			};
+		PARSE_loc_rules(rules, ccr);
+        }
+
+	{
+		struct dict_object *rule_avp;
+		struct dict_avp_request vpa;
+		vpa.avp_vendor = 10415;
+		vpa.avp_name = "Address-Domain";
+		CHECK_dict_search(DICT_AVP, AVP_BY_NAME_AND_VENDOR, &vpa, &rule_avp);
+		struct local_rules_definition rules[] =
+			{
+				{ { .avp_vendor = 10415, .avp_name = "Domain-Name" }, RULE_OPTIONAL, -1, 1 },
+				{ { .avp_vendor = 10415, .avp_name = "3GPP-IMSI-MCC-MNC" }, RULE_OPTIONAL, -1, 1 },
+			};
+			PARSE_loc_rules(rules, rule_avp);
+        }
+
+	{
+		struct dict_object *rule_avp;
+		struct dict_avp_request vpa;
+		vpa.avp_vendor = 10415;
+		vpa.avp_name = "Application-Server-Information";
+		CHECK_dict_search(DICT_AVP, AVP_BY_NAME_AND_VENDOR, &vpa, &rule_avp);
+		struct local_rules_definition rules[] =
+			{
+				{ { .avp_vendor = 10415, .avp_name = "Application-Server" }, RULE_REQUIRED, -1, 1 },
+				{ { .avp_vendor = 10415, .avp_name = "Application-Provided-Called-Party-Address" }, RULE_OPTIONAL, -1, -1 },
+			};
+			PARSE_loc_rules(rules, rule_avp);
+        }
+
+	{
+		struct dict_object *rule_avp;
+		struct dict_avp_request vpa;
+		vpa.avp_vendor = 10415;
+		vpa.avp_name = "Destination-Interface";
+		CHECK_dict_search(DICT_AVP, AVP_BY_NAME_AND_VENDOR, &vpa, &rule_avp);
+		struct local_rules_definition rules[] =
+			{
+				{ { .avp_vendor = 10415, .avp_name = "Interface-Id" }, RULE_OPTIONAL, -1, 1 },
+				{ { .avp_vendor = 10415, .avp_name = "Interface-Text" }, RULE_OPTIONAL, -1, 1 },
+				{ { .avp_vendor = 10415, .avp_name = "Interface-Port" }, RULE_OPTIONAL, -1, 1 },
+				{ { .avp_vendor = 10415, .avp_name = "Interface-Type" }, RULE_OPTIONAL, -1, 1 },
+			};
+			PARSE_loc_rules(rules, rule_avp);
+        }
+
+	{
+		struct dict_object *rule_avp;
+		struct dict_avp_request vpa;
+		vpa.avp_vendor = 10415;
+		vpa.avp_name = "Envelope";
+		CHECK_dict_search(DICT_AVP, AVP_BY_NAME_AND_VENDOR, &vpa, &rule_avp);
+		struct local_rules_definition rules[] =
+			{
+				{ { .avp_vendor = 10415, .avp_name = "Envelope-Start-Time" }, RULE_REQUIRED, -1, 1 },
+				{ { .avp_vendor = 10415, .avp_name = "Envelope-End-Time" }, RULE_OPTIONAL, -1, 1 },
+				{ { .avp_vendor = 0,     .avp_name = "CC-Total-Octets" }, RULE_REQUIRED, -1, 1 },
+				{ { .avp_vendor = 0,     .avp_name = "CC-Input-Octets" }, RULE_OPTIONAL, -1, 1 },
+				{ { .avp_vendor = 0,     .avp_name = "CC-Output-Octets" }, RULE_OPTIONAL, -1, 1 },
+				{ { .avp_vendor = 0,     .avp_name = "CC-Service-Specific-Units" }, RULE_OPTIONAL, -1, 1 },
+			};
+			PARSE_loc_rules(rules, rule_avp);
+        }
+
+	{
+		struct dict_object *rule_avp;
+		struct dict_avp_request vpa;
+		vpa.avp_vendor = 10415;
+		vpa.avp_name = "Event-Type";
+		CHECK_dict_search(DICT_AVP, AVP_BY_NAME_AND_VENDOR, &vpa, &rule_avp);
+		struct local_rules_definition rules[] =
+			{
+				{ { .avp_vendor = 10415, .avp_name = "SIP-Method" }, RULE_OPTIONAL, -1, 1 },
+				{ { .avp_vendor = 10415, .avp_name = "Event" }, RULE_OPTIONAL, -1, 1 },
+				{ { .avp_vendor = 10415, .avp_name = "Expires" }, RULE_OPTIONAL, -1, 1 },
+			};
+			PARSE_loc_rules(rules, rule_avp);
+        }
+
+	{
+		struct dict_object *rule_avp;
+		struct dict_avp_request vpa;
+		vpa.avp_vendor = 10415;
+		vpa.avp_name = "IMS-Information";
+		CHECK_dict_search(DICT_AVP, AVP_BY_NAME_AND_VENDOR, &vpa, &rule_avp);
+		struct local_rules_definition rules[] =
+			{
+				{ { .avp_vendor = 10415, .avp_name = "Event-Type" }, RULE_OPTIONAL, -1, 1 },
+				{ { .avp_vendor = 10415, .avp_name = "Role-Of-Node" }, RULE_OPTIONAL, -1, 1 },
+				{ { .avp_vendor = 10415, .avp_name = "Node-Functionality" }, RULE_REQUIRED, -1, 1 },
+				{ { .avp_vendor = 10415, .avp_name = "User-Session-Id" }, RULE_OPTIONAL, -1, 1 },
+				{ { .avp_vendor = 10415, .avp_name = "Outgoing-Session-Id" }, RULE_OPTIONAL, -1, 1 },
+				{ { .avp_vendor = 10415, .avp_name = "Session-Priority" }, RULE_OPTIONAL, -1, 1 },
+				{ { .avp_vendor = 10415, .avp_name = "Calling-Party-Address" }, RULE_OPTIONAL, -1, -1 },
+				{ { .avp_vendor = 10415, .avp_name = "Called-Party-Address" }, RULE_OPTIONAL, -1, 1 },
+				{ { .avp_vendor = 10415, .avp_name = "Called-Asserted-Identity" }, RULE_OPTIONAL, -1, -1 },
+				{ { .avp_vendor = 10415, .avp_name = "Number-Portability-Routing-Information" }, RULE_OPTIONAL, -1, 1 },
+				{ { .avp_vendor = 10415, .avp_name = "Carrier-Select-Routing-Information" }, RULE_OPTIONAL, -1, 1 },
+				{ { .avp_vendor = 10415, .avp_name = "Alternate-Charged-Party-Address" }, RULE_OPTIONAL, -1, 1 },
+				{ { .avp_vendor = 10415, .avp_name = "Requested-Party-Address" }, RULE_OPTIONAL, -1, -1 },
+				{ { .avp_vendor = 10415, .avp_name = "Associated-URI" }, RULE_OPTIONAL, -1, -1 },
+				{ { .avp_vendor = 10415, .avp_name = "Time-Stamps" }, RULE_OPTIONAL, -1, 1 },
+				{ { .avp_vendor = 10415, .avp_name = "Application-Server-Information" }, RULE_OPTIONAL, -1, -1 },
+				{ { .avp_vendor = 10415, .avp_name = "Inter-Operator-Identifier" }, RULE_OPTIONAL, -1, -1 },
+				{ { .avp_vendor = 10415, .avp_name = "Transit-IOI-List" }, RULE_OPTIONAL, -1, 1 },
+				{ { .avp_vendor = 10415, .avp_name = "IMS-Charging-Identifier" }, RULE_OPTIONAL, -1, 1 },
+				{ { .avp_vendor = 10415, .avp_name = "SDP-Session-Description" }, RULE_OPTIONAL, -1, -1 },
+				{ { .avp_vendor = 10415, .avp_name = "SDP-Media-Component" }, RULE_OPTIONAL, -1, -1 },
+				{ { .avp_vendor = 10415, .avp_name = "Served-Party-IP-Address" }, RULE_OPTIONAL, -1, 1 },
+				{ { .avp_vendor = 10415, .avp_name = "Server-Capabilities" }, RULE_OPTIONAL, -1, 1 },
+				{ { .avp_vendor = 10415, .avp_name = "Trunk-Group-Id" }, RULE_OPTIONAL, -1, 1 },
+				{ { .avp_vendor = 10415, .avp_name = "Bearer-Service" }, RULE_OPTIONAL, -1, 1 },
+				{ { .avp_vendor = 10415, .avp_name = "Service-Id" }, RULE_OPTIONAL, -1, 1 },
+				{ { .avp_vendor = 10415, .avp_name = "Service-Specific-Info" }, RULE_OPTIONAL, -1, -1 },
+				{ { .avp_vendor = 10415, .avp_name = "Message-Body" }, RULE_OPTIONAL, -1, -1 },
+				{ { .avp_vendor = 10415, .avp_name = "Cause-Code" }, RULE_OPTIONAL, -1, 1 },
+				{ { .avp_vendor = 10415, .avp_name = "Access-Network-Information" }, RULE_OPTIONAL, -1, 1 },
+				{ { .avp_vendor = 10415, .avp_name = "Early-Media-Description" }, RULE_OPTIONAL, -1, -1 },
+				{ { .avp_vendor = 10415, .avp_name = "IMS-Communication-Service-Identifier" }, RULE_OPTIONAL, -1, 1 },
+				{ { .avp_vendor = 10415, .avp_name = "IMS-Application-Reference-Identifier" }, RULE_OPTIONAL, -1, 1 },
+				{ { .avp_vendor = 10415, .avp_name = "Online-Charging-Flag" }, RULE_OPTIONAL, -1, 1 },
+				{ { .avp_vendor = 10415, .avp_name = "Real-Time-Tariff-Information" }, RULE_OPTIONAL, -1, 1 },
+				{ { .avp_vendor = 10415, .avp_name = "Account-Expiration" }, RULE_OPTIONAL, -1, 1 },
+				{ { .avp_vendor = 10415, .avp_name = "Initial-IMS-Charging-Identifier" }, RULE_OPTIONAL, -1, 1 },
+				{ { .avp_vendor = 10415, .avp_name = "NNI-Information" }, RULE_OPTIONAL, -1, -1 },
+				{ { .avp_vendor = 10415, .avp_name = "From-Address" }, RULE_OPTIONAL, -1, 1 },
+				{ { .avp_vendor = 10415, .avp_name = "IMS-Emergency-Indicator" }, RULE_OPTIONAL, -1, 1 },
+				{ { .avp_vendor = 10415, .avp_name = "Access-Transfer-Information" }, RULE_OPTIONAL, -1, -1 },
+			};
+			PARSE_loc_rules(rules, rule_avp);
+        }
+
+	{
+		struct dict_object *rule_avp;
+		struct dict_avp_request vpa;
+		vpa.avp_vendor = 10415;
+		vpa.avp_name = "Message-Class";
+		CHECK_dict_search(DICT_AVP, AVP_BY_NAME_AND_VENDOR, &vpa, &rule_avp);
+		struct local_rules_definition rules[] =
+			{
+				{ { .avp_vendor = 10415, .avp_name = "Class-Identifier" }, RULE_OPTIONAL, -1, 1 },
+				{ { .avp_vendor = 10415, .avp_name = "Token-Text" }, RULE_OPTIONAL, -1, 1 },
+			};
+			PARSE_loc_rules(rules, rule_avp);
+        }
+
+	{
+		struct dict_object *rule_avp;
+		struct dict_avp_request vpa;
+		vpa.avp_vendor = 10415;
+		vpa.avp_name = "MMS-Information";
+		CHECK_dict_search(DICT_AVP, AVP_BY_NAME_AND_VENDOR, &vpa, &rule_avp);
+		struct local_rules_definition rules[] =
+			{
+				{ { .avp_vendor = 10415, .avp_name = "Originator-Address" }, RULE_OPTIONAL, -1, 1 },
+				{ { .avp_vendor = 10415, .avp_name = "Recipient-Address" }, RULE_OPTIONAL, -1, -1 },
+				{ { .avp_vendor = 10415, .avp_name = "Submission-Time" }, RULE_OPTIONAL, -1, 1 },
+				{ { .avp_vendor = 10415, .avp_name = "MM-Content-Type" }, RULE_OPTIONAL, -1, 1 },
+				{ { .avp_vendor = 10415, .avp_name = "Priority" }, RULE_OPTIONAL, -1, -1 },
+				{ { .avp_vendor = 10415, .avp_name = "Message-ID" }, RULE_OPTIONAL, -1, 1 },
+				{ { .avp_vendor = 10415, .avp_name = "Message-Type" }, RULE_OPTIONAL, -1, 1 },
+				{ { .avp_vendor = 10415, .avp_name = "Message-Size" }, RULE_OPTIONAL, -1, 1 },
+				{ { .avp_vendor = 10415, .avp_name = "Message-Class" }, RULE_OPTIONAL, -1, 1 },
+				{ { .avp_vendor = 10415, .avp_name = "Delivery-Report-Requested" }, RULE_OPTIONAL, -1, 1 },
+				{ { .avp_vendor = 10415, .avp_name = "Read-Reply-Report-Requested" }, RULE_OPTIONAL, -1, 1 },
+				{ { .avp_vendor = 10415, .avp_name = "MMBox-Storage-Requested" }, RULE_OPTIONAL, -1, 1 },
+				{ { .avp_vendor = 10415, .avp_name = "Applic-ID" }, RULE_OPTIONAL, -1, 1 },
+				{ { .avp_vendor = 10415, .avp_name = "Reply-Applic-ID" }, RULE_OPTIONAL, -1, 1 },
+				{ { .avp_vendor = 10415, .avp_name = "Aux-Applic-Info" }, RULE_OPTIONAL, -1, 1 },
+				{ { .avp_vendor = 10415, .avp_name = "Content-Class" }, RULE_OPTIONAL, -1, 1 },
+				{ { .avp_vendor = 10415, .avp_name = "DRM-Content" }, RULE_OPTIONAL, -1, 1 },
+				{ { .avp_vendor = 10415, .avp_name = "Adaptations" }, RULE_OPTIONAL, -1, 1 },
+				{ { .avp_vendor = 10415, .avp_name = "VASP-ID" }, RULE_OPTIONAL, -1, 1 },
+				{ { .avp_vendor = 10415, .avp_name = "VAS-ID" }, RULE_OPTIONAL, -1, 1 },
+			};
+			PARSE_loc_rules(rules, rule_avp);
+        }
+
+        {
+		/* Multiple-Services-Credit-Control */
+		/* additional allowed AVPs */
+		struct dict_object *rule_avp;
+		struct dict_avp_request vpa;
+		vpa.avp_vendor = 0;
+		vpa.avp_name = "Multiple-Services-Credit-Control";
+		CHECK_dict_search(DICT_AVP, AVP_BY_NAME_AND_VENDOR, &vpa, &rule_avp);
+		struct local_rules_definition rules[] =
+			{
+				{ { .avp_vendor = 10415, .avp_name = "Time-Quota-Threshold" }, RULE_OPTIONAL, -1, 1 },
+				{ { .avp_vendor = 10415, .avp_name = "Volume-Quota-Threshold" }, RULE_OPTIONAL, -1, 1 },
+				{ { .avp_vendor = 10415, .avp_name = "Unit-Quota-Threshold" }, RULE_OPTIONAL, -1, 1 },
+				{ { .avp_vendor = 10415, .avp_name = "Quota-Holding-Time" }, RULE_OPTIONAL, -1, 1 },
+				{ { .avp_vendor = 10415, .avp_name = "Quota-Consumption-Time" }, RULE_OPTIONAL, -1, 1 },
+				{ { .avp_vendor = 10415, .avp_name = "Reporting-Reason" }, RULE_OPTIONAL, -1, -1 },
+				{ { .avp_vendor = 10415, .avp_name = "Trigger" }, RULE_OPTIONAL, -1, 1 },
+				{ { .avp_vendor = 10415, .avp_name = "PS-Furnish-Charging-Information" }, RULE_OPTIONAL, -1, 1 },
+				{ { .avp_vendor = 10415, .avp_name = "Refund-Information" }, RULE_OPTIONAL, -1, 1 },
+				{ { .avp_vendor = 10415, .avp_name = "AF-Correlation-Information" }, RULE_OPTIONAL, -1, -1 },
+				{ { .avp_vendor = 10415, .avp_name = "Envelope" }, RULE_OPTIONAL, -1, -1 },
+				{ { .avp_vendor = 10415, .avp_name = "Envelope-Reporting" }, RULE_OPTIONAL, -1, 1 },
+				{ { .avp_vendor = 10415, .avp_name = "Time-Quota-Mechanism" }, RULE_OPTIONAL, -1, 1 },
+				{ { .avp_vendor = 10415, .avp_name = "Service-Specific-Info" }, RULE_OPTIONAL, -1, -1 },
+				{ { .avp_vendor = 10415, .avp_name = "QoS-Information" }, RULE_OPTIONAL, -1, 1 },
+			};
+		PARSE_loc_rules(rules, rule_avp);
+        }
+
+	{
+		struct dict_object *rule_avp;
+		struct dict_avp_request vpa;
+		vpa.avp_vendor = 10415;
+		vpa.avp_name = "Offline-Charging";
+		CHECK_dict_search(DICT_AVP, AVP_BY_NAME_AND_VENDOR, &vpa, &rule_avp);
+		struct local_rules_definition rules[] =
+			{
+				{ { .avp_vendor = 10415, .avp_name = "Quota-Consumption-Time" }, RULE_OPTIONAL, -1, 1 },
+				{ { .avp_vendor = 10415, .avp_name = "Time-Quota-Mechanism" }, RULE_OPTIONAL, -1, 1 },
+				{ { .avp_vendor = 10415, .avp_name = "Envelope-Reporting" }, RULE_OPTIONAL, -1, 1 },
+				{ { .avp_vendor = 0,     .avp_name = "Multiple-Services-Credit-Control" }, RULE_OPTIONAL, -1, -1 },
+			};
+			PARSE_loc_rules(rules, rule_avp);
+        }
+
+	{
+		struct dict_object *rule_avp;
+		struct dict_avp_request vpa;
+		vpa.avp_vendor = 10415;
+		vpa.avp_name = "Originator-Address";
+		CHECK_dict_search(DICT_AVP, AVP_BY_NAME_AND_VENDOR, &vpa, &rule_avp);
+		struct local_rules_definition rules[] =
+			{
+				{ { .avp_vendor = 10415, .avp_name = "Address-Type" }, RULE_OPTIONAL, -1, 1 },
+				{ { .avp_vendor = 10415, .avp_name = "Address-Data" }, RULE_OPTIONAL, -1, 1 },
+				{ { .avp_vendor = 10415, .avp_name = "Address-Domain" }, RULE_OPTIONAL, -1, 1 },
+			};
+			PARSE_loc_rules(rules, rule_avp);
+        }
+
+	{
+		struct dict_object *rule_avp;
+		struct dict_avp_request vpa;
+		vpa.avp_vendor = 10415;
+		vpa.avp_name = "Originator-Interface";
+		CHECK_dict_search(DICT_AVP, AVP_BY_NAME_AND_VENDOR, &vpa, &rule_avp);
+		struct local_rules_definition rules[] =
+			{
+				{ { .avp_vendor = 10415, .avp_name = "Interface-Id" }, RULE_OPTIONAL, -1, 1 },
+				{ { .avp_vendor = 10415, .avp_name = "Interface-Text" }, RULE_OPTIONAL, -1, 1 },
+				{ { .avp_vendor = 10415, .avp_name = "Interface-Port" }, RULE_OPTIONAL, -1, 1 },
+				{ { .avp_vendor = 10415, .avp_name = "Interface-Type" }, RULE_OPTIONAL, -1, 1 },
+			};
+			PARSE_loc_rules(rules, rule_avp);
+        }
+
+	{
+		struct dict_object *rule_avp;
+		struct dict_avp_request vpa;
+		vpa.avp_vendor = 10415;
+		vpa.avp_name = "PS-Furnish-Charging-Information";
+		CHECK_dict_search(DICT_AVP, AVP_BY_NAME_AND_VENDOR, &vpa, &rule_avp);
+		struct local_rules_definition rules[] =
+			{
+				{ { .avp_vendor = 10415, .avp_name = "3GPP-Charging-Id" }, RULE_REQUIRED, -1, 1 },
+				{ { .avp_vendor = 10415, .avp_name = "PS-Free-Format-Data" }, RULE_REQUIRED, -1, 1 },
+				{ { .avp_vendor = 10415, .avp_name = "PS-Append-Free-Format-Data" }, RULE_OPTIONAL, -1, 1 },
+			};
+			PARSE_loc_rules(rules, rule_avp);
+        }
+
+	{
+		struct dict_object *rule_avp;
+		struct dict_avp_request vpa;
+		vpa.avp_vendor = 10415;
+		vpa.avp_name = "PS-Information";
+		CHECK_dict_search(DICT_AVP, AVP_BY_NAME_AND_VENDOR, &vpa, &rule_avp);
+		struct local_rules_definition rules[] =
+			{
+				{ { .avp_vendor = 10415, .avp_name = "3GPP-Charging-Id" }, RULE_OPTIONAL, -1, 1 },
+				{ { .avp_vendor = 10415, .avp_name = "PDN-Connection-Charging-ID" }, RULE_OPTIONAL, -1, 1 },
+				{ { .avp_vendor = 10415, .avp_name = "Node-Id" }, RULE_OPTIONAL, -1, 1 },
+				{ { .avp_vendor = 10415, .avp_name = "3GPP-PDP-Type" }, RULE_OPTIONAL, -1, 1 },
+				{ { .avp_vendor = 10415, .avp_name = "PDP-Address" }, RULE_OPTIONAL, -1, -1 },
+				{ { .avp_vendor = 10415, .avp_name = "PDP-Address-Prefix-Length" }, RULE_OPTIONAL, -1, 1 },
+				{ { .avp_vendor = 10415, .avp_name = "Dynamic-Address-Flag" }, RULE_OPTIONAL, -1, 1 },
+				{ { .avp_vendor = 10415, .avp_name = "Dynamic-Address-Flag-Extension" }, RULE_OPTIONAL, -1, 1 },
+				{ { .avp_vendor = 10415, .avp_name = "QoS-Information" }, RULE_OPTIONAL, -1, 1 },
+				{ { .avp_vendor = 10415, .avp_name = "SGSN-Address" }, RULE_OPTIONAL, -1, -1 },
+				{ { .avp_vendor = 10415, .avp_name = "GGSN-Address" }, RULE_OPTIONAL, -1, -1 },
+				{ { .avp_vendor = 10415, .avp_name = "SGW-Address" }, RULE_OPTIONAL, -1, -1 },
+				{ { .avp_vendor = 10415, .avp_name = "CG-Address" }, RULE_OPTIONAL, -1, 1 },
+				{ { .avp_vendor = 10415, .avp_name = "Serving-Node-Type" }, RULE_OPTIONAL, -1, 1 },
+				{ { .avp_vendor = 10415, .avp_name = "SGW-Change" }, RULE_OPTIONAL, -1, 1 },
+				{ { .avp_vendor = 10415, .avp_name = "3GPP-IMSI-MCC-MNC" }, RULE_OPTIONAL, -1, 1 },
+				{ { .avp_vendor = 10415, .avp_name = "IMSI-Unauthenticated-Flag" }, RULE_OPTIONAL, -1, 1 },
+				{ { .avp_vendor = 10415, .avp_name = "3GPP-GGSN-MCC-MNC" }, RULE_OPTIONAL, -1, 1 },
+				{ { .avp_vendor = 10415, .avp_name = "3GPP-NSAPI" }, RULE_OPTIONAL, -1, 1 },
+				{ { .avp_vendor = 0,     .avp_name = "Called-Station-Id" }, RULE_OPTIONAL, -1, 1 },
+				{ { .avp_vendor = 10415, .avp_name = "3GPP-Session-Stop-Indicator" }, RULE_OPTIONAL, -1, 1 },
+				{ { .avp_vendor = 10415, .avp_name = "3GPP-Selection-Mode" }, RULE_OPTIONAL, -1, 1 },
+				{ { .avp_vendor = 10415, .avp_name = "3GPP-Charging-Characteristics" }, RULE_OPTIONAL, -1, 1 },
+				{ { .avp_vendor = 10415, .avp_name = "Charging-Characteristics-Selection-Mode" }, RULE_OPTIONAL, -1, 1 },
+				{ { .avp_vendor = 10415, .avp_name = "3GPP-SGSN-MCC-MNC" }, RULE_OPTIONAL, -1, 1 },
+				{ { .avp_vendor = 10415, .avp_name = "3GPP-MS-TimeZone" }, RULE_OPTIONAL, -1, 1 },
+				{ { .avp_vendor = 10415, .avp_name = "Charging-Rule-Base-Name" }, RULE_OPTIONAL, -1, 1 },
+				{ { .avp_vendor = 10415, .avp_name = "3GPP-User-Location-Info" }, RULE_OPTIONAL, -1, 1 },
+				{ { .avp_vendor = 10415, .avp_name = "User-CSG-Information" }, RULE_OPTIONAL, -1, 1 },
+				{ { .avp_vendor = 5535,  .avp_name = "3GPP2-BSID" }, RULE_OPTIONAL, -1, 1 },
+				{ { .avp_vendor = 10415, .avp_name = "3GPP-RAT-Type" }, RULE_OPTIONAL, -1, 1 },
+				{ { .avp_vendor = 10415, .avp_name = "PS-Furnish-Charging-Information" }, RULE_OPTIONAL, -1, 1 },
+				{ { .avp_vendor = 10415, .avp_name = "PDP-Context-Type" }, RULE_OPTIONAL, -1, 1 },
+				{ { .avp_vendor = 10415, .avp_name = "Offline-Charging" }, RULE_OPTIONAL, -1, 1 },
+				{ { .avp_vendor = 10415, .avp_name = "Traffic-Data-Volumes" }, RULE_OPTIONAL, -1, -1 },
+				{ { .avp_vendor = 10415, .avp_name = "Service-Data-Container" }, RULE_OPTIONAL, -1, -1 },
+				{ { .avp_vendor = 0,     .avp_name = "User-Equipment-Info" }, RULE_OPTIONAL, -1, 1 },
+				{ { .avp_vendor = 10415, .avp_name = "Terminal-Information" }, RULE_OPTIONAL, -1, 1 },
+				{ { .avp_vendor = 10415, .avp_name = "Start-Time" }, RULE_OPTIONAL, -1, 1 },
+				{ { .avp_vendor = 10415, .avp_name = "Stop-Time" }, RULE_OPTIONAL, -1, 1 },
+				{ { .avp_vendor = 10415, .avp_name = "Change-Condition" }, RULE_OPTIONAL, -1, 1 },
+				{ { .avp_vendor = 10415, .avp_name = "Diagnostics" }, RULE_OPTIONAL, -1, 1 },
+				{ { .avp_vendor = 10415, .avp_name = "Low-Priority-Indicator" }, RULE_OPTIONAL, -1, 1 },
+				{ { .avp_vendor = 10415, .avp_name = "MME-Number-for-MT-SMS" }, RULE_OPTIONAL, -1, 1 },
+				{ { .avp_vendor = 10415, .avp_name = "MME-Name" }, RULE_OPTIONAL, -1, 1 },
+				{ { .avp_vendor = 10415, .avp_name = "MME-Realm" }, RULE_OPTIONAL, -1, 1 },
+			};
+			PARSE_loc_rules(rules, rule_avp);
+        }
+
+	{
+		struct dict_object *rule_avp;
+		struct dict_avp_request vpa;
+		vpa.avp_vendor = 10415;
+		vpa.avp_name = "Recipient-Address";
+		CHECK_dict_search(DICT_AVP, AVP_BY_NAME_AND_VENDOR, &vpa, &rule_avp);
+		struct local_rules_definition rules[] =
+			{
+				{ { .avp_vendor = 10415, .avp_name = "Address-Type" }, RULE_OPTIONAL, -1, 1 },
+				{ { .avp_vendor = 10415, .avp_name = "Address-Data" }, RULE_OPTIONAL, -1, 1 },
+				{ { .avp_vendor = 10415, .avp_name = "Address-Domain" }, RULE_OPTIONAL, -1, 1 },
+				{ { .avp_vendor = 10415, .avp_name = "Addressee-Type" }, RULE_OPTIONAL, -1, 1 },
+			};
+			PARSE_loc_rules(rules, rule_avp);
+        }
+
+	{
+		struct dict_object *rule_avp;
+		struct dict_avp_request vpa;
+		vpa.avp_vendor = 10415;
+		vpa.avp_name = "Recipient-Info";
+		CHECK_dict_search(DICT_AVP, AVP_BY_NAME_AND_VENDOR, &vpa, &rule_avp);
+		struct local_rules_definition rules[] =
+			{
+				{ { .avp_vendor = 10415, .avp_name = "Destination-Interface" }, RULE_OPTIONAL, -1, 1 },
+				{ { .avp_vendor = 10415, .avp_name = "Recipient-Address" }, RULE_OPTIONAL, -1, -1 },
+				{ { .avp_vendor = 10415, .avp_name = "Recipient-Received-Address" }, RULE_OPTIONAL, -1, -1 },
+				{ { .avp_vendor = 10415, .avp_name = "Recipient-SCCP-Address" }, RULE_OPTIONAL, -1, 1 },
+				{ { .avp_vendor = 10415, .avp_name = "SM-Protocol-ID" }, RULE_OPTIONAL, -1, 1 },
+			};
+			PARSE_loc_rules(rules, rule_avp);
+        }
+
+	{
+		struct dict_object *rule_avp;
+		struct dict_avp_request vpa;
+		vpa.avp_vendor = 10415;
+		vpa.avp_name = "Recipient-Received-Address";
+		CHECK_dict_search(DICT_AVP, AVP_BY_NAME_AND_VENDOR, &vpa, &rule_avp);
+		struct local_rules_definition rules[] =
+			{
+				{ { .avp_vendor = 10415, .avp_name = "Address-Type" }, RULE_OPTIONAL, -1, 1 },
+				{ { .avp_vendor = 10415, .avp_name = "Address-Data" }, RULE_OPTIONAL, -1, 1 },
+				{ { .avp_vendor = 10415, .avp_name = "Address-Domain" }, RULE_OPTIONAL, -1, 1 },
+			};
+			PARSE_loc_rules(rules, rule_avp);
+        }
+
+	{
+		struct dict_object *rule_avp;
+		struct dict_avp_request vpa;
+		vpa.avp_vendor = 10415;
+		vpa.avp_name = "SDP-Media-Component";
+		CHECK_dict_search(DICT_AVP, AVP_BY_NAME_AND_VENDOR, &vpa, &rule_avp);
+		struct local_rules_definition rules[] =
+			{
+				{ { .avp_vendor = 10415, .avp_name = "SDP-Media-Name" }, RULE_OPTIONAL, -1, 1 },
+				{ { .avp_vendor = 10415, .avp_name = "SDP-Media-Description" }, RULE_OPTIONAL, -1, -1 },
+				{ { .avp_vendor = 10415, .avp_name = "Local-GW-Inserted-Indication" }, RULE_OPTIONAL, -1, 1 },
+				{ { .avp_vendor = 10415, .avp_name = "IP-Realm-Default-Indication" }, RULE_OPTIONAL, -1, 1 },
+				{ { .avp_vendor = 10415, .avp_name = "Transcoder-Inserted-Indication" }, RULE_OPTIONAL, -1, 1 },
+				{ { .avp_vendor = 10415, .avp_name = "Media-Initiator-Flag" }, RULE_OPTIONAL, -1, 1 },
+				{ { .avp_vendor = 10415, .avp_name = "Media-Initiator-Party" }, RULE_OPTIONAL, -1, 1 },
+				{ { .avp_vendor = 10415, .avp_name = "3GPP-Charging-Id" }, RULE_OPTIONAL, -1, 1 },
+				{ { .avp_vendor = 10415, .avp_name = "Access-Network-Charging-Identifier-Value" }, RULE_OPTIONAL, -1, 1 },
+				{ { .avp_vendor = 10415, .avp_name = "SDP-Type" }, RULE_OPTIONAL, -1, 1 },
+			};
+			PARSE_loc_rules(rules, rule_avp);
+        }
+
+	{
+		struct dict_object *rule_avp;
+		struct dict_avp_request vpa;
+		vpa.avp_vendor = 10415;
+		vpa.avp_name = "Service-Information";
+		CHECK_dict_search(DICT_AVP, AVP_BY_NAME_AND_VENDOR, &vpa, &rule_avp);
+		struct local_rules_definition rules[] =
+			{
+				{ { .avp_vendor = 0,     .avp_name = "Subscription-Id" }, RULE_OPTIONAL, -1, -1 },
+				{ { .avp_vendor = 10415, .avp_name = "AoC-Information" }, RULE_OPTIONAL, -1, 1 },
+				{ { .avp_vendor = 10415, .avp_name = "PS-Information" }, RULE_OPTIONAL, -1, 1 },
+				{ { .avp_vendor = 10415, .avp_name = "WLAN-Information" }, RULE_OPTIONAL, -1, 1 },
+				{ { .avp_vendor = 10415, .avp_name = "IMS-Information" }, RULE_OPTIONAL, -1, 1 },
+				{ { .avp_vendor = 10415, .avp_name = "MMS-Information" }, RULE_OPTIONAL, -1, 1 },
+				{ { .avp_vendor = 10415, .avp_name = "LCS-Information" }, RULE_OPTIONAL, -1, 1 },
+				{ { .avp_vendor = 10415, .avp_name = "PoC-Information" }, RULE_OPTIONAL, -1, 1 },
+				{ { .avp_vendor = 10415, .avp_name = "MBMS-Information" }, RULE_OPTIONAL, -1, 1 },
+				{ { .avp_vendor = 10415, .avp_name = "SMS-Information" }, RULE_OPTIONAL, -1, 1 },
+				{ { .avp_vendor = 10415, .avp_name = "MMTel-Information" }, RULE_OPTIONAL, -1, 1 },
+				{ { .avp_vendor = 10415, .avp_name = "Service-Generic-Information" }, RULE_OPTIONAL, -1, 1 },
+				{ { .avp_vendor = 10415, .avp_name = "IM-Information" }, RULE_OPTIONAL, -1, 1 },
+				{ { .avp_vendor = 10415, .avp_name = "DCD-Information" }, RULE_OPTIONAL, -1, 1 },
+			};
+			PARSE_loc_rules(rules, rule_avp);
+        }
+
+	{
+		struct dict_object *rule_avp;
+		struct dict_avp_request vpa;
+		vpa.avp_vendor = 10415;
+		vpa.avp_name = "SMS-Information";
+		CHECK_dict_search(DICT_AVP, AVP_BY_NAME_AND_VENDOR, &vpa, &rule_avp);
+		struct local_rules_definition rules[] =
+			{
+				{ { .avp_vendor = 10415, .avp_name = "SMS-Node" }, RULE_OPTIONAL, -1, 1 },
+				{ { .avp_vendor = 10415, .avp_name = "Client-Address" }, RULE_OPTIONAL, -1, 1 },
+				{ { .avp_vendor = 10415, .avp_name = "Originator-SCCP-Address" }, RULE_OPTIONAL, -1, 1 },
+				{ { .avp_vendor = 10415, .avp_name = "SMSC-Address" }, RULE_OPTIONAL, -1, 1 },
+				{ { .avp_vendor = 10415, .avp_name = "Data-Coding-Scheme" }, RULE_OPTIONAL, -1, 1 },
+				{ { .avp_vendor = 10415, .avp_name = "SM-Discharge-Time" }, RULE_OPTIONAL, -1, 1 },
+				{ { .avp_vendor = 10415, .avp_name = "SM-Message-Type" }, RULE_OPTIONAL, -1, 1 },
+				{ { .avp_vendor = 10415, .avp_name = "Originator-Interface" }, RULE_OPTIONAL, -1, 1 },
+				{ { .avp_vendor = 10415, .avp_name = "SM-Protocol-ID" }, RULE_OPTIONAL, -1, 1 },
+				{ { .avp_vendor = 10415, .avp_name = "Reply-Path-Requested" }, RULE_OPTIONAL, -1, 1 },
+				{ { .avp_vendor = 10415, .avp_name = "SM-Status" }, RULE_OPTIONAL, -1, 1 },
+				{ { .avp_vendor = 10415, .avp_name = "SM-User-Data-Header" }, RULE_OPTIONAL, -1, 1 },
+				{ { .avp_vendor = 10415, .avp_name = "Number-Of-Messages-Sent" }, RULE_OPTIONAL, -1, 1 },
+				{ { .avp_vendor = 10415, .avp_name = "Recipient-Info" }, RULE_OPTIONAL, -1, -1 },
+				{ { .avp_vendor = 10415, .avp_name = "Originator-Received-Address" }, RULE_OPTIONAL, -1, 1 },
+				{ { .avp_vendor = 10415, .avp_name = "SM-Service-Type" }, RULE_OPTIONAL, -1, 1 },
+			};
+			PARSE_loc_rules(rules, rule_avp);
+        }
+
+	{
+		struct dict_object *rule_avp;
+		struct dict_avp_request vpa;
+		vpa.avp_vendor = 10415;
+		vpa.avp_name = "Time-Quota-Mechanism";
+		CHECK_dict_search(DICT_AVP, AVP_BY_NAME_AND_VENDOR, &vpa, &rule_avp);
+		struct local_rules_definition rules[] =
+			{
+				{ { .avp_vendor = 10415, .avp_name = "Time-Quota-Type" }, RULE_REQUIRED, -1, 1 },
+				{ { .avp_vendor = 10415, .avp_name = "Base-Time-Interval" }, RULE_REQUIRED, -1, 1 },
+			};
+			PARSE_loc_rules(rules, rule_avp);
+        }
+
+	{
+		struct dict_object *rule_avp;
+		struct dict_avp_request vpa;
+		vpa.avp_vendor = 10415;
+		vpa.avp_name = "Time-Stamps";
+		CHECK_dict_search(DICT_AVP, AVP_BY_NAME_AND_VENDOR, &vpa, &rule_avp);
+		struct local_rules_definition rules[] =
+			{
+				{ { .avp_vendor = 10415, .avp_name = "SIP-Request-Timestamp" }, RULE_OPTIONAL, -1, 1 },
+				{ { .avp_vendor = 10415, .avp_name = "SIP-Response-Timestamp" }, RULE_OPTIONAL, -1, 1 },
+				{ { .avp_vendor = 10415, .avp_name = "SIP-Request-Timestamp-Fraction" }, RULE_OPTIONAL, -1, 1 },
+				{ { .avp_vendor = 10415, .avp_name = "SIP-Response-Timestamp-Fraction" }, RULE_OPTIONAL, -1, 1 },
+			};
+			PARSE_loc_rules(rules, rule_avp);
+        }
+
+	{
+		/* Used-Service-Unit */
+		/* additional allowed AVPs */
+		struct dict_object *rule_avp;
+		struct dict_avp_request vpa;
+		vpa.avp_vendor = 0;
+		vpa.avp_name = "Used-Service-Unit";
+		CHECK_dict_search(DICT_AVP, AVP_BY_NAME_AND_VENDOR, &vpa, &rule_avp);
+		struct local_rules_definition rules[] =
+			{
+				{ { .avp_vendor = 10415, .avp_name = "Reporting-Reason" }, RULE_OPTIONAL, -1, 1 },
+				{ { .avp_vendor = 10415, .avp_name = "Event-Charging-TimeStamp" }, RULE_OPTIONAL, -1, -1 },
+			};
+		PARSE_loc_rules(rules, rule_avp);
+        }
+
+	/* OMA */
+	{
+		struct dict_object *rule_avp;
+		struct dict_avp_request vpa;
+		vpa.avp_vendor = 10415;
+		vpa.avp_name = "DCD-Information";
+		CHECK_dict_search(DICT_AVP, AVP_BY_NAME_AND_VENDOR, &vpa, &rule_avp);
+		struct local_rules_definition rules[] =
+			{
+				{ { .avp_vendor = 10415, .avp_name = "Content-ID" }, RULE_OPTIONAL, -1, 1 },
+				{ { .avp_vendor = 10415, .avp_name = "Content-provider-ID" }, RULE_OPTIONAL, -1, 1 },
+			};
+			PARSE_loc_rules(rules, rule_avp);
+        }
+	{
+		struct dict_object *rule_avp;
+		struct dict_avp_request vpa;
+		vpa.avp_vendor = 10415;
+		vpa.avp_name = "IM-Information";
+		CHECK_dict_search(DICT_AVP, AVP_BY_NAME_AND_VENDOR, &vpa, &rule_avp);
+		struct local_rules_definition rules[] =
+			{
+				{ { .avp_vendor = 10415, .avp_name = "Total-Number-Of-Messages-Sent" }, RULE_OPTIONAL, -1, 1 },
+				{ { .avp_vendor = 10415, .avp_name = "Total-Number-Of-Messages-Exploded" }, RULE_OPTIONAL, -1, 1 },
+				{ { .avp_vendor = 10415, .avp_name = "Number-Of-Messages-Successfully-Sent" }, RULE_OPTIONAL, -1, 1 },
+				{ { .avp_vendor = 10415, .avp_name = "Number-Of-Messages-Successfully-Exploded" }, RULE_OPTIONAL, -1, 1 },
+			};
+			PARSE_loc_rules(rules, rule_avp);
+        }
+	{
+		struct dict_object *rule_avp;
+		struct dict_avp_request vpa;
+		vpa.avp_vendor = 10415;
+		vpa.avp_name = "Service-Generic-Information";
+		CHECK_dict_search(DICT_AVP, AVP_BY_NAME_AND_VENDOR, &vpa, &rule_avp);
+		struct local_rules_definition rules[] =
+			{
+				{ { .avp_vendor = 10415, .avp_name = "Application-Server-Id" }, RULE_OPTIONAL, -1, 1 },
+				{ { .avp_vendor = 10415, .avp_name = "Application-Service-Type" }, RULE_OPTIONAL, -1, 1 },
+				{ { .avp_vendor = 10415, .avp_name = "Application-Session-Id" }, RULE_OPTIONAL, -1, 1 },
+				{ { .avp_vendor = 10415, .avp_name = "Delivery-Status" }, RULE_OPTIONAL, -1, 1 },
+			};
+			PARSE_loc_rules(rules, rule_avp);
+        }
+	
+	LOG_D( "Extension 'Dictionary definitions for DCCA 3GPP' initialized");
+	return 0;
+}
+
+EXTENSION_ENTRY("dict_dcca_3gpp", dict_dcca_3gpp_entry, "dict_dcca");
diff --git a/extensions/dict_dcca_3gpp/dict_dcca_3gpp.org b/extensions/dict_dcca_3gpp/dict_dcca_3gpp.org
new file mode 100644
index 0000000..e7eb34f
--- /dev/null
+++ b/extensions/dict_dcca_3gpp/dict_dcca_3gpp.org
@@ -0,0 +1,789 @@
+| Attribute Name                                                | Code | Section defined | Value Type       | MUST | MAY | SHLD NOT | MUST NOT | Encr |
+| # 3GPP 29.061-c00 (12.0.0 2012.12.20)                         |      |                 |                  |      |     |          |          |      |
+| # 3GPP 29.061 is not very clear and self-inconsistent about M |      |                 |                  |      |     |          |          |      |
+| # for this reason, other sources are assumed more trustworthy |      |                 |                  |      |     |          |          |      |
+| # M inconsistently specified                                  |      |                 |                  |      |     |          |          |      |
+| 3GPP-IMSI                                                     |    1 |          16.4.7 | UTF8String       | M,V  | P   |          |          |      |
+| # 29.061 says OctetString; dumps say UInt32; manually changed |      |                 |                  |      |     |          |          |      |
+| # 29.061 says MUST NOT M; dumps say MUST                      |      |                 |                  |      |     |          |          |      |
+| 3GPP-Charging-Id                                              |    2 |          16.4.7 | Unsigned32       | M,V  | P   |          |          |      |
+| # 29.061 says MUST NOT M; dumps say MUST                      |      |                 |                  |      |     |          |          |      |
+| 3GPP-PDP-Type                                                 |    3 |          16.4.7 | Enumerated       | M,V  | P   |          |          |      |
+| 3GPP-CG-Address                                               |    4 |          16.4.7 | OctetString      | V    | P   |          | M        |      |
+| # 29.061 says MUST NOT M; old contrib/3gpp says MUST          |      |                 |                  |      |     |          |          |      |
+| 3GPP-GPRS-Negotiated-QoS-Profile                              |    5 |          16.4.7 | UTF8String       | M,V  | P   |          |          |      |
+| # M inconsistently specified; old contrib/3gg says MUST NOT   |      |                 |                  |      |     |          |          |      |
+| 3GPP-SGSN-Address                                             |    6 |          16.4.7 | OctetString      | V    | P   |          | M        |      |
+| 3GPP-GGSN-Address                                             |    7 |          16.4.7 | OctetString      | V    | P   |          | M        |      |
+| # 29.061 says MUST NOT M; dumps say MUST                      |      |                 |                  |      |     |          |          |      |
+| 3GPP-IMSI-MCC-MNC                                             |    8 |          16.4.7 | UTF8String       | M,V  | P   |          |          |      |
+| # 29.061 says MUST NOT M; old contrib/3gpp says MUST          |      |                 |                  |      |     |          |          |      |
+| 3GPP-GGSN-MCC-MNC                                             |    9 |          16.4.7 | UTF8String       | M,V  | P   |          |          |      |
+| # 29.061 says MUST NOT M; old contrib/3gpp says MUST          |      |                 |                  |      |     |          |          |      |
+| 3GPP-NSAPI                                                    |   10 |          16.4.7 | OctetString      | M,V  | P   |          |          |      |
+| # added manually, missing in AVP table                        |      |                 |                  |      |     |          |          |      |
+| 3GPP-Session-Stop-Indicator                                   |   11 |          16.4.7 | OctetString      | V    | P   |          | M        |      |
+| # 29.061 says MUST NOT M; old contrib/3gpp says MUST          |      |                 |                  |      |     |          |          |      |
+| 3GPP-Selection-Mode                                           |   12 |          16.4.7 | UTF8String       | M,V  | P   |          |          |      |
+| # 29.061 says MUST NOT M; old contrib/3gpp says MUST          |      |                 |                  |      |     |          |          |      |
+| 3GPP-Charging-Characteristics                                 |   13 |          16.4.7 | UTF8String       | M,V  | P   |          |          |      |
+| # 29.061 says MUST NOT M; old contrib/3gpp says MUST          |      |                 |                  |      |     |          |          |      |
+| 3GPP-CG-IPv6-Address                                          |   14 |          16.4.7 | OctetString      | M,V  | P   |          |          |      |
+| # M inconsistently specified                                  |      |                 |                  |      |     |          |          |      |
+| # 29.061 says MUST NOT M; old contrib/3gpp says MUST          |      |                 |                  |      |     |          |          |      |
+| 3GPP-SGSN-IPv6-Address                                        |   15 |          16.4.7 | OctetString      | M,V  | P   |          |          |      |
+| # 29.061 says MUST NOT M; old contrib/3gpp says MUST          |      |                 |                  |      |     |          |          |      |
+| 3GPP-GGSN-IPv6-Address                                        |   16 |          16.4.7 | OctetString      | M,V  | P   |          |          |      |
+| # 29.061 says MUST NOT M; old contrib/3gpp says MUST          |      |                 |                  |      |     |          |          |      |
+| 3GPP-IPv6-DNS-Servers                                         |   17 |          16.4.7 | OctetString      | M,V  | P   |          |          |      |
+| # 29.061 says MUST NOT M; old contrib/3gpp says MUST          |      |                 |                  |      |     |          |          |      |
+| 3GPP-SGSN-MCC-MNC                                             |   18 |          16.4.7 | UTF8String       | M,V  | P   |          |          |      |
+| # M inconsistently specified                                  |      |                 |                  |      |     |          |          |      |
+| 3GPP-IMEISV                                                   |   20 |          16.4.7 | OctetString      | M,V  | P   |          |          |      |
+| # M inconsistently specified                                  |      |                 |                  |      |     |          |          |      |
+| 3GPP-RAT-Type                                                 |   21 |          16.4.7 | OctetString      | M,V  | P   |          |          |      |
+| # M inconsistently specified                                  |      |                 |                  |      |     |          |          |      |
+| 3GPP-User-Location-Info                                       |   22 |          16.4.7 | OctetString      | M,V  | P   |          |          |      |
+| # M inconsistently specified                                  |      |                 |                  |      |     |          |          |      |
+| 3GPP-MS-TimeZone                                              |   23 |          16.4.7 | OctetString      | M,V  | P   |          |          |      |
+| 3GPP-CAMEL-Charging-Info                                      |   24 |          16.4.7 | OctetString      | V    | P   |          | M        |      |
+| 3GPP-Packet-Filter                                            |   25 |          16.4.7 | OctetString      | V    | P   |          | M        |      |
+| 3GPP-Negotiated-DSCP                                          |   26 |          16.4.7 | OctetString      | V    | P   |          | M        |      |
+| 3GPP-Allocate-IP-Type                                         |   27 |          16.4.7 | OctetString      | V    | P   |          | M        |      |
+| # added manually, missing in AVP table                        |      |                 |                  |      |     |          |          |      |
+| External-Identifier                                           |   28 |          16.4.7 | OctetString      | V    | P   |          | M        |      |
+| TMGI                                                          |  900 |        17.07.02 | OctetString      | M,V  | P   |          |          |      |
+| Required-MBMS-Bearer-Capabilities                             |  901 |        17.07.03 | UTF8String       | M,V  | P   |          |          |      |
+| MBMS-StartStop-Indication                                     |  902 |        17.07.05 | Enumerated       | M,V  | P   |          |          |      |
+| MBMS-Service-Area                                             |  903 |        17.07.06 | OctetString      | M,V  | P   |          |          |      |
+| MBMS-Session-Duration                                         |  904 |        17.07.07 | OctetString      | M,V  | P   |          |          |      |
+| Alternative-APN                                               |  905 |        17.07.08 | UTF8String       | M,V  | P   |          |          |      |
+| MBMS-Service-Type                                             |  906 |        17.07.09 | Enumerated       | M,V  | P   |          |          |      |
+| MBMS-2G-3G-Indicator                                          |  907 |        17.07.10 | Enumerated       | M,V  | P   |          |          |      |
+| MBMS-Session-Identity                                         |  908 |        17.07.11 | OctetString      | M.V  | P   |          |          |      |
+| RAI                                                           |  909 |        17.07.12 | UTF8String       | M,V  | P   |          |          |      |
+| Additional-MBMS-Trace-Info                                    |  910 |        17.07.13 | OctetString      | M,V  | P   |          |          |      |
+| MBMS-Time-To-Data-Transfer                                    |  911 |        17.07.14 | OctetString      | M,V  | P   |          |          |      |
+| MBMS-Session-Repetition-Number                                |  912 |        17.07.15 | OctetString      | M.V  | P   |          |          |      |
+| MBMS-Required-QoS                                             |  913 |        17.07.16 | UTF8String       | M.V  | P   |          |          |      |
+| MBMS-Counting-Information                                     |  914 |        17.07.17 | Enumerated       | M.V  | P   |          |          |      |
+| MBMS-User-Data-Mode-Indication                                |  915 |        17.07.18 | Enumerated       | M.V  | P   |          |          |      |
+| MBMS-GGSN-Address                                             |  916 |        17.07.19 | OctetString      | M.V  | P   |          |          |      |
+| MBMS-GGSN-IPv6-Address                                        |  917 |        17.07.20 | OctetString      | M.V  | P   |          |          |      |
+| MBMS-BMSC-SSM-IP-Address                                      |  918 |        17.07.21 | OctetString      | M.V  | P   |          |          |      |
+| MBMS-BMSC-SSM-IPv6-Address                                    |  919 |        17.07.22 | OctetString      | M.V  | P   |          |          |      |
+| MBMS-Flow-Identifier                                          |  920 |         17.7.23 | OctetString      | M,V  | P   |          |          |      |
+| CN-IP-Multicast-Distribution                                  |  921 |         17.7.24 | Enumerated       | M,V  | P   |          |          |      |
+| MBMS-HC-Indicator                                             |  922 |         17.7.25 | Enumerated       | M,V  | P   |          |          |      |
+| # 3GPP 29.140-700 (7.0.0 2007.07.05)                          |      |                 |                  |      |     |          |          |      |
+| Served-User-Identity                                          | 1100 |           6.3.1 | Grouped          | M,V  |     |          |          | N    |
+| # reuses: MSISDN                                              |  701 |           6.3.2 | OctetString      | M,V  |     |          |          | N    |
+| VASP-ID                                                       | 1101 |           6.3.3 | UTF8String       | M,V  |     |          |          | N    |
+| VAS-ID                                                        | 1102 |           6.3.4 | UTF8String       | M,V  |     |          |          | N    |
+| Trigger-Event                                                 | 1103 |           6.3.5 | Enumerated       | M,V  |     |          |          | N    |
+| # reuses: 3GPP-IMSI                                           |    1 |           6.3.6 | UTF8String       | M,V  |     |          |          | N    |
+| Sender-Address                                                | 1104 |           6.3.7 | UTF8String       | M,V  |     |          |          | N    |
+| Initial-Recipient-Address                                     | 1105 |           6.3.8 | Grouped          | M,V  |     |          |          | N    |
+| Result-Recipient-Address                                      | 1106 |           6.3.9 | Grouped          | M,V  |     |          |          | N    |
+| # conflicts with one in (more common) 32.329                  |      |                 |                  |      |     |          |          |      |
+| Sequence-Number-29.140                                        | 1107 |          6.3.10 | Unsigned32       | M,V  |     |          |          | N    |
+| # conflicts with one in (more common) 32.299                  |      |                 |                  |      |     |          |          |      |
+| Recipient-Address-29.140                                      | 1108 |          6.3.11 | UTF8String       | M,V  |     |          |          | N    |
+| Routeing-Address                                              | 1109 |          6.3.12 | UTF8String       | M,V  |     |          |          | N    |
+| Originating-Interface                                         | 1110 |          6.3.13 | Enumerated       | M,V  |     |          |          | N    |
+| Delivery-Report                                               | 1111 |          6.3.14 | Enumerated       | M,V  |     |          |          | N    |
+| Read-Reply                                                    | 1112 |          6.3.15 | Enumerated       | M,V  |     |          |          | N    |
+| Sender-Visibility                                             | 1113 |          6.3.16 | Enumerated       | M,V  |     |          |          | N    |
+| Service-Key                                                   | 1114 |          6.3.17 | UTF8String       | M,V  |     |          |          | N    |
+| Billing-Information                                           | 1115 |          6.3.18 | UTF8String       | M,V  |     |          |          | N    |
+| # conflicts with one in (more common) 32.299                  |      |                 |                  |      |     |          |          |      |
+| Status-29.140                                                 | 1116 |          6.3.19 | Grouped          | M,V  |     |          |          | N    |
+| Status-Code                                                   | 1117 |          6.3.20 | UTF8String       | M,V  |     |          |          | N    |
+| Status-Text                                                   | 1118 |          6.3.21 | UTF8String       | M,V  |     |          |          | N    |
+| Routeing-Address-Resolution                                   | 1119 |          6.3.22 | Enumerated       | M,V  |     |          |          | N    |
+| # 3GPP 29.173-c00 (12.0.0 2013.03.13)                         |      |                 |                  |      |     |          |          |      |
+| LMSI                                                          | 2400 |           6.4.2 | OctetString      | M,V  |     |          |          | N    |
+| Serving-Node                                                  | 2401 |           6.4.3 | Grouped          | M,V  |     |          |          | N    |
+| MME-Name                                                      | 2402 |           6.4.4 | DiameterIdentity | M,V  |     |          |          | N    |
+| MSC-Number                                                    | 2403 |           6.4.5 | OctetString      | M,V  |     |          |          | N    |
+| LCS-Capabilities-Sets                                         | 2404 |           6.4.6 | Unsigned32       | M,V  |     |          |          | N    |
+| GMLC-Address                                                  | 2405 |           6.4.7 | Address          | M,V  |     |          |          | N    |
+| Additional-Serving-Node                                       | 2406 |           6.4.8 | Grouped          | M,V  |     |          |          | N    |
+| PPR-Address                                                   | 2407 |           6.4.9 | Address          | M,V  |     |          |          | N    |
+| MME-Realm                                                     | 2408 |          6.4.12 | DiameterIdentity | V    |     |          | M        | N    |
+| SGSN-Name                                                     | 2409 |          6.4.13 | DiameterIdentity | V    |     |          | M        | N    |
+| SGSN-Realm                                                    | 2410 |          6.4.14 | DiameterIdentity | V    |     |          | M        | N    |
+| # 3GPP 29.210-670 (6.7.0 2006-12-18)                          |      |                 |                  |      |     |          |          |      |
+| PDP-Session-Operation                                         | 1015 |          5.2.21 | Enumerated       | M,V  | P   |          |          | Y    |
+| # 3GPP 29.212-c00 (12.0.0 2013.03.15)                         |      |                 |                  |      |     |          |          |      |
+| # Gx-specific                                                 |      |                 |                  |      |     |          |          |      |
+| ADC-Revalidation-Time                                         | 2801 |          5.3.93 | Time             | V    | P   |          | M        | Y    |
+| ADC-Rule-Install                                              | 1092 |          5.3.85 | Grouped          | V    | P   |          | M        | Y    |
+| ADC-Rule-Remove                                               | 1093 |          5.3.86 | Grouped          | V    | P   |          | M        | Y    |
+| ADC-Rule-Definition                                           | 1094 |          5.3.87 | Grouped          | V    | P   |          | M        | Y    |
+| ADC-Rule-Base-Name                                            | 1095 |          5.3.88 | UTF8String       | V    | P   |          | M        | Y    |
+| ADC-Rule-Name                                                 | 1096 |          5.3.89 | OctetString      | V    | P   |          | M        | Y    |
+| ADC-Rule-Report                                               | 1097 |          5.3.90 | Grouped          | V    | P   |          | M        | Y    |
+| Application-Detection-Information                             | 1098 |          5.3.91 | Grouped          | V    | P   |          | M        | Y    |
+| Access-Network-Charging-Identifier-Gx                         | 1022 |          5.3.22 | Grouped          | M,V  | P   |          |          | Y    |
+| Allocation-Retention-Priority                                 | 1034 |          5.3.32 | Grouped          | V    | P   |          | M        | Y    |
+| AN-GW-Address                                                 | 1050 |          5.3.49 | Address          | V    | P   |          | M        | Y    |
+| APN-Aggregate-Max-Bitrate-DL                                  | 1040 |          5.3.39 | Unsigned32       | V    | P   |          | M        | Y    |
+| APN-Aggregate-Max-Bitrate-UL                                  | 1041 |          5.3.40 | Unsigned32       | V    | P   |          | M        | Y    |
+| Bearer-Control-Mode                                           | 1023 |          5.3.23 | Enumerated       | M,V  | P   |          |          | Y    |
+| Bearer-Identifier                                             | 1020 |          5.3.20 | OctetString      | M,V  | P   |          |          | Y    |
+| Bearer-Operation                                              | 1021 |          5.3.21 | Enumerated       | M,V  | P   |          |          | Y    |
+| Bearer-Usage                                                  | 1000 |           5.3.1 | Enumerated       | M,V  | P   |          |          | Y    |
+| Charging-Rule-Install                                         | 1001 |           5.3.2 | Grouped          | M,V  | P   |          |          | Y    |
+| Charging-Rule-Remove                                          | 1002 |           5.3.3 | Grouped          | M,V  | P   |          |          | Y    |
+| Charging-Rule-Definition                                      | 1003 |           5.3.4 | Grouped          | M,V  | P   |          |          | Y    |
+| Charging-Rule-Base-Name                                       | 1004 |           5.3.5 | UTF8String       | M,V  | P   |          |          | Y    |
+| Charging-Rule-Name                                            | 1005 |           5.3.6 | OctetString      | M,V  | P   |          |          | Y    |
+| Charging-Rule-Report                                          | 1018 |          5.3.18 | Grouped          | M,V  | P   |          |          | Y    |
+| Charging-Correlation-Indicator                                | 1073 |          5.3.67 | Enumerated       | V    | P   |          | M        | Y    |
+| CoA-IP-Address                                                | 1035 |          5.3.33 | Address          | V    | P   |          | M        | Y    |
+| CoA-Information                                               | 1039 |          5.3.37 | Grouped          | V    | P   |          | M        | Y    |
+| CSG-Information-Reporting                                     | 1071 |          5.3.64 | Enumerated       | V    | P   |          | M        | Y    |
+| Default-EPS-Bearer-QoS                                        | 1049 |          5.3.48 | Grouped          | V    | P   |          | M        | Y    |
+| Event-Report-Indication                                       | 1033 |          5.3.30 | Grouped          | V    | P   |          | M        | Y    |
+| Event-Trigger                                                 | 1006 |           5.3.7 | Enumerated       | M,V  | P   |          |          | Y    |
+| Flow-Direction                                                | 1080 |          5.3.65 | Enumerated       | V    | P   |          | M        | Y    |
+| Flow-Information                                              | 1058 |          5.3.53 | Grouped          | V    | P   |          | M        | Y    |
+| Flow-Label                                                    | 1057 |          5.3.52 | OctetString      | V    | P   |          | M        | Y    |
+| IP-CAN-Type                                                   | 1027 |          5.3.27 | Enumerated       | M,V  | P   |          |          | Y    |
+| Guaranteed-Bitrate-DL                                         | 1025 |          5.3.25 | Unsigned32       | M,V  | P   |          |          | Y    |
+| Guaranteed-Bitrate-UL                                         | 1026 |          5.3.26 | Unsigned32       | M,V  | P   |          |          | Y    |
+| HeNB-Local-IP-Address                                         | 2804 |          5.3.95 | Address          | V    | P   |          | M        | Y    |
+| Metering-Method                                               | 1007 |           5.3.8 | Enumerated       | M,V  | P   |          |          | Y    |
+| Monitoring-Key                                                | 1066 |          5.3.59 | OctetString      | V    | P   |          | M        | Y    |
+| Mute-Notification                                             | 2809 |          5.3.98 | Enumerated       | V    | P   |          | M        | Y    |
+| Monitoring-Time                                               | 2810 |          5.3.99 | Time             | V    | P   |          | M        | Y    |
+| Network-Request-Support                                       | 1024 |          5.3.24 | Enumerated       | M,V  | P   |          |          | Y    |
+| Offline                                                       | 1008 |           5.3.9 | Enumerated       | M,V  | P   |          |          | Y    |
+| Online                                                        | 1009 |          5.3.10 | Enumerated       | M,V  | P   |          |          | Y    |
+| Packet-Filter-Content                                         | 1059 |          5.3.54 | IPFilterRule     | V    | P   |          | M        | Y    |
+| Packet-Filter-Identifier                                      | 1060 |          5.3.55 | OctetString      | V    | P   |          | M        | Y    |
+| Packet-Filter-Information                                     | 1061 |          5.3.56 | Grouped          | V    | P   |          | M        | Y    |
+| Packet-Filter-Operation                                       | 1062 |          5.3.57 | Enumerated       | V    | P   |          | M        | Y    |
+| Packet-Filter-Usage                                           | 1072 |          5.3.66 | Enumerated       | V    | P   |          | M        | Y    |
+| PDN-Connection-ID                                             | 1065 |          5.3.58 | OctetString      | V    | P   |          |          | Y    |
+| Precedence                                                    | 1010 |          5.3.11 | Unsigned32       | M,V  | P   |          |          | Y    |
+| Pre-emption-Capability                                        | 1047 |          5.3.46 | Enumerated       | V    | P   |          | M        | Y    |
+| Pre-emption-Vulnerability                                     | 1048 |          5.3.47 | Enumerated       | V    | P   |          | M        | Y    |
+| Priority-Level                                                | 1046 |          5.3.45 | Unsigned32       | V    | P   |          | M        | Y    |
+| Redirect-Information                                          | 1085 |          5.3.82 | Grouped          | V    | P   |          | M        | Y    |
+| Redirect-Support                                              | 1086 |          5.3.83 | Enumerated       | V    | P   |          | M        | Y    |
+| Reporting-Level                                               | 1011 |          5.3.12 | Enumerated       | M,V  | P   |          |          | Y    |
+| Routing-Filter                                                | 1078 |          5.3.72 | Grouped          | V    | P   |          | M        | Y    |
+| Routing-IP-Address                                            | 1079 |          5.3.73 | Address          | V    | P   |          | M        | Y    |
+| Routing-Rule-Definition                                       | 1076 |          5.3.70 | Grouped          | V    | P   |          | M        | Y    |
+| Routing-Rule-Identifier                                       | 1077 |          5.3.71 | OctetString      | V    | P   |          | M        | Y    |
+| Routing-Rule-Install                                          | 1081 |          5.3.68 | Grouped          | V    | P   |          | M        | Y    |
+| Routing-Rule-Remove                                           | 1075 |          5.3.69 | Grouped          | V    | P   |          | M        | Y    |
+| PCC-Rule-Status                                               | 1019 |          5.3.19 | Enumerated       | M,V  | P   |          |          | Y    |
+| Session-Release-Cause                                         | 1045 |          5.3.44 | Enumerated       | M,V  | P   |          |          | Y    |
+| TDF-Information                                               | 1087 |          5.3.78 | Grouped          | V    | P   |          | M        | Y    |
+| TDF-Application-Identifier                                    | 1088 |          5.3.77 | OctetString      | V    | P   |          | M        | Y    |
+| TDF-Application-Instance-Identifier                           | 2802 |          5.3.92 | OctetString      | V    | P   |          | M        | Y    |
+| TDF-Destination-Host                                          | 1089 |          5.3.80 | DiameterIdentity | V    | P   |          | M        | Y    |
+| TDF-Destination-Realm                                         | 1090 |          5.3.79 | DiameterIdentity | V    | P   |          | M        | Y    |
+| TDF-IP-Address                                                | 1091 |          5.3.81 | Address          | V    | P   |          | M        | Y    |
+| QoS-Class-Identifier                                          | 1028 |          5.3.17 | Enumerated       | M,V  | P   |          |          | Y    |
+| QoS-Information                                               | 1016 |          5.3.16 | Grouped          | M.V  | P   |          |          | Y    |
+| QoS-Negotiation                                               | 1029 |          5.3.28 | Enumerated       | M,V  | P   |          |          | Y    |
+| QoS-Upgrade                                                   | 1030 |          5.3.29 | Enumerated       | M.V  | P   |          |          | Y    |
+| PS-to-CS-Session-Continuity                                   | 1099 |          5.3.84 | Enumerated       | V    | P   |          |          | Y    |
+| Resource-Allocation-Notification                              | 1063 |          5.3.50 | Enumerated       | V    | P   |          | M        | Y    |
+| Rule-Failure-Code                                             | 1031 |          5.3.38 | Enumerated       | M.V  | P   |          |          | Y    |
+| Security-Parameter-Index                                      | 1056 |          5.3.51 | OctetString      | V    | P   |          | M        | Y    |
+| TFT-Filter                                                    | 1012 |          5.3.13 | IPFilterRule     | M,V  | P   |          |          | Y    |
+| TFT-Packet-Filter-Information                                 | 1013 |          5.3.14 | Grouped          | M,V  | P   |          |          | Y    |
+| ToS-Traffic-Class                                             | 1014 |          5.3.15 | OctetString      | M,V  | P   |          |          | Y    |
+| Tunnel-Header-Filter                                          | 1036 |          5.3.34 | IPFilterRule     | V    | P   |          | M        | Y    |
+| Tunnel-Header-Length                                          | 1037 |          5.3.35 | Unsigned32       | V    | P   |          | M        | Y    |
+| Tunnel-Information                                            | 1038 |          5.3.36 | Grouped          | V    | P   |          | M        | Y    |
+| RAT-Type                                                      | 1032 |          5.3.31 | Enumerated       | V    | P   |          | M        | Y    |
+| Revalidation-Time                                             | 1042 |          5.3.41 | Time             | M,V  | P   |          |          | Y    |
+| Rule-Activation-Time                                          | 1043 |          5.3.42 | Time             | M,V  | P   |          |          | Y    |
+| UDP-Source-Port                                               | 2806 |          5.3.97 | Unsigned32       | V    | P   |          | M        | Y    |
+| UE-Local-IP-Address                                           | 2805 |          5.3.96 | Address          | V    | P   |          | M        | Y    |
+| Usage-Monitoring-Information                                  | 1067 |          5.3.60 | Grouped          | V    | P   |          | M        | Y    |
+| Rule-Deactivation-Time                                        | 1044 |          5.3.43 | Time             | M,V  | P   |          |          | Y    |
+| Usage-Monitoring-Level                                        | 1068 |          5.3.61 | Enumerated       | V    | P   |          | M        | Y    |
+| Usage-Monitoring-Report                                       | 1069 |          5.3.62 | Enumerated       | V    | P   |          | M        | Y    |
+| Usage-Monitoring-Support                                      | 1070 |          5.3.63 | Enumerated       | V    | P   |          | M        | Y    |
+| # Gxx-specific                                                |      |                 |                  |      |     |          |          |      |
+| QoS-Rule-Install                                              | 1051 |          5a.3.1 | Grouped          | M,V  | P   |          |          | Y    |
+| QoS-Rule-Remove                                               | 1052 |          5a.3.2 | Grouped          | M,V  | P   |          |          | Y    |
+| QoS-Rule-Definition                                           | 1053 |          5a.3.3 | Grouped          | M,V  | P   |          |          | Y    |
+| QoS-Rule-Name                                                 | 1054 |          5a.3.4 | OctetString      | M,V  | P   |          |          | Y    |
+| QoS-Rule-Base-Name                                            | 1074 |          5a.3.7 | UTF8String       | V    | P   |          | M        | Y    |
+| QoS-Rule-Report                                               | 1055 |          5a.3.5 | Grouped          | M,V  | P   |          |          | Y    |
+| Session-Linking-Indicator                                     | 1064 |          5a.3.6 | Enumerated       | M,V  | P   |          |          | Y    |
+| # S15-specific                                                |      |                 |                  |      |     |          |          |      |
+| CS-Service-Qos-Request-Identifier                             | 2807 |         E.6.3.2 | OctetString      | M,V  | P   |          |          | Y    |
+| CS-Service-QoS-Request-Operation                              | 2808 |         E.6.3.3 | Enumerated       | M.V  | P   |          |          | Y    |
+| # 3GPP 29.214-b80 (11.8.0 2013.03.15)                         |      |                 |                  |      |     |          |          |      |
+| Abort-Cause                                                   |  500 |           5.3.1 | Enumerated       | M,V  | P   |          |          | Y    |
+| Access-Network-Charging-Address                               |  501 |           5.3.2 | Address          | M,V  | P   |          |          | Y    |
+| Access-Network-Charging-Identifier                            |  502 |           5.3.3 | Grouped          | M,V  | P   |          |          | Y    |
+| Access-Network-Charging-Identifier-Value                      |  503 |           5.3.4 | OctetString      | M,V  | P   |          |          | Y    |
+| Acceptable-Service-Info                                       |  526 |          5.3.24 | Grouped          | M,V  | P   |          |          | Y    |
+| AF-Application-Identifier                                     |  504 |           5.3.5 | OctetString      | M,V  | P   |          |          | Y    |
+| AF-Charging-Identifier                                        |  505 |           5.3.6 | OctetString      | M,V  | P   |          |          | Y    |
+| Application-Service-Provider-Identity                         |  532 |          5.3.29 | UTF8String       | V    | P   |          | M        | Y    |
+| Codec-Data                                                    |  524 |           5.3.7 | OctetString      | M,V  | P   |          |          | Y    |
+| Flow-Description                                              |  507 |           5.3.8 | IPFilterRule     | M,V  | P   |          |          | Y    |
+| Flow-Number                                                   |  509 |           5.3.9 | Unsigned32       | M,V  | P   |          |          | Y    |
+| Flows                                                         |  510 |          5.3.10 | Grouped          | M,V  | P   |          |          | Y    |
+| Flow-Status                                                   |  511 |          5.3.11 | Enumerated       | M,V  | P   |          |          | Y    |
+| Flow-Usage                                                    |  512 |          5.3.12 | Enumerated       | M,V  | P   |          |          | Y    |
+| Service-URN                                                   |  525 |          5.3.23 | OctetString      | M,V  | P   |          |          | Y    |
+| Specific-Action                                               |  513 |          5.3.13 | Enumerated       | M,V  | P   |          |          | Y    |
+| Max-Requested-Bandwidth-DL                                    |  515 |          5.3.14 | Unsigned32       | M,V  | P   |          |          | Y    |
+| Max-Requested-Bandwidth-UL                                    |  516 |          5.3.15 | Unsigned32       | M,V  | P   |          |          | Y    |
+| Media-Component-Description                                   |  517 |          5.3.16 | Grouped          | M,V  | P   |          |          | Y    |
+| Media-Component-Number                                        |  518 |          5.3.17 | Unsigned32       | M,V  | P   |          |          | Y    |
+| Media-Sub-Component                                           |  519 |          5.3.18 | Grouped          | M,V  | P   |          |          | Y    |
+| Media-Type                                                    |  520 |          5.3.19 | Enumerated       | M,V  | P   |          |          | Y    |
+| MPS-Identifier                                                |  528 |          5.3.30 | OctetString      | V    | P   |          | M        | Y    |
+| Min-Requested-Bandwidth-DL                                    |  534 |          5.3.32 | Unsigned32       | V    | P   |          | M        | Y    |
+| Min-Requested-Bandwidth-UL                                    |  535 |          5.3.33 | Unsigned32       | V    | P   |          | M        | Y    |
+| RR-Bandwidth                                                  |  521 |          5.3.20 | Unsigned32       | M,V  | P   |          |          | Y    |
+| RS-Bandwidth                                                  |  522 |          5.3.21 | Unsigned32       | M,V  | P   |          |          | Y    |
+| Service-Info-Status                                           |  527 |          5.3.25 | Enumerated       | M,V  | P   |          |          | Y    |
+| SIP-Forking-Indication                                        |  523 |          5.3.22 | Enumerated       | M,V  | P   |          |          | Y    |
+| Sponsor-Identity                                              |  531 |          5.3.28 | UTF8String       | V    | P   |          | M        | Y    |
+| Sponsored-Connectivity-Data                                   |  530 |          5.3.27 | Grouped          | V    | P   |          | M        | Y    |
+| AF-Signalling-Protocol                                        |  529 |          5.3.26 | Enumerated       | V    | P   |          | M        | Y    |
+| Required-Access-Info                                          |  536 |          5.3.34 | Enumerated       | V    | P   |          | M        | Y    |
+| Rx-Request-Type                                               |  533 |          5.3.31 | Enumerated       | V    | P   |          | M        | Y    |
+| IP-Domain-Id                                                  |  537 |          5.3.35 | OctetString      | V    | P   |          | M        | Y    |
+| # 3GPP 29.229-b20 (11.2.0 2012.12.21)                         |      |                 |                  |      |     |          |          |      |
+| Associated-Identities                                         |  632 |          6.3.33 | Grouped          | V    |     |          | M        | N    |
+| Associated-Registered-Identities                              |  647 |          6.3.50 | Grouped          | V    |     |          | M        | N    |
+| Call-ID-SIP-Header                                            |  643 |        6.3.49.1 | OctetString      | V    |     |          | M        | N    |
+| Charging-Information                                          |  618 |          6.3.19 | Grouped          | M,V  |     |          |          | N    |
+| Confidentiality-Key                                           |  625 |          6.3.27 | OctetString      | M,V  |     |          |          | N    |
+| Contact                                                       |  641 |          6.3.48 | OctetString      | V    |     |          | M        | N    |
+| Deregistration-Reason                                         |  615 |          6.3.16 | Grouped          | M,V  |     |          |          | N    |
+| Digest-Algorithm                                              |  111 |          6.3.39 | UTF8String       | M    |     |          | V        | N    |
+| Digest-HA1                                                    |  121 |          6.3.41 | UTF8String       | M    |     |          | V        | N    |
+| Digest-QoP                                                    |  110 |          6.3.40 | UTF8String       | M    |     |          | V        | N    |
+| Digest-Realm                                                  |  104 |          6.3.37 | UTF8String       | M    |     |          | V        | N    |
+| Feature-List                                                  |  630 |          6.3.31 | Unsigned32       | V    |     |          | M        | N    |
+| Feature-List-ID                                               |  629 |          6.3.30 | Unsigned32       | V    |     |          | M        | N    |
+| From-SIP-Header                                               |  644 |        6.3.49.2 | OctetString      | V    |     |          | M        | N    |
+| Identity-with-Emergency-Registration                          |  651 |          6.3.57 | Grouped          | V    |     |          | M        | N    |
+| Integrity-Key                                                 |  626 |          6.3.28 | OctetString      | M,V  |     |          |          | N    |
+| LIA-Flags                                                     |  653 |          6.3.59 | Unsigned32       | V    |     |          | M        | N    |
+| Loose-Route-Indication                                        |  638 |          6.3.45 | Enumerated       | V    |     |          | M        | N    |
+| Mandatory-Capability                                          |  604 |           6.3.5 | Unsigned32       | M,V  |     |          |          | N    |
+| Multiple-Registration-Indication                              |  648 |          6.3.51 | Enumerated       | V    |     |          | M        | N    |
+| Optional-Capability                                           |  605 |           6.3.6 | Unsigned32       | M,V  |     |          |          | N    |
+| Originating-Request                                           |  633 |          6.3.34 | Enumerated       | M,V  |     |          |          | N    |
+| Path                                                          |  640 |          6.3.47 | OctetString      | V    |     |          | M        | N    |
+| Primary-Charging-Collection-Function-Name                     |  621 |          6.3.22 | DiameterURI      | M,V  |     |          |          | N    |
+| Primary-Event-Charging-Function-Name                          |  619 |          6.3.20 | DiameterURI      | M,V  |     |          |          | N    |
+| Priviledged-Sender-Indication                                 |  652 |          6.3.58 | Enumerated       | V    |     |          | M        | N    |
+| Public-Identity                                               |  601 |           6.3.2 | UTF8String       | M,V  |     |          |          | N    |
+| Reason-Code                                                   |  616 |          6.3.17 | Enumerated       | M,V  |     |          |          | N    |
+| Reason-Info                                                   |  617 |          6.3.18 | UTF8String       | M,V  |     |          |          | N    |
+| Record-Route                                                  |  646 |        6.3.49.4 | OctetString      | V    |     |          | M        | N    |
+| Restoration-Info                                              |  649 |          6.3.52 | Grouped          | V    |     |          | M        | N    |
+| SCSCF-Restoration-Info                                        |  639 |          6.3.46 | Grouped          | V    |     |          | M        | N    |
+| SIP-Auth-Data-Item                                            |  612 |          6.3.13 | Grouped          | M,V  |     |          |          | N    |
+| SIP-Authenticate                                              |  609 |          6.3.10 | OctetString      | M,V  |     |          |          | N    |
+| SIP-Authentication-Context                                    |  611 |          6.3.12 | OctetString      | M,V  |     |          |          | N    |
+| SIP-Authentication-Scheme                                     |  608 |           6.3.9 | UTF8String       | M,V  |     |          |          | N    |
+| SIP-Authorization                                             |  610 |          6.3.11 | OctetString      | M,V  |     |          |          | N    |
+| SIP-Digest-Authenticate                                       |  635 |          6.3.36 | Grouped          | V    |     |          | M        | N    |
+| SIP-Item-Number                                               |  613 |          6.3.14 | Unsigned32       | M,V  |     |          |          | N    |
+| SIP-Number-Auth-Items                                         |  607 |           6.3.8 | Unsigned32       | M,V  |     |          |          | N    |
+| Secondary-Charging-Collection-Function-Name                   |  622 |          6.3.23 | DiameterURI      | M,V  |     |          |          | N    |
+| Secondary-Event-Charging-Function-Name                        |  620 |          6.3.21 | DiameterURI      | M,V  |     |          |          | N    |
+| Server-Assignment-Type                                        |  614 |          6.3.15 | Enumerated       | M,V  |     |          |          | N    |
+| Server-Capabilities                                           |  603 |           6.3.4 | Grouped          | M,V  |     |          |          | N    |
+| Server-Name                                                   |  602 |           6.3.3 | UTF8String       | M,V  |     |          |          | N    |
+| Session-Priority                                              |  650 |          6.3.56 | Enumerated       | V    |     |          | M        | N    |
+| Subscription-Info                                             |  642 |          6.3.49 | Grouped          | V    |     |          | M        | N    |
+| Supported-Applications                                        |  631 |          6.3.32 | Grouped          | V    |     |          | M        | N    |
+| Supported-Features                                            |  628 |          6.3.29 | Grouped          | V    | M   |          |          | N    |
+| To-SIP-Header                                                 |  645 |        6.3.49.3 | OctetString      | V    |     |          | M        | N    |
+| UAR-Flags                                                     |  637 |          6.3.44 | Unsigned32       | V    |     |          | M        | N    |
+| User-Authorization-Type                                       |  623 |          6.3.24 | Enumerated       | M,V  |     |          |          | N    |
+| User-Data                                                     |  606 |           6.3.7 | OctetString      | M,V  |     |          |          | N    |
+| User-Data-Already-Available                                   |  624 |          6.3.26 | Enumerated       | M,V  |     |          |          | N    |
+| Visited-Network-Identifier                                    |  600 |           6.3.1 | OctetString      | M,V  |     |          |          | N    |
+| Wildcarded-Public-Identity                                    |  634 |          6.3.35 | UTF8String       | V    |     |          | M        | N    |
+| # 3GPP 32.299-b60 (11.6.0 2012.12.21)                         |      |                 |                  |      |     |          |          |      |
+| AF-Correlation-Information                                    | 1276 |                 | Grouped          | M,V  | P   |          |          | N    |
+| Access-Network-Information                                    | 1263 |                 | OctetString      | M,V  | P   |          |          | N    |
+| Access-Transfer-Information                                   | 2709 |                 | Grouped          | M,V  | P   |          |          | N    |
+| Access-Transfer-Type                                          | 2710 |                 | Enumerated       | M,V  | P   |          |          | N    |
+| Account-Expiration                                            | 2309 |                 | Time             | M,V  | P   |          |          | N    |
+| Accumulated-Cost                                              | 2052 |                 | Grouped          | M,V  | P   |          |          | N    |
+| Adaptations                                                   | 1217 |                 | Enumerated       | M,V  | P   |          |          | N    |
+| Additional-Content-Information                                | 1207 |                 | Grouped          | M,V  | P   |          |          | N    |
+| Additional-Type-Information                                   | 1205 |                 | UTF8String       | M,V  | P   |          |          | N    |
+| Address-Data                                                  |  897 |                 | UTF8String       | M,V  | P   |          |          | N    |
+| Address-Domain                                                |  898 |                 | Grouped          | M,V  | P   |          |          | N    |
+| Address-Type                                                  |  899 |                 | Enumerated       | M,V  | P   |          |          | N    |
+| Addressee-Type                                                | 1208 |                 | Enumerated       | M,V  | P   |          |          | N    |
+| Alternate-Charged-Party-Address                               | 1280 |                 | UTF8String       | V.M  | P   |          |          | N    |
+| AoC-Cost-Information                                          | 2053 |                 | Grouped          | M,V  | P   |          |          | N    |
+| AoC-Format                                                    | 2310 |                 | Enumerated       | M,V  | P   |          |          | N    |
+| AoC-Information                                               | 2054 |                 | Grouped          | V.M  | P   |          |          | N    |
+| AoC-Request-Type                                              | 2055 |                 | Enumerated       | V.M  | P   |          |          | N    |
+| AoC-Service                                                   | 2311 |                 | Grouped          | M,V  | P   |          |          | N    |
+| AoC-Service-Obligatory-Type                                   | 2312 |                 | Enumerated       | M,V  | P   |          |          | N    |
+| AoC-Service-Type                                              | 2313 |                 | Enumerated       | M,V  | P   |          |          | N    |
+| AoC-Subscription-Information                                  | 2314 |                 | Grouped          | M,V  | P   |          |          | N    |
+| Applic-ID                                                     | 1218 |                 | UTF8String       | M,V  | P   |          |          | N    |
+| Application-Server                                            |  836 |                 | UTF8String       | M,V  | P   |          |          | N    |
+| Application-Server-Information                                |  850 |                 | Grouped          | M,V  | P   |          |          | N    |
+| Application-Provided-Called-Party-Address                     |  837 |                 | UTF8String       | M,V  | P   |          |          | N    |
+| Associated-Party-Address                                      | 2035 |                 | UTF8String       | M,V  | P   |          |          | N    |
+| Associated-URI                                                |  856 |                 | UTF8String       | M,V  | P   |          |          | N    |
+| Aux-Applic-Info                                               | 1219 |                 | UTF8String       | M,V  | P   |          |          | N    |
+| Base-Time-Interval                                            | 1265 |                 | Unsigned32       | M,V  | P   |          |          | N    |
+| Bearer-Service                                                |  854 |                 | OctetString      | M,V  | P   |          |          | N    |
+| CG-Address                                                    |  846 |                 | Address          | M,V  | P   |          |          | Y    |
+| CSG-Access-Mode                                               | 2317 |                 | Enumerated       | M,V  | P   |          |          | N    |
+| CSG-Membership-Indication                                     | 2318 |                 | Enumerated       | M,V  | P   |          |          | N    |
+| CUG-Information                                               | 2304 |                 | OctetString      | M,V  | P   |          |          | N    |
+| Called-Asserted-Identity                                      | 1250 |                 | UTF8String       | M,V  | P   |          |          | N    |
+| Called-Party-Address                                          |  832 |                 | UTF8String       | M,V  | P   |          |          | N    |
+| Calling-Party-Address                                         |  831 |                 | UTF8String       | M,V  | P   |          |          | N    |
+| Carrier-Select-Routing-Information                            | 2023 |                 | UTF8String       | M,V  | P   |          |          | N    |
+| Cause-Code                                                    |  861 |                 | Integer32        | M,V  | P   |          |          | N    |
+| Change-Condition                                              | 2037 |                 | Integer32        | M,V  | P   |          |          | N    |
+| Change-Time                                                   | 2038 |                 | Time             | M,V  | P   |          |          | N    |
+| Charge-Reason-Code                                            | 2118 |                 | Enumerated       | M,V  | P   |          |          | N    |
+| Charged-Party                                                 |  857 |                 | UTF8String       | M,V  | P   |          |          | N    |
+| Charging-Characteristics-Selection-Mode                       | 2066 |                 | Enumerated       | M,V  | P   |          |          | N    |
+| Class-Identifier                                              | 1214 |                 | Enumerated       | M,V  | P   |          |          | N    |
+| Client-Address                                                | 2018 |                 | Address          | M,V  | P   |          |          | N    |
+| Content-Class                                                 | 1220 |                 | Enumerated       | M,V  | P   |          |          | N    |
+| Content-Disposition                                           |  828 |                 | UTF8String       | M,V  | P   |          |          | N    |
+| Content-Length                                                |  827 |                 | Unsigned32       | M,V  | P   |          |          | N    |
+| Content-Size                                                  | 1206 |                 | Unsigned32       | M,V  | P   |          |          | N    |
+| Content-Type                                                  |  826 |                 | UTF8String       | M,V  | P   |          |          | N    |
+| Current-Tariff                                                | 2056 |                 | Grouped          | M,V  | P   |          |          | N    |
+| DRM-Content                                                   | 1221 |                 | Enumerated       | M,V  | P   |          |          | N    |
+| Data-Coding-Scheme                                            | 2001 |                 | Integer32        | M,V  | P   |          |          | N    |
+| Deferred-Location-Event-Type                                  | 1230 |                 | UTF8String       | M,V  | P   |          |          | N    |
+| Delivery-Report-Requested                                     | 1216 |                 | Enumerated       | M,V  | P   |          |          | N    |
+| Destination-Interface                                         | 2002 |                 | Grouped          | M,V  | P   |          |          | N    |
+| Diagnostics                                                   | 2039 |                 | Integer32        | M,V  | P   |          |          | N    |
+| Domain-Name                                                   | 1200 |                 | UTF8String       | M,V  | P   |          |          | N    |
+| Dynamic-Address-Flag                                          | 2051 |                 | Enumerated       | M,V  | P   |          |          | N    |
+| Dynamic-Address-Flag-Extension                                | 2068 |                 | Enumerated       | M,V  | P   |          |          | N    |
+| Early-Media-Description                                       | 1272 |                 | Grouped          | M,V  | P   |          |          | N    |
+| Envelope                                                      | 1266 |                 | Grouped          | M,V  | P   |          |          | N    |
+| Envelope-End-Time                                             | 1267 |                 | Time             | M,V  | P   |          |          | N    |
+| Envelope-Reporting                                            | 1268 |                 | Enumerated       | M,V  | P   |          |          | N    |
+| Envelope-Start-Time                                           | 1269 |                 | Time             | M,V  | P   |          |          | N    |
+| Event                                                         |  825 |                 | UTF8String       | M,V  | P   |          |          | N    |
+| Event-Charging-TimeStamp                                      | 1258 |                 | Time             | M,V  | P   |          |          | N    |
+| Event-Type                                                    |  823 |                 | Grouped          | M,V  | P   |          |          | N    |
+| Expires                                                       |  888 |                 | Unsigned32       | M,V  | P   |          |          | N    |
+| File-Repair-Supported                                         | 1224 |                 | Enumerated       | M,V  | P   |          |          | Y    |
+| From-Address                                                  | 2708 |                 | UTF8String       | M,V  | P   |          |          | N    |
+| GGSN-Address                                                  |  847 |                 | Address          | M,V  | P   |          |          | N    |
+| IMS-Application-Reference-Identifier                          | 2601 |                 | UTF8String       | M,V  | P   |          |          | N    |
+| IMS-Charging-Identifier                                       |  841 |                 | UTF8String       | M,V  | P   |          |          | N    |
+| IMS-Communication-Service-Identifier                          | 1281 |                 | UTF8String       | M,V  | P   |          |          | N    |
+| IMS-Emergency-Indicator                                       | 2322 |                 | Enumerated       | M,V  | P   |          |          | N    |
+| IMS-Information                                               |  876 |                 | Grouped          | M,V  | P   |          |          | N    |
+| IMSI-Unauthenticated-Flag                                     | 2308 |                 | Enumerated       | M,V  | P   |          |          | N    |
+| IP-Realm-Default-Indication                                   | 2603 |                 | Enumerated       | M,V  | P   |          |          | N    |
+| Incoming-Trunk-Group-Id                                       |  852 |                 | UTF8String       | M,V  | P   |          |          | N    |
+| Incremental-Cost                                              | 2062 |                 | Grouped          | M,V  | P   |          |          | N    |
+| Initial-IMS-Charging-Identifier                               | 2321 |                 | UTF8String       | M,V  | P   |          |          | N    |
+| Inter-Operator-Identifier                                     |  838 |                 | Grouped          | M,V  | P   |          |          | N    |
+| Interface-Id                                                  | 2003 |                 | UTF8String       | M,V  | P   |          |          | N    |
+| Interface-Port                                                | 2004 |                 | UTF8String       | M,V  | P   |          |          | N    |
+| Interface-Text                                                | 2005 |                 | UTF8String       | M,V  | P   |          |          | N    |
+| Interface-Type                                                | 2006 |                 | Enumerated       | M,V  | P   |          |          | N    |
+| LCS-APN                                                       | 1231 |                 | UTF8String       | M,V  | P   |          |          | N    |
+| LCS-Client-Dialed-By-MS                                       | 1233 |                 | UTF8String       | M,V  | P   |          |          | N    |
+| LCS-Client-External-ID                                        | 1234 |                 | UTF8String       | M,V  | P   |          |          | N    |
+| LCS-Client-Id                                                 | 1232 |                 | Grouped          | M,V  | P   |          |          | N    |
+| LCS-Client-Name                                               | 1235 |                 | Grouped          | M,V  | P   |          |          | N    |
+| LCS-Client-Type                                               | 1241 |                 | Enumerated       | M,V  | P   |          |          | N    |
+| LCS-Data-Coding-Scheme                                        | 1236 |                 | UTF8String       | M,V  | P   |          |          | N    |
+| LCS-Format-Indicator                                          | 1237 |                 | Enumerated       | M,V  | P   |          |          | N    |
+| LCS-Information                                               |  878 |                 | Grouped          | M,V  | P   |          |          | N    |
+| LCS-Name-String                                               | 1238 |                 | UTF8String       | M,V  | P   |          |          | N    |
+| LCS-Requestor-Id                                              | 1239 |                 | Grouped          | M,V  | P   |          |          | N    |
+| LCS-Requestor-Id-String                                       | 1240 |                 | UTF8String       | M,V  | P   |          |          | N    |
+| Local-GW-Inserted-Indication                                  | 2604 |                 | Enumerated       | M,V  | P   |          |          | N    |
+| Local-Sequence-Number                                         | 2063 |                 | Unsigned32       | M,V  | P   |          |          | N    |
+| Location-Estimate                                             | 1242 |                 | OctetString      | M,V  | P   |          |          | N    |
+| Location-Estimate-Type                                        | 1243 |                 | Enumerated       | M,V  | P   |          |          | N    |
+| Location-Type                                                 | 1244 |                 | Grouped          | M,V  | P   |          |          | N    |
+| Low-Balance-Indication                                        | 2020 |                 | Enumerated       | M,V  | P   |          |          | N    |
+| Low-Priority-Indicator                                        | 2602 |                 | Enumerated       | M,V  | P   |          |          | N    |
+| MBMS GW-Address                                               | 2307 |                 | Address          | M,V  | P   |          |          | N    |
+| MBMS-Information                                              |  880 |                 | Grouped          | M,V  | P   |          |          | N    |
+| MBMS-User-Service-Type                                        | 1225 |                 | Enumerated       | M,V  | P   |          |          | Y    |
+| MM-Content-Type                                               | 1203 |                 | Grouped          | M,V  | P   |          |          | N    |
+| MMBox-Storage-Requested                                       | 1248 |                 | Enumerated       | M,V  | P   |          |          | N    |
+| MMS-Information                                               |  877 |                 | Grouped          | M,V  | P   |          |          | N    |
+| MMTel-Information                                             | 2030 |                 | Grouped          | M,V  | P   |          |          | N    |
+| MMTel-SService-Type                                           | 2031 |                 | Unsigned32       | M,V  | P   |          |          | N    |
+| Media-Initiator-Flag                                          |  882 |                 | Enumerated       | M,V  | P   |          |          | N    |
+| Media-Initiator-Party                                         | 1288 |                 | UTF8String       | M,V  | P   |          |          | N    |
+| Message-Body                                                  |  889 |                 | Grouped          | M,V  | P   |          |          | N    |
+| Message-Class                                                 | 1213 |                 | Grouped          | M,V  | P   |          |          | N    |
+| Message-ID                                                    | 1210 |                 | UTF8String       | M,V  | P   |          |          | N    |
+| Message-Size                                                  | 1212 |                 | Unsigned32       | M,V  | P   |          |          | N    |
+| Message-Type                                                  | 1211 |                 | Enumerated       | M,V  | P   |          |          | N    |
+| NNI-Information                                               | 2703 |                 | Grouped          | M,V  | P   |          |          | N    |
+| NNI-Type                                                      | 2704 |                 | Enumerated       | M,V  | P   |          |          | N    |
+| Neighbour-Node-Address                                        | 2705 |                 | Address          | M,V  | P   |          |          | N    |
+| Next-Tariff                                                   | 2057 |                 | Grouped          | V/M  | P   |          |          | N    |
+| Node-Functionality                                            |  862 |                 | Enumerated       | M,V  | P   |          |          | N    |
+| Node-Id                                                       | 2064 |                 | UTF8String       | M,V  | P   |          |          | N    |
+| Number-Of-Diversions                                          | 2034 |                 | Unsigned32       | M,V  | P   |          |          | N    |
+| Number-Of-Messages-Sent                                       | 2019 |                 | Unsigned32       | M,V  | P   |          |          | N    |
+| Number-Of-Participants                                        |  885 |                 | Unsigned32       | M,V  | P   |          |          | N    |
+| Number-Of-Received-Talk-Bursts                                | 1282 |                 | Unsigned32       | M,V  | P   |          |          | N    |
+| Number-Of-Talk-Bursts                                         | 1283 |                 | Unsigned32       | M,V  | P   |          |          | N    |
+| Number-Portability-Routing-Information                        | 2024 |                 | UTF8String       | M,V  | P   |          |          | N    |
+| Offline-Charging                                              | 1278 |                 | Grouped          | M,V  | P   |          |          | N    |
+| Online-Charging-Flag                                          | 2303 |                 | Enumerated       | M,V  | P   |          |          | N    |
+| Originating-IOI                                               |  839 |                 | UTF8String       | M,V  | P   |          |          | N    |
+| Originator                                                    |  864 |                 | Enumerated       | M,V  | P   |          |          | N    |
+| Originator-Address                                            |  886 |                 | Grouped          | M,V  | P   |          |          | N    |
+| Originator-Interface                                          | 2009 |                 | Grouped          | M,V  | P   |          |          | N    |
+| Originator-Received-Address                                   | 2027 |                 | Grouped          | M,V  | P   |          |          | N    |
+| Originator-SCCP-Address                                       | 2008 |                 | Address          | M,V  | P   |          |          | N    |
+| Outgoing-Session-Id                                           | 2320 |                 | UTF8String       | M,V  | P   |          |          | N    |
+| Outgoing-Trunk-Group-Id                                       |  853 |                 | UTF8String       | M,V  | P   |          |          | N    |
+| PDG-Address                                                   |  895 |                 | Address          | M,V  | P   |          |          | N    |
+| PDG-Charging-Id                                               |  896 |                 | Unsigned32       | M,V  | P   |          |          | N    |
+| PDN-Connection-Charging-ID                                    | 2050 |                 | Unsigned32       | M,V  | P   |          |          | N    |
+| PDP-Address                                                   | 1227 |                 | Address          | M,V  | P   |          |          | Y    |
+| PDP-Address-Prefix-Length                                     | 2606 |                 | Unsigned32       | M,V  | P   |          |          | Y    |
+| PDP-Context-Type                                              | 1247 |                 | Enumerated       | M,V  | P   |          |          | N    |
+| PS-Append-Free-Format-Data                                    |  867 |                 | Enumerated       | M,V  | P   |          |          | N    |
+| PS-Free-Format-Data                                           |  866 |                 | OctetString      | M,V  | P   |          |          | N    |
+| PS-Furnish-Charging-Information                               |  865 |                 | Grouped          | M,V  | P   |          |          | N    |
+| PS-Information                                                |  874 |                 | Grouped          | M,V  | P   |          |          | N    |
+| Participant-Access-Priority                                   | 1259 |                 | Enumerated       | M,V  | P   |          |          | N    |
+| Participant-Action-Type                                       | 2049 |                 | Enumerated       | M,V  | P   |          |          | N    |
+| Participant-Group                                             | 1260 |                 | Grouped          | M,V  | P   |          |          | N    |
+| Participants-Involved                                         |  887 |                 | UTF8String       | M,V  | P   |          |          | N    |
+| PoC-Change-Condition                                          | 1261 |                 | Enumerated       | M,V  | P   |          |          | N    |
+| PoC-Change-Time                                               | 1262 |                 | Time             | M,V  | P   |          |          | N    |
+| PoC-Controlling-Address                                       |  858 |                 | UTF8String       | M,V  | P   |          |          | N    |
+| PoC-Event-Type                                                | 2025 |                 | Enumerated       | M,V  | P   |          |          | N    |
+| PoC-Group-Name                                                |  859 |                 | UTF8String       | M,V  | P   |          |          | N    |
+| PoC-Information                                               |  879 |                 | Grouped          | M,V  | P   |          |          | N    |
+| PoC-Server-Role                                               |  883 |                 | Enumerated       | M,V  | P   |          |          | N    |
+| PoC-Session-Id                                                | 1229 |                 | UTF8String       | M,V  | P   |          |          | N    |
+| PoC-Session-Initiation-type                                   | 1277 |                 | Enumerated       | M,V  | P   |          |          | N    |
+| PoC-Session-Type                                              |  884 |                 | Enumerated       | M,V  | P   |          |          | N    |
+| PoC-User-Role                                                 | 1252 |                 | Grouped          | M,V  | P   |          |          | N    |
+| PoC-User-Role-IDs                                             | 1253 |                 | UTF8String       | M,V  | P   |          |          | N    |
+| PoC-User-Role-info-Units                                      | 1254 |                 | Enumerated       | M,V  | P   |          |          | N    |
+| Positioning-Data                                              | 1245 |                 | UTF8String       | M,V  | P   |          |          | N    |
+| Preferred-AoC-Currency                                        | 2315 |                 | Unsigned32       | M,V  | P   |          |          | N    |
+| Priority                                                      | 1209 |                 | Enumerated       | M,V  | P   |          |          | N    |
+| Quota-Consumption-Time                                        |  881 |                 | Unsigned32       | M,V  | P   |          |          | N    |
+| Quota-Holding-Time                                            |  871 |                 | Unsigned32       | M,V  | P   |          |          | N    |
+| Rate-Element                                                  | 2058 |                 | Grouped          | M,V  | P   |          |          | N    |
+| Read-Reply-Report-Requested                                   | 1222 |                 | Enumerated       | M,V  | P   |          |          | N    |
+| Real-Time-Tariff-Information                                  | 2305 |                 | Grouped          | M,V  | P   |          |          | N    |
+| Received-Talk-Burst-Time                                      | 1284 |                 | Unsigned32       | M,V  | P   |          |          | N    |
+| Received-Talk-Burst-Volume                                    | 1285 |                 | Unsigned32       | M,V  | P   |          |          | N    |
+| Recipient-Address                                             | 1201 |                 | Grouped          | M,V  | P   |          |          | N    |
+| Recipient-Info                                                | 2026 |                 | Grouped          | M,V  | P   |          |          | N    |
+| Recipient-Received-Address                                    | 2028 |                 | Grouped          | M,V  | P   |          |          | N    |
+| Recipient-SCCP-Address                                        | 2010 |                 | Address          | M,V  | P   |          |          | N    |
+| Refund-Information                                            | 2022 |                 | OctetString      | M,V  | P   |          |          | N    |
+| Relationship-Mode                                             | 2706 |                 | Enumerated       | M,V  | P   |          |          | N    |
+| Remaining-Balance                                             | 2021 |                 | Grouped          | M,V  | P   |          |          | N    |
+| Reply-Applic-ID                                               | 1223 |                 | UTF8String       | M,V  | P   |          |          | N    |
+| Reply-Path-Requested                                          | 2011 |                 | Enumerated       | M,V  | P   |          |          | N    |
+| Reporting-Reason                                              |  872 |                 | Enumerated       | M,V  | P   |          |          | N    |
+| Requested-Party-Address                                       | 1251 |                 | UTF8String       | M,V  | P   |          |          | N    |
+| Role-Of-Node                                                  |  829 |                 | Enumerated       | M,V  | P   |          |          | N    |
+| SDP-Answer-Timestamp                                          | 1275 |                 | Time             | M,V  | P   |          |          | N    |
+| SDP-Media-Component                                           |  843 |                 | Grouped          | M,V  | P   |          |          | N    |
+| SDP-Media-Description                                         |  845 |                 | UTF8String       | M,V  | P   |          |          | N    |
+| SDP-Media-Name                                                |  844 |                 | UTF8String       | M,V  | P   |          |          | N    |
+| SDP-Offer-Timestamp                                           | 1274 |                 | Time             | M,V  | P   |          |          | N    |
+| SDP-Session-Description                                       |  842 |                 | UTF8String       | M,V  | P   |          |          | N    |
+| SDP-TimeStamps                                                | 1273 |                 | Grouped          | M,V  | P   |          |          | N    |
+| SDP-Type                                                      | 2036 |                 | Enumerated       | M,V  | P   |          |          | N    |
+| SGSN-Address                                                  | 1228 |                 | Address          | M,V  | P   |          |          | N    |
+| SGW-Address                                                   | 2067 |                 | Address          | M,V  | P   |          |          | N    |
+| SGW-Change                                                    | 2065 |                 | Enumerated       | M,V  | P   |          |          | N    |
+| SIP-Method                                                    |  824 |                 | UTF8String       | M,V  | P   |          |          | N    |
+| SIP-Request-Timestamp                                         |  834 |                 | Time             | M,V  | P   |          |          | N    |
+| SIP-Request-Timestamp-Fraction                                | 2301 |                 | Unsigned32       | M,V  | P   |          |          | N    |
+| SIP-Response-Timestamp                                        |  835 |                 | Time             | M,V  | P   |          |          | N    |
+| SIP-Response-Timestamp-Fraction                               | 2302 |                 | Unsigned32       | M,V  | P   |          |          | N    |
+| SM-Discharge-Time                                             | 2012 |                 | Time             | M,V  | P   |          |          | N    |
+| SM-Message-Type                                               | 2007 |                 | Enumerated       | M,V  | P   |          |          | N    |
+| SM-Protocol-ID                                                | 2013 |                 | OctetString      | M,V  | P   |          |          | N    |
+| SM-Service-Type                                               | 2029 |                 | Enumerated       | M,V  | P   |          |          | N    |
+| SM-Status                                                     | 2014 |                 | OctetString      | M,V  | P   |          |          | N    |
+| SM-User-Data-Header                                           | 2015 |                 | OctetString      | M,V  | P   |          |          | N    |
+| SMS-Information                                               | 2000 |                 | Grouped          | M,V  | P   |          |          | N    |
+| SMS-Node                                                      | 2016 |                 | Enumerated       | M,V  | P   |          |          | N    |
+| SMSC-Address                                                  | 2017 |                 | Address          | M,V  | P   |          |          | N    |
+| Scale-Factor                                                  | 2059 |                 | Grouped          | M,V  | P   |          |          | N    |
+| Served-Party-IP-Address                                       |  848 |                 | Address          | M,V  | P   |          |          | N    |
+| Service-Data-Container                                        | 2040 |                 | Grouped          | M,V  | P   |          |          | N    |
+| Service-Id                                                    |  855 |                 | UTF8String       | M,V  | P   |          |          | N    |
+| Service-Information                                           |  873 |                 | Grouped          | M,V  | P   |          |          | N    |
+| Service-Mode                                                  | 2032 |                 | Unsigned32       | M,V  | P   |          |          | N    |
+| Service-Specific-Data                                         |  863 |                 | UTF8String       | M,V  | P   |          |          | N    |
+| Service-Specific-Info                                         | 1249 |                 | Grouped          | M,V  | P   |          |          | N    |
+| Service-Specific-Type                                         | 1257 |                 | Unsigned32       | M,V  | P   |          |          | N    |
+| Serving-Node-Type                                             | 2047 |                 | Enumerated       | M,V  | P   |          |          | N    |
+| Session-Direction                                             | 2707 |                 | Enumerated       | M,V  | P   |          |          | N    |
+| Start-Time                                                    | 2041 |                 | Time             | M,V  | P   |          |          | N    |
+| Status                                                        | 2702 |                 | Enumerated       | M,V  | P   |          |          | N    |
+| Stop-Time                                                     | 2042 |                 | Time             | M,V  | P   |          |          | N    |
+| Submission-Time                                               | 1202 |                 | Time             | M,V  | P   |          |          | N    |
+| Subscriber-Role                                               | 2033 |                 | Enumerated       | M,V  | P   |          |          | N    |
+| Supplementary-Service                                         | 2048 |                 | Grouped          | M,V  | P   |          |          | N    |
+| Talk-Burst-Exchange                                           | 1255 |                 | Grouped          | M,V  | P   |          |          | N    |
+| Talk-Burst-Time                                               | 1286 |                 | Unsigned32       | M,V  | P   |          |          | N    |
+| Talk-Burst-Volume                                             | 1287 |                 | Unsigned32       | M,V  | P   |          |          | N    |
+| Tariff-Information                                            | 2060 |                 | Grouped          | M,V  | P   |          |          | N    |
+| Tariff-XML                                                    | 2306 |                 | UTF8String       | M,V  | P   |          |          | N    |
+| Terminating-IOI                                               |  840 |                 | UTF8String       | M,V  | P   |          |          | N    |
+| Time-First-Usage                                              | 2043 |                 | Time             | M,V  | P   |          |          | N    |
+| Time-Last-Usage                                               | 2044 |                 | Time             | M,V  | P   |          |          | N    |
+| Time-Quota-Mechanism                                          | 1270 |                 | Grouped          | M,V  | P   |          |          | N    |
+| Time-Quota-Threshold                                          |  868 |                 | Unsigned32       | M,V  | P   |          |          | N    |
+| Time-Quota-Type                                               | 1271 |                 | Enumerated       | M,V  | P   |          |          | N    |
+| Time-Stamps                                                   |  833 |                 | Grouped          | M,V  | P   |          |          | N    |
+| Time-Usage                                                    | 2045 |                 | Unsigned32       | M,V  | P   |          |          | N    |
+| Token-Text                                                    | 1215 |                 | UTF8String       | M,V  | P   |          |          | N    |
+| Traffic-Data-Volumes                                          | 2046 |                 | Grouped          | M,V  | P   |          |          | N    |
+| Transcoder-Inserted-Indication                                | 2605 |                 | Enumerated       | M,V  | P   |          |          | N    |
+| Transit-IOI-List                                              | 2701 |                 | UTF8String       | M,V  | P   |          |          | N    |
+| Trigger                                                       | 1264 |                 | Grouped          | M,V  | P   |          |          | N    |
+| Trigger-Type                                                  |  870 |                 | Enumerated       | M,V  | P   |          |          | N    |
+| Trunk-Group-Id                                                |  851 |                 | Grouped          | M,V  | P   |          |          | N    |
+| Type-Number                                                   | 1204 |                 | Enumerated       | M,V  | P   |          |          | N    |
+| Unit-Cost                                                     | 2061 |                 | Grouped          | M,V  | P   |          |          | N    |
+| Unit-Quota-Threshold                                          | 1226 |                 | Unsigned32       | M,V  | P   |          |          | N    |
+| User-CSG-Information                                          | 2319 |                 | Grouped          | M,V  | P   |          |          | N    |
+| User-Participating-Type                                       | 1279 |                 | Enumerated       | M,V  | P   |          |          | N    |
+| User-Session-Id                                               |  830 |                 | UTF8String       | M,V  | P   |          |          | N    |
+| Volume-Quota-Threshold                                        |  869 |                 | Unsigned32       | M,V  | P   |          |          | N    |
+| WAG-Address                                                   |  890 |                 | Address          | M,V  | P   |          |          | N    |
+| WAG-PLMN-Id                                                   |  891 |                 | OctetString      | M,V  | P   |          |          | N    |
+| WLAN-Information                                              |  875 |                 | Grouped          | M,V  | P   |          |          | N    |
+| WLAN-Radio-Container                                          |  892 |                 | Grouped          | M,V  | P   |          |          | N    |
+| WLAN-Session-Id                                               | 1246 |                 | UTF8String       | M,V  | P   |          |          | N    |
+| WLAN-Technology                                               |  893 |                 | Unsigned32       | M,V  | P   |          |          | N    |
+| WLAN-UE-Local-IPAddress                                       |  894 |                 | Address          | M,V  | P   |          |          | N    |
+| # 3GPP 29.272-c00 (12.0.0 2013.03.13)                         |      |                 |                  |      |     |          |          |      |
+| Subscription-Data                                             | 1400 |           7.3.2 | Grouped          | M,V  |     |          |          | N    |
+| Terminal-Information                                          | 1401 |           7.3.3 | Grouped          | M,V  |     |          |          | N    |
+| IMEI                                                          | 1402 |           7.3.4 | UTF8String       | M,V  |     |          |          | N    |
+| Software-Version                                              | 1403 |           7.3.5 | UTF8String       | M,V  |     |          |          | N    |
+| QoS-Subscribed                                                | 1404 |          7.3.77 | OctetString      | M,V  |     |          |          | N    |
+| ULR-Flags                                                     | 1405 |           7.3.7 | Unsigned32       | M,V  |     |          |          | N    |
+| ULA-Flags                                                     | 1406 |           7.3.8 | Unsigned32       | M,V  |     |          |          | N    |
+| Visited-PLMN-Id                                               | 1407 |           7.3.9 | OctetString      | M,V  |     |          |          | N    |
+| Requested-EUTRAN-Authentication-Info                          | 1408 |          7.3.11 | Grouped          | M,V  |     |          |          | N    |
+| Requested-UTRAN- GERAN-Authentication-Info                    | 1409 |          7.3.12 | Grouped          | M,V  |     |          |          | N    |
+| Number-Of-Requested-Vectors                                   | 1410 |          7.3.14 | Unsigned32       | M,V  |     |          |          | N    |
+| Re-Synchronization-Info                                       | 1411 |          7.3.15 | OctetString      | M,V  |     |          |          | N    |
+| Immediate-Response-Preferred                                  | 1412 |          7.3.16 | Unsigned32       | M,V  |     |          |          | N    |
+| Authentication-Info                                           | 1413 |          7.3.17 | Grouped          | M,V  |     |          |          | N    |
+| E-UTRAN-Vector                                                | 1414 |          7.3.18 | Grouped          | M,V  |     |          |          | N    |
+| UTRAN-Vector                                                  | 1415 |          7.3.19 | Grouped          | M,V  |     |          |          | N    |
+| GERAN-Vector                                                  | 1416 |          7.3.20 | Grouped          | M,V  |     |          |          | N    |
+| Network-Access-Mode                                           | 1417 |          7.3.21 | Enumerated       | M,V  |     |          |          | N    |
+| HPLMN-ODB                                                     | 1418 |          7.3.22 | Unsigned32       | M,V  |     |          |          | N    |
+| Item-Number                                                   | 1419 |          7.3.23 | Unsigned32       | M,V  |     |          |          | N    |
+| Cancellation-Type                                             | 1420 |          7.3.24 | Enumerated       | M,V  |     |          |          | N    |
+| DSR-Flags                                                     | 1421 |          7.3.25 | Unsigned32       | M,V  |     |          |          | N    |
+| DSA-Flags                                                     | 1422 |          7.3.26 | Unsigned32       | M,V  |     |          |          | N    |
+| Context-Identifier                                            | 1423 |          7.3.27 | Unsigned32       | M,V  |     |          |          | N    |
+| Subscriber-Status                                             | 1424 |          7.3.29 | Enumerated       | M,V  |     |          |          | N    |
+| Operator-Determined-Barring                                   | 1425 |          7.3.30 | Unsigned32       | M,V  |     |          |          | N    |
+| Access-Restriction-Data                                       | 1426 |          7.3.31 | Unsigned32       | M,V  |     |          |          | N    |
+| APN-OI-Replacement                                            | 1427 |          7.3.32 | UTF8String       | M,V  |     |          |          | N    |
+| All-APN-Configurations-Included-Indicator                     | 1428 |          7.3.33 | Enumerated       | M,V  |     |          |          | N    |
+| APN-Configuration-Profile                                     | 1429 |          7.3.34 | Grouped          | M,V  |     |          |          | N    |
+| APN-Configuration                                             | 1430 |          7.3.35 | Grouped          | M,V  |     |          |          | N    |
+| EPS-Subscribed-QoS-Profile                                    | 1431 |          7.3.37 | Grouped          | M,V  |     |          |          | N    |
+| VPLMN-Dynamic-Address-Allowed                                 | 1432 |          7.3.38 | Enumerated       | M,V  |     |          |          | N    |
+| STN-SR                                                        | 1433 |          7.3.39 | OctetString      | M,V  |     |          |          | N    |
+| Alert-Reason                                                  | 1434 |          7.3.83 | Enumerated       | M,V  |     |          |          | N    |
+| AMBR                                                          | 1435 |          7.3.41 | Grouped          | M,V  |     |          |          | N    |
+| CSG-Subscription-Data                                         | 1436 |          7.3.78 | Grouped          | M. V |     |          |          | N    |
+| CSG-Id                                                        | 1437 |          7.3.79 | Unsigned32       | M,V  |     |          |          | N    |
+| PDN-GW-Allocation-Type                                        | 1438 |          7.3.44 | Enumerated       | M,V  |     |          |          | N    |
+| Expiration-Date                                               | 1439 |          7.3.80 | Time             | M,V  |     |          |          | N    |
+| RAT-Frequency-Selection-Priority-ID                           | 1440 |          7.3.46 | Unsigned32       | M,V  |     |          |          | N    |
+| IDA-Flags                                                     | 1441 |          7.3.47 | Unsigned32       | M,V  |     |          |          | N    |
+| PUA-Flags                                                     | 1442 |          7.3.48 | Unsigned32       | M,V  |     |          |          | N    |
+| NOR-Flags                                                     | 1443 |          7.3.49 | Unsigned32       | M,V  |     |          |          | N    |
+| User-Id                                                       | 1444 |          7.3.50 | UTF8String       | V    |     |          | M        | N    |
+| Equipment-Status                                              | 1445 |          7.3.51 | Enumerated       | M,V  |     |          |          | N    |
+| Regional-Subscription-Zone-Code                               | 1446 |          7.3.52 | OctetString      | M,V  |     |          |          | N    |
+| RAND                                                          | 1447 |          7.3.53 | OctetString      | M,V  |     |          |          | N    |
+| XRES                                                          | 1448 |          7.3.54 | OctetString      | M,V  |     |          |          | N    |
+| AUTN                                                          | 1449 |          7.3.55 | OctetString      | M,V  |     |          |          | N    |
+| KASME                                                         | 1450 |          7.3.56 | OctetString      | M,V  |     |          |          | N    |
+| Trace-Collection-Entity                                       | 1452 |          7.3.98 | Address          | M,V  |     |          |          | N    |
+| Kc                                                            | 1453 |          7.3.59 | OctetString      | M,V  |     |          |          | N    |
+| SRES                                                          | 1454 |          7.3.60 | OctetString      | M,V  |     |          |          | N    |
+| PDN-Type                                                      | 1456 |          7.3.62 | Enumerated       | M,V  |     |          |          | N    |
+| Roaming-Restricted-Due-To-Unsupported-Feature                 | 1457 |          7.3.81 | Enumerated       | M,V  |     |          |          | N    |
+| Trace-Data                                                    | 1458 |          7.3.63 | Grouped          | M,V  |     |          |          | N    |
+| Trace-Reference                                               | 1459 |          7.3.64 | OctetString      | M,V  |     |          |          | N    |
+| Trace-Depth                                                   | 1462 |          7.3.67 | Enumerated       | M,V  |     |          |          | N    |
+| Trace-NE-Type-List                                            | 1463 |          7.3.68 | OctetString      | M,V  |     |          |          | N    |
+| Trace-Interface-List                                          | 1464 |          7.3.69 | OctetString      | M,V  |     |          |          | N    |
+| Trace-Event-List                                              | 1465 |          7.3.70 | OctetString      | M,V  |     |          |          | N    |
+| OMC-Id                                                        | 1466 |          7.3.71 | OctetString      | M,V  |     |          |          | N    |
+| GPRS-Subscription-Data                                        | 1467 |          7.3.72 | Grouped          | M,V  |     |          |          | N    |
+| Complete-Data-List-Included-Indicator                         | 1468 |          7.3.73 | Enumerated       | M,V  |     |          |          | N    |
+| PDP-Context                                                   | 1469 |          7.3.74 | Grouped          | M,V  |     |          |          | N    |
+| PDP-Type                                                      | 1470 |          7.3.75 | OctetString      | M,V  |     |          |          | N    |
+| 3GPP2-MEID                                                    | 1471 |           7.3.6 | OctetString      | M,V  |     |          |          | N    |
+| Specific-APN-Info                                             | 1472 |          7.3.82 | Grouped          | M,V  |     |          |          | N    |
+| LCS-Info                                                      | 1473 |          7.3.84 | Grouped          | M,V  |     |          |          | N    |
+| GMLC-Number                                                   | 1474 |          7.3.85 | OctetString      | M,V  |     |          |          | N    |
+| LCS-PrivacyException                                          | 1475 |          7.3.86 | Grouped          | M,V  |     |          |          | N    |
+| SS-Code                                                       | 1476 |          7.3.87 | OctetString      | M,V  |     |          |          | N    |
+| SS-Status                                                     | 1477 |          7.3.88 | Grouped          | M,V  |     |          |          | N    |
+| Notification-To-UE-User                                       | 1478 |          7.3.89 | Enumerated       | M,V  |     |          |          | N    |
+| External-Client                                               | 1479 |          7.3.90 | Grouped          | M,V  |     |          |          | N    |
+| Client-Identity                                               | 1480 |          7.3.91 | OctetString      | M,V  |     |          |          | N    |
+| GMLC-Restriction                                              | 1481 |          7.3.92 | Enumerated       | M,V  |     |          |          | N    |
+| PLMN-Client                                                   | 1482 |          7.3.93 | Enumerated       | M,V  |     |          |          | N    |
+| Service-Type                                                  | 1483 |          7.3.94 | Grouped          | M,V  |     |          |          | N    |
+| ServiceTypeIdentity                                           | 1484 |          7.3.95 | Unsigned32       | M,V  |     |          |          | N    |
+| MO-LR                                                         | 1485 |          7.3.96 | Grouped          | M,V  |     |          |          | N    |
+| Teleservice-List                                              | 1486 |          7.3.99 | Grouped          | M,V  |     |          |          | N    |
+| TS-Code                                                       | 1487 |         7.3.100 | OctetString      | M,V  |     |          |          | N    |
+| Call-Barring-Infor-List                                       | 1488 |         7.3.101 | Grouped          | M,V  |     |          |          | N    |
+| SGSN-Number                                                   | 1489 |         7.3.102 | OctetString      | M,V  |     |          |          | N    |
+| IDR-Flags                                                     | 1490 |         7.3.103 | Unsigned32       | M,V  |     |          |          | N    |
+| ICS-Indicator                                                 | 1491 |         7.3.104 | Enumerated       | V    |     |          | M        | N    |
+| IMS-Voice-Over-PS-Sessions-Supported                          | 1492 |         7.3.106 | Enumerated       | V    |     |          | M        | N    |
+| Homogeneous-Support-of-IMS-Voice-Over-PS-Sessions             | 1493 |         7.3.107 | Enumerated       | V    |     |          | M        | N    |
+| Last-UE-Activity-Time                                         | 1494 |         7.3.108 | Time             | V    |     |          | M        | N    |
+| EPS-User-State                                                | 1495 |         7.3.110 | Grouped          | V    |     |          | M        | N    |
+| EPS-Location-Information                                      | 1496 |         7.3.111 | Grouped          | V    |     |          | M        | N    |
+| MME-User-State                                                | 1497 |         7.3.112 | Grouped          | V    |     |          | M        | N    |
+| SGSN-User-State                                               | 1498 |         7.3.113 | Grouped          | V    |     |          | M        | N    |
+| User-State                                                    | 1499 |         7.3.114 | Enumerated       | V    |     |          | M        | N    |
+| MME-Location Information                                      | 1600 |         7.3.115 | Grouped          | V    |     |          | M        | N    |
+| SGSN-Location-Information                                     | 1601 |         7.3.116 | Grouped          | V    |     |          | M        | N    |
+| E-UTRAN-Cell-Global-Identity                                  | 1602 |         7.3.117 | OctetString      | V    |     |          | M        | N    |
+| Tracking-Area-Identity                                        | 1603 |         7.3.118 | OctetString      | V    |     |          | M        | N    |
+| Cell-Global-Identity                                          | 1604 |         7.3.119 | OctetString      | V    |     |          | M        | N    |
+| Routing-Area-Identity                                         | 1605 |         7.3.120 | OctetString      | V    |     |          | M        | N    |
+| Location-Area-Identity                                        | 1606 |         7.3.121 | OctetString      | V    |     |          | M        | N    |
+| Service-Area-Identity                                         | 1607 |         7.3.122 | OctetString      | V    |     |          | M        | N    |
+| Geographical-Information                                      | 1608 |         7.3.123 | OctetString      | V    |     |          | M        | N    |
+| Geodetic-Information                                          | 1609 |         7.3.124 | OctetString      | V    |     |          | M        | N    |
+| Current-Location-Retrieved                                    | 1610 |         7.3.125 | Enumerated       | V    |     |          | M        | N    |
+| Age-Of-Location-Information                                   | 1611 |         7.3.126 | Unsigned32       | V    |     |          | M        | N    |
+| Active-APN                                                    | 1612 |         7.3.127 | Grouped          | V    |     |          | M        | N    |
+| Error-Diagnostic                                              | 1614 |         7.3.128 | Enumerated       | V    |     |          | M        | N    |
+| Ext-PDP-Address                                               | 1621 |         7.3.129 | Address          | V    |     |          | M        | N    |
+| UE-SRVCC-Capability                                           | 1615 |         7.3.130 | Enumerated       | V    |     |          | M        | N    |
+| MPS-Priority                                                  | 1616 |         7.3.131 | Unsigned32       | V    |     |          | M        | N    |
+| VPLMN-LIPA-Allowed                                            | 1617 |         7.3.132 | Enumerated       | V    |     |          | M        | N    |
+| LIPA-Permission                                               | 1618 |         7.3.133 | Enumerated       | V    |     |          | M        | N    |
+| Subscribed-Periodic-RAU-TAU-Timer                             | 1619 |         7.3.134 | Unsigned32       | V    |     |          | M        | N    |
+| Ext-PDP-Type                                                  | 1620 |         7.3.75A | OctetString      | V    |     |          | M        | N    |
+| SIPTO-Permission                                              | 1613 |         7.3.135 | Enumerated       | V    |     |          | M        | N    |
+| MDT-Configuration                                             | 1622 |         7.3.136 | Grouped          | V    |     |          | M        | N    |
+| Job-Type                                                      | 1623 |         7.3.137 | Enumerated       | V    |     |          | M        | N    |
+| Area-Scope                                                    | 1624 |         7.3.138 | Grouped          | V    |     |          | M        | N    |
+| List-Of-Measurements                                          | 1625 |         7.3.139 | Unsigned32       | V    |     |          | M        | N    |
+| Reporting-Trigger                                             | 1626 |         7.3.140 | Unsigned32       | V    |     |          | M        | N    |
+| Report-Interval                                               | 1627 |         7.3.141 | Enumerated       | V    |     |          | M        | N    |
+| Report-Amount                                                 | 1628 |         7.3.142 | Enumerated       | V    |     |          | M        | N    |
+| Event-Threshold-RSRP                                          | 1629 |         7.3.143 | Unsigned32       | V    |     |          | M        | N    |
+| Event-Threshold-RSRQ                                          | 1630 |         7.3.144 | Unsigned32       | V    |     |          | M        | N    |
+| Logging-Interval                                              | 1631 |         7.3.145 | Enumerated       | V    |     |          | M        | N    |
+| Logging-Duration                                              | 1632 |         7.3.146 | Enumerated       | V    |     |          | M        | N    |
+| Relay-Node-Indicator                                          | 1633 |         7.3.147 | Enumerated       | V    |     |          | M        | N    |
+| MDT-User-Consent                                              | 1634 |         7.3.148 | Enumerated       | V    |     |          | M        | N    |
+| PUR-Flags                                                     | 1635 |         7.3.149 | Unsigned32       | V    |     |          | M        | N    |
+| Subscribed-VSRVCC                                             | 1636 |         7.3.150 | Enumerated       | V    |     |          | M        | N    |
+| Equivalent-PLMN-List                                          | 1637 |         7.3.151 | Grouped          | V    |     |          | M        | N    |
+| CLR-Flags                                                     | 1638 |         7.3.152 | Unsigned32       | V    |     |          | M        | N    |
+| UVR-Flags                                                     | 1639 |         7.3.153 | Unsigned32       | M,V  |     |          |          | N    |
+| UVA-Flags                                                     | 1640 |         7.3.154 | Unsigned32       | M,V  |     |          |          | N    |
+| VPLMN-CSG-Subscription-Data                                   | 1641 |         7.3.155 | Grouped          | M,V  |     |          |          | N    |
+| Time-Zone                                                     | 1642 |         7.3.163 | UTF8String       | V    |     |          | M        | N    |
+| A-MSISDN                                                      | 1643 |         7.3.157 | OctetString      | V    |     |          | M        | N    |
+| MME-Number-for-MT-SMS                                         | 1645 |         7.3.159 | OctetString      | V    |     |          | M        | N    |
+| SMS-Register-Request                                          | 1648 |         7.3.162 | Enumerated       | V    |     |          | M        | N    |
+| Local-Time-Zone                                               | 1649 |         7.3.156 | Grouped          | V    |     |          | M        | N    |
+| Daylight-Saving-Time                                          | 1650 |         7.3.164 | Enumerated       | V    |     |          | M        | N    |
+| Subscription-Data-Flags                                       | 1654 |         7.3.165 | Unsigned32       | V    |     |          | M        | N    |
+| Measurement-Period-UMTS                                       | 1655 |         7.3.166 | Enumerated       | V    |     |          | M        | N    |
+| Measurement-Period-LTE                                        | 1656 |         7.3.167 | Enumerated       | V    |     |          | M        | N    |
+| Collection-Period-RRM-LTE                                     | 1657 |         7.3.168 | Enumerated       | V    |     |          | M        | N    |
+| Collection-Period-RRM-UMTS                                    | 1658 |         7.3.169 | Enumerated       | V    |     |          | M        | N    |
+| Positioning-Method                                            | 1659 |         7.3.170 | OctetString      | V    |     |          | M        | N    |
+| Measurement-Quantity                                          | 1660 |         7.3.171 | OctetString      | V    |     |          | M        | N    |
+| Event-Threshold-Event-1F                                      | 1661 |         7.3.172 | Integer32        | V    |     |          | M        | N    |
+| Event-Threshold-Event-1I                                      | 1662 |         7.3.173 | Integer32        | V    |     |          | M        | N    |
+| # 3GPP 29.329-b50 (11.5.0 2012.12.21)                         |      |                 |                  |      |     |          |          |      |
+| User-Identity                                                 |  700 |           6.3.1 | Grouped          | M,V  |     |          |          | N    |
+| MSISDN                                                        |  701 |           6.3.2 | OctetString      | M,V  |     |          |          | N    |
+| # Name conflict with 29.229 User-Data (606), renamed          |      |                 |                  |      |     |          |          |      |
+| User-Data-29.329                                              |  702 |           6.3.3 | OctetString      | M,V  |     |          |          | N    |
+| Data-Reference                                                |  703 |           6.3.4 | Enumerated       | M,V  |     |          |          | N    |
+| Service-Indication                                            |  704 |           6.3.5 | OctetString      | M,V  |     |          |          | N    |
+| Subs-Req-Type                                                 |  705 |           6.3.6 | Enumerated       | M,V  |     |          |          | N    |
+| Requested-Domain                                              |  706 |           6.3.7 | Enumerated       | M,V  |     |          |          | N    |
+| Current-Location                                              |  707 |           6.3.8 | Enumerated       | M,V  |     |          |          | N    |
+| Identity-Set                                                  |  708 |          6.3.10 | Enumerated       | V    |     |          | M        | N    |
+| Expiry-Time                                                   |  709 |          6.3.16 | Time             | V    |     |          | M        | N    |
+| Send-Data-Indication                                          |  710 |          6.3.17 | Enumerated       | V    |     |          | M        | N    |
+| # in 29.229                                                   |      |                 |                  |      |     |          |          |      |
+| # Server-Name                                                 |  602 |           6.3.9 | UTF8String       | M,V  |     |          |          | N    |
+| # Supported-Features                                          |  628 |          6.3.11 | Grouped          | V    | M   |          |          | N    |
+| # Feature-List-ID                                             |  629 |          6.3.12 | Unsigned32       | V    |     |          | M        | N    |
+| # Feature-List                                                |  630 |          6.3.13 | Unsigned32       | V    |     |          | M        | N    |
+| # Supported-Applications                                      |  631 |          6.3.14 | Grouped          | V    |     |          | M        | N    |
+| # Public-Identity                                             |  601 |          6.3.15 | UTF8String       | M,V  |     |          |          | N    |
+| DSAI-Tag                                                      |  711 |          6.3.18 | OctetString      | M,V  |     |          |          | N    |
+| # in 29.229                                                   |      |                 |                  |      |     |          |          |      |
+| # Wildcarded-Public-Identity                                  |  634 |          6.3.19 | UTF8String       | V    |     |          | M        | N    |
+| Wildcarded-IMPU                                               |  636 |          6.3.20 | UTF8String       | V    |     |          | M        | N    |
+| # in 29.229                                                   |      |                 |                  |      |     |          |          |      |
+| # Session-Priority                                            |  650 |          6.3.21 | Enumerated       | V    |     |          | M        | N    |
+| One-Time-Notification                                         |  712 |          6.3.22 | Enumerated       | V    |     |          | M        | N    |
+| Requested-Nodes                                               |  713 |          6.3.7A | Unsigned32       | V    |     |          | M        | N    |
+| Serving-Node-Indication                                       |  714 |          6.3.23 | Enumerated       | V    |     |          | M        | N    |
+| Repository-Data-ID                                            |  715 |          6.3.24 | Grouped          | V    |     |          | M        | N    |
+| Sequence-Number                                               |  716 |          6.3.25 | Unsigned32       | V    |     |          | M        | N    |
+| UDR-Flags                                                     |  719 |          6.3.28 | Unsigned32       | V    |     |          | M        | N    |
+| # OMA DDS Charging_Data V1.0 20110201-A                       |      |                 |                  |      |     |          |          |      |
+| Application-Server-Id                                         | 2101 |             8.4 | UTF8String       | M,V  |     |          |          | Y    |
+| Application-Service-Type                                      | 2102 |             8.4 | UTF8String       | M,V  |     |          |          | Y    |
+| Application-Session-Id                                        | 2103 |             8.4 | UTF8String       | M,V  |     |          |          | Y    |
+| Content-ID                                                    | 2116 |             8.4 | UTF8String       | M,V  |     |          |          | Y    |
+| Content-provider-ID                                           | 2117 |             8.4 | UTF8String       | M,V  |     |          |          | Y    |
+| DCD-Information                                               | 2115 |           8.5.5 | Grouped          | M,V  |     |          |          | Y    |
+| Delivery-Status                                               | 2104 |             8.4 | UTF8String       | M,V  |     |          |          | Y    |
+| IM-Information                                                | 2110 |           8.5.6 | Grouped          | M,V  |     |          |          | Y    |
+| Number-Of-Messages-Successfully-Exploded                      | 2111 |             8.4 | Unsigned32       | M,V  |     |          |          | Y    |
+| Number-Of-Messages-Successfully-Sent                          | 2112 |             8.4 | Unsigned32       | M,V  |     |          |          | Y    |
+| Service-Generic-Information                                   | 1256 |          8.5.10 | Grouped          | M,V  |     |          |          | Y    |
+| Total-Number-Of-Messages-Exploded                             | 2113 |             8.4 | Unsigned32       | M,V  |     |          |          | Y    |
+| Total-Number-Of-Messages-Sent                                 | 2114 |             8.4 | Unsigned32       | M,V  |     |          |          | Y    |
diff --git a/extensions/dict_dcca_starent/CMakeLists.txt b/extensions/dict_dcca_starent/CMakeLists.txt
new file mode 100644
index 0000000..8152a02
--- /dev/null
+++ b/extensions/dict_dcca_starent/CMakeLists.txt
@@ -0,0 +1,14 @@
+# The dict_dcca_starent extension
+PROJECT("Diameter DCCA (Diameter Credit Control Application) Starent dictionary definitions " C)
+
+# Compile as a module
+FD_ADD_EXTENSION(dict_dcca_starent dict_dcca_starent.c)
+
+
+####
+## INSTALL section ##
+
+INSTALL(TARGETS dict_dcca_starent
+	LIBRARY DESTINATION ${INSTALL_EXTENSIONS_SUFFIX}
+	COMPONENT freeDiameter-dictionary-rfc4006-extension-starent)
+
diff --git a/extensions/dict_dcca_starent/dict_dcca_starent.c b/extensions/dict_dcca_starent/dict_dcca_starent.c
new file mode 100644
index 0000000..e791f1f
--- /dev/null
+++ b/extensions/dict_dcca_starent/dict_dcca_starent.c
@@ -0,0 +1,478 @@
+/* 
+ * Dictionary definitions of objects specified in DCCA by Starent.
+ */
+#include <freeDiameter/extension.h>
+
+
+/* The content of this file follows the same structure as dict_base_proto.c */
+
+#define CHECK_dict_new( _type, _data, _parent, _ref )	\
+	CHECK_FCT(  fd_dict_new( fd_g_config->cnf_dict, (_type), (_data), (_parent), (_ref))  );
+
+#define CHECK_dict_search( _type, _criteria, _what, _result )	\
+	CHECK_FCT(  fd_dict_search( fd_g_config->cnf_dict, (_type), (_criteria), (_what), (_result), ENOENT) );
+
+struct local_rules_definition {
+	char 			*avp_name;
+	enum rule_position	position;
+	int 			min;
+	int			max;
+};
+
+#define RULE_ORDER( _position ) ((((_position) == RULE_FIXED_HEAD) || ((_position) == RULE_FIXED_TAIL)) ? 1 : 0 )
+
+/* Attention! This version of the macro uses AVP_BY_NAME_ALL_VENDORS, in contrast to most other copies! */
+#define PARSE_loc_rules( _rulearray, _parent) {								\
+	int __ar;											\
+	for (__ar=0; __ar < sizeof(_rulearray) / sizeof((_rulearray)[0]); __ar++) {			\
+		struct dict_rule_data __data = { NULL, 							\
+			(_rulearray)[__ar].position,							\
+			0, 										\
+			(_rulearray)[__ar].min,								\
+			(_rulearray)[__ar].max};							\
+		__data.rule_order = RULE_ORDER(__data.rule_position);					\
+		CHECK_FCT(  fd_dict_search( 								\
+			fd_g_config->cnf_dict,								\
+			DICT_AVP, 									\
+			AVP_BY_NAME_ALL_VENDORS, 							\
+			(_rulearray)[__ar].avp_name, 							\
+			&__data.rule_avp, 0 ) );							\
+		if ( !__data.rule_avp ) {								\
+			TRACE_DEBUG(INFO, "AVP Not found: '%s'", (_rulearray)[__ar].avp_name );		\
+			return ENOENT;									\
+		}											\
+		CHECK_FCT_DO( fd_dict_new( fd_g_config->cnf_dict, DICT_RULE, &__data, _parent, NULL),	\
+			{							        		\
+				TRACE_DEBUG(INFO, "Error on rule with AVP '%s'",      			\
+					 (_rulearray)[__ar].avp_name );		      			\
+				return EINVAL;					      			\
+			} );							      			\
+	}									      			\
+}
+
+#define enumval_def_u32( _val_, _str_ ) \
+		{ _str_, 		{ .u32 = _val_ }}
+
+#define enumval_def_os( _len_, _val_, _str_ ) \
+		{ _str_, 		{ .os = { .data = (unsigned char *)_val_, .len = _len_ }}}
+
+
+static int dict_dcca_starent_entry(char * conffile)
+{
+	/* Applications section */
+	{		
+                /* Create the vendors */
+                {
+                        struct dict_vendor_data vendor_data = { 8164, "Starent" };
+                        CHECK_FCT(fd_dict_new(fd_g_config->cnf_dict, DICT_VENDOR, &vendor_data, NULL, NULL));
+                }                                
+  
+	}
+	
+
+	struct dict_object * Address_type;
+	struct dict_object * DiameterIdentity_type;
+	struct dict_object * DiameterURI_type;
+	struct dict_object * IPFilterRule_type;
+	struct dict_object * Time_type;
+	struct dict_object * UTF8String_type;
+
+	CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "Address", &Address_type);
+	CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "DiameterIdentity", &DiameterIdentity_type);
+	CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "DiameterURI", &DiameterURI_type);
+	CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "IPFilterRule", &IPFilterRule_type);
+	CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "Time", &Time_type);                                
+	CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "UTF8String", &UTF8String_type);
+
+	/* The following is created automatically. Do not modify. */
+	/* Changes will be lost during the next update. Modify the source org file instead. */
+
+	/* Cisco ASR 5000 Series AAA Interface                                              */
+	/* Administration and Reference                                                     */
+	/* Release 8.x and 9.0                                                              */
+	/* Last Updated June 30, 2010                                                       */
+	/* updated using v15 docs from Jan 2014                                             */
+	/* www.cisco.com/c/dam/en/us/td/docs/wireless/asr_5000/15-0/15-0-AAA-Reference.pdf  */
+	/* SN-Volume-Quota-Threshold */
+	{
+		struct dict_avp_data data = {
+			501,	/* Code */
+			8164,	/* Vendor */
+			"SN-Volume-Quota-Threshold",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_UNSIGNED32	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* SN-Unit-Quota-Threshold */
+	{
+		struct dict_avp_data data = {
+			502,	/* Code */
+			8164,	/* Vendor */
+			"SN-Unit-Quota-Threshold",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_UNSIGNED32	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* SN-Time-Quota-Threshold */
+	{
+		struct dict_avp_data data = {
+			503,	/* Code */
+			8164,	/* Vendor */
+			"SN-Time-Quota-Threshold",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_UNSIGNED32	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* SN-Total-Used-Service-Unit */
+	{
+		struct dict_avp_data data = {
+			504,	/* Code */
+			8164,	/* Vendor */
+			"SN-Total-Used-Service-Unit",	/* Name */
+			AVP_FLAG_VENDOR,	/* Fixed flags */
+			AVP_FLAG_VENDOR,	/* Fixed flag values */
+			AVP_TYPE_GROUPED	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* SN-Absolute-Validity-Time */
+	{
+		struct dict_avp_data data = {
+			505,	/* Code */
+			8164,	/* Vendor */
+			"SN-Absolute-Validity-Time",	/* Name */
+			AVP_FLAG_VENDOR,	/* Fixed flags */
+			AVP_FLAG_VENDOR,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, Time_type, NULL);
+	};
+
+	/* SN-Bandwidth-Control */
+	{
+		struct dict_avp_data data = {
+			512,	/* Code */
+			8164,	/* Vendor */
+			"SN-Bandwidth-Control",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_INTEGER32	/* base type of data */
+		};
+		struct dict_object		*type;
+		struct dict_type_data	 tdata = { AVP_TYPE_INTEGER32, "Starent/Enumerated(SN-Bandwidth-Control)", NULL, NULL, NULL };
+		CHECK_dict_new(DICT_TYPE, &tdata, NULL, &type);
+		CHECK_dict_new(DICT_AVP, &data, type, NULL);
+	};
+
+	/* SN-Transparent-Data */
+	{
+		struct dict_avp_data data = {
+			513,	/* Code */
+			8164,	/* Vendor */
+			"SN-Transparent-Data",	/* Name */
+			AVP_FLAG_VENDOR,	/* Fixed flags */
+			AVP_FLAG_VENDOR,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* SN-Traffic-Policy */
+	{
+		struct dict_avp_data data = {
+			514,	/* Code */
+			8164,	/* Vendor */
+			"SN-Traffic-Policy",	/* Name */
+			AVP_FLAG_VENDOR,	/* Fixed flags */
+			AVP_FLAG_VENDOR,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, UTF8String_type, NULL);
+	};
+
+	/* SN-Firewall-Policy */
+	{
+		struct dict_avp_data data = {
+			515,	/* Code */
+			8164,	/* Vendor */
+			"SN-Firewall-Policy",	/* Name */
+			AVP_FLAG_VENDOR,	/* Fixed flags */
+			AVP_FLAG_VENDOR,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, UTF8String_type, NULL);
+	};
+
+	/* SN-Usage-Monitoring-Control */
+	{
+		struct dict_avp_data data = {
+			517,	/* Code */
+			8164,	/* Vendor */
+			"SN-Usage-Monitoring-Control",	/* Name */
+			AVP_FLAG_VENDOR,	/* Fixed flags */
+			AVP_FLAG_VENDOR,	/* Fixed flag values */
+			AVP_TYPE_GROUPED	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* SN-Monitoring-Key */
+	{
+		struct dict_avp_data data = {
+			518,	/* Code */
+			8164,	/* Vendor */
+			"SN-Monitoring-Key",	/* Name */
+			AVP_FLAG_VENDOR,	/* Fixed flags */
+			AVP_FLAG_VENDOR,	/* Fixed flag values */
+			AVP_TYPE_UNSIGNED32	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* SN-Usage-Volume */
+	{
+		struct dict_avp_data data = {
+			519,	/* Code */
+			8164,	/* Vendor */
+			"SN-Usage-Volume",	/* Name */
+			AVP_FLAG_VENDOR,	/* Fixed flags */
+			AVP_FLAG_VENDOR,	/* Fixed flag values */
+			AVP_TYPE_UNSIGNED64	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* SN-Service-Flow-Detection */
+	{
+		struct dict_avp_data data = {
+			520,	/* Code */
+			8164,	/* Vendor */
+			"SN-Service-Flow-Detection",	/* Name */
+			AVP_FLAG_VENDOR,	/* Fixed flags */
+			AVP_FLAG_VENDOR,	/* Fixed flag values */
+			AVP_TYPE_INTEGER32	/* base type of data */
+		};
+		struct dict_object		*type;
+		struct dict_type_data	 tdata = { AVP_TYPE_INTEGER32, "Starent/Enumerated(SN-Service-Flow-Detection)", NULL, NULL, NULL };
+		CHECK_dict_new(DICT_TYPE, &tdata, NULL, &type);
+		CHECK_dict_new(DICT_AVP, &data, type, NULL);
+	};
+
+	/* SN-Usage-Monitoring */
+	{
+		struct dict_avp_data data = {
+			521,	/* Code */
+			8164,	/* Vendor */
+			"SN-Usage-Monitoring",	/* Name */
+			AVP_FLAG_VENDOR,	/* Fixed flags */
+			AVP_FLAG_VENDOR,	/* Fixed flag values */
+			AVP_TYPE_INTEGER32	/* base type of data */
+		};
+		struct dict_object		*type;
+		struct dict_type_data	 tdata = { AVP_TYPE_INTEGER32, "Starent/Enumerated(SN-Usage-Monitoring)", NULL, NULL, NULL };
+		CHECK_dict_new(DICT_TYPE, &tdata, NULL, &type);
+		CHECK_dict_new(DICT_AVP, &data, type, NULL);
+	};
+
+	/* SN-Session-Start-Indicator */
+	{
+		struct dict_avp_data data = {
+			522,	/* Code */
+			8164,	/* Vendor */
+			"SN-Session-Start-Indicator",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* SN-Phase0-PSAPName */
+	{
+		struct dict_avp_data data = {
+			523,	/* Code */
+			8164,	/* Vendor */
+			"SN-Phase0-PSAPName",	/* Name */
+			AVP_FLAG_VENDOR,	/* Fixed flags */
+			AVP_FLAG_VENDOR,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, UTF8String_type, NULL);
+	};
+
+	/* SN-Charging-Id */
+	{
+		struct dict_avp_data data = {
+			525,	/* Code */
+			8164,	/* Vendor */
+			"SN-Charging-Id",	/* Name */
+			AVP_FLAG_VENDOR,	/* Fixed flags */
+			AVP_FLAG_VENDOR,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* SN-Remaining-Service-Unit */
+	{
+		struct dict_avp_data data = {
+			526,	/* Code */
+			8164,	/* Vendor */
+			"SN-Remaining-Service-Unit",	/* Name */
+			AVP_FLAG_VENDOR,	/* Fixed flags */
+			AVP_FLAG_VENDOR,	/* Fixed flag values */
+			AVP_TYPE_GROUPED	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* SN-Service-Start-Timestamp */
+	{
+		struct dict_avp_data data = {
+			527,	/* Code */
+			8164,	/* Vendor */
+			"SN-Service-Start-Timestamp",	/* Name */
+			AVP_FLAG_VENDOR,	/* Fixed flags */
+			AVP_FLAG_VENDOR,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, Time_type, NULL);
+	};
+
+	/* SN-Rulebase-Id */
+	{
+		struct dict_avp_data data = {
+			528,	/* Code */
+			8164,	/* Vendor */
+			"SN-Rulebase-Id",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, UTF8String_type, NULL);
+	};
+
+	/* SN-CF-Policy-ID */
+	{
+		struct dict_avp_data data = {
+			529,	/* Code */
+			8164,	/* Vendor */
+			"SN-CF-Policy-ID",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_UNSIGNED32	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* SN-Charging-Collection-Function-Name */
+	{
+		struct dict_avp_data data = {
+			530,	/* Code */
+			8164,	/* Vendor */
+			"SN-Charging-Collection-Function-Name",	/* Name */
+			AVP_FLAG_VENDOR,	/* Fixed flags */
+			AVP_FLAG_VENDOR,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, UTF8String_type, NULL);
+	};
+
+	/* SN-Fast-Reauth-Username */
+	{
+		struct dict_avp_data data = {
+			11010,	/* Code */
+			8164,	/* Vendor */
+			"SN-Fast-Reauth-Username",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* SN-Pseudonym-Username */
+	{
+		struct dict_avp_data data = {
+			11011,	/* Code */
+			8164,	/* Vendor */
+			"SN-Pseudonym-Username",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+
+
+	/* Rules section */
+
+	/* SN-Remaining-Service-Unit */
+	{
+		struct dict_object *rule_avp;
+		struct dict_avp_request vpa;
+		vpa.avp_vendor = 8164;
+		vpa.avp_name = "SN-Remaining-Service-Unit";
+		CHECK_dict_search(DICT_AVP, AVP_BY_NAME_AND_VENDOR, &vpa, &rule_avp);
+		struct local_rules_definition rules[] = {
+			{  "Tariff-Change-Usage",	RULE_OPTIONAL,	-1, 1 },
+			{  "CC-Time",	       		RULE_OPTIONAL,	-1, 1 },
+			{  "CC-Total-Octets",		RULE_OPTIONAL,	-1, 1 },
+			{  "CC-Input-Octets",		RULE_OPTIONAL,	-1, 1 },
+			{  "CC-Output-Octets",		RULE_OPTIONAL,	-1, 1 },
+			{  "CC-Service-Specific-Units",	RULE_OPTIONAL,	-1, 1 },
+			{  "Reporting-Reason",		RULE_OPTIONAL,	-1, 1 }
+		};
+		PARSE_loc_rules( rules, rule_avp );
+	}
+
+	/* SN-Total-Used-Service-Unit */
+	{
+		struct dict_object *rule_avp;
+		struct dict_avp_request vpa;
+		vpa.avp_vendor = 8164;
+		vpa.avp_name = "SN-Total-Used-Service-Unit";
+		CHECK_dict_search(DICT_AVP, AVP_BY_NAME_AND_VENDOR, &vpa, &rule_avp);
+		struct local_rules_definition rules[] = {
+			{  "Tariff-Change-Usage",	RULE_OPTIONAL,	-1, 1 },
+			{  "CC-Time",	       		RULE_OPTIONAL,	-1, 1 },
+			{  "CC-Total-Octets",		RULE_OPTIONAL,	-1, 1 },
+			{  "CC-Input-Octets",		RULE_OPTIONAL,	-1, 1 },
+			{  "CC-Output-Octets",		RULE_OPTIONAL,	-1, 1 },
+			{  "CC-Service-Specific-Units",	RULE_OPTIONAL,	-1, 1 },
+			{  "Reporting-Reason",		RULE_OPTIONAL,	-1, 1 }
+		};
+		PARSE_loc_rules( rules, rule_avp );
+	}
+
+	/* SN-Usage-Monitoring-Control */
+	{
+		struct dict_object *rule_avp;
+		struct dict_avp_request vpa;
+		vpa.avp_vendor = 8164;
+		vpa.avp_name = "SN-Usage-Monitoring-Control";
+		CHECK_dict_search(DICT_AVP, AVP_BY_NAME_AND_VENDOR, &vpa, &rule_avp);
+		struct local_rules_definition rules[] = {
+			{  "SN-Monitoring-Key",		RULE_OPTIONAL,	-1, 1 },
+			{  "SN-Usage-Monitoring",	RULE_OPTIONAL,	-1, 1 },
+			{  "SN-Usage-Volume",		RULE_OPTIONAL,	-1, 1 },
+		};
+		PARSE_loc_rules( rules, rule_avp );
+	}
+
+	LOG_D( "Extension 'Dictionary definitions for DCCA Starent' initialized");
+	return 0;
+}
+
+EXTENSION_ENTRY("dict_dcca_starent", dict_dcca_starent_entry, "dict_dcca_3gpp");
diff --git a/extensions/dict_dcca_starent/dict_dcca_starent.org b/extensions/dict_dcca_starent/dict_dcca_starent.org
new file mode 100644
index 0000000..7514d9f
--- /dev/null
+++ b/extensions/dict_dcca_starent/dict_dcca_starent.org
@@ -0,0 +1,31 @@
+| Attribute Name                                                                    |  Code | Section defined | Value Type  | MUST | MAY | SHLD NOT | MUST NOT | Encr |
+| # Cisco ASR 5000 Series AAA Interface                                             |       |                 |             |      |     |          |          |      |
+| # Administration and Reference                                                    |       |                 |             |      |     |          |          |      |
+| # Release 8.x and 9.0                                                             |       |                 |             |      |     |          |          |      |
+| # Last Updated June 30, 2010                                                      |       |                 |             |      |     |          |          |      |
+| # updated using v15 docs from Jan 2014                                            |       |                 |             |      |     |          |          |      |
+| # www.cisco.com/c/dam/en/us/td/docs/wireless/asr_5000/15-0/15-0-AAA-Reference.pdf |       |                 |             |      |     |          |          |      |
+| SN-Volume-Quota-Threshold                                                         |   501 |                 | Unsigned32  | M,V  |     |          |          |      |
+| SN-Unit-Quota-Threshold                                                           |   502 |                 | Unsigned32  | M,V  |     |          |          |      |
+| SN-Time-Quota-Threshold                                                           |   503 |                 | Unsigned32  | M,V  |     |          |          |      |
+| SN-Total-Used-Service-Unit                                                        |   504 |                 | Grouped     | V    |     |          |          |      |
+| SN-Absolute-Validity-Time                                                         |   505 |                 | Time        | V    |     |          |          |      |
+| SN-Bandwidth-Control                                                              |   512 |                 | Enumerated  | M,V  |     |          |          |      |
+| SN-Transparent-Data                                                               |   513 |                 | OctetString | V    |     |          |          |      |
+| SN-Traffic-Policy                                                                 |   514 |                 | UTF8String  | V    |     |          |          |      |
+| SN-Firewall-Policy                                                                |   515 |                 | UTF8String  | V    |     |          |          |      |
+| SN-Usage-Monitoring-Control                                                       |   517 |                 | Grouped     | V    |     |          |          |      |
+| SN-Monitoring-Key                                                                 |   518 |                 | Unsigned32  | V    |     |          |          |      |
+| SN-Usage-Volume                                                                   |   519 |                 | Unsigned64  | V    |     |          |          |      |
+| SN-Service-Flow-Detection                                                         |   520 |                 | Enumerated  | V    |     |          |          |      |
+| SN-Usage-Monitoring                                                               |   521 |                 | Enumerated  | V    |     |          |          |      |
+| SN-Session-Start-Indicator                                                        |   522 |                 | OctetString | M,V  |     |          |          |      |
+| SN-Phase0-PSAPName                                                                |   523 |                 | UTF8String  | V    |     |          |          |      |
+| SN-Charging-Id                                                                    |   525 |                 | OctetString | V    |     |          |          |      |
+| SN-Remaining-Service-Unit                                                         |   526 |                 | Grouped     | V    |     |          |          |      |
+| SN-Service-Start-Timestamp                                                        |   527 |                 | Time        | V    |     |          |          |      |
+| SN-Rulebase-Id                                                                    |   528 |                 | UTF8String  | M,V  |     |          |          |      |
+| SN-CF-Policy-ID                                                                   |   529 |                 | Unsigned32  | M,V  |     |          |          |      |
+| SN-Charging-Collection-Function-Name                                              |   530 |                 | UTF8String  | V    |     |          |          |      |
+| SN-Fast-Reauth-Username                                                           | 11010 |                 | OctetString | M,V  |     |          |          |      |
+| SN-Pseudonym-Username                                                             | 11011 |                 | OctetString | M,V  |     |          |          |      |
diff --git a/extensions/dict_draftload_avps/CMakeLists.txt b/extensions/dict_draftload_avps/CMakeLists.txt
new file mode 100644
index 0000000..a0c8244
--- /dev/null
+++ b/extensions/dict_draftload_avps/CMakeLists.txt
@@ -0,0 +1,16 @@
+# The dict_draftload_avps extension
+PROJECT("dict_draftload_avps library generated by FdGen " C)
+
+# Compile as a module
+FD_ADD_EXTENSION(dict_draftload_avps dict_draftload_avps.c)
+
+
+####
+## INSTALL section ##
+
+INSTALL(TARGETS dict_draftload_avps
+	LIBRARY DESTINATION ${INSTALL_EXTENSIONS_SUFFIX}
+COMPONENT freeDiameter-dictionary-DRAFTLOAD_AVPS)
+
+
+
diff --git a/extensions/dict_draftload_avps/dict_draftload_avps.c b/extensions/dict_draftload_avps/dict_draftload_avps.c
new file mode 100644
index 0000000..aa8c760
--- /dev/null
+++ b/extensions/dict_draftload_avps/dict_draftload_avps.c
@@ -0,0 +1,236 @@
+/*
+* Copyright (c) 2017 Sprint
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*    http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+/****************
+ Generated By: fdtool enhancements to diafuzzer
+ License: same as freeDiameter
+****************/
+
+
+/* 
+ * Dictionary definitions of objects specified in draftload_avps.
+ */
+#include <freeDiameter/extension.h>
+
+#define PROTO_VER "unspecified"
+#define GEN_DATE  1506697143.4
+
+const char *draftload_avps_proto_ver = PROTO_VER;
+const double draftload_avps_gen_date = GEN_DATE;
+
+/* The content of this file follows the same structure as dict_base_proto.c */
+
+#define CHECK_dict_new( _type, _data, _parent, _ref )                                     \
+{                                                                                         \
+    int _ret = fd_dict_new( fd_g_config->cnf_dict, (_type), (_data), (_parent), (_ref) ); \
+    if ( _ret != 0 && _ret != EEXIST )                                                    \
+       return _ret;                                                                       \
+}
+
+#define CHECK_dict_search( _type, _criteria, _what, _result )		\
+    CHECK_FCT(  fd_dict_search( fd_g_config->cnf_dict, (_type), (_criteria), (_what), (_result), ENOENT) );
+
+struct local_rules_definition {
+    struct dict_avp_request avp_vendor_plus_name;
+    enum rule_position	position;
+    int 			min;
+    int			max;
+};
+
+#define RULE_ORDER( _position ) ((((_position) == RULE_FIXED_HEAD) || ((_position) == RULE_FIXED_TAIL)) ? 1 : 0 )
+
+/* Attention! This version of the macro uses AVP_BY_NAME_AND_VENDOR, in contrast to most other copies! */
+#define PARSE_loc_rules( _rulearray, _parent) {                                                         \
+        int __ar;                                                                                       \
+        for (__ar=0; __ar < sizeof(_rulearray) / sizeof((_rulearray)[0]); __ar++) {                     \
+                struct dict_rule_data __data = { NULL,                                                  \
+                        (_rulearray)[__ar].position,                                                    \
+                        0,                                                                              \
+                        (_rulearray)[__ar].min,                                                         \
+                        (_rulearray)[__ar].max};                                                        \
+                __data.rule_order = RULE_ORDER(__data.rule_position);                                   \
+                CHECK_FCT(  fd_dict_search(                                                             \
+                        fd_g_config->cnf_dict,                                                          \
+                        DICT_AVP,                                                                       \
+                        AVP_BY_NAME_AND_VENDOR,                                                         \
+                        &(_rulearray)[__ar].avp_vendor_plus_name,                                       \
+                        &__data.rule_avp, 0 ) );                                                        \
+                if ( !__data.rule_avp ) {                                                               \
+                        TRACE_DEBUG(INFO, "AVP Not found: '%s'", (_rulearray)[__ar].avp_vendor_plus_name.avp_name);             \
+                        return ENOENT;                                                                  \
+                }                                                                                       \
+                {                                                                                       \
+                         int _ret = fd_dict_new( fd_g_config->cnf_dict, DICT_RULE, &(__data), (_parent), NULL ); \
+                         if ( _ret != 0 && _ret != EEXIST )      {                                      \
+                                TRACE_DEBUG(INFO, "Error on rule with AVP '%s'",                        \
+                                            (_rulearray)[__ar].avp_vendor_plus_name.avp_name);          \
+                                return EINVAL;                                                          \
+                         }                                                                              \
+                }                                                                                       \
+        }                                                                                               \
+}
+
+#define CHECK_vendor_new( _data ) { \
+        struct dict_object * vendor_found; \
+        if (fd_dict_search(fd_g_config->cnf_dict,DICT_VENDOR,VENDOR_BY_ID,&_data.vendor_id,&vendor_found,ENOENT) == ENOENT) { \
+                CHECK_FCT(fd_dict_new(fd_g_config->cnf_dict, DICT_VENDOR, &_data, NULL, NULL)); \
+        } \
+}
+
+#define enumval_def_u32( _val_, _str_ )		\
+    { _str_, 		{ .u32 = _val_ }}
+
+#define enumval_def_os( _len_, _val_, _str_ )				\
+    { _str_, 		{ .os = { .data = (unsigned char *)_val_, .len = _len_ }}}
+
+
+static int dict_draftload_avps_load_defs(char * conffile)
+{
+   TRACE_ENTRY("%p", conffile);
+
+   /* AVP section */
+   {
+		struct dict_object * Address_type;
+		struct dict_object * UTF8String_type;
+		struct dict_object * DiameterIdentity_type;
+		struct dict_object * DiameterURI_type;
+		struct dict_object * Time_type;
+		struct dict_object * IPFilterRule_type;
+
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "Address", &Address_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "UTF8String", &UTF8String_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "DiameterIdentity", &DiameterIdentity_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "DiameterURI", &DiameterURI_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "Time", &Time_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "IPFilterRule", &IPFilterRule_type);
+		/* Load-Type */
+		{
+			struct dict_avp_data data = {
+				651,	/* Code */
+				0,	/* Vendor */
+				"Load-Type",	/* Name */
+				AVP_FLAG_VENDOR,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "Enumerated(Load-Type)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "HOST", { .i32=0 }};
+			struct dict_enumval_data        t_2 = { "PEER", { .i32=1 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* Load-Value */
+		{
+			struct dict_avp_data data = {
+				652,	/* Code */
+				0,	/* Vendor */
+				"Load-Value",	/* Name */
+				AVP_FLAG_VENDOR,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED64	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* SourceID */
+		{
+			struct dict_avp_data data = {
+				649,	/* Code */
+				0,	/* Vendor */
+				"SourceID",	/* Name */
+				AVP_FLAG_VENDOR,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, DiameterIdentity_type, NULL);
+		};
+		/* Load */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				650,	/* Code */
+				0,	/* Vendor */
+				"Load",	/* Name */
+				AVP_FLAG_VENDOR,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+
+	
+   }
+
+   /* Commands section */
+   {
+
+   }
+
+   return 0;
+}
+
+static int dict_draftload_avps_load_rules(char * conffile)
+{
+   /* Grouped AVP section */
+   {
+	  /* Load */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 0, .avp_name = "Load"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 0, .avp_name = "Load-Type"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Load-Value"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "SourceID"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+
+   }	
+
+   /* Commands section */
+   {
+
+   }
+
+   LOG_D( "Extension 'Dictionary definitions for draftload_avps (None)' initialized");
+   return 0;
+}
+
+int dict_entry(char * conffile)
+{
+	dict_draftload_avps_load_defs(conffile);
+	return dict_draftload_avps_load_rules(conffile);
+}
+
+const char* dict_draftload_avps_proto_ver(char * conffile) {
+	return draftload_avps_proto_ver;
+}
+
+const double dict_draftload_avps_gen_ts(char * conffile) {
+	return draftload_avps_gen_date;
+}
+
+EXTENSION_ENTRY2("dict_draftload_avps", dict_draftload_avps_load_defs, dict_draftload_avps_load_rules);
+
+
+
diff --git a/extensions/dict_draftload_avps/draftload_avps.did b/extensions/dict_draftload_avps/draftload_avps.did
new file mode 100644
index 0000000..930430e
--- /dev/null
+++ b/extensions/dict_draftload_avps/draftload_avps.did
@@ -0,0 +1 @@
+dict_draftload_avps
diff --git a/extensions/dict_eap/CMakeLists.txt b/extensions/dict_eap/CMakeLists.txt
new file mode 100644
index 0000000..c10b557
--- /dev/null
+++ b/extensions/dict_eap/CMakeLists.txt
@@ -0,0 +1,13 @@
+# The dict_eap extension
+PROJECT("Diameter EAP (RFC4072) dictionary definitions" C)
+
+# Compile as a module
+FD_ADD_EXTENSION(dict_eap dict_eap.c)
+
+
+####
+## INSTALL section ##
+
+INSTALL(TARGETS dict_eap
+	LIBRARY DESTINATION ${INSTALL_EXTENSIONS_SUFFIX}
+	COMPONENT freeDiameter-dictionary-RFC4072)
diff --git a/extensions/dict_eap/dict_eap.c b/extensions/dict_eap/dict_eap.c
new file mode 100644
index 0000000..0de5731
--- /dev/null
+++ b/extensions/dict_eap/dict_eap.c
@@ -0,0 +1,519 @@
+/*********************************************************************************************************
+* Software License Agreement (BSD License)                                                               *
+* Author: Sebastien Decugis <sdecugis@freediameter.net>							 *
+*													 *
+* Copyright (c) 2013, WIDE Project and NICT								 *
+* All rights reserved.											 *
+* 													 *
+* Redistribution and use of this software in source and binary forms, with or without modification, are  *
+* permitted provided that the following conditions are met:						 *
+* 													 *
+* * Redistributions of source code must retain the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer.										 *
+*    													 *
+* * Redistributions in binary form must reproduce the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer in the documentation and/or other						 *
+*   materials provided with the distribution.								 *
+* 													 *
+* * Neither the name of the WIDE Project or NICT nor the 						 *
+*   names of its contributors may be used to endorse or 						 *
+*   promote products derived from this software without 						 *
+*   specific prior written permission of WIDE Project and 						 *
+*   NICT.												 *
+* 													 *
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED *
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
+* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR *
+* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 	 *
+* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 	 *
+* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR *
+* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF   *
+* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.								 *
+*********************************************************************************************************/
+
+/* 
+ * Dictionary definitions of objects specified in Diameter EAP application (RFC4072).
+ */
+#include <freeDiameter/extension.h>
+
+/* The content of this file follows the same structure as dict_base_proto.c */
+
+#define CHECK_dict_new( _type, _data, _parent, _ref )	\
+	CHECK_FCT(  fd_dict_new( fd_g_config->cnf_dict, (_type), (_data), (_parent), (_ref))  );
+
+#define CHECK_dict_search( _type, _criteria, _what, _result )	\
+	CHECK_FCT(  fd_dict_search( fd_g_config->cnf_dict, (_type), (_criteria), (_what), (_result), ENOENT) );
+
+struct local_rules_definition {
+	char 			*avp_name;
+	enum rule_position	position;
+	int 			min;
+	int			max;
+};
+
+#define RULE_ORDER( _position ) ((((_position) == RULE_FIXED_HEAD) || ((_position) == RULE_FIXED_TAIL)) ? 1 : 0 )
+
+#define PARSE_loc_rules( _rulearray, _parent) {								\
+	int __ar;											\
+	for (__ar=0; __ar < sizeof(_rulearray) / sizeof((_rulearray)[0]); __ar++) {			\
+		struct dict_rule_data __data = { NULL, 							\
+			(_rulearray)[__ar].position,							\
+			0, 										\
+			(_rulearray)[__ar].min,								\
+			(_rulearray)[__ar].max};							\
+		__data.rule_order = RULE_ORDER(__data.rule_position);					\
+		CHECK_FCT(  fd_dict_search( 								\
+			fd_g_config->cnf_dict,								\
+			DICT_AVP, 									\
+			AVP_BY_NAME, 									\
+			(_rulearray)[__ar].avp_name, 							\
+			&__data.rule_avp, 0 ) );							\
+		if ( !__data.rule_avp ) {								\
+			TRACE_DEBUG(INFO, "AVP Not found: '%s'", (_rulearray)[__ar].avp_name );		\
+			return ENOENT;									\
+		}											\
+		CHECK_FCT_DO( fd_dict_new( fd_g_config->cnf_dict, DICT_RULE, &__data, _parent, NULL),	\
+			{							        		\
+				TRACE_DEBUG(INFO, "Error on rule with AVP '%s'",      			\
+					 (_rulearray)[__ar].avp_name );		      			\
+				return EINVAL;					      			\
+			} );							      			\
+	}									      			\
+}
+
+#define enumval_def_u32( _val_, _str_ ) \
+		{ _str_, 		{ .u32 = _val_ }}
+
+#define enumval_def_os( _len_, _val_, _str_ ) \
+		{ _str_, 		{ .os = { .data = (unsigned char *)_val_, .len = _len_ }}}
+
+
+static int deap_entry(char * conffile)
+{
+	struct dict_object * eap;
+	TRACE_ENTRY("%p", conffile);
+	
+	/* Applications section */
+	{
+		/* EAP (RFC 4072) */
+		{
+			struct dict_application_data data  = { 	5, "Diameter Extensible Authentication Protocol (EAP) Application"	};
+			CHECK_dict_new( DICT_APPLICATION, &data , NULL, &eap);
+		}
+	}
+	
+	/* AVP section */
+	{
+		/* EAP-Payload */
+		{
+			/*
+				The EAP-Payload AVP (AVP Code 462) is of type OctetString and is used
+				to encapsulate the actual EAP packet that is being exchanged between
+				the EAP client and the home Diameter server.
+			*/
+			struct dict_avp_data data = { 
+					462, 					/* Code */
+					0, 					/* Vendor */
+					"EAP-Payload", 				/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,		 	/* Fixed flag values */
+					AVP_TYPE_OCTETSTRING 			/* base type of data */
+					};
+			CHECK_dict_new( DICT_AVP, &data , NULL, NULL);
+		}
+		
+		/* EAP-Reissued-Payload */
+		{
+			/*
+				The EAP-Reissued-Payload AVP (AVP Code 463) is of type OctetString.
+			*/
+			struct dict_avp_data data = { 
+					463, 					/* Code */
+					0, 					/* Vendor */
+					"EAP-Reissued-Payload", 		/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,		 	/* Fixed flag values */
+					AVP_TYPE_OCTETSTRING 			/* base type of data */
+					};
+			CHECK_dict_new( DICT_AVP, &data , NULL, NULL);
+		}
+		
+		/* EAP-Master-Session-Key */
+		{
+			/*
+				The EAP-Master-Session-Key AVP (AVP Code 464) is of type OctetString.
+				It contains keying material for protecting the communications between
+				the user and the NAS.  Exactly how this keying material is used
+				depends on the link layer in question, and is beyond the scope of
+				this document.
+			*/
+			struct dict_avp_data data = { 
+					464, 					/* Code */
+					0, 					/* Vendor */
+					"EAP-Master-Session-Key", 		/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,		 	/* Fixed flag values */
+					AVP_TYPE_OCTETSTRING 			/* base type of data */
+					};
+			CHECK_dict_new( DICT_AVP, &data , NULL, NULL);
+		}
+		
+		/* EAP-Key-Name */
+		{
+			/*
+				The EAP-Key-Name AVP (Radius Attribute Type 102) is of type
+				OctetString.  It contains an opaque key identifier (name) generated
+				by the EAP method.  Exactly how this name is used depends on the link
+				layer in question, and is beyond the scope of this document (see
+				[EAPKey] for more discussion).
+
+				Note that not all link layers use this name, and currently most EAP
+				methods do not generate it.  Since the NAS operates in pass-through
+				mode, it cannot know the Key-Name before receiving it from the AAA
+				server.  As a result, a Key-Name AVP sent in a Diameter-EAP-Request
+				MUST NOT contain any data.  A home Diameter server receiving a
+				Diameter-EAP-Request with a Key-Name AVP with non-empty data MUST
+				silently discard the AVP.  In addition, the home Diameter server
+				SHOULD include this AVP in Diameter-EAP-Response only if an empty
+				EAP-Key-Name AVP was present in Diameter-EAP-Request.
+			*/
+			struct dict_avp_data data = { 
+					102, 					/* Code */
+					0, 					/* Vendor */
+					"EAP-Key-Name", 			/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,		 	/* Fixed flag values */
+					AVP_TYPE_OCTETSTRING 			/* base type of data */
+					};
+			CHECK_dict_new( DICT_AVP, &data , NULL, NULL);
+		}
+		
+		/* Accounting-EAP-Auth-Method */
+		{
+			/*
+				The Accounting-EAP-Auth-Method AVP (AVP Code 465) is of type
+				Unsigned64.  In case of expanded types [EAP, Section 5.7], this AVP
+				contains the value ((Vendor-Id * 2^32) + Vendor-Type).
+			*/
+			struct dict_avp_data data = { 
+					465, 					/* Code */
+					0, 					/* Vendor */
+					"Accounting-EAP-Auth-Method", 		/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,		 	/* Fixed flag values */
+					AVP_TYPE_UNSIGNED64 			/* base type of data */
+					};
+			CHECK_dict_new( DICT_AVP, &data , NULL, NULL);
+		}
+		
+	}
+
+/********************/		
+/* Commands section */
+/********************/		
+	{
+		/* To avoid defining global variables for all the AVP that we use here, we do search the dictionary in each sub-block.
+		 * This is far from optimal, but the code is clearer like this, and the time it requires at execution is not noticeable.
+		 */
+		/* Diameter-EAP-Request (DER) Command */
+		{
+			/*
+				The Diameter-EAP-Request (DER) command, indicated by the Command-Code
+				field set to 268 and the 'R' bit set in the Command Flags field, is
+				sent by a Diameter client to a Diameter server, and conveys an
+				EAP-Response from the EAP client.  The Diameter-EAP-Request MUST
+				contain one EAP-Payload AVP containing the actual EAP payload.  An
+				EAP-Payload AVP with no data MAY be sent to the Diameter server to
+				initiate an EAP authentication session.
+
+				The DER message MAY be the result of a multi-round authentication
+				exchange that occurs when the DEA is received with the Result-Code
+				AVP set to DIAMETER_MULTI_ROUND_AUTH [BASE].  A subsequent DER
+				message MUST include any State AVPs [NASREQ] that were present in the
+				DEA.  For re-authentication, it is recommended that the Identity
+				request be skipped in order to reduce the number of authentication
+				round trips.  This is only possible when the user's identity is
+				already known by the home Diameter server.
+
+				Message format
+
+				<Diameter-EAP-Request> ::= < Diameter Header: 268, REQ, PXY >
+                        				 < Session-Id >
+                        				 { Auth-Application-Id }
+                        				 { Origin-Host }
+                        				 { Origin-Realm }
+                        				 { Destination-Realm }
+                        				 { Auth-Request-Type }
+                        				 [ Destination-Host ]
+                        				 [ NAS-Identifier ]
+                        				 [ NAS-IP-Address ]
+                        				 [ NAS-IPv6-Address ]
+                        				 [ NAS-Port ]
+                        				 [ NAS-Port-Id ]
+                        				 [ NAS-Port-Type ]
+                        				 [ Origin-State-Id ]
+                        				 [ Port-Limit ]
+                        				 [ User-Name ]
+                        				 { EAP-Payload }
+                        				 [ EAP-Key-Name ]
+                        				 [ Service-Type ]
+                        				 [ State ]
+                        				 [ Authorization-Lifetime ]
+                        				 [ Auth-Grace-Period ]
+                        				 [ Auth-Session-State ]
+                        				 [ Callback-Number ]
+                        				 [ Called-Station-Id ]
+                        				 [ Calling-Station-Id ]
+                        				 [ Originating-Line-Info ]
+                        				 [ Connect-Info ]
+                				       * [ Framed-Compression ]
+                        				 [ Framed-Interface-Id ]
+                        				 [ Framed-IP-Address ]
+                				       * [ Framed-IPv6-Prefix ]
+                        				 [ Framed-IP-Netmask ]
+                        				 [ Framed-MTU ]
+                        				 [ Framed-Protocol ]
+                				       * [ Tunneling ]
+                				       * [ Proxy-Info ]
+                				       * [ Route-Record ]
+                				       * [ AVP ]
+			*/
+			struct dict_object * cmd;
+			struct dict_cmd_data data = { 
+					268, 					/* Code */
+					"Diameter-EAP-Request", 		/* Name */
+					CMD_FLAG_REQUEST | CMD_FLAG_PROXIABLE | CMD_FLAG_ERROR, /* Fixed flags */
+					CMD_FLAG_REQUEST | CMD_FLAG_PROXIABLE 			/* Fixed flag values */
+					};
+			struct local_rules_definition rules[] = 
+						{ 	 {  "Session-Id", 			RULE_FIXED_HEAD, -1, 1 }
+						 	,{  "Auth-Application-Id", 		RULE_REQUIRED,   -1, 1 }
+						 	,{  "Origin-Host", 			RULE_REQUIRED,   -1, 1 }
+							,{  "Origin-Realm",			RULE_REQUIRED,   -1, 1 }
+							,{  "Destination-Realm",		RULE_REQUIRED,   -1, 1 }
+						 	,{  "Auth-Request-Type", 		RULE_REQUIRED,   -1, 1 }
+							,{  "Destination-Host",			RULE_OPTIONAL,   -1, 1 }
+							,{  "NAS-Identifier",			RULE_OPTIONAL,   -1, 1 }
+							,{  "NAS-IP-Address",			RULE_OPTIONAL,   -1, 1 }
+							,{  "NAS-IPv6-Address",			RULE_OPTIONAL,   -1, 1 }
+							,{  "NAS-Port",				RULE_OPTIONAL,   -1, 1 }
+							,{  "NAS-Port-Id",			RULE_OPTIONAL,   -1, 1 }
+							,{  "NAS-Port-Type",			RULE_OPTIONAL,   -1, 1 }
+							,{  "Origin-State-Id",			RULE_OPTIONAL,   -1, 1 }
+							,{  "Port-Limit",			RULE_OPTIONAL,   -1, 1 }
+							,{  "User-Name",			RULE_OPTIONAL,   -1, 1 }
+							,{  "EAP-Payload",			RULE_REQUIRED,   -1, 1 }
+							,{  "EAP-Key-Name",			RULE_OPTIONAL,   -1, 1 }
+							,{  "Service-Type",			RULE_OPTIONAL,   -1, 1 }
+							,{  "State",				RULE_OPTIONAL,   -1, 1 }
+							,{  "Authorization-Lifetime",		RULE_OPTIONAL,   -1, 1 }
+							,{  "Auth-Grace-Period",		RULE_OPTIONAL,   -1, 1 }
+							,{  "Auth-Session-State",		RULE_OPTIONAL,   -1, 1 }
+							,{  "Callback-Number",			RULE_OPTIONAL,   -1, 1 }
+							,{  "Called-Station-Id",		RULE_OPTIONAL,   -1, 1 }
+							,{  "Calling-Station-Id",		RULE_OPTIONAL,   -1, 1 }
+							,{  "Originating-Line-Info",		RULE_OPTIONAL,   -1, 1 }
+							,{  "Connect-Info",			RULE_OPTIONAL,   -1, 1 }
+							,{  "Framed-Compression",		RULE_OPTIONAL,   -1,-1 }
+							,{  "Framed-Interface-Id",		RULE_OPTIONAL,   -1, 1 }
+							,{  "Framed-IP-Address",		RULE_OPTIONAL,   -1, 1 }
+							,{  "Framed-IPv6-Prefix",		RULE_OPTIONAL,   -1,-1 }
+							,{  "Framed-IP-Netmask",		RULE_OPTIONAL,   -1, 1 }
+							,{  "Framed-MTU",			RULE_OPTIONAL,   -1, 1 }
+							,{  "Framed-Protocol",			RULE_OPTIONAL,   -1, 1 }
+							,{  "Tunneling",			RULE_OPTIONAL,   -1,-1 }
+							,{  "Proxy-Info",			RULE_OPTIONAL,   -1,-1 }
+							,{  "Route-Record",			RULE_OPTIONAL,   -1,-1 }
+						};
+			
+			CHECK_dict_new( DICT_COMMAND, &data , eap, &cmd);
+			PARSE_loc_rules( rules, cmd );
+		}
+		
+		/* Diameter-EAP-Answer (DEA) Command */
+		{
+			/*
+				The Diameter-EAP-Answer (DEA) message, indicated by the Command-Code
+				field set to 268 and the 'R' bit cleared in the Command Flags field,
+				is sent by the Diameter server to the client for one of the following
+				reasons:
+
+				1.  The message is part of a multi-round authentication exchange, and
+				the server is expecting a subsequent Diameter-EAP-Request.  This
+				is indicated by setting the Result-Code to
+				DIAMETER_MULTI_ROUND_AUTH, and MAY include zero or more State
+				AVPs.
+
+				2.  The EAP client has been successfully authenticated and
+				authorized, in which case the message MUST include the
+				Result-Code AVP indicating success, and SHOULD include an
+				EAP-Payload of type EAP-Success.  This event MUST cause the
+				access device to provide service to the EAP client.
+
+				3.  The EAP client has not been successfully authenticated and/or
+				authorized, and the Result-Code AVP is set to indicate failure.
+				This message SHOULD include an EAP-Payload, but this AVP is not
+				used to determine whether service is to be provided.
+
+				If the message from the Diameter client included a request for
+				authorization, a successful response MUST include the authorization
+				AVPs that are relevant to the service being provided.
+
+				Message format
+
+				<Diameter-EAP-Answer> ::= < Diameter Header: 268, PXY >
+                        				< Session-Id >
+                        				{ Auth-Application-Id }
+                        				{ Auth-Request-Type }
+                        				{ Result-Code }
+                        				{ Origin-Host }
+                        				{ Origin-Realm }
+                        				[ User-Name ]
+                        				[ EAP-Payload ]
+                        				[ EAP-Reissued-Payload ]
+                        				[ EAP-Master-Session-Key ]
+                        				[ EAP-Key-Name ]
+                        				[ Multi-Round-Time-Out ]
+                        				[ Accounting-EAP-Auth-Method ]
+                        				[ Service-Type ]
+                				      * [ Class ]
+                				      * [ Configuration-Token ]
+                        				[ Acct-Interim-Interval ]
+                        				[ Error-Message ]
+                        				[ Error-Reporting-Host ]
+                				      * [ Failed-AVP ]
+                        				[ Idle-Timeout ]
+                        				[ Authorization-Lifetime ]
+                        				[ Auth-Grace-Period ]
+                        				[ Auth-Session-State ]
+                        				[ Re-Auth-Request-Type ]
+                        				[ Session-Timeout ]
+                        				[ State ]
+                				      * [ Reply-Message ]
+                        				[ Origin-State-Id ]
+                				      * [ Filter-Id ]
+                        				[ Port-Limit ]
+                        				[ Callback-Id ]
+                        				[ Callback-Number ]
+                        				[ Framed-Appletalk-Link ]
+                				      * [ Framed-Appletalk-Network ]
+                        				[ Framed-Appletalk-Zone ]
+                				      * [ Framed-Compression ]
+                        				[ Framed-Interface-Id ]
+                        				[ Framed-IP-Address ]
+                				      * [ Framed-IPv6-Prefix ]
+                        				[ Framed-IPv6-Pool ]
+                				      * [ Framed-IPv6-Route ]
+                        				[ Framed-IP-Netmask ]
+                				      * [ Framed-Route ]
+                        				[ Framed-Pool ]
+                        				[ Framed-IPX-Network ]
+                        				[ Framed-MTU ]
+                        				[ Framed-Protocol ]
+                        				[ Framed-Routing ]
+                				      * [ NAS-Filter-Rule ]
+                				      * [ QoS-Filter-Rule ]
+                				      * [ Tunneling ]
+                				      * [ Redirect-Host ]
+                        				[ Redirect-Host-Usage ]
+                        				[ Redirect-Max-Cache-Time ]
+                				      * [ Proxy-Info ]
+                				      * [ AVP ]
+			*/
+			struct dict_object * cmd;
+			struct dict_cmd_data data = { 
+					268, 					/* Code */
+					"Diameter-EAP-Answer", 			/* Name */
+					CMD_FLAG_REQUEST | CMD_FLAG_PROXIABLE,	/* Fixed flags */
+							   CMD_FLAG_PROXIABLE	/* Fixed flag values */
+					};
+			struct local_rules_definition rules[] = 
+						{ 	 {  "Session-Id", 			RULE_FIXED_HEAD, -1, 1 }
+						 	,{  "Auth-Application-Id", 		RULE_REQUIRED,   -1, 1 }
+						 	,{  "Auth-Request-Type", 		RULE_REQUIRED,   -1, 1 }
+						 	,{  "Result-Code", 			RULE_REQUIRED,   -1, 1 }
+						 	,{  "Origin-Host", 			RULE_REQUIRED,   -1, 1 }
+							,{  "Origin-Realm",			RULE_REQUIRED,   -1, 1 }
+							,{  "User-Name",			RULE_OPTIONAL,   -1, 1 }
+							,{  "EAP-Payload",			RULE_OPTIONAL,   -1, 1 }
+							,{  "EAP-Reissued-Payload",		RULE_OPTIONAL,   -1, 1 }
+							,{  "EAP-Master-Session-Key",		RULE_OPTIONAL,   -1, 1 }
+							,{  "EAP-Key-Name",			RULE_OPTIONAL,   -1, 1 }
+							,{  "Multi-Round-Time-Out",		RULE_OPTIONAL,   -1, 1 }
+							,{  "Accounting-EAP-Auth-Method",	RULE_OPTIONAL,   -1, 1 }
+							,{  "Service-Type",			RULE_OPTIONAL,   -1, 1 }
+							,{  "Class",				RULE_OPTIONAL,   -1,-1 }
+							,{  "Configuration-Token",		RULE_OPTIONAL,   -1,-1 }
+							,{  "Acct-Interim-Interval",		RULE_OPTIONAL,   -1, 1 }
+							,{  "Error-Message",			RULE_OPTIONAL,   -1, 1 }
+							,{  "Error-Reporting-Host",		RULE_OPTIONAL,   -1, 1 }
+							,{  "Failed-AVP",			RULE_OPTIONAL,   -1,-1 }
+							,{  "Idle-Timeout",			RULE_OPTIONAL,   -1, 1 }
+							,{  "Authorization-Lifetime",		RULE_OPTIONAL,   -1, 1 }
+							,{  "Auth-Grace-Period",		RULE_OPTIONAL,   -1, 1 }
+							,{  "Auth-Session-State",		RULE_OPTIONAL,   -1, 1 }
+							,{  "Re-Auth-Request-Type",		RULE_OPTIONAL,   -1, 1 }
+							,{  "Session-Timeout",			RULE_OPTIONAL,   -1, 1 }
+							,{  "State",				RULE_OPTIONAL,   -1, 1 }
+							,{  "Reply-Message",			RULE_OPTIONAL,   -1,-1 }
+							,{  "Origin-State-Id",			RULE_OPTIONAL,   -1, 1 }
+							,{  "Filter-Id",			RULE_OPTIONAL,   -1,-1 }
+							,{  "Port-Limit",			RULE_OPTIONAL,   -1, 1 }
+							,{  "Callback-Id",			RULE_OPTIONAL,   -1, 1 }
+							,{  "Callback-Number",			RULE_OPTIONAL,   -1, 1 }
+							,{  "Framed-AppleTalk-Link",		RULE_OPTIONAL,   -1, 1 }
+							,{  "Framed-AppleTalk-Network",		RULE_OPTIONAL,   -1,-1 }
+							,{  "Framed-AppleTalk-Zone",		RULE_OPTIONAL,   -1, 1 }
+							,{  "Framed-Compression",		RULE_OPTIONAL,   -1,-1 }
+							,{  "Framed-Interface-Id",		RULE_OPTIONAL,   -1, 1 }
+							,{  "Framed-IP-Address",		RULE_OPTIONAL,   -1, 1 }
+							,{  "Framed-IPv6-Prefix",		RULE_OPTIONAL,   -1,-1 }
+							,{  "Framed-IPv6-Pool",			RULE_OPTIONAL,   -1, 1 }
+							,{  "Framed-IPv6-Route",		RULE_OPTIONAL,   -1,-1 }
+							,{  "Framed-IP-Netmask",		RULE_OPTIONAL,   -1, 1 }
+							,{  "Framed-Route",			RULE_OPTIONAL,   -1,-1 }
+							,{  "Framed-Pool",			RULE_OPTIONAL,   -1, 1 }
+							,{  "Framed-IPX-Network",		RULE_OPTIONAL,   -1, 1 }
+							,{  "Framed-MTU",			RULE_OPTIONAL,   -1, 1 }
+							,{  "Framed-Protocol",			RULE_OPTIONAL,   -1, 1 }
+							,{  "Framed-Routing",			RULE_OPTIONAL,   -1, 1 }
+							,{  "NAS-Filter-Rule",			RULE_OPTIONAL,   -1,-1 }
+							,{  "QoS-Filter-Rule",			RULE_OPTIONAL,   -1,-1 }
+							,{  "Tunneling",			RULE_OPTIONAL,   -1,-1 }
+							,{  "Redirect-Host",			RULE_OPTIONAL,   -1,-1 }
+							,{  "Redirect-Host-Usage",		RULE_OPTIONAL,   -1, 1 }
+							,{  "Redirect-Max-Cache-Time",		RULE_OPTIONAL,   -1, 1 }
+							,{  "Proxy-Info",			RULE_OPTIONAL,   -1,-1 }
+						};
+			
+			CHECK_dict_new( DICT_COMMAND, &data , eap, &cmd);
+			PARSE_loc_rules( rules, cmd );
+		}
+		
+		/* Accounting-Request */
+		{
+			/*
+				Add additional rules of the ABNF (compared to Base definition):
+
+				Attribute Name                         | ACR | ACA |
+				---------------------------------------|-----+-----+
+				Accounting-EAP-Auth-Method             |  0+ |  0  |
+			*/
+			struct dict_object * cmd;
+			struct local_rules_definition rules[] = 
+						{ 	 {  "Accounting-EAP-Auth-Method",	RULE_OPTIONAL,   -1,-1 }
+						};
+			
+			CHECK_dict_search( DICT_COMMAND, CMD_BY_NAME, "Accounting-Request", &cmd);
+			PARSE_loc_rules( rules, cmd );
+		}
+		
+	}
+	
+	LOG_D( "Extension 'Dictionary definitions for EAP' initialized");
+	return 0;
+}
+
+EXTENSION_ENTRY("dict_eap", deap_entry, "dict_nasreq");
diff --git a/extensions/dict_etsi283034_avps/CMakeLists.txt b/extensions/dict_etsi283034_avps/CMakeLists.txt
new file mode 100644
index 0000000..9f4aa25
--- /dev/null
+++ b/extensions/dict_etsi283034_avps/CMakeLists.txt
@@ -0,0 +1,16 @@
+# The dict_etsi283034_avps extension
+PROJECT("dict_etsi283034_avps library generated by FdGen " C)
+
+# Compile as a module
+FD_ADD_EXTENSION(dict_etsi283034_avps dict_etsi283034_avps.c)
+
+
+####
+## INSTALL section ##
+
+INSTALL(TARGETS dict_etsi283034_avps
+	LIBRARY DESTINATION ${INSTALL_EXTENSIONS_SUFFIX}
+COMPONENT freeDiameter-dictionary-ETSI283034_AVPS)
+
+
+
diff --git a/extensions/dict_etsi283034_avps/dict_etsi283034_avps.c b/extensions/dict_etsi283034_avps/dict_etsi283034_avps.c
new file mode 100644
index 0000000..37d1221
--- /dev/null
+++ b/extensions/dict_etsi283034_avps/dict_etsi283034_avps.c
@@ -0,0 +1,250 @@
+/*
+* Copyright (c) 2017 Sprint
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*    http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+/****************
+ Generated By: fdtool enhancements to diafuzzer
+ License: same as freeDiameter
+****************/
+
+
+/* 
+ * Dictionary definitions of objects specified in etsi283034_avps.
+ */
+#include <freeDiameter/extension.h>
+
+#define PROTO_VER "unspecified"
+#define GEN_DATE  1506697184.91
+
+const char *etsi283034_avps_proto_ver = PROTO_VER;
+const double etsi283034_avps_gen_date = GEN_DATE;
+
+/* The content of this file follows the same structure as dict_base_proto.c */
+
+#define CHECK_dict_new( _type, _data, _parent, _ref )                                     \
+{                                                                                         \
+    int _ret = fd_dict_new( fd_g_config->cnf_dict, (_type), (_data), (_parent), (_ref) ); \
+    if ( _ret != 0 && _ret != EEXIST )                                                    \
+       return _ret;                                                                       \
+}
+
+#define CHECK_dict_search( _type, _criteria, _what, _result )		\
+    CHECK_FCT(  fd_dict_search( fd_g_config->cnf_dict, (_type), (_criteria), (_what), (_result), ENOENT) );
+
+struct local_rules_definition {
+    struct dict_avp_request avp_vendor_plus_name;
+    enum rule_position	position;
+    int 			min;
+    int			max;
+};
+
+#define RULE_ORDER( _position ) ((((_position) == RULE_FIXED_HEAD) || ((_position) == RULE_FIXED_TAIL)) ? 1 : 0 )
+
+/* Attention! This version of the macro uses AVP_BY_NAME_AND_VENDOR, in contrast to most other copies! */
+#define PARSE_loc_rules( _rulearray, _parent) {                                                         \
+        int __ar;                                                                                       \
+        for (__ar=0; __ar < sizeof(_rulearray) / sizeof((_rulearray)[0]); __ar++) {                     \
+                struct dict_rule_data __data = { NULL,                                                  \
+                        (_rulearray)[__ar].position,                                                    \
+                        0,                                                                              \
+                        (_rulearray)[__ar].min,                                                         \
+                        (_rulearray)[__ar].max};                                                        \
+                __data.rule_order = RULE_ORDER(__data.rule_position);                                   \
+                CHECK_FCT(  fd_dict_search(                                                             \
+                        fd_g_config->cnf_dict,                                                          \
+                        DICT_AVP,                                                                       \
+                        AVP_BY_NAME_AND_VENDOR,                                                         \
+                        &(_rulearray)[__ar].avp_vendor_plus_name,                                       \
+                        &__data.rule_avp, 0 ) );                                                        \
+                if ( !__data.rule_avp ) {                                                               \
+                        TRACE_DEBUG(INFO, "AVP Not found: '%s'", (_rulearray)[__ar].avp_vendor_plus_name.avp_name);             \
+                        return ENOENT;                                                                  \
+                }                                                                                       \
+                {                                                                                       \
+                         int _ret = fd_dict_new( fd_g_config->cnf_dict, DICT_RULE, &(__data), (_parent), NULL ); \
+                         if ( _ret != 0 && _ret != EEXIST )      {                                      \
+                                TRACE_DEBUG(INFO, "Error on rule with AVP '%s'",                        \
+                                            (_rulearray)[__ar].avp_vendor_plus_name.avp_name);          \
+                                return EINVAL;                                                          \
+                         }                                                                              \
+                }                                                                                       \
+        }                                                                                               \
+}
+
+#define CHECK_vendor_new( _data ) { \
+        struct dict_object * vendor_found; \
+        if (fd_dict_search(fd_g_config->cnf_dict,DICT_VENDOR,VENDOR_BY_ID,&_data.vendor_id,&vendor_found,ENOENT) == ENOENT) { \
+                CHECK_FCT(fd_dict_new(fd_g_config->cnf_dict, DICT_VENDOR, &_data, NULL, NULL)); \
+        } \
+}
+
+#define enumval_def_u32( _val_, _str_ )		\
+    { _str_, 		{ .u32 = _val_ }}
+
+#define enumval_def_os( _len_, _val_, _str_ )				\
+    { _str_, 		{ .os = { .data = (unsigned char *)_val_, .len = _len_ }}}
+
+
+static int dict_etsi283034_avps_load_defs(char * conffile)
+{
+   TRACE_ENTRY("%p", conffile);
+	/* Application Section */
+	{
+		/* Create the vendors */		{
+			struct dict_vendor_data vendor_data = { 13019, "ETSI" };
+			CHECK_dict_new(DICT_VENDOR, &vendor_data, NULL, NULL)
+		}
+	}
+
+
+   /* AVP section */
+   {
+		struct dict_object * Address_type;
+		struct dict_object * UTF8String_type;
+		struct dict_object * DiameterIdentity_type;
+		struct dict_object * DiameterURI_type;
+		struct dict_object * Time_type;
+		struct dict_object * IPFilterRule_type;
+
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "Address", &Address_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "UTF8String", &UTF8String_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "DiameterIdentity", &DiameterIdentity_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "DiameterURI", &DiameterURI_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "Time", &Time_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "IPFilterRule", &IPFilterRule_type);
+		/* Address-Realm */
+		{
+			struct dict_avp_data data = {
+				301,	/* Code */
+				13019,	/* Vendor */
+				"Address-Realm",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Logical-Access-Id */
+		{
+			struct dict_avp_data data = {
+				302,	/* Code */
+				13019,	/* Vendor */
+				"Logical-Access-Id",	/* Name */
+				AVP_FLAG_VENDOR,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Physical-Access-Id */
+		{
+			struct dict_avp_data data = {
+				303,	/* Code */
+				13019,	/* Vendor */
+				"Physical-Access-Id",	/* Name */
+				AVP_FLAG_VENDOR,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, UTF8String_type, NULL);
+		};
+		/* Line-Identifier */
+		{
+			struct dict_avp_data data = {
+				500,	/* Code */
+				13019,	/* Vendor */
+				"Line-Identifier",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, UTF8String_type, NULL);
+		};
+		/* Reservation-Priority */
+		{
+			struct dict_avp_data data = {
+				458,	/* Code */
+				13019,	/* Vendor */
+				"Reservation-Priority",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "ETSI/Enumerated(Reservation-Priority)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "PRIORITY_ONE", { .i32=1 }};
+			struct dict_enumval_data        t_2 = { "PRIORITY_TWO", { .i32=2 }};
+			struct dict_enumval_data        t_3 = { "PRIORITY_THREE", { .i32=3 }};
+			struct dict_enumval_data        t_4 = { "PRIORITY_FOUR", { .i32=4 }};
+			struct dict_enumval_data        t_5 = { "PRIORITY_FIVE", { .i32=5 }};
+			struct dict_enumval_data        t_6 = { "PRIORITY_SIX", { .i32=6 }};
+			struct dict_enumval_data        t_7 = { "PRIORITY_SEVEN", { .i32=7 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_3, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_4, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_5, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_6, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_7, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+
+	
+   }
+
+   /* Commands section */
+   {
+
+   }
+
+   return 0;
+}
+
+static int dict_etsi283034_avps_load_rules(char * conffile)
+{
+   /* Grouped AVP section */
+   {
+
+   }	
+
+   /* Commands section */
+   {
+
+   }
+
+   LOG_D( "Extension 'Dictionary definitions for etsi283034_avps (None)' initialized");
+   return 0;
+}
+
+int dict_entry(char * conffile)
+{
+	dict_etsi283034_avps_load_defs(conffile);
+	return dict_etsi283034_avps_load_rules(conffile);
+}
+
+const char* dict_etsi283034_avps_proto_ver(char * conffile) {
+	return etsi283034_avps_proto_ver;
+}
+
+const double dict_etsi283034_avps_gen_ts(char * conffile) {
+	return etsi283034_avps_gen_date;
+}
+
+EXTENSION_ENTRY2("dict_etsi283034_avps", dict_etsi283034_avps_load_defs, dict_etsi283034_avps_load_rules);
+
+
+
diff --git a/extensions/dict_etsi283034_avps/etsi283034_avps.did b/extensions/dict_etsi283034_avps/etsi283034_avps.did
new file mode 100644
index 0000000..f2e2c1f
--- /dev/null
+++ b/extensions/dict_etsi283034_avps/etsi283034_avps.did
@@ -0,0 +1 @@
+dict_etsi283034_avps
diff --git a/extensions/dict_legacy_xml/CMakeLists.txt b/extensions/dict_legacy_xml/CMakeLists.txt
new file mode 100644
index 0000000..561fbc5
--- /dev/null
+++ b/extensions/dict_legacy_xml/CMakeLists.txt
@@ -0,0 +1,35 @@
+# The dict_legacy_xml extension
+PROJECT("Legacy XML dictionary files support" C)
+
+# Parser files
+BISON_FILE(dict_lxml.y)
+FLEX_FILE(dict_lxml.l)
+SET_SOURCE_FILES_PROPERTIES(lex.dict_lxml.c dict_lxml.tab.c PROPERTIES COMPILE_FLAGS "-I ${CMAKE_CURRENT_SOURCE_DIR}")
+
+# We use LibXml2 (from GNOME) to parse XML files
+FIND_PACKAGE(LibXml2 REQUIRED)
+
+# List of source files
+SET( DICT_LXML_SRC
+	dict_lxml.c
+	dict_lxml_xml.c
+	dict_lxml.h
+	lex.dict_lxml.c
+	dict_lxml.tab.c
+	dict_lxml.tab.h
+)
+INCLUDE_DIRECTORIES(${CMAKE_CURRENT_BINARY_DIR})
+INCLUDE_DIRECTORIES(${LIBXML2_INCLUDE_DIR})
+
+# Compile these files as a freeDiameter extension
+FD_ADD_EXTENSION(dict_legacy_xml ${DICT_LXML_SRC})
+
+TARGET_LINK_LIBRARIES(dict_legacy_xml ${LIBXML2_LIBRARIES} )
+
+
+####
+## INSTALL section ##
+
+INSTALL(TARGETS dict_legacy_xml
+	LIBRARY DESTINATION ${INSTALL_EXTENSIONS_SUFFIX}
+	COMPONENT freeDiameter-dictionary-legacy)
diff --git a/extensions/dict_legacy_xml/dict_lxml.c b/extensions/dict_legacy_xml/dict_lxml.c
new file mode 100644
index 0000000..e4b8d8f
--- /dev/null
+++ b/extensions/dict_legacy_xml/dict_lxml.c
@@ -0,0 +1,54 @@
+/*********************************************************************************************************
+* Software License Agreement (BSD License)                                                               *
+* Author: Sebastien Decugis <sdecugis@freediameter.net>							 *
+*													 *
+* Copyright (c) 2011, WIDE Project and NICT								 *
+* All rights reserved.											 *
+* 													 *
+* Redistribution and use of this software in source and binary forms, with or without modification, are  *
+* permitted provided that the following conditions are met:						 *
+* 													 *
+* * Redistributions of source code must retain the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer.										 *
+*    													 *
+* * Redistributions in binary form must reproduce the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer in the documentation and/or other						 *
+*   materials provided with the distribution.								 *
+* 													 *
+* * Neither the name of the WIDE Project or NICT nor the 						 *
+*   names of its contributors may be used to endorse or 						 *
+*   promote products derived from this software without 						 *
+*   specific prior written permission of WIDE Project and 						 *
+*   NICT.												 *
+* 													 *
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED *
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
+* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR *
+* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 	 *
+* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 	 *
+* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR *
+* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF   *
+* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.								 *
+*********************************************************************************************************/
+
+/* 
+ * Legacy XML dictionary files support for freeDiameter.
+ */
+
+#include "dict_lxml.h"
+
+/* entry point */
+static int dict_lxml_entry(char * conffile)
+{
+	TRACE_ENTRY("%p", conffile);
+	
+	/* Parse the configuration file -- everything happens there */
+	CHECK_FCT( dict_lxml_handle(conffile) );
+	
+	/* We're done */
+	return 0;
+}
+
+EXTENSION_ENTRY("dict_legacy_xml", dict_lxml_entry);
diff --git a/extensions/dict_legacy_xml/dict_lxml.h b/extensions/dict_legacy_xml/dict_lxml.h
new file mode 100644
index 0000000..e862d62
--- /dev/null
+++ b/extensions/dict_legacy_xml/dict_lxml.h
@@ -0,0 +1,48 @@
+/*********************************************************************************************************
+* Software License Agreement (BSD License)                                                               *
+* Author: Sebastien Decugis <sdecugis@freediameter.net>							 *
+*													 *
+* Copyright (c) 2011, WIDE Project and NICT								 *
+* All rights reserved.											 *
+* 													 *
+* Redistribution and use of this software in source and binary forms, with or without modification, are  *
+* permitted provided that the following conditions are met:						 *
+* 													 *
+* * Redistributions of source code must retain the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer.										 *
+*    													 *
+* * Redistributions in binary form must reproduce the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer in the documentation and/or other						 *
+*   materials provided with the distribution.								 *
+* 													 *
+* * Neither the name of the WIDE Project or NICT nor the 						 *
+*   names of its contributors may be used to endorse or 						 *
+*   promote products derived from this software without 						 *
+*   specific prior written permission of WIDE Project and 						 *
+*   NICT.												 *
+* 													 *
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED *
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
+* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR *
+* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 	 *
+* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 	 *
+* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR *
+* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF   *
+* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.								 *
+*********************************************************************************************************/
+
+/* Header file for the dict_legacy_xml extension. 
+ *
+ *  See the dict_legacy_xml.conf.sample file for the format of the configuration file.
+ */
+ 
+/* FreeDiameter's common include file */
+#include <freeDiameter/extension.h>
+
+/* Parse the configuration file */
+int dict_lxml_handle(char * conffile);
+
+/* Parse an XML file and return the number of dictionary objects or -1 on error */
+int dict_lxml_parse(char * xmlfilename);
diff --git a/extensions/dict_legacy_xml/dict_lxml.l b/extensions/dict_legacy_xml/dict_lxml.l
new file mode 100644
index 0000000..fc612bb
--- /dev/null
+++ b/extensions/dict_legacy_xml/dict_lxml.l
@@ -0,0 +1,98 @@
+/*********************************************************************************************************
+* Software License Agreement (BSD License)                                                               *
+* Author: Sebastien Decugis <sdecugis@freediameter.net>							 *
+*													 *
+* Copyright (c) 2013, WIDE Project and NICT								 *
+* All rights reserved.											 *
+* 													 *
+* Redistribution and use of this software in source and binary forms, with or without modification, are  *
+* permitted provided that the following conditions are met:						 *
+* 													 *
+* * Redistributions of source code must retain the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer.										 *
+*    													 *
+* * Redistributions in binary form must reproduce the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer in the documentation and/or other						 *
+*   materials provided with the distribution.								 *
+* 													 *
+* * Neither the name of the WIDE Project or NICT nor the 						 *
+*   names of its contributors may be used to endorse or 						 *
+*   promote products derived from this software without 						 *
+*   specific prior written permission of WIDE Project and 						 *
+*   NICT.												 *
+* 													 *
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED *
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
+* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR *
+* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 	 *
+* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 	 *
+* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR *
+* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF   *
+* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.								 *
+*********************************************************************************************************/
+
+/* Tokenizer
+ *
+ */
+
+%{
+#include "dict_lxml.h"
+/* Include yacc tokens definitions */
+#include "dict_lxml.tab.h"
+
+/* Update the column information */
+#define YY_USER_ACTION { 						\
+	yylloc->first_column = yylloc->last_column + 1; 		\
+	yylloc->last_column = yylloc->first_column + yyleng - 1;	\
+}
+
+/* Avoid warning with newer flex */
+#define YY_NO_INPUT
+
+%}
+
+qstring		\"[^\"\n]*\"
+
+
+%option bison-bridge bison-locations
+%option noyywrap
+%option nounput
+
+%%
+
+	/* Update the line count */
+\n			{
+				yylloc->first_line++; 
+				yylloc->last_line++; 
+				yylloc->last_column=0; 
+			}
+	 
+	/* Eat all spaces but not new lines */
+([[:space:]]{-}[\n])+	;
+	/* Eat all comments */
+#.*$			;
+
+	/* Recognize quoted strings */
+{qstring}		{
+				/* Match a quoted string. */
+				CHECK_MALLOC_DO( yylval->string = strdup(yytext+1), 
+				{
+					TRACE_DEBUG(INFO, "Unable to copy the string '%s': %s", yytext, strerror(errno));
+					return LEX_ERROR; /* trig an error in yacc parser */
+				} );
+				yylval->string[strlen(yytext) - 2] = '\0';
+				return QSTRING;
+			}
+	
+	/* Valid single characters for yyparse */
+[;]			{ return yytext[0]; }
+
+	/* Unrecognized sequence, if it did not match any previous pattern */
+[^[:space:]\";\n]+	{ 
+				fd_log_debug("Unrecognized text on line %d col %d: '%s'.", yylloc->first_line, yylloc->first_column, yytext);
+			 	return LEX_ERROR; 
+			}
+
+%%
diff --git a/extensions/dict_legacy_xml/dict_lxml.y b/extensions/dict_legacy_xml/dict_lxml.y
new file mode 100644
index 0000000..4cafb4f
--- /dev/null
+++ b/extensions/dict_legacy_xml/dict_lxml.y
@@ -0,0 +1,141 @@
+/*********************************************************************************************************
+* Software License Agreement (BSD License)                                                               *
+* Author: Sebastien Decugis <sdecugis@freediameter.net>							 *
+*													 *
+* Copyright (c) 2013, WIDE Project and NICT								 *
+* All rights reserved.											 *
+* 													 *
+* Redistribution and use of this software in source and binary forms, with or without modification, are  *
+* permitted provided that the following conditions are met:						 *
+* 													 *
+* * Redistributions of source code must retain the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer.										 *
+*    													 *
+* * Redistributions in binary form must reproduce the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer in the documentation and/or other						 *
+*   materials provided with the distribution.								 *
+* 													 *
+* * Neither the name of the WIDE Project or NICT nor the 						 *
+*   names of its contributors may be used to endorse or 						 *
+*   promote products derived from this software without 						 *
+*   specific prior written permission of WIDE Project and 						 *
+*   NICT.												 *
+* 													 *
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED *
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
+* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR *
+* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 	 *
+* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 	 *
+* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR *
+* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF   *
+* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.								 *
+*********************************************************************************************************/
+
+/* Yacc extension's configuration parser.
+ * See doc/dict_legacy_xml.conf.sample for configuration file format
+ */
+
+/* For development only : */
+%debug 
+%error-verbose
+
+/* The parser receives the configuration file filename as parameter */
+%parse-param {char * conffile}
+
+/* Keep track of location */
+%locations 
+%pure-parser
+
+%{
+#include "dict_lxml.h"
+#include "dict_lxml.tab.h"	/* bison is not smart enough to define the YYLTYPE before including this code, so... */
+
+/* Forward declaration */
+int yyparse(char * conffile);
+
+static int nb_files = 0;
+static int nb_dict = 0;
+
+/* Parse the configuration file */
+int dict_lxml_handle(char * conffile)
+{
+	extern FILE * dict_lxmlin;
+	int ret;
+	
+	TRACE_ENTRY("%p", conffile);
+	
+	TRACE_DEBUG (FULL, "Parsing configuration file: %s...", conffile);
+	
+	dict_lxmlin = fopen(conffile, "r");
+	if (dict_lxmlin == NULL) {
+		ret = errno;
+		fd_log_debug("Unable to open extension configuration file %s for reading: %s", conffile, strerror(ret));
+		TRACE_DEBUG (INFO, "Error occurred, message logged -- configuration file.");
+		return ret;
+	}
+
+	ret = yyparse(conffile);
+
+	fclose(dict_lxmlin);
+
+	if (ret != 0) {
+		TRACE_DEBUG (INFO, "Unable to parse the configuration file.");
+		return EINVAL;
+	} else {
+		TRACE_DEBUG(FULL, "%d XML dictionary files parsed successfully, %d dictionary objects added.", nb_files, nb_dict);
+	}
+	
+	return 0;
+}
+
+/* The Lex parser prototype */
+int dict_lxmllex(YYSTYPE *lvalp, YYLTYPE *llocp);
+
+/* Function to report the errors */
+void yyerror (YYLTYPE *ploc, char * conffile, char const *s)
+{
+	TRACE_DEBUG(INFO, "Error in configuration parsing");
+	
+	if (ploc->first_line != ploc->last_line)
+		fd_log_debug("%s:%d.%d-%d.%d : %s", conffile, ploc->first_line, ploc->first_column, ploc->last_line, ploc->last_column, s);
+	else if (ploc->first_column != ploc->last_column)
+		fd_log_debug("%s:%d.%d-%d : %s", conffile, ploc->first_line, ploc->first_column, ploc->last_column, s);
+	else
+		fd_log_debug("%s:%d.%d : %s", conffile, ploc->first_line, ploc->first_column, s);
+}
+
+%}
+
+/* Values returned by lex for token */
+%union {
+	char 		*string;	/* The string is allocated by strdup in lex.*/
+}
+
+/* In case of error in the lexical analysis */
+%token 		LEX_ERROR
+
+/* A (de)quoted string (malloc'd in lex parser; it must be freed after use) */
+%token <string>	QSTRING
+
+/* -------------------------------------- */
+%%
+
+	/* The grammar definition */
+conffile:		/* empty grammar is OK */
+			| conffile xmlfile
+			;
+			
+	/* a RULE entry */
+xmlfile:		QSTRING ';'
+			{
+				int ret = dict_lxml_parse($1);
+				if (ret < 0) {
+					yyerror (&yylloc, conffile, "An error occurred while parsing a file, aborting...");
+					YYERROR;
+				}
+				nb_files++;
+				nb_dict += ret;
+			}
+			;
diff --git a/extensions/dict_legacy_xml/dict_lxml_xml.c b/extensions/dict_legacy_xml/dict_lxml_xml.c
new file mode 100644
index 0000000..748c43f
--- /dev/null
+++ b/extensions/dict_legacy_xml/dict_lxml_xml.c
@@ -0,0 +1,1816 @@
+/*********************************************************************************************************
+* Software License Agreement (BSD License)                                                               *
+* Author: Sebastien Decugis <sdecugis@freediameter.net>							 *
+*													 *
+* Copyright (c) 2013, WIDE Project and NICT								 *
+* All rights reserved.											 *
+* 													 *
+* Redistribution and use of this software in source and binary forms, with or without modification, are  *
+* permitted provided that the following conditions are met:						 *
+* 													 *
+* * Redistributions of source code must retain the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer.										 *
+*    													 *
+* * Redistributions in binary form must reproduce the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer in the documentation and/or other						 *
+*   materials provided with the distribution.								 *
+* 													 *
+* * Neither the name of the WIDE Project or NICT nor the 						 *
+*   names of its contributors may be used to endorse or 						 *
+*   promote products derived from this software without 						 *
+*   specific prior written permission of WIDE Project and 						 *
+*   NICT.												 *
+* 													 *
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED *
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
+* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR *
+* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 	 *
+* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 	 *
+* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR *
+* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF   *
+* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.								 *
+*********************************************************************************************************/
+
+#include "dict_lxml.h"
+
+/*
+The internal freeDiameter dictionary has strong dependency relations between
+the different objects, as follow:
+
+           vendor
+           /    \
+   application   \
+     /    \      |
+ command   \     |
+  |       type   |
+  |       /   \  |
+   \  enumval  \ | 
+    \          avp
+     \    _____/    
+      \  /
+      rule
+
+It means an AVP cannot be defined unless the parent TYPE has already been defined, 
+in turn depending on parent APPLICATION, etc. (top-to-bottom dependencies on the graph)
+
+On the other hand, the hierarchy of the XML format described in draft-frascone-xml-dictionary-00 
+does not enforce most of these dependencies, the structure is as follows:
+
+ vendor     application
+	   /     |     \
+      command    |     avp 
+	 /      type     \
+       rule	        enumval
+
+(in addition if DTD validation was performed, command and avp refer to vendor, avp refers to type, 
+but we do not do it for larger compatibility -- we just report when errors are found)
+
+As a consequence of this difference, it is impossible to parse the XML tree and create the dictionary objects in freeDiameter
+in only 1 pass. To avoid parsing the tree several times, we use a temporary structure in memory to contain all the data
+from the XML file, and when the parsing is complete we store all the objects in the dictionary. 
+*/
+
+/* We use the SAX interface of libxml2 (from GNOME) to parse the XML file. */ 
+#include <libxml/parser.h>
+
+/*******************************************/
+ /* Helper functions */
+static int xmltoint(xmlChar * xmlinteger, uint32_t * conv) {
+	TRACE_ENTRY("%p %p", xmlinteger, conv);
+	
+	/* Attempt at converting the string to an integer */
+	if (sscanf((char *)xmlinteger, "%u", conv) != 1) {
+		TRACE_DEBUG(INFO, "Unable to convert '%s' to integer.", (char *)xmlinteger)
+		return EINVAL;
+	}
+	
+	return 0;
+}
+
+
+/*******************************************
+ The temporary structure that is being built when the XML file is parsed 
+ *******************************************/
+
+/* VENDOR */
+struct t_vend {
+	struct fd_list 	chain; /* link in the t_dictionary->vendors */
+	uint32_t	id;
+	uint8_t *	name;
+};
+
+static int new_vendor(struct fd_list * parent, xmlChar * xmlid, xmlChar * xmlname) {
+	struct t_vend * new;
+	uint32_t id = 0;
+	
+	TRACE_ENTRY("%p %p %p", parent, xmlid, xmlname);
+	CHECK_PARAMS( parent && xmlid && xmlname );
+	
+	CHECK_FCT( xmltoint(xmlid, &id) );
+	
+	CHECK_MALLOC( new = malloc(sizeof(struct t_vend)) );
+	memset(new, 0, sizeof(struct t_vend));
+	fd_list_init(&new->chain, NULL);
+	new->id = id;
+	CHECK_MALLOC( new->name = (uint8_t *)strdup((char *)xmlname) );
+	
+	fd_list_insert_before(parent, &new->chain);
+	
+	return 0;
+}
+
+static void dump_vendor(struct t_vend * v) {
+	fd_log_debug(" Vendor %d:'%s'", v->id, (char *)v->name);
+}
+
+static void del_vendor_contents(struct t_vend * v) {
+	TRACE_ENTRY("%p", v);
+	free(v->name);
+}
+
+
+/* RULE */
+struct t_rule {
+	struct fd_list  chain;	/* link in either t_cmd or t_avp */
+	uint8_t *	avpname;
+	int		max;
+	int		min;
+};
+
+static int new_rule(struct fd_list * parent, xmlChar * xmlname, /* position is never used */ xmlChar * xmlmaximum, xmlChar * xmlminimum) {
+	struct t_rule * new;
+	uint32_t min, max;
+	
+	TRACE_ENTRY("%p %p %p %p", parent, xmlname, xmlmaximum, xmlminimum);
+	CHECK_PARAMS( parent && xmlname );
+	
+	CHECK_MALLOC( new = malloc(sizeof(struct t_rule)) );
+	memset(new, 0, sizeof(struct t_rule));
+	fd_list_init(&new->chain, NULL);
+	if (xmlminimum) {
+		CHECK_FCT( xmltoint(xmlminimum, &min) );
+		new->min = (int) min;
+	} else {
+		new->min = -1;
+	}
+	if (xmlmaximum) {
+		CHECK_FCT( xmltoint(xmlmaximum, &max) );
+		new->max = (int) max;
+	} else {
+		new->max = -1;
+	}
+	CHECK_MALLOC( new->avpname = (uint8_t *)strdup((char *)xmlname) );
+	
+	fd_list_insert_before(parent, &new->chain);
+	
+	return 0;
+}
+
+static void dump_rule(struct t_rule * r, char * prefix) {
+	fd_log_debug("%s ", prefix);
+	if (r->min != -1)
+		fd_log_debug("m:%d ", r->min);
+	if (r->max != -1)
+		fd_log_debug("M:%d ", r->max);
+	fd_log_debug("%s", (char *)r->avpname);
+}
+
+static void del_rule_contents(struct t_rule * r) {
+	TRACE_ENTRY("%p",r);
+	free(r->avpname);
+}
+
+
+/* COMMAND */
+struct t_cmd {
+	struct fd_list  chain;    /* link in t_appl->commands */
+	uint32_t	code;
+	uint8_t *	name;
+	uint8_t		flags;
+	uint8_t		fmask;
+	struct fd_list  reqrules_fixed;     /* list of t_rule */
+	struct fd_list  reqrules_required;  /* list of t_rule */
+	struct fd_list  reqrules_optional;  /* list of t_rule */
+	struct fd_list  ansrules_fixed;     /* list of t_rule */
+	struct fd_list  ansrules_required;  /* list of t_rule */
+	struct fd_list  ansrules_optional;  /* list of t_rule */
+};
+
+static int new_cmd(struct fd_list * parent, xmlChar * xmlcode, xmlChar * xmlname /*, ignore the vendor id because we don't use it */, xmlChar * xmlpbit, struct t_cmd **ret) {
+	struct t_cmd * new;
+	uint32_t code;
+	uint32_t flag = 0;
+	uint32_t fmask = 0;
+	
+	TRACE_ENTRY("%p %p %p %p", parent, xmlcode, xmlname, xmlpbit);
+	CHECK_PARAMS( parent && xmlcode && xmlname );
+	
+	CHECK_FCT( xmltoint(xmlcode, &code) );
+	
+	if (xmlpbit) {
+		uint32_t val;
+		CHECK_FCT( xmltoint(xmlpbit, &val) );
+		fmask |= CMD_FLAG_PROXIABLE;
+		if (val)
+			flag |= CMD_FLAG_PROXIABLE;
+	}
+	
+	CHECK_MALLOC( new = malloc(sizeof(struct t_cmd)) );
+	memset(new, 0, sizeof(struct t_cmd));
+	fd_list_init(&new->chain, NULL);
+	new->code = code;
+	CHECK_MALLOC( new->name = (uint8_t *)strdup((char *)xmlname) );
+	new->flags = flag;
+	new->fmask = fmask;
+	fd_list_init(&new->reqrules_fixed, NULL);
+	fd_list_init(&new->reqrules_required, NULL);
+	fd_list_init(&new->reqrules_optional, NULL);
+	fd_list_init(&new->ansrules_fixed, NULL);
+	fd_list_init(&new->ansrules_required, NULL);
+	fd_list_init(&new->ansrules_optional, NULL);
+	
+	fd_list_insert_before(parent, &new->chain);
+	
+	*ret = new;
+	
+	return 0;
+}
+
+static void dump_cmd(struct t_cmd * c) {
+	struct fd_list * li;
+	fd_log_debug("  Command %d %s: %s", c->code, 
+		c->fmask ? ( c->flags ? "[P=1]" : "[P=0]") : "", c->name);
+	for (li = c->reqrules_fixed.next; li != &c->reqrules_fixed; li = li->next)
+		dump_rule((struct t_rule *)li, "    Request fixed    AVP:");
+	for (li = c->reqrules_required.next; li != &c->reqrules_required; li = li->next)
+		dump_rule((struct t_rule *)li, "    Request required AVP:");
+	for (li = c->reqrules_optional.next; li != &c->reqrules_optional; li = li->next)
+		dump_rule((struct t_rule *)li, "    Request optional AVP:");
+	for (li = c->ansrules_fixed.next; li != &c->ansrules_fixed; li = li->next)
+		dump_rule((struct t_rule *)li, "    Answer fixed    AVP:");
+	for (li = c->ansrules_required.next; li != &c->ansrules_required; li = li->next)
+		dump_rule((struct t_rule *)li, "    Answer required AVP:");
+	for (li = c->ansrules_optional.next; li != &c->ansrules_optional; li = li->next)
+		dump_rule((struct t_rule *)li, "    Answer optional AVP:");
+}
+
+static void del_cmd_contents(struct t_cmd * c) {
+	TRACE_ENTRY("%p", c);
+	free(c->name);
+	while (!FD_IS_LIST_EMPTY(&c->reqrules_fixed)) {
+		struct fd_list * li = c->reqrules_fixed.next;
+		fd_list_unlink(li);
+		del_rule_contents((struct t_rule *)li);
+		free(li);
+	}
+	while (!FD_IS_LIST_EMPTY(&c->reqrules_required)) {
+		struct fd_list * li = c->reqrules_required.next;
+		fd_list_unlink(li);
+		del_rule_contents((struct t_rule *)li);
+		free(li);
+	}
+	while (!FD_IS_LIST_EMPTY(&c->reqrules_optional)) {
+		struct fd_list * li = c->reqrules_optional.next;
+		fd_list_unlink(li);
+		del_rule_contents((struct t_rule *)li);
+		free(li);
+	}
+	while (!FD_IS_LIST_EMPTY(&c->ansrules_fixed)) {
+		struct fd_list * li = c->ansrules_fixed.next;
+		fd_list_unlink(li);
+		del_rule_contents((struct t_rule *)li);
+		free(li);
+	}
+	while (!FD_IS_LIST_EMPTY(&c->ansrules_required)) {
+		struct fd_list * li = c->ansrules_required.next;
+		fd_list_unlink(li);
+		del_rule_contents((struct t_rule *)li);
+		free(li);
+	}
+	while (!FD_IS_LIST_EMPTY(&c->ansrules_optional)) {
+		struct fd_list * li = c->ansrules_optional.next;
+		fd_list_unlink(li);
+		del_rule_contents((struct t_rule *)li);
+		free(li);
+	}
+}
+
+/* TYPE */
+struct t_typedefn {
+	struct fd_list  chain;	/* link in t_appl->types */
+	uint8_t *	name;
+	uint8_t *	parent_name;
+};
+
+static int new_type(struct fd_list * parent, xmlChar * xmlname, xmlChar * xmlparent /*, xmlChar * xmldescription -- ignore */) {
+	struct t_typedefn * new;
+	
+	TRACE_ENTRY("%p %p %p", parent, xmlname, xmlparent);
+	CHECK_PARAMS( parent && xmlname );
+	
+	CHECK_MALLOC( new = malloc(sizeof(struct t_typedefn)) );
+	memset(new, 0, sizeof(struct t_typedefn));
+	fd_list_init(&new->chain, NULL);
+	CHECK_MALLOC( new->name = (uint8_t *)strdup((char *)xmlname) );
+	if (xmlparent) {
+		CHECK_MALLOC( new->parent_name = (uint8_t *)strdup((char *)xmlparent) );
+	}
+	
+	fd_list_insert_before(parent, &new->chain);
+	
+	return 0;
+}
+
+static void dump_type(struct t_typedefn * t) {
+	fd_log_debug("  Type %s%s%s%s", (char *)t->name,
+		     t->parent_name ? "(parent: " : "", 
+		     t->parent_name ? (char *)t->parent_name : "", 
+		     t->parent_name ? ")" : "");
+}
+
+static void del_type_contents(struct t_typedefn * t) {
+	TRACE_ENTRY("%p", t);
+	free(t->name);
+	free(t->parent_name);
+}
+	
+
+/* TYPE INSIDE AVP */
+struct t_avptype {
+	struct fd_list  chain;  /* link in t_avp->type */
+	uint8_t *	type_name;
+};
+
+static int new_avptype(struct fd_list * parent, xmlChar * xmlname) {
+	struct t_avptype * new;
+	
+	TRACE_ENTRY("%p %p", parent, xmlname);
+	CHECK_PARAMS( parent && xmlname );
+	
+	CHECK_MALLOC( new = malloc(sizeof(struct t_avptype)) );
+	memset(new, 0, sizeof(struct t_avptype));
+	fd_list_init(&new->chain, NULL);
+	CHECK_MALLOC( new->type_name = (uint8_t *)strdup((char *)xmlname) );
+	
+	fd_list_insert_before(parent, &new->chain);
+	
+	return 0;
+}
+
+static void dump_avptype(struct t_avptype * t) {
+	fd_log_debug("    data type: %s", t->type_name);
+}
+
+static void del_avptype_contents(struct t_avptype * t) {
+	TRACE_ENTRY("%p", t);
+	free(t->type_name);
+}
+	
+
+/* ENUM */
+struct t_enum {
+	struct fd_list  chain;  /* link in t_avp->enums */
+	uint32_t	code;
+	uint8_t *	name;
+};
+
+static int new_enum(struct fd_list * parent, xmlChar * xmlcode, xmlChar * xmlname) {
+	struct t_enum * new;
+	uint32_t code = 0;
+	
+	TRACE_ENTRY("%p %p %p", parent, xmlcode, xmlname);
+	CHECK_PARAMS( parent && xmlcode && xmlname );
+	
+	CHECK_FCT( xmltoint(xmlcode, &code) );
+	
+	CHECK_MALLOC( new = malloc(sizeof(struct t_enum)) );
+	memset(new, 0, sizeof(struct t_enum));
+	fd_list_init(&new->chain, NULL);
+	new->code = code;
+	CHECK_MALLOC( new->name = (uint8_t *)strdup((char *)xmlname) );
+	
+	fd_list_insert_before(parent, &new->chain);
+	
+	return 0;
+}
+
+static void dump_enum(struct t_enum * e) {
+	fd_log_debug("    Value: %d == %s", e->code, e->name);
+}	
+
+static void del_enum_contents(struct t_enum * e) {
+	TRACE_ENTRY("%p", e);
+	free(e->name);
+}
+
+/* AVP */
+struct t_avp {
+	struct fd_list  chain;  /* link in t_appl->avps */
+	uint32_t	code;
+	uint8_t *	name;
+	uint8_t		flags;
+	uint8_t		fmask;
+	uint32_t	vendor;
+	struct fd_list  type;             /* list of t_avptype -- there must be at max 1 item in the list */
+	struct fd_list  enums;            /* list of t_enum */
+	struct fd_list  grouped_fixed;    /* list of t_rule */
+	struct fd_list  grouped_required; /* list of t_rule */
+	struct fd_list  grouped_optional; /* list of t_rule */
+};
+
+static int new_avp(struct fd_list * parent, xmlChar * xmlcode, xmlChar * xmlname, xmlChar * xmlmandatory, xmlChar * xmlvendor, struct t_avp **ret) {
+	/* we ignore description, may-encrypt, protected, ... */
+	struct t_avp * new;
+	uint32_t code;
+	uint32_t vendor = 0;
+	uint32_t flag = 0;
+	uint32_t fmask = 0;
+	
+	TRACE_ENTRY("%p %p %p %p %p", parent, xmlcode, xmlname, xmlmandatory, xmlvendor);
+	CHECK_PARAMS( parent && xmlcode && xmlname );
+	
+	CHECK_FCT( xmltoint(xmlcode, &code) );
+	
+	if (xmlmandatory && !strcasecmp((char *)xmlmandatory, "must")) {
+		flag |= AVP_FLAG_MANDATORY;
+		fmask |= AVP_FLAG_MANDATORY;
+	}
+	
+	if (xmlvendor) {
+		CHECK_FCT( xmltoint(xmlvendor, &vendor) );
+		if (vendor)
+			flag |= AVP_FLAG_VENDOR;
+		fmask |= AVP_FLAG_VENDOR;
+	}
+	
+	CHECK_MALLOC( new = malloc(sizeof(struct t_avp)) );
+	memset(new, 0, sizeof(struct t_avp));
+	fd_list_init(&new->chain, NULL);
+	new->code = code;
+	CHECK_MALLOC( new->name = (uint8_t *)strdup((char *)xmlname) );
+	new->flags = flag;
+	new->fmask = fmask;
+	new->vendor= vendor; 
+	fd_list_init(&new->type, NULL);
+	fd_list_init(&new->enums, NULL);
+	fd_list_init(&new->grouped_fixed, NULL);
+	fd_list_init(&new->grouped_required, NULL);
+	fd_list_init(&new->grouped_optional, NULL);
+	
+	fd_list_insert_before(parent, &new->chain);
+	
+	*ret = new;
+	
+	return 0;
+}
+
+static void dump_avp(struct t_avp * a) {
+	struct fd_list * li;
+	fd_log_debug("  AVP %d %s%s: %s", a->code, 
+		a->fmask & AVP_FLAG_MANDATORY ? ( a->flags & AVP_FLAG_MANDATORY ? "[M=1]" : "[M=0]") : "", 
+		a->fmask & AVP_FLAG_VENDOR ? ( a->flags & AVP_FLAG_VENDOR ? "[V=1]" : "[V=0]") : "", 
+		a->name);
+	if (a->fmask & AVP_FLAG_VENDOR)
+		fd_log_debug("    vendor: %d", a->vendor);
+	for (li = a->type.next; li != &a->type; li = li->next)
+		dump_avptype((struct t_avptype *)li);
+	for (li = a->enums.next; li != &a->enums; li = li->next)
+		dump_enum((struct t_enum *)li);
+	for (li = a->grouped_fixed.next; li != &a->grouped_fixed; li = li->next)
+		dump_rule((struct t_rule *)li, "    Grouped, fixed    AVP:");
+	for (li = a->grouped_required.next; li != &a->grouped_required; li = li->next)
+		dump_rule((struct t_rule *)li, "    Grouped, required AVP:");
+	for (li = a->grouped_optional.next; li != &a->grouped_optional; li = li->next)
+		dump_rule((struct t_rule *)li, "    Grouped, optional AVP:");
+}
+
+static void del_avp_contents(struct t_avp * a) {
+	TRACE_ENTRY("%p", a);
+	free(a->name);
+	while (!FD_IS_LIST_EMPTY(&a->type)) {
+		struct fd_list * li = a->type.next;
+		fd_list_unlink(li);
+		del_avptype_contents((struct t_avptype *)li);
+		free(li);
+	}
+	while (!FD_IS_LIST_EMPTY(&a->enums)) {
+		struct fd_list * li = a->enums.next;
+		fd_list_unlink(li);
+		del_enum_contents((struct t_enum *)li);
+		free(li);
+	}
+	while (!FD_IS_LIST_EMPTY(&a->grouped_fixed)) {
+		struct fd_list * li = a->grouped_fixed.next;
+		fd_list_unlink(li);
+		del_rule_contents((struct t_rule *)li);
+		free(li);
+	}
+	while (!FD_IS_LIST_EMPTY(&a->grouped_required)) {
+		struct fd_list * li = a->grouped_required.next;
+		fd_list_unlink(li);
+		del_rule_contents((struct t_rule *)li);
+		free(li);
+	}
+	while (!FD_IS_LIST_EMPTY(&a->grouped_optional)) {
+		struct fd_list * li = a->grouped_optional.next;
+		fd_list_unlink(li);
+		del_rule_contents((struct t_rule *)li);
+		free(li);
+	}
+}
+
+
+/* APPLICATION */
+struct t_appl {
+	struct fd_list 	chain; /* link in the t_dictionary->base_and_applications, the sentinel corresponds to "base" */
+	uint32_t	id;
+	uint8_t *	name;
+	struct fd_list  commands; /* list of t_cmd */
+	struct fd_list	types;    /* list of t_typedefn */
+	struct fd_list  avps;     /* list of t_avp */
+};
+
+static int new_appl(struct fd_list * parent, xmlChar * xmlid, xmlChar * xmlname /* We ignore the URI */, struct t_appl **ret) {
+	struct t_appl * new;
+	uint32_t id = 0;
+	
+	TRACE_ENTRY("%p %p %p", parent, xmlid, xmlname);
+	CHECK_PARAMS( parent && xmlid && xmlname );
+	
+	CHECK_FCT( xmltoint(xmlid, &id) );
+	
+	CHECK_MALLOC( new = malloc(sizeof(struct t_appl)) );
+	memset(new, 0, sizeof(struct t_appl));
+	fd_list_init(&new->chain, NULL);
+	new->id = id;
+	CHECK_MALLOC( new->name = (uint8_t *)strdup((char *)xmlname) );
+	
+	fd_list_init(&new->commands, NULL);
+	fd_list_init(&new->types, NULL);
+	fd_list_init(&new->avps, NULL);
+	
+	fd_list_insert_before(parent, &new->chain);
+	
+	*ret = new;
+	
+	return 0;
+}
+
+static void dump_appl(struct t_appl * a) {
+	struct fd_list * li;
+	fd_log_debug(" Application %d: %s", a->id, a->name);
+	for (li = a->commands.next; li != &a->commands; li = li->next)
+		dump_cmd((struct t_cmd *)li);
+	for (li = a->types.next; li != &a->types; li = li->next)
+		dump_type((struct t_typedefn *)li);
+	for (li = a->avps.next; li != &a->avps; li = li->next)
+		dump_avp((struct t_avp *)li);
+}
+
+static void del_appl_contents(struct t_appl * a) {
+	TRACE_ENTRY("%p", a);
+	free(a->name);
+	while (!FD_IS_LIST_EMPTY(&a->commands)) {
+		struct fd_list * li = a->commands.next;
+		fd_list_unlink(li);
+		del_cmd_contents((struct t_cmd *)li);
+		free(li);
+	}
+	while (!FD_IS_LIST_EMPTY(&a->types)) {
+		struct fd_list * li = a->types.next;
+		fd_list_unlink(li);
+		del_type_contents((struct t_typedefn *)li);
+		free(li);
+	}
+	while (!FD_IS_LIST_EMPTY(&a->avps)) {
+		struct fd_list * li = a->avps.next;
+		fd_list_unlink(li);
+		del_avp_contents((struct t_avp *)li);
+		free(li);
+	}
+}
+
+/* DICTIONARY */	
+struct t_dictionary {
+	struct fd_list  vendors;
+	struct t_appl   base_and_applications;
+};
+
+static void dump_dict(struct t_dictionary * d) {
+	struct fd_list * li;
+	for (li = d->vendors.next; li != &d->vendors; li = li->next)
+		dump_vendor((struct t_vend *)li);
+	dump_appl(&d->base_and_applications);
+	for (li = d->base_and_applications.chain.next; li != &d->base_and_applications.chain; li = li->next)
+		dump_appl((struct t_appl *)li);
+}
+
+static void del_dict_contents(struct t_dictionary * d) {
+	TRACE_ENTRY("%p", d);
+	while (!FD_IS_LIST_EMPTY(&d->vendors)) {
+		struct fd_list * li = d->vendors.next;
+		fd_list_unlink(li);
+		del_vendor_contents((struct t_vend *)li);
+		free(li);
+	}
+	while (!FD_IS_LIST_EMPTY(&d->base_and_applications.chain)) {
+		struct fd_list * li = d->base_and_applications.chain.next;
+		fd_list_unlink(li);
+		del_appl_contents((struct t_appl *)li);
+		free(li);
+	}
+	d->base_and_applications.name = NULL;
+	del_appl_contents(&d->base_and_applications);
+}
+
+/*********************************************/
+	
+/* The states for the SAX parser, corresponding roughly to the expected structure of the XML file. 
+We use the states mostly to validate the XML file. */
+enum state {
+	INIT = 0,
+	START, /* In "dictionary" */
+	 IN_VENDOR,
+	 IN_APPLICATION,        /* note that "base" is equivalent to "application" for our state machine */
+	  IN_COMMAND,
+	   IN_REQRULES,
+	    IN_REQRULES_FIXED,
+	    IN_REQRULES_REQUIRED,
+	    IN_REQRULES_OPTIONAL,
+	   IN_ANSRULES,
+	    IN_ANSRULES_FIXED,
+	    IN_ANSRULES_REQUIRED,
+	    IN_ANSRULES_OPTIONAL,
+	  IN_TYPEDEFN,
+	  IN_AVP,
+	   IN_AVP_TYPE,
+	   IN_AVP_ENUM,
+	   IN_AVP_GROUPED,
+	    IN_AVP_GROUPED_FIXED,
+	    IN_AVP_GROUPED_REQUIRED,
+	    IN_AVP_GROUPED_OPTIONAL
+};
+
+
+/* The context passed to the SAX parser */
+struct parser_ctx {
+	enum state 		state; 	     /* the current state */
+	int        		error_depth; /* if non 0, we are in an unexpected element, wait until the count goes back to 0 to resume normal parsing. */
+	struct t_dictionary 	dict;        /* The dictionary being built */
+	struct t_appl *		cur_app;
+	struct t_cmd  *		cur_cmd;
+	struct t_avp  *		cur_avp;
+	char * 			xmlfilename; /* Name of the file, for error messages */
+};
+
+/* Find an attribute with given name in the list */
+static void get_attr(const xmlChar ** atts_array, const char * attr_name, xmlChar ** attr_val) {
+	int i;
+	*attr_val = NULL;
+	if (atts_array == NULL)
+		return;
+	for (i=0; atts_array[i] != NULL; i+=2) {
+		if (!strcasecmp((char *)atts_array[i], attr_name)) {
+			/* found */
+			*attr_val = (xmlChar *)atts_array[i+1];
+			return;
+		}
+	}
+	/* not found */
+	return;
+}
+
+/* The following macro avoids duplicating a lot of code in the state machine */
+#define ADD_RULE( _parent_list ) { 				\
+	xmlChar *xname, *xmin, *xmax;				\
+	/* We are expecting an <avprule> tag at this point */	\
+	if (strcasecmp((char *)name, "avprule"))		\
+		goto xml_tree_error;				\
+	/* Search the expected attributes */			\
+	get_attr(atts, "name", &xname);				\
+	get_attr(atts, "maximum", &xmax);			\
+	get_attr(atts, "minimum", &xmin);			\
+	/* Check the mandatory name is here */			\
+	CHECK_PARAMS_DO(xname, 					\
+		{ TRACE_DEBUG(INFO, "Invalid 'avprule' tag found without 'name' attribute."); goto xml_tree_error; } );	\
+	/* Create the rule and add into the parent list */	\
+	CHECK_FCT_DO( new_rule((_parent_list), xname, xmax, xmin),\
+		{ TRACE_DEBUG(INFO, "An error occurred while parsing an avprule tag. Entry ignored."); goto xml_tree_error; } ); \
+	/* Done. we don't change the state */			\
+}
+	
+	
+/* The function called on each XML element start tag (startElementSAXFunc) */
+static void SAXstartelem (void * ctx, const xmlChar * name, const xmlChar ** atts)
+{
+	struct parser_ctx * data = ctx;
+	TRACE_ENTRY("%p %p %p", ctx, name, atts);
+	CHECK_PARAMS_DO( ctx && name, { return; } );
+	
+	TRACE_DEBUG(CALL, "Tag: <%s>", (char *)name);
+	
+	if (data->error_depth) /* we are in an unknown element, just skip until it is closed */
+		goto xml_tree_error;
+	
+	switch (data->state) {
+		case INIT: /* we are just starting. We only expect a <dictionary> tag, reject anything else. */
+			if (strcasecmp((char *)name, "dictionary"))
+				goto xml_tree_error;
+			
+			data->state = START;
+			break;
+			
+		case START: 
+			/* We are in <dictionary> 
+				Valid tags are: <vendor>, <base>, <application> */
+			if (!strcasecmp((char *)name, "vendor")) {
+				xmlChar *xid, *xname;
+				
+				get_attr(atts, "id", &xid);
+				get_attr(atts, "name", &xname);
+				
+				/* id and name are required */
+				CHECK_PARAMS_DO(xid && xname, 
+					{ TRACE_DEBUG(INFO, "Invalid 'vendor' tag found without 'id' or 'name' attribute."); goto xml_tree_error; } );
+				
+				
+				CHECK_FCT_DO( new_vendor(&data->dict.vendors, xid, xname),
+					{ TRACE_DEBUG(INFO, "An error occurred while parsing a vendor tag. Entry ignored."); goto xml_tree_error; } )
+				
+				data->state = IN_VENDOR;
+				break;
+			}
+			
+			if (!strcasecmp((char *)name, "base")) {
+				/* we don't care for the 'uri' attribute */
+				data->cur_app = &data->dict.base_and_applications;
+				data->state = IN_APPLICATION;
+				break;
+			}
+			
+			if (!strcasecmp((char *)name, "application")) {
+				/* we don't care for the 'uri' attribute */
+				xmlChar *xid, *xname;
+				char buf[50];
+				
+				get_attr(atts, "id", &xid);
+				get_attr(atts, "name", &xname);
+				
+				CHECK_PARAMS_DO(xid, 
+					{ TRACE_DEBUG(INFO, "Invalid 'application' tag found without 'id' attribute."); goto xml_tree_error; } );
+				
+				/* Name is optional, if not provided we create a name */
+				if (!xname) {
+					snprintf(buf, sizeof(buf), "Application %s", xid);
+					xname = (xmlChar *)buf;
+				}
+				
+				CHECK_FCT_DO( new_appl(&data->dict.base_and_applications.chain, xid, xname, &data->cur_app),
+					{ TRACE_DEBUG(INFO, "An error occurred while parsing an application tag. Entry ignored."); goto xml_tree_error; } )
+				
+				data->state = IN_APPLICATION;
+				break;
+			}
+			
+			/* Other tags are errors */
+			goto xml_tree_error;
+			
+			
+		case IN_VENDOR: /* nothing is allowed inside <vendor> */
+			goto xml_tree_error;
+				
+		case IN_APPLICATION: 
+			/* We are in <base> or <application>
+				Valid tags are: <command>, <typedefn>, <avp> */
+			if (!strcasecmp((char *)name, "command")) {
+				/* we don't care for the 'vendor-id' attribute. */
+				xmlChar *xcode, *xname, *xpbit;
+				
+				get_attr(atts, "code", &xcode);
+				get_attr(atts, "name", &xname);
+				get_attr(atts, "pbit", &xpbit);
+				
+				/* code and name are required */
+				CHECK_PARAMS_DO(xcode && xname, 
+					{ TRACE_DEBUG(INFO, "Invalid 'command' tag found without 'code' or 'name' attribute."); goto xml_tree_error; } );
+				
+				CHECK_FCT_DO( new_cmd( &data->cur_app->commands, xcode, xname, xpbit, &data->cur_cmd),
+					{ TRACE_DEBUG(INFO, "An error occurred while parsing a command tag. Entry ignored."); goto xml_tree_error; } )
+				
+				data->state = IN_COMMAND;
+				break;
+			}
+			
+			if (!strcasecmp((char *)name, "typedefn")) {
+				/* we don't care for the 'description' attribute. */
+				xmlChar *xname, *xparent;
+				
+				get_attr(atts, "type-name", &xname);
+				get_attr(atts, "type-parent", &xparent);
+				
+				/* name is required */
+				CHECK_PARAMS_DO(xname, 
+					{ TRACE_DEBUG(INFO, "Invalid 'typedefn' tag found without 'name' attribute."); goto xml_tree_error; } );
+				
+				CHECK_FCT_DO( new_type( &data->cur_app->types, xname, xparent),
+					{ TRACE_DEBUG(INFO, "An error occurred while parsing a typedefn tag. Entry ignored."); goto xml_tree_error; } )
+				
+				data->state = IN_TYPEDEFN;
+				break;
+			}
+			
+			if (!strcasecmp((char *)name, "avp")) {
+				/* we don't care for the description, may-encrypt, and protected attributes */
+				xmlChar *xname, *xcode, *xmandatory, *xvendor;
+				
+				get_attr(atts, "name", &xname);
+				get_attr(atts, "code", &xcode);
+				get_attr(atts, "mandatory", &xmandatory);
+				get_attr(atts, "vendor-id", &xvendor);
+				
+				/* code and name are required */
+				CHECK_PARAMS_DO(xcode && xname, 
+					{ TRACE_DEBUG(INFO, "Invalid 'avp' tag found without 'code' or 'name' attribute."); goto xml_tree_error; } );
+				
+				CHECK_FCT_DO( new_avp(&data->cur_app->avps, xcode, xname, xmandatory, xvendor, &data->cur_avp),
+					{ TRACE_DEBUG(INFO, "An error occurred while parsing an avp tag. Entry ignored."); goto xml_tree_error; } )
+				
+				data->state = IN_AVP;
+				break;
+			}
+			/* Other tags are errors */
+			goto xml_tree_error;
+		
+			
+		case IN_COMMAND: 
+			/* We are in <command>
+				Valid tags are: <requestrules>, <answerrules> */
+			if (!strcasecmp((char *)name, "requestrules")) {
+				data->state = IN_REQRULES;
+				break;
+			}
+			if (!strcasecmp((char *)name, "answerrules")) {
+				data->state = IN_ANSRULES;
+				break;
+			}
+			/* Other tags are errors */
+			goto xml_tree_error;
+		
+		case IN_REQRULES: 
+			/* We are in <requestrules>
+				Valid tags are: <fixed>, <required>, <optional> */
+			if (!strcasecmp((char *)name, "fixed")) {
+				data->state = IN_REQRULES_FIXED;
+				break;
+			}
+			if (!strcasecmp((char *)name, "required")) {
+				data->state = IN_REQRULES_REQUIRED;
+				break;
+			}
+			if (!strcasecmp((char *)name, "optional")) {
+				data->state = IN_REQRULES_OPTIONAL;
+				break;
+			}
+			/* Other tags are errors */
+			goto xml_tree_error;
+		
+		case IN_ANSRULES: 
+			/* We are in <answerrules>
+				Valid tags are: <fixed>, <required>, <optional> */
+			if (!strcasecmp((char *)name, "fixed")) {
+				data->state = IN_ANSRULES_FIXED;
+				break;
+			}
+			if (!strcasecmp((char *)name, "required")) {
+				data->state = IN_ANSRULES_REQUIRED;
+				break;
+			}
+			if (!strcasecmp((char *)name, "optional")) {
+				data->state = IN_ANSRULES_OPTIONAL;
+				break;
+			}
+			/* Other tags are errors */
+			goto xml_tree_error;
+			
+		case IN_REQRULES_FIXED:
+			/* We are in <command><answerrules><fixed>
+				Valid tags are: <avprule> */
+			ADD_RULE( &data->cur_cmd->reqrules_fixed );
+			break;
+		case IN_REQRULES_REQUIRED:
+			ADD_RULE( &data->cur_cmd->reqrules_required );
+			break;
+		case IN_REQRULES_OPTIONAL:
+			ADD_RULE( &data->cur_cmd->reqrules_optional );
+			break;
+		case IN_ANSRULES_FIXED:
+			ADD_RULE( &data->cur_cmd->ansrules_fixed );
+			break;
+		case IN_ANSRULES_REQUIRED:
+			ADD_RULE( &data->cur_cmd->ansrules_required );
+			break;
+		case IN_ANSRULES_OPTIONAL:
+			ADD_RULE( &data->cur_cmd->ansrules_optional );
+			break;
+			
+		
+		case IN_TYPEDEFN: /* nothing is allowed inside <typedefn> */
+			goto xml_tree_error;
+				
+		
+		case IN_AVP: 
+			/* We are in <avp>
+				Valid tags are: <type>, <enum>, <grouped> */
+			if (!strcasecmp((char *)name, "type")) {
+				xmlChar *xname;
+				
+				get_attr(atts, "type-name", &xname);
+				
+				/* name is required */
+				CHECK_PARAMS_DO(xname, 
+					{ TRACE_DEBUG(INFO, "Invalid 'type' tag found without 'name' attribute."); goto xml_tree_error; } );
+				
+				/* Check there is only 1 type */
+				if (!FD_IS_LIST_EMPTY(&data->cur_avp->type)) {
+					TRACE_DEBUG(INFO, "Multiple 'type' tags found for AVP.");
+					goto xml_tree_error;
+				}
+				
+				/* Add the new type */
+				CHECK_FCT_DO( new_avptype(&data->cur_avp->type, xname),
+					{ TRACE_DEBUG(INFO, "An error occurred while parsing a type tag. Entry ignored."); goto xml_tree_error; } )
+				
+				data->state = IN_AVP_TYPE;
+				break;
+			}
+			if (!strcasecmp((char *)name, "enum")) {
+				xmlChar *xcode, *xname;
+				
+				get_attr(atts, "code", &xcode);
+				get_attr(atts, "name", &xname);
+				
+				/* code and name are required */
+				CHECK_PARAMS_DO(xcode && xname, 
+					{ TRACE_DEBUG(INFO, "Invalid 'enum' tag found without 'code' or 'name' attribute."); goto xml_tree_error; } );
+				
+				CHECK_FCT_DO( new_enum(&data->cur_avp->enums, xcode, xname),
+					{ TRACE_DEBUG(INFO, "An error occurred while parsing a command tag. Entry ignored."); goto xml_tree_error; } )
+			
+				data->state = IN_AVP_ENUM;
+				break;
+			}
+			if (!strcasecmp((char *)name, "grouped")) {
+				/* no attribute for this one */
+				data->state = IN_AVP_GROUPED;
+				break;
+			}
+			/* Other tags are errors */
+			goto xml_tree_error;
+		
+		case IN_AVP_TYPE: /* nothing is allowed inside <type> */
+			goto xml_tree_error;
+			
+		case IN_AVP_ENUM: /* nothing is allowed inside <enum> */
+			goto xml_tree_error;
+			
+		case IN_AVP_GROUPED: 
+			/* We are in <avp><grouped>
+				Valid tags are: <fixed>, <required>, <optional> */
+			if (!strcasecmp((char *)name, "fixed")) {
+				data->state = IN_AVP_GROUPED_FIXED;
+				break;
+			}
+			if (!strcasecmp((char *)name, "required")) {
+				data->state = IN_AVP_GROUPED_REQUIRED;
+				break;
+			}
+			if (!strcasecmp((char *)name, "optional")) {
+				data->state = IN_AVP_GROUPED_OPTIONAL;
+				break;
+			}
+			/* Other tags are errors */
+			goto xml_tree_error;
+			
+		case IN_AVP_GROUPED_FIXED:
+			/* We are in <avp><grouped><fixed>
+				Valid tags are: <avprule> */
+			ADD_RULE( &data->cur_avp->grouped_fixed );
+			break;
+		case IN_AVP_GROUPED_REQUIRED:
+			ADD_RULE( &data->cur_avp->grouped_required );
+			break;
+		case IN_AVP_GROUPED_OPTIONAL:
+			ADD_RULE( &data->cur_avp->grouped_optional );
+			break;
+		
+			
+		default:
+			TRACE_DEBUG(INFO, "Internal parsing error, unexpected state %d.", data->state);
+	}
+	
+	return;
+	
+xml_tree_error:
+	if (!data->error_depth) {
+		TRACE_DEBUG(INFO, "Unexpected XML element found: '%s'. Ignoring...", name);
+	}
+	data->error_depth += 1;
+	if (data->cur_app || data->cur_cmd || data->cur_avp) {
+		TRACE_DEBUG(INFO, "Error encountered while parsing tag of:");
+		if (data->cur_app)
+			fd_log_debug("  Application: '%s'", data->cur_app->name);
+		if (data->cur_cmd)
+			fd_log_debug("  Command    : '%s'", data->cur_cmd->name);
+		if (data->cur_avp)
+			fd_log_debug("  AVP        : '%s'", data->cur_avp->name);
+	}
+	return;
+}
+
+/* The function called on each XML element end tag (endElementSAXFunc) */
+static void SAXendelem (void * ctx, const xmlChar * name)
+{
+	struct parser_ctx * data = ctx;
+	TRACE_ENTRY("%p %p", ctx, name);
+	CHECK_PARAMS_DO( ctx && name, { return; } );
+	
+	TRACE_DEBUG(CALL, "Tag: </%s>", (char *)name);
+	
+	if (data->error_depth) {
+		/* we are recovering from an erroneous element */
+		data->error_depth -= 1;
+		return;
+	}
+	
+	switch (data->state) {
+		case INIT: 
+			goto state_machine_error;
+			
+		case START:
+			if (strcasecmp((char *)name, "dictionary"))
+				goto state_machine_error;
+			
+			data->state = 0;
+			break;
+		
+		case IN_VENDOR:
+			if (strcasecmp((char *)name, "vendor"))
+				goto state_machine_error;
+			
+			data->state = START;
+			break;
+		
+		case IN_APPLICATION:
+			if (strcasecmp((char *)name, "base") && strcasecmp((char *)name, "application"))
+				goto state_machine_error;
+			
+			data->cur_app = NULL;
+			data->state = START;
+			break;
+		
+		case IN_COMMAND:
+			if (strcasecmp((char *)name, "command"))
+				goto state_machine_error;
+			
+			data->cur_cmd = NULL;
+			data->state = IN_APPLICATION;
+			break;
+			
+		case IN_REQRULES:
+			if (strcasecmp((char *)name, "requestrules"))
+				goto state_machine_error;
+			
+			data->state = IN_COMMAND;
+			break;
+		
+		case IN_REQRULES_FIXED:
+			if (!strcasecmp((char *)name, "avprule"))
+				/* we don't have a special state for these, just ignore */
+				return;
+			if (strcasecmp((char *)name, "fixed"))
+				goto state_machine_error;
+			data->state = IN_REQRULES;
+			break;
+		case IN_REQRULES_REQUIRED:
+			if (!strcasecmp((char *)name, "avprule"))
+				/* we don't have a special state for these, just ignore */
+				return;
+			if (strcasecmp((char *)name, "required"))
+				goto state_machine_error;
+			data->state = IN_REQRULES;
+			break;
+		case IN_REQRULES_OPTIONAL:
+			if (!strcasecmp((char *)name, "avprule"))
+				/* we don't have a special state for these, just ignore */
+				return;
+			if (strcasecmp((char *)name, "optional"))
+				goto state_machine_error;
+			data->state = IN_REQRULES;
+			break;
+			
+		case IN_ANSRULES: 
+			if (strcasecmp((char *)name, "answerrules"))
+				goto state_machine_error;
+			
+			data->state = IN_COMMAND;
+			break;			
+		case IN_ANSRULES_FIXED:
+			if (!strcasecmp((char *)name, "avprule"))
+				/* we don't have a special state for these, just ignore */
+				return;
+			if (strcasecmp((char *)name, "fixed"))
+				goto state_machine_error;
+			data->state = IN_ANSRULES;
+			break;
+		case IN_ANSRULES_REQUIRED:
+			if (!strcasecmp((char *)name, "avprule"))
+				/* we don't have a special state for these, just ignore */
+				return;
+			if (strcasecmp((char *)name, "required"))
+				goto state_machine_error;
+			data->state = IN_ANSRULES;
+			break;
+		case IN_ANSRULES_OPTIONAL:
+			if (!strcasecmp((char *)name, "avprule"))
+				/* we don't have a special state for these, just ignore */
+				return;
+			if (strcasecmp((char *)name, "optional"))
+				goto state_machine_error;
+			data->state = IN_ANSRULES;
+			break;
+		
+		
+		case IN_TYPEDEFN:
+			if (strcasecmp((char *)name, "typedefn"))
+				goto state_machine_error;
+			
+			data->state = IN_APPLICATION;
+			break;
+		
+		case IN_AVP: 
+			if (strcasecmp((char *)name, "avp"))
+				goto state_machine_error;
+			
+			data->cur_avp = NULL;
+			data->state = IN_APPLICATION;
+			break;
+		
+		case IN_AVP_TYPE:
+			if (strcasecmp((char *)name, "type"))
+				goto state_machine_error;
+			
+			data->state = IN_AVP;
+			break;
+		
+		case IN_AVP_ENUM:
+			if (strcasecmp((char *)name, "enum"))
+				goto state_machine_error;
+			
+			data->state = IN_AVP;
+			break;
+		
+		case IN_AVP_GROUPED:
+			if (strcasecmp((char *)name, "grouped"))
+				goto state_machine_error;
+			
+			data->state = IN_AVP;
+			break;
+		
+		case IN_AVP_GROUPED_FIXED:
+			if (!strcasecmp((char *)name, "avprule"))
+				/* we don't have a special state for these, just ignore */
+				return;
+			if (strcasecmp((char *)name, "fixed"))
+				goto state_machine_error;
+			data->state = IN_AVP_GROUPED;
+			break;
+		case IN_AVP_GROUPED_REQUIRED:
+			if (!strcasecmp((char *)name, "avprule"))
+				return;
+			if (strcasecmp((char *)name, "required"))
+				goto state_machine_error;
+			data->state = IN_AVP_GROUPED;
+			break;
+		case IN_AVP_GROUPED_OPTIONAL:
+			if (!strcasecmp((char *)name, "avprule"))
+				return;
+			if (strcasecmp((char *)name, "optional"))
+				goto state_machine_error;
+			data->state = IN_AVP_GROUPED;
+			break;
+			
+		default:
+			TRACE_DEBUG(INFO, "Internal parsing error, unexpected state %d.", data->state);
+	}
+	
+	return;
+	
+state_machine_error:
+	TRACE_DEBUG(INFO, "Internal parsing error, ignored [state %d, closing tag '%s'].", data->state, name);
+	return;
+}
+
+/* The SAX parser sends a warning, error, fatalerror -- do we need these ?
+static void SAXwarning (void * ctx, const char * msg, ...)
+{
+
+}
+static void SAXerror (void * ctx, const char * msg, ...)
+{
+
+}
+static void SAXfatal (void * ctx, const char * msg, ...)
+{
+
+}
+*/
+
+
+
+
+/*********************************************/
+ /* 2nd pass: from memory to fD dictionary */
+/*********************************************/
+
+/* Find or create a vendor */
+static int vend_to_fD(struct t_vend * v, struct dictionary * fD_dict, struct dict_object ** fd_v, int * nb_added)
+{
+	int ret;
+	struct dict_object * prev = NULL;
+	struct dict_vendor_data vd;
+
+	TRACE_ENTRY("%p %p %p %p", v, fD_dict, fd_v, nb_added);
+	
+	CHECK_PARAMS(v && fD_dict);
+	
+	/* Prepare the data in fD's format */
+	memset(&vd, 0, sizeof(vd));
+	vd.vendor_id   = v->id;
+	vd.vendor_name = (char *)v->name;
+	
+	/* Create or search in the dictionary */
+	ret = fd_dict_new ( fD_dict, DICT_VENDOR, &vd, NULL, &prev );
+	if (fd_v)
+		*fd_v = prev;
+	if (ret == EEXIST) {
+		/* Conflict with existing entry */
+		CHECK_FCT( fd_dict_getval(prev, &vd) );
+		TRACE_DEBUG(INFO, "[dict_legacy_xml] Warning: Conflicting entry.");
+		TRACE_DEBUG(INFO, "[dict_legacy_xml]   New entry (ignored): %u - '%s'", v->id, (char *)v->name);
+		TRACE_DEBUG(INFO, "[dict_legacy_xml]   Old entry          : %u - '%s'", vd.vendor_id, vd.vendor_name);
+		return 0;
+	} else {
+		/* other errors are stoppers */
+		CHECK_FCT(ret);
+	}
+	
+	/* Update count */
+	if (nb_added)
+		*nb_added += 1;
+	
+	/* Done */
+	return 0;
+}
+
+/* Find the base fD type from a type name */
+static int resolve_base_type(struct dictionary * fD_dict, uint8_t * type_name, enum dict_avp_basetype * basetype, struct dict_object **type)
+{
+	int ret;
+	struct dict_type_data td;
+	struct dict_object *t;
+	
+	TRACE_ENTRY("%p, %p %p", fD_dict, type_name, basetype);
+	CHECK_PARAMS( fD_dict && type_name && basetype );
+	
+	/* First, check if the type is already in the dictionary */
+	ret = fd_dict_search ( fD_dict, DICT_TYPE, TYPE_BY_NAME, type_name, &t, ENOENT);
+	switch (ret) {
+		case 0: /* the type is already in the dictionary */
+			CHECK_FCT( fd_dict_getval(t, &td) );
+			*basetype = td.type_base;
+			if (type)
+				*type = t;
+			return 0;
+		
+		case ENOENT: /* We did not find it, it is maybe normal */
+			break;
+			
+		default:
+			/* An unexpected error occurred */
+			CHECK_FCT(ret);
+	}
+	
+	/* at this point we did not find the type in the dictionary */
+#define PREDEF_TYPES( _typename_, _basetype_ )			\
+	if (!strcasecmp((char *)type_name, (_typename_))) {	\
+		*basetype = (_basetype_);			\
+		return 0;					\
+	}
+	
+	PREDEF_TYPES( "OctetString", AVP_TYPE_OCTETSTRING );
+	PREDEF_TYPES( "Integer32",   AVP_TYPE_INTEGER32   );
+	PREDEF_TYPES( "Integer64",   AVP_TYPE_INTEGER64   );
+	PREDEF_TYPES( "Unsigned32",  AVP_TYPE_UNSIGNED32  );
+	PREDEF_TYPES( "Enumerated",  AVP_TYPE_INTEGER32  );
+	PREDEF_TYPES( "Unsigned64",  AVP_TYPE_UNSIGNED64  );
+	PREDEF_TYPES( "Float32",     AVP_TYPE_FLOAT32     );
+	PREDEF_TYPES( "Float64",     AVP_TYPE_FLOAT64     );
+	
+	/* When we reach this point, we have not yet found this type anywhere. */
+	TODO("Type not found. Maybe search in whole xmldictionary if it is defined later?");
+	TRACE_DEBUG(INFO, "The type '%s' could not be resolved. Please check it is defined before use.", type_name);
+	return ENOENT;
+}
+
+/* Find or create a type. */
+static int typdefn_to_fD(struct t_typedefn * t, struct dictionary * fD_dict, struct dict_object * fd_appl, struct dict_object ** fd_t, int * nb_added)
+{
+	int ret;
+	struct dict_object * prev = NULL;
+	struct dict_type_data td;
+
+	TRACE_ENTRY("%p %p %p %p %p", t, fD_dict, fd_appl, fd_t, nb_added);
+	
+	CHECK_PARAMS(t && fD_dict);
+	
+	/* Prepare the data in fD's format */
+	memset(&td, 0, sizeof(td));
+	td.type_name = (char *)t->name;
+	
+	/* infer td.type_base from t->parent_name */
+	CHECK_FCT( resolve_base_type(fD_dict, t->parent_name, &td.type_base, NULL) );
+	
+	/* Create or search in the dictionary */
+	ret = fd_dict_new ( fD_dict, DICT_TYPE, &td, fd_appl, &prev );
+	if (fd_t)
+		*fd_t = prev;
+	if (ret == EEXIST) {
+		/* Conflict with existing entry */
+		enum dict_avp_basetype xmlbt = td.type_base;
+		extern const char * type_base_name[]; /* in libfreeDiameter/dictionary.c */
+		CHECK_FCT( fd_dict_getval(prev, &td) );
+		TRACE_DEBUG(INFO, "[dict_legacy_xml] Warning: Conflicting entry.");
+		TRACE_DEBUG(INFO, "[dict_legacy_xml]   New entry (ignored): '%s' (%d - %s)", t->name, xmlbt, type_base_name[xmlbt] );
+		TRACE_DEBUG(INFO, "[dict_legacy_xml]   Old entry          : '%s' (%d - %s)", td.type_name, td.type_base, type_base_name[td.type_base]);
+		return 0;
+	} else {
+		/* other errors are stoppers */
+		CHECK_FCT(ret);
+	}
+	
+	/* Update count */
+	if (nb_added)
+		*nb_added += 1;
+	
+	/* Done */
+	return 0;
+}
+
+/* Process one list of rules */
+static int rules_to_fD_onelist(struct dictionary * fD_dict, struct dict_object * parent, enum rule_position position, struct fd_list * list, int * nb_added)
+{
+	struct dict_rule_data rd;
+	struct fd_list * li;
+	int order = 0;
+	int ret;
+
+	TRACE_ENTRY("%p %p %d %p %p", fD_dict, parent, position, list, nb_added);
+	
+	CHECK_PARAMS(fD_dict && parent && position && list);
+	
+	for (li = list->next; li != list; li = li->next) {
+		struct t_rule * r = (struct t_rule *)li;
+		
+		/* The [AVP] rule in all ABNF definitions is implicit in freeDiameter, skip it */
+		if (!strcmp((char *)r->avpname, "AVP"))
+			continue;
+		
+		/* Prepare rule data */
+		memset(&rd, 0, sizeof(rd));
+		rd.rule_position = position;
+		rd.rule_order = ++order; /* actually only used for fixed rules, but no harm for others */
+		rd.rule_min = r->min;
+		rd.rule_max = r->max;
+		
+		/* Resolve the AVP */
+		ret = fd_dict_search(fD_dict, DICT_AVP, AVP_BY_NAME_ALL_VENDORS, r->avpname, &rd.rule_avp, ENOENT);
+		if (ret == ENOENT) {
+			TRACE_DEBUG(INFO, "[dict_legacy_xml] Error: AVP '%s' used in a rule before being defined.", r->avpname);
+		}
+		CHECK_FCT(ret);
+		
+		/* Now create the new rule */
+		CHECK_FCT_DO( ret = fd_dict_new ( fD_dict, DICT_RULE, &rd, parent, NULL ),
+			{ TRACE_DEBUG(INFO, "Error creating rule for sub-AVP '%s'", r->avpname); return ret; } );
+		if (nb_added)
+			*nb_added += 1;
+	}
+	
+	return 0;
+}
+
+/* Process lists of rules */
+static int rules_to_fD(struct dictionary * fD_dict, struct dict_object * parent, struct fd_list * fixed, struct fd_list * required, struct fd_list * optional, int * nb_added)
+{
+	int ret;
+	
+	TRACE_ENTRY("%p %p %p %p %p %p", fD_dict, parent, fixed, required, optional, nb_added);
+	
+	/* Process the rules */
+	CHECK_FCT_DO( ret = rules_to_fD_onelist(fD_dict, parent, RULE_FIXED_HEAD, fixed, nb_added),
+		{ TRACE_DEBUG(INFO, "Error processing FIXED rules"); return ret; } );
+	CHECK_FCT_DO( ret = rules_to_fD_onelist(fD_dict, parent, RULE_REQUIRED, required, nb_added),
+		{ TRACE_DEBUG(INFO, "Error processing REQUIRED rules"); return ret; } );
+	CHECK_FCT_DO( ret = rules_to_fD_onelist(fD_dict, parent, RULE_OPTIONAL, optional, nb_added),
+		{ TRACE_DEBUG(INFO, "Error processing OPTIONAL rules"); return ret; } );
+	
+	return 0;
+}
+
+/* Find or create an AVP (and dependent objects) */
+static int avp_to_fD(struct t_avp * a, struct dictionary * fD_dict, struct dict_object * fd_appl, struct dict_object ** fd_a, int * nb_added)
+{
+	int ret;
+	struct dict_object * prev = NULL, *type = NULL;
+	struct dict_avp_data ad;
+	struct fd_list * li;
+
+	TRACE_ENTRY("%p %p %p %p %p", a, fD_dict, fd_appl, fd_a, nb_added);
+	
+	CHECK_PARAMS(a && fD_dict);
+	
+	/* Prepare the data in fD's format */
+	memset(&ad, 0, sizeof(ad));
+	ad.avp_code   = a->code;
+	ad.avp_vendor = a->vendor;
+	ad.avp_name   = (char *)a->name;
+	ad.avp_flag_mask = a->fmask | AVP_FLAG_VENDOR;
+	ad.avp_flag_val  = a->flags;
+	
+	if (!FD_IS_LIST_EMPTY(&a->type)) {
+		/* special exception: we use per-AVP enumerated types in fD */
+		if (!strcasecmp("Enumerated", (char *)((struct t_avptype *)a->type.next)->type_name))
+			goto enumerated;
+		/* Let's allow "Integer32" instead of "Enumerated" also... */
+		if ((!FD_IS_LIST_EMPTY(&a->enums)) && (!strcasecmp("Integer32", (char *)((struct t_avptype *)a->type.next)->type_name)))
+			goto enumerated;
+		
+		/* The type was explicitly specified, resolve it */
+		CHECK_FCT( resolve_base_type(fD_dict, ((struct t_avptype *)a->type.next)->type_name, &ad.avp_basetype, &type) );
+	} else {
+		/* The type was not specified, try to infer it from provided data */
+		if (       !FD_IS_LIST_EMPTY(&a->grouped_optional)
+			|| !FD_IS_LIST_EMPTY(&a->grouped_required)
+			|| !FD_IS_LIST_EMPTY(&a->grouped_fixed) ) {
+			/* The AVP has rules, it is a grouped AVP */
+			CHECK_PARAMS_DO( FD_IS_LIST_EMPTY(&a->enums), 
+				{ TRACE_DEBUG(INFO, "Conflict: The AVP '%s' has both enum values and rules.", ad.avp_name); return EINVAL; } );
+			ad.avp_basetype = AVP_TYPE_GROUPED;
+		} else {
+			/* It should be an enumerated AVP... */
+			if (FD_IS_LIST_EMPTY(&a->enums)) {
+				TRACE_DEBUG(INFO, "Error: Missing type information for AVP '%s'", ad.avp_name);
+				return EINVAL;
+			} else {
+				/* We create a new type to hold the enumerated values -- fD specifics */
+				char typename[256];
+				struct dict_type_data 	tdata;
+				
+enumerated:
+				snprintf(typename, sizeof(typename), "Enumerated(%s)", ad.avp_name);
+				memset(&tdata, 0, sizeof(tdata));
+				tdata.type_base = AVP_TYPE_INTEGER32;
+				tdata.type_name = &typename[0];
+				CHECK_FCT( fd_dict_new ( fD_dict, DICT_TYPE, &tdata, fd_appl, &type ) );
+				if (nb_added)
+					*nb_added += 1;
+				
+				ad.avp_basetype = AVP_TYPE_INTEGER32;
+			}
+		}
+	}
+	
+	/* At this point, ad.avp_basetype is defined and type might also be */
+	
+	/* Create or search in the dictionary */
+	ret = fd_dict_new ( fD_dict, DICT_AVP, &ad, type, &prev );
+	if (fd_a)
+		*fd_a = prev;
+	if (ret == EEXIST) {
+		/* Conflict with existing entry */
+		CHECK_FCT( fd_dict_getval(prev, &ad) );
+		TRACE_DEBUG(INFO, "[dict_legacy_xml] Warning: Conflicting entry.");
+		TRACE_DEBUG(INFO, "[dict_legacy_xml]   New entry (ignored): %u - '%s'", a->code, (char *)a->name);
+		TRACE_DEBUG(INFO, "[dict_legacy_xml]   Old entry          : %u - '%s'", ad.avp_code, ad.avp_name);
+		goto inside;
+	} else {
+		/* other errors are stoppers */
+		CHECK_FCT(ret);
+	}
+	
+	/* Update count */
+	if (nb_added)
+		*nb_added += 1;
+	
+inside:
+	/* Now, the inner elements, if any */
+	
+	if ( (!FD_IS_LIST_EMPTY(&a->enums)) && (ad.avp_basetype != AVP_TYPE_UNSIGNED32)) {
+		TRACE_DEBUG(INFO, "AVP '%s' type is not an Unsigned32 but it has enum values (invalid in this extension).", ad.avp_name);
+		return EINVAL;
+	}
+
+	/* In case of enumeration, define the enum values */
+	for (li = a->enums.next; li != &a->enums; li = li->next) {
+		struct t_enum * e = (struct t_enum *)li;
+		struct dict_enumval_data ed;
+		
+		memset(&ed, 0, sizeof(ed));
+		ed.enum_name = (char *)e->name;
+		ed.enum_value.u32 = e->code;
+		
+		CHECK_FCT_DO( ret = fd_dict_new ( fD_dict, DICT_ENUMVAL, &ed, type, NULL ),
+			{
+				TRACE_DEBUG(INFO, "Error defining constant value '%s' for AVP '%s': %s", ed.enum_name, ad.avp_name, strerror(ret));
+				return ret;
+			} );
+		if (nb_added)
+			*nb_added += 1;
+	}
+	
+	/* In case of grouped AVP, check the type is really grouped */
+	if ( !FD_IS_LIST_EMPTY(&a->grouped_optional)
+	  || !FD_IS_LIST_EMPTY(&a->grouped_required)
+	  || !FD_IS_LIST_EMPTY(&a->grouped_fixed) ) {
+		CHECK_PARAMS_DO( ad.avp_basetype == AVP_TYPE_GROUPED, 
+			{ TRACE_DEBUG(INFO, "Got rules for non-grouped AVP '%s'", ad.avp_name); return EINVAL;} );
+		CHECK_FCT_DO( ret = rules_to_fD(fD_dict, prev, &a->grouped_fixed, &a->grouped_required, &a->grouped_optional, nb_added),
+			{ TRACE_DEBUG(INFO, "Error processing rules for AVP '%s': %s", ad.avp_name, strerror(ret)); return ret; } );
+	}
+	
+	/* done! */
+	return 0;
+}
+
+/* Find or create a command. */
+static int cmd_to_fD(struct t_cmd * c, struct dictionary * fD_dict, struct dict_object * fd_appl, struct dict_object ** fd_req, int * nb_added)
+{
+	int ret;
+	struct dict_object * req = NULL, *ans = NULL;
+	struct dict_cmd_data cd;
+	char cmdname[512];
+
+	TRACE_ENTRY("%p %p %p %p %p", c, fD_dict, fd_appl, fd_req, nb_added);
+	
+	CHECK_PARAMS(c && fD_dict);
+	
+	/* Prepare the request data in fD's format */
+	memset(&cd, 0, sizeof(cd));
+	cd.cmd_code = c->code;
+	snprintf(cmdname, sizeof(cmdname), "%s-Request", (char *)c->name);
+	cd.cmd_name = &cmdname[0];
+	cd.cmd_flag_mask = c->fmask | CMD_FLAG_REQUEST | CMD_FLAG_ERROR;
+	cd.cmd_flag_val  = c->flags | CMD_FLAG_REQUEST;
+	
+	/* Create or search in the dictionary */
+	ret = fd_dict_new ( fD_dict, DICT_COMMAND, &cd, fd_appl, &req );
+	if (fd_req)
+		*fd_req = req;
+	if (ret == EEXIST) {
+		struct dict_cmd_data prevcd;
+		/* Conflict with existing entry */
+		CHECK_FCT( fd_dict_getval(req, &prevcd) );
+		TRACE_DEBUG(INFO, "[dict_legacy_xml] Warning: Conflicting entry.");
+		TRACE_DEBUG(INFO, "[dict_legacy_xml]   New entry (ignored): %u - '%s'", cd.cmd_code, cd.cmd_name);
+		TRACE_DEBUG(INFO, "[dict_legacy_xml]   Old entry          : %u - '%s'", prevcd.cmd_code, prevcd.cmd_name);
+		goto answer;
+	} else {
+		/* other errors are stoppers */
+		CHECK_FCT(ret);
+	}
+	
+	/* Update count */
+	if (nb_added)
+		*nb_added += 1;
+	
+answer:
+	/* update data for the answer */
+	snprintf(cmdname, sizeof(cmdname), "%s-Answer", (char *)c->name);
+	cd.cmd_flag_val &= ~CMD_FLAG_REQUEST;
+	cd.cmd_flag_mask &= ~CMD_FLAG_ERROR;
+	
+	ret = fd_dict_new ( fD_dict, DICT_COMMAND, &cd, fd_appl, &ans );
+	if (ret == EEXIST) {
+		struct dict_cmd_data prevcd;
+		/* Conflict with existing entry */
+		CHECK_FCT( fd_dict_getval(ans, &prevcd) );
+		TRACE_DEBUG(INFO, "[dict_legacy_xml] Warning: Conflicting entry.");
+		TRACE_DEBUG(INFO, "[dict_legacy_xml]   New entry (ignored): %u - '%s'", cd.cmd_code, cd.cmd_name);
+		TRACE_DEBUG(INFO, "[dict_legacy_xml]   Old entry          : %u - '%s'", prevcd.cmd_code, prevcd.cmd_name);
+		goto rules;
+	} else {
+		/* other errors are stoppers */
+		CHECK_FCT(ret);
+	}
+	
+	/* Update count */
+	if (nb_added)
+		*nb_added += 1;
+	
+rules:
+	/* Now process the rules inside the command */
+	CHECK_FCT_DO( ret = rules_to_fD(fD_dict, req, &c->reqrules_fixed, &c->reqrules_required, &c->reqrules_optional, nb_added),
+			{
+				TRACE_DEBUG(INFO, "Error converting data from request rules: %s", strerror(ret));
+				return ret;
+			}   );
+	CHECK_FCT_DO( ret = rules_to_fD(fD_dict, ans, &c->ansrules_fixed, &c->ansrules_required, &c->ansrules_optional, nb_added),
+			{
+				TRACE_DEBUG(INFO, "Error converting data from answer rules: %s", strerror(ret));
+				return ret;
+			}   );
+	
+	/* Done */
+	return 0;
+}
+
+/* Find or create an application (and dependent objects) */
+static int appl_to_fD(struct t_appl * a, struct dictionary * fD_dict, struct dict_object ** fd_a, int * nb_added)
+{
+	int ret;
+	struct dict_object * prev = NULL;
+	struct dict_application_data ad;
+	struct fd_list * li;
+
+	TRACE_ENTRY("%p %p %p %p", a, fD_dict, fd_a, nb_added);
+	
+	CHECK_PARAMS(a && fD_dict);
+	
+	if (a->id) { /* skip app 0 */
+	
+		/* Prepare the data in fD's format */
+		memset(&ad, 0, sizeof(ad));
+		ad.application_id   = a->id;
+		ad.application_name = (char *)a->name;
+
+		/* Create or search in the dictionary */
+		ret = fd_dict_new ( fD_dict, 
+					DICT_APPLICATION, 
+					&ad, 
+					NULL /* we don't have a parent vendor in XML files, so currently everything links to no vendor */, 
+					&prev );
+		if (fd_a)
+			*fd_a = prev;
+		if (ret == EEXIST) {
+			/* Conflict with existing entry */
+			CHECK_FCT( fd_dict_getval(prev, &ad) );
+			TRACE_DEBUG(INFO, "[dict_legacy_xml] Warning: Conflicting entry.");
+			TRACE_DEBUG(INFO, "[dict_legacy_xml]   New entry (ignored): %u - '%s'", a->id, (char *)a->name);
+			TRACE_DEBUG(INFO, "[dict_legacy_xml]   Old entry          : %u - '%s'", ad.application_id, ad.application_name);
+			goto inside;
+		} else {
+			/* other errors are stoppers */
+			CHECK_FCT(ret);
+		}
+
+		/* Update count */
+		if (nb_added)
+			*nb_added += 1;
+	}
+	
+inside:
+	/* Now, the inner elements */
+	
+	/* First, define all the types */
+	for (li = a->types.next; li != &a->types; li = li->next) {
+		CHECK_FCT_DO( ret = typdefn_to_fD((struct t_typedefn *)li, fD_dict, prev, NULL, nb_added),
+			{
+				TRACE_DEBUG(INFO, "Error converting data from typedefn '%s': %s", ((struct t_typedefn *)li)->name, strerror(ret));
+				return ret;
+			}  );
+	}
+	
+	/* Then, AVPs, enums, and grouped AVP rules */
+	for (li = a->avps.next; li != &a->avps; li = li->next) {
+		CHECK_FCT_DO( ret = avp_to_fD((struct t_avp *)li, fD_dict, prev, NULL, nb_added),
+			{
+				TRACE_DEBUG(INFO, "Error converting data from AVP '%s': %s", ((struct t_avp *)li)->name, strerror(ret));
+				return ret;
+			}  );
+	}
+	
+	/* Finally, the commands and rules */
+	for (li = a->commands.next; li != &a->commands; li = li->next) {
+		CHECK_FCT_DO( ret = cmd_to_fD((struct t_cmd *)li, fD_dict, prev, NULL, nb_added),
+			{
+				TRACE_DEBUG(INFO, "Error converting data from command '%s': %s", ((struct t_cmd *)li)->name, strerror(ret));
+				return ret;
+			}  );
+	}
+	
+	/* done! */
+	return 0;
+}
+
+
+static int dict_to_fD(struct dictionary * fD_dict, struct t_dictionary * xmldict, int * nb_added)
+{
+	struct fd_list * li;
+	int ret;
+	
+	TRACE_ENTRY("%p %p %p", fD_dict, xmldict, nb_added);
+	
+	CHECK_PARAMS(fD_dict && xmldict && nb_added);
+	
+	*nb_added = 0;
+	
+	/* Create all the vendors */
+	for (li = xmldict->vendors.next; li != &xmldict->vendors; li = li->next) {
+		CHECK_FCT_DO( ret = vend_to_fD((struct t_vend *)li, fD_dict, NULL, nb_added),
+			{
+				TRACE_DEBUG(INFO, "Error converting data from vendor '%s': %s", ((struct t_vend *)li)->name, strerror(ret));
+				return ret;
+			} );
+	}
+	
+	/* Now, process each application */
+	CHECK_FCT_DO( ret = appl_to_fD(&xmldict->base_and_applications, fD_dict, NULL, nb_added),
+			{
+				TRACE_DEBUG(INFO, "Error converting data from Base application: %s", strerror(ret));
+				return ret;
+			} );
+	for (li = xmldict->base_and_applications.chain.next; li != &xmldict->base_and_applications.chain; li = li->next) {
+		CHECK_FCT_DO( ret = appl_to_fD((struct t_appl *) li, fD_dict, NULL, nb_added),
+			{
+				TRACE_DEBUG(INFO, "Error converting data from application '%s': %s", ((struct t_appl *)li)->name, strerror(ret));
+				return ret;
+			}  );
+	}
+	
+	/* Complete! */
+	return 0;
+}
+
+
+
+
+
+/*********************************************/
+
+int dict_lxml_parse(char * xmlfilename)
+{
+	xmlSAXHandler handler;
+	struct parser_ctx data;
+	int ret;
+
+	TRACE_ENTRY("%p", xmlfilename);
+	
+	CHECK_PARAMS_DO(xmlfilename, { return -1; } );
+	
+	TRACE_DEBUG(FULL, "Parsing next XML file: %s...", xmlfilename);
+	
+	/* Initialize the parser */
+	memset(&handler, 0, sizeof(handler));
+	handler.startElement = SAXstartelem;
+	handler.endElement   = SAXendelem;
+	
+	/* Initialize the data */
+	memset(&data, 0, sizeof(data));
+	fd_list_init( &data.dict.vendors, NULL );
+	fd_list_init( &data.dict.base_and_applications.chain, NULL );
+	data.dict.base_and_applications.name = (uint8_t *)"[Diameter Base Protocol]";
+	fd_list_init( &data.dict.base_and_applications.commands, NULL );
+	fd_list_init( &data.dict.base_and_applications.types, NULL );
+	fd_list_init( &data.dict.base_and_applications.avps, NULL );
+	data.xmlfilename = xmlfilename;
+	
+	/* Parse the file */
+	ret = xmlSAXUserParseFile(&handler, &data, xmlfilename);
+	if (ret < 0) {
+		TRACE_DEBUG(INFO, "An error occurred while parsing %s, aborting.", xmlfilename);
+		del_dict_contents(&data.dict);
+		return -1;
+	}
+	
+	TRACE_DEBUG(FULL, "XML file parsing, 1st pass completed.");
+	if (TRACE_BOOL(ANNOYING)) {
+		dump_dict(&data.dict);
+	}
+	
+	/* Now, convert all the objects from the temporary tree into the freeDiameter dictionary */
+	CHECK_FCT_DO( dict_to_fD(fd_g_config->cnf_dict, &data.dict, &ret), 
+		{ 
+			TRACE_DEBUG(INFO, "Error while converting data read from file '%s'", xmlfilename);
+			del_dict_contents(&data.dict); 
+			return -1; 
+		} );
+	
+	TRACE_DEBUG(FULL, "Conversion from '%s' to freeDiameter internal format complete.", xmlfilename);
+	
+	/* Done */
+	del_dict_contents(&data.dict);
+	
+	return ret;
+}
diff --git a/extensions/dict_mip6a/CMakeLists.txt b/extensions/dict_mip6a/CMakeLists.txt
new file mode 100644
index 0000000..44a9c93
--- /dev/null
+++ b/extensions/dict_mip6a/CMakeLists.txt
@@ -0,0 +1,13 @@
+# The dict_mip6a extension
+PROJECT("Diameter Mobile IPv6 Auth (MIP6A) Dictionary Definitions" C)
+
+# Compile as a module
+FD_ADD_EXTENSION(dict_mip6a dict_mip6a.c)
+
+
+####
+## INSTALL section ##
+
+INSTALL(TARGETS dict_mip6a
+	LIBRARY DESTINATION ${INSTALL_EXTENSIONS_SUFFIX}
+	COMPONENT freeDiameter-dictionary-mip6)
diff --git a/extensions/dict_mip6a/dict_mip6a.c b/extensions/dict_mip6a/dict_mip6a.c
new file mode 100644
index 0000000..a31aeed
--- /dev/null
+++ b/extensions/dict_mip6a/dict_mip6a.c
@@ -0,0 +1,1094 @@
+/*********************************************************************************************************
+* Software License Agreement (BSD License)                                                               *
+* Author: Francois Bard <francois@tera.ics.keio.ac.jp>							 *
+*													 *
+* Copyright (c) 2010, Teraoka Laboratory, Keio University						 *
+* All rights reserved.											 *
+* 													 *
+* Redistribution and use of this software in source and binary forms, with or without modification, are  *
+* permitted provided that the following conditions are met:						 *
+* 													 *
+* * Redistributions of source code must retain the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer.										 *
+*    													 *
+* * Redistributions in binary form must reproduce the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer in the documentation and/or other						 *
+*   materials provided with the distribution.								 *
+* 													 *
+* * Neither the name of the Teraoka Laboratory nor the 							 *
+*   names of its contributors may be used to endorse or 						 *
+*   promote products derived from this software without 						 *
+*   specific prior written permission of Teraoka Laboratory 						 *
+*   													 *
+* 													 *
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED *
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
+* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR *
+* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 	 *
+* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 	 *
+* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR *
+* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF   *
+* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.								 *
+*********************************************************************************************************/
+
+/*
+
+The following table complete the one in RFC 5778, page 18. The AVPs are implemented below following the order of this table.
+We try to keep the structure of the grouped AVP by declaring the contained AVPs just before the grouped AVP they depend on.
+The number of '+' indicates the depth of the contained AVP.
+
+DEPTH	NAME					AVP	RFC		TYPE			NOTES
+
+	MIP6-Feature-Vector			124	5447		Unsigned64
+	User-Name				1	3588		UTF8String
+	Service-Selection			493	5778		UTF8String
+	MIP-MN-AAA-SPI				341	5778		Unsigned32
++	MIP-Home-Agent-Address			334	4004		Address
+++	Destination-Host			293	3588		DiameterIdentity
+++	Destination-Realm			283	3588		DiameterIdentity
++	MIP-Home-Agent-Host			348	4004		Grouped
++	MIP6-Home-Link-Prefix			125	5447		OctetString
+	MIP6-Agent-Info				486	5447		Grouped
++	MIP-Replay-Mode				346	4004		Enumerated
++	MIP-Algorithm-Type			345	4004		Enumerated
++	MIP-MN-HA-SPI				491	5778		Unsigned32
++	MIP-MSA-Lifetime			367	4004		Unsigned32
++	MIP-Session-Key				343	4004		OctetString
+	MIP-MN-HA-MSA				492	5778		Grouped			different from MIP-MN-to-HA-MSA (331)
+	MIP-Mobile-Node-Address			333	4004		Address
+	MIP-Careof-Address			487	5778		Address
+	MIP-Authenticator			488	5778		OctetString
+	MIP-MAC-Mobility-Data			489	5778		OctetString
+	MIP-Timestamp				490	5778		OctetString
+	Chargeable-User-Identity		89	5778		OctetString
+	MIP6-Auth-Mode				494	5778		Enumerated
+
+QoS AVPs (RFC 5777 - implemented in the corresponding dictionary)
+
+	QoS-Capability				578	5777		Grouped
+	QoS-Resources				508	5777		Grouped
+
+ACCOUNTING AVPs (section 6.21)
+
+	Accounting-Input-Octets			363	4004, 4005	Unsigned64
+	Accounting-Output-Octets		364	4004, 4005	Unsigned64
+	Accounting-Input-Packets		365	4004, 4005	Unsigned64
+	Accounting-Output-Packets		366	4004, 4005	Unsigned64
+	Acct-Multi-Session-Id			50	3588		UTF8String
+	Acct-Session-Time			46	2866, 4004	Unsigned32
+	MIP6-Feature-Vector			----------------------------------
+	MIP-Mobile-Node-Address			----------------------------------
+	MIP6-Agent-Info				----------------------------------
+	Chargeable-User-Identity		----------------------------------
+	Service-Selection			----------------------------------
+	QoS-Resources				----------------------------------
+	QoS-Capability				----------------------------------
+	MIP-Careof-Address			----------------------------------
+
+RADIUS AVPs (contained in the MIR/MIA)
+
+	NAS-Identifier				32	2865		radius (see avp)
+	NAS-IP-Address				4	2865            radius (see avp)
+	NAS-IPv6-Address			95	3162            radius (see avp)
+	NAS-Port-Type				61	2865            radius (see avp)
+	Called-Station-Id			30	2865            radius (see avp)
+	Calling-Station-Id			31	2865            radius (see avp)
+
+
+*/
+
+/****************************************************************************************************************************************
+*																	*
+* This table is a copy of the registry named "MIP6 Authentication Mode Registry" and managed by IANA.					*
+* source : http://www.iana.org/assignments/aaa-parameters/aaa-parameters.txt								*
+* up to date on october 2010														*
+*																	*
+*      Value          Token       Reference												*
+*        0       Reserved         [RFC5778]												*
+*        1       MIP6_AUTH_MN_AAA [RFC5778]												*
+*   2-4294967295 Unassigned														*
+*																	*
+****************************************************************************************************************************************/
+
+
+/*
+
+NOTES
+
+check for omissions !
+
+*/
+
+#include <freeDiameter/extension.h>
+
+#define CHECK_dict_new( _type, _data, _parent, _ref )	\
+	CHECK_FCT(  fd_dict_new( fd_g_config->cnf_dict, (_type), (_data), (_parent), (_ref))  );
+
+#define CHECK_dict_search( _type, _criteria, _what, _result )	\
+	CHECK_FCT(  fd_dict_search( fd_g_config->cnf_dict, (_type), (_criteria), (_what), (_result), ENOENT) );
+
+struct local_rules_definition {
+	char 			*avp_name;
+	enum rule_position	position;
+	int 			min;
+	int			max;
+};
+
+#define RULE_ORDER( _position ) ((((_position) == RULE_FIXED_HEAD) || ((_position) == RULE_FIXED_TAIL)) ? 1 : 0 )
+
+#define PARSE_loc_rules( _rulearray, _parent) {								\
+	int __ar;											\
+	for (__ar=0; __ar < sizeof(_rulearray) / sizeof((_rulearray)[0]); __ar++) {			\
+		struct dict_rule_data __data = { NULL, 							\
+			(_rulearray)[__ar].position,							\
+			0, 										\
+			(_rulearray)[__ar].min,								\
+			(_rulearray)[__ar].max};							\
+		__data.rule_order = RULE_ORDER(__data.rule_position);					\
+		CHECK_FCT(  fd_dict_search( 								\
+			fd_g_config->cnf_dict,								\
+			DICT_AVP, 									\
+			AVP_BY_NAME, 									\
+			(_rulearray)[__ar].avp_name, 							\
+			&__data.rule_avp, 0 ) );							\
+		if ( !__data.rule_avp ) {								\
+			TRACE_DEBUG(INFO, "AVP Not found: '%s'", (_rulearray)[__ar].avp_name );		\
+			return ENOENT;									\
+		}											\
+		CHECK_FCT_DO( fd_dict_new( fd_g_config->cnf_dict, DICT_RULE, &__data, _parent, NULL),	\
+			{							        		\
+				TRACE_DEBUG(INFO, "Error on rule with AVP '%s'",      			\
+					 (_rulearray)[__ar].avp_name );		      			\
+				return EINVAL;					      			\
+			} );							      			\
+	}									      			\
+}
+
+#define enumval_def_u32( _val_, _str_ ) \
+		{ _str_, 		{ .u32 = _val_ }}
+
+#define enumval_def_os( _len_, _val_, _str_ ) \
+		{ _str_, 		{ .os = { .data = (unsigned char *)_val_, .len = _len_ }}}
+
+
+
+/* Defines if there are any */
+
+//New Result-Code for MIP (RFC5778, Section 7.*)
+#define DIAMETER_SUCCESS_RELOCATE_HA 2009
+#define DIAMETER_ERROR_MIP6_AUTH_MODE 5041
+
+//Others
+#define MIP6_AUTH_MN_AAA 1
+
+/* Dictionary */
+
+int dict_mip6a_init(char * conffile)
+{
+	struct dict_object * mip6a;
+	{
+		struct dict_application_data data  = { 	8, "Diameter Mobile IPv6 Auth (MIP6A) Application" };
+		CHECK_dict_new( DICT_APPLICATION, &data , NULL, &mip6a);
+	}
+
+	/***************/
+	/* AVP section */
+	/***************/
+	{
+		/* Loading all the derived data formats */
+
+		struct dict_object * Address_type;
+		struct dict_object * UTF8String_type;
+		struct dict_object * DiameterIdentity_type;
+		struct dict_object * DiameterURI_type;
+		struct dict_object * Time_type;
+		
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "Address", &Address_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "UTF8String", &UTF8String_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "DiameterIdentity", &DiameterIdentity_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "DiameterURI", &DiameterURI_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "Time", &Time_type);
+
+	///////////////////////////////////////////
+	/* AVPs for Mobile IPv6 Auth Application */
+	///////////////////////////////////////////
+
+		/* MIP6-Feature-Vector - RFC 5447 */
+		{
+			/*
+
+			*/
+
+			struct dict_avp_data data = { 
+					124, 					/* Code */
+					0, 					/* Vendor */
+					"MIP6-Feature-Vector", 			/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,		 	/* Fixed flag values */
+					AVP_TYPE_UNSIGNED64			/* base type of data */
+					};
+			
+			CHECK_dict_new( DICT_AVP, &data , NULL, NULL);
+		}
+
+		/* User-Name - RFC 3588 */
+
+			/*
+			Implemented in the base protocol
+			*/
+
+		/* Service-Selection - RFC 5778 */
+		{
+			/*
+
+			*/
+
+			struct dict_avp_data data = {
+					493, 					/* Code */
+					0, 					/* Vendor */
+					"Service-Selection",			/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,		 	/* Fixed flag values */
+					AVP_TYPE_OCTETSTRING 			/* base type of data */
+					};
+
+			CHECK_dict_new( DICT_AVP, &data , UTF8String_type, NULL);
+		}
+
+		/* MIP-MN-AAA-SPI - RFC 5778 */
+		{
+			/*
+
+			*/
+
+			struct dict_avp_data data = {
+					341, 					/* Code */
+					0, 					/* Vendor */
+					"MIP-MN-AAA-SPI",			/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,		 	/* Fixed flag values */
+					AVP_TYPE_UNSIGNED32 			/* base type of data */
+					};
+
+			CHECK_dict_new( DICT_AVP, &data , NULL, NULL);
+		}
+
+		/* Destination-Host - Base Protocol */
+
+			/*
+			Implemented in the base protocol
+			*/
+
+		/* Destination-Realm - Base Protocol */
+
+			/*
+			Implemented in the base protocol
+			*/
+
+		/* MIP-Home-Agent-Address - RFC 4004 */
+		{
+			/*
+
+			*/
+
+			struct dict_avp_data data = {
+					334, 					/* Code */
+					0, 					/* Vendor */
+					"MIP-Home-Agent-Address",		/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,		 	/* Fixed flag values */
+					AVP_TYPE_OCTETSTRING			/* base type of data */
+					};
+
+			CHECK_dict_new( DICT_AVP, &data , Address_type, NULL);
+		}
+
+		/* MIP-Home-Agent-Host - RFC 4004 */
+		{
+			/*
+
+			*/
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+					348, 					/* Code */
+					0, 					/* Vendor */
+					"MIP-Home-Agent-Host",			/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,		 	/* Fixed flag values */
+					AVP_TYPE_GROUPED 			/* base type of data */
+					};
+
+			struct local_rules_definition rules[] =
+						{ 	 {  "Destination-Realm",	RULE_REQUIRED,	-1, 1 }
+							,{  "Destination-Host",		RULE_REQUIRED,	-1, 1 }
+						};
+
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+			PARSE_loc_rules( rules, avp );
+		}
+
+		/* MIP6-Home-Link-Prefix - RFC 5447 */
+		{
+			/*
+
+			*/
+
+			struct dict_avp_data data = {
+					125, 					/* Code */
+					0, 					/* Vendor */
+					"MIP6-Home-Link-Prefix", 		/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,		 	/* Fixed flag values */
+					AVP_TYPE_OCTETSTRING			/* base type of data */
+					};
+
+			CHECK_dict_new( DICT_AVP, &data , NULL, NULL);
+		}
+
+		/* MIP6-Agent-Info - RFC 5447*/
+		{
+			/*
+			
+			*/
+			struct dict_object * avp;
+			struct dict_avp_data data = { 
+					486, 					/* Code */
+					0, 					/* Vendor */
+					"MIP6-Agent-Info",			/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,		 	/* Fixed flag values */
+					AVP_TYPE_GROUPED 			/* base type of data */
+					};
+
+			struct local_rules_definition rules[] = 
+						{ 	 {  "MIP-Home-Agent-Address", 		RULE_OPTIONAL, -1, 2 }
+							,{  "MIP-Home-Agent-Host",		RULE_OPTIONAL, -1, 1 }
+							,{  "MIP6-Home-Link-Prefix",		RULE_OPTIONAL, -1, 1 }
+						};
+			
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+			PARSE_loc_rules( rules, avp );
+		}
+
+		/* MIP-Replay-Mode - RFC 5778 & 4004 */
+		{
+			/*
+
+			*/
+			struct dict_object * 	 type;
+			struct dict_type_data 	 tdata = { AVP_TYPE_INTEGER32, "Enumerated(MIP-Replay-Mode)", NULL, NULL, NULL };
+			struct dict_enumval_data t_0 = { "None", 	{ .i32 = 1 }};
+			struct dict_enumval_data t_1 = { "Timestamp", 	{ .i32 = 2 }};
+			struct dict_avp_data data = {
+					346, 					/* Code */
+					0, 					/* Vendor */
+					"MIP-Replay-Mode",			/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,		 	/* Fixed flag values */
+					AVP_TYPE_INTEGER32 			/* base type of data */
+					};
+
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata , NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_0 , type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1 , type, NULL);
+			CHECK_dict_new( DICT_AVP, &data , type, NULL);
+		}
+
+		/* MIP-Algorithm-Type - RFC 5778 & 4004 */
+		{
+			/*
+
+			*/
+			struct dict_object * 	 type;
+			struct dict_type_data 	 tdata = { AVP_TYPE_INTEGER32, "Enumerated(MIP-Algorithm-Type)", NULL, NULL, NULL };
+			struct dict_enumval_data t_2 = { "HMAC-SHA-1 [HMAC]", { .i32 = 2 }};
+			struct dict_avp_data data = {
+					345, 					/* Code */
+					0, 					/* Vendor */
+					"MIP-Algorithm-Type",			/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,		 	/* Fixed flag values */
+					AVP_TYPE_INTEGER32 			/* base type of data */
+					};
+
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata , NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2 , type, NULL);
+			CHECK_dict_new( DICT_AVP, &data , type, NULL);
+		}
+
+		/* MIP-MN-HA-SPI - RFC 5778 */
+		{
+			/*
+
+			*/
+			struct dict_avp_data data = {
+					491, 					/* Code */
+					0, 					/* Vendor */
+					"MIP-MN-HA-SPI",			/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,		 	/* Fixed flag values */
+					AVP_TYPE_UNSIGNED32 			/* base type of data */
+					};
+
+			CHECK_dict_new( DICT_AVP, &data , NULL, NULL);
+		}
+
+		/* MIP-MSA-Lifetime - RFC 4004 */
+		{
+			/*
+
+			*/
+			struct dict_avp_data data = {
+					367, 					/* Code */
+					0, 					/* Vendor */
+					"MIP-MSA-Lifetime",			/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,		 	/* Fixed flag values */
+					AVP_TYPE_UNSIGNED32 			/* base type of data */
+					};
+
+			CHECK_dict_new( DICT_AVP, &data , NULL, NULL);
+		}
+
+		/* MIP-Session-Key - RFC 5778 */
+		{
+			/*
+
+			*/
+			struct dict_avp_data data = {
+					343, 					/* Code */
+					0, 					/* Vendor */
+					"MIP-Session-Key",			/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,		 	/* Fixed flag values */
+					AVP_TYPE_OCTETSTRING 			/* base type of data */
+					};
+
+			CHECK_dict_new( DICT_AVP, &data , NULL, NULL);
+		}
+
+		/* MIP-MN-HA-MSA - RFC 5778 */
+		{
+			/*
+			
+			*/
+			struct dict_object * avp;
+			struct dict_avp_data data = { 
+					492, 					/* Code */
+					0, 					/* Vendor */
+					"MIP-MN-HA-MSA",			/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,		 	/* Fixed flag values */
+					AVP_TYPE_GROUPED 			/* base type of data */
+					};
+
+			struct local_rules_definition rules[] = 
+						{ 	 {  "MIP-Session-Key", 		RULE_REQUIRED, -1, 1 }
+							,{  "MIP-MSA-Lifetime", 	RULE_REQUIRED, -1, 1 }
+							,{  "MIP-MN-HA-SPI", 		RULE_OPTIONAL, -1, 1 }
+							,{  "MIP-Algorithm-Type", 	RULE_OPTIONAL, -1, 1 }
+							,{  "MIP-Replay-Mode", 		RULE_OPTIONAL, -1, 1 }
+						};
+
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+			PARSE_loc_rules( rules, avp );
+		}
+
+		/* MIP-Mobile-Node-Address - RFC 4004 */
+		{
+			/*
+
+			*/
+
+			struct dict_avp_data data = {
+					333, 					/* Code */
+					0, 					/* Vendor */
+					"MIP-Mobile-Node-Address",		/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,		 	/* Fixed flag values */
+					AVP_TYPE_OCTETSTRING			/* base type of data */
+					};
+
+			CHECK_dict_new( DICT_AVP, &data , Address_type, NULL);
+		}
+
+		/* MIP-Careof-Address - RFC 5778 */
+		{
+			/*
+
+			*/
+			struct dict_avp_data data = {
+					487, 					/* Code */
+					0, 					/* Vendor */
+					"MIP-Careof-Address",			/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,		 	/* Fixed flag values */
+					AVP_TYPE_OCTETSTRING 			/* base type of data */
+					};
+
+			CHECK_dict_new( DICT_AVP, &data , Address_type, NULL);
+		}
+
+		/* MIP-Authenticator - RFC 5778 */
+		{
+			/*
+			
+			*/
+			struct dict_avp_data data = { 
+					488, 					/* Code */
+					0, 					/* Vendor */
+					"MIP-Authenticator",			/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,		 	/* Fixed flag values */
+					AVP_TYPE_OCTETSTRING 			/* base type of data */
+					};
+
+			CHECK_dict_new( DICT_AVP, &data , NULL, NULL);
+		}
+
+		/* MIP-MAC-Mobility-Data - RFC 5778 */
+		{
+			/*
+			
+			*/
+			struct dict_avp_data data = { 
+					489, 					/* Code */
+					0, 					/* Vendor */
+					"MIP-MAC-Mobility-Data",		/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,		 	/* Fixed flag values */
+					AVP_TYPE_OCTETSTRING 			/* base type of data */
+					};
+
+			CHECK_dict_new( DICT_AVP, &data , NULL, NULL);
+		}
+
+		/* MIP-Timestamp - RFC 5778 */
+		{
+			/*
+			
+			*/
+			struct dict_avp_data data = { 
+					490, 					/* Code */
+					0, 					/* Vendor */
+					"MIP-Timestamp",			/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,		 	/* Fixed flag values */
+					AVP_TYPE_OCTETSTRING 			/* base type of data */
+					};
+
+			CHECK_dict_new( DICT_AVP, &data , NULL, NULL);
+		}
+
+		/* Chargeable-User-Identity - RFC 5778 */
+		{
+			/*
+			
+			*/
+			struct dict_avp_data data = { 
+					89, 					/* Code */
+					0, 					/* Vendor */
+					"Chargeable-User-Identity",		/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,		 	/* Fixed flag values */
+					AVP_TYPE_OCTETSTRING 			/* base type of data */
+					};
+
+			CHECK_dict_new( DICT_AVP, &data , NULL, NULL);
+		}
+
+		/* MIP6-Auth-Mode - RFC 5778 */
+		{
+			/*
+			
+			*/
+			struct dict_object * 	 type;
+			struct dict_type_data 	 tdata = { AVP_TYPE_INTEGER32, "Enumerated(MIP6-Auth-Mode)", NULL, NULL, NULL };
+			struct dict_enumval_data t_0 = { "None", 	{ .i32 = MIP6_AUTH_MN_AAA }};
+			struct dict_avp_data data = { 
+					494, 					/* Code */
+					0, 					/* Vendor */
+					"MIP6-Auth-Mode",			/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,		 	/* Fixed flag values */
+					AVP_TYPE_INTEGER32 			/* base type of data */
+					};
+
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata , NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_0 , type, NULL);
+			CHECK_dict_new( DICT_AVP, &data , type, NULL);
+		}
+
+	//////////////
+	/* QoS AVPs */
+	//////////////
+
+		/* QoS-Capability */
+
+			/*
+			Implemented in RFC 5777
+			*/
+
+		/* QoS-Resources */
+
+			/*
+			Implemented in RFC 5777
+			*/
+
+	/////////////////////
+	/* Accounting AVPs */
+	/////////////////////
+
+		/* Accounting-Input-Octets - RFC 4004 */
+		{
+			/*
+
+			*/
+			struct dict_avp_data data = {
+					363, 					/* Code */
+					0, 					/* Vendor */
+					"Accounting-Input-Octets",		/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,		 	/* Fixed flag values */
+					AVP_TYPE_UNSIGNED64 			/* base type of data */
+					};
+
+			CHECK_dict_new( DICT_AVP, &data , NULL, NULL);
+		}
+
+		/* Accounting-Output-Octets - RFC 4004 */
+		{
+			/*
+
+			*/
+			struct dict_avp_data data = {
+					364, 					/* Code */
+					0, 					/* Vendor */
+					"Accounting-Output-Octets",		/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,		 	/* Fixed flag values */
+					AVP_TYPE_UNSIGNED64 			/* base type of data */
+					};
+
+			CHECK_dict_new( DICT_AVP, &data , NULL, NULL);
+		}
+
+		/* Accounting-Input-Packets - RFC 4004 */
+		{
+			/*
+
+			*/
+			struct dict_avp_data data = {
+					365, 					/* Code */
+					0, 					/* Vendor */
+					"Accounting-Input-Packets",		/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,		 	/* Fixed flag values */
+					AVP_TYPE_UNSIGNED64 			/* base type of data */
+					};
+
+			CHECK_dict_new( DICT_AVP, &data , NULL, NULL);
+		}
+
+		/* Accounting-Output-Packets - RFC 4004 */
+		{
+			/*
+
+			*/
+			struct dict_avp_data data = {
+					366, 					/* Code */
+					0, 					/* Vendor */
+					"Accounting-Output-Packets",		/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,		 	/* Fixed flag values */
+					AVP_TYPE_UNSIGNED64 			/* base type of data */
+					};
+
+			CHECK_dict_new( DICT_AVP, &data , NULL, NULL);
+		}
+
+		/* Acct-Multi-Session-Id - RFC 3588 */
+
+			/*
+			Implemented in the base protocol
+			*/
+
+		/* Acct-Session-Time - RFC 4004 */
+		{
+			/*
+
+			*/
+			struct dict_avp_data data = {
+					46, 					/* Code */
+					0, 					/* Vendor */
+					"Acct-Session-Time",			/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,		 	/* Fixed flag values */
+					AVP_TYPE_UNSIGNED32 			/* base type of data */
+					};
+
+			CHECK_dict_new( DICT_AVP, &data , NULL, NULL);
+		}
+
+	/////////////////////////////////////
+	/* Radius AVPs - used in MIR & MIA */
+	/////////////////////////////////////
+
+	/*
+	We used the following correspondences for determining the type of the Radius AVPs
+
+		Radius		Diameter
+
+		text		UTF8Sting
+		string		OctetString
+		address		Address
+		integer		Unsigned32
+		time		Time
+	*/
+
+
+		/* NAS-Identifier				32	3575 */
+		{
+			/*
+			string -> OctetString
+			*/
+
+			struct dict_avp_data data = {
+					32, 					/* Code */
+					0, 					/* Vendor */
+					"NAS-Identifier",			/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,		 	/* Fixed flag values */
+					AVP_TYPE_OCTETSTRING			/* base type of data */
+					};
+
+			CHECK_dict_new( DICT_AVP, &data , NULL, NULL);
+		}
+
+		/* NAS-IP-Address				4	3575 */
+		{
+			/*
+			address -> Address
+			*/
+
+			struct dict_avp_data data = {
+					4, 					/* Code */
+					0, 					/* Vendor */
+					"NAS-IP-Address",			/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,		 	/* Fixed flag values */
+					AVP_TYPE_OCTETSTRING			/* base type of data */
+					};
+
+			CHECK_dict_new( DICT_AVP, &data , Address_type, NULL);
+		}
+
+		/* NAS-IPv6-Address			95	3162 */
+		{
+			/*
+			address -> Address
+			*/
+
+			struct dict_avp_data data = {
+					95, 					/* Code */
+					0, 					/* Vendor */
+					"NAS-IPv6-Address",			/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,		 	/* Fixed flag values */
+					AVP_TYPE_OCTETSTRING			/* base type of data */
+					};
+
+			CHECK_dict_new( DICT_AVP, &data , Address_type, NULL);
+		}
+
+		/* NAS-Port-Type			61	2865 */
+		{
+			/*
+			integer -> Unsigned32
+
+			   Value
+
+			      The Value field is four octets.  "Virtual" refers to a connection
+			      to the NAS via some transport protocol, instead of through a
+			      physical port.  For example, if a user telnetted into a NAS to
+			      authenticate himself as an Outbound-User, the Access-Request might
+			      include NAS-Port-Type = Virtual as a hint to the RADIUS server
+			      that the user was not on a physical port.
+
+			      0       Async
+			      1       Sync
+			      2       ISDN Sync
+			      3       ISDN Async V.120
+			      4       ISDN Async V.110
+			      5       Virtual
+			      6       PIAFS
+			      7       HDLC Clear Channel
+			      8       X.25
+			      9       X.75
+			      10      G.3 Fax
+			      11      SDSL - Symmetric DSL
+			      12      ADSL-CAP - Asymmetric DSL, Carrierless Amplitude Phase
+				      Modulation
+			      13      ADSL-DMT - Asymmetric DSL, Discrete Multi-Tone
+			      14      IDSL - ISDN Digital Subscriber Line
+			      15      Ethernet
+			      16      xDSL - Digital Subscriber Line of unknown type
+			      17      Cable
+			      18      Wireless - Other
+			      19      Wireless - IEEE 802.11
+
+			      PIAFS is a form of wireless ISDN commonly used in Japan, and
+			      stands for PHS (Personal Handyphone System) Internet Access Forum
+			      Standard (PIAFS).
+			*/
+
+			struct dict_avp_data data = {
+					61, 					/* Code */
+					0, 					/* Vendor */
+					"NAS-Port-Type",			/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,		 	/* Fixed flag values */
+					AVP_TYPE_UNSIGNED32			/* base type of data */
+					};
+
+			CHECK_dict_new( DICT_AVP, &data , NULL, NULL);
+		}
+
+		/* Called-Station-Id			30	2865 */
+		{
+			/*
+			string -> OctetString
+			*/
+
+			struct dict_avp_data data = {
+					30, 					/* Code */
+					0, 					/* Vendor */
+					"Called-Station-Id",			/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,		 	/* Fixed flag values */
+					AVP_TYPE_OCTETSTRING			/* base type of data */
+					};
+
+			CHECK_dict_new( DICT_AVP, &data , NULL, NULL);
+		}
+		/* Calling-Station-Id			31	2865 */
+		{
+			/*
+			string -> OctetString
+			*/
+
+			struct dict_avp_data data = {
+					31, 					/* Code */
+					0, 					/* Vendor */
+					"Calling-Station-Id",			/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,		 	/* Fixed flag values */
+					AVP_TYPE_OCTETSTRING			/* base type of data */
+					};
+
+			CHECK_dict_new( DICT_AVP, &data , NULL, NULL);
+		}
+	}
+
+/*******************/
+/* Command section */
+/*******************/
+
+	{
+		/* MIP6-Request (MIR) */
+		{
+			/*
+
+			The MIP6-Request (MIR), indicated by the Command-Code field set to
+			325 and the 'R' bit set in the Command Flags field, is sent by the
+			HA, acting as a Diameter client, in order to request the
+			authentication and authorization of an MN.
+
+			Although the HA provides the Diameter server with replay protection-
+			related information, the HA is responsible for the replay protection.
+
+			The message format is shown below.
+
+			<MIP6-Request> ::= < Diameter Header: 325, REQ, PXY >
+					   < Session-ID >
+					   { Auth-Application-Id }
+					   { User-Name }
+					   { Destination-Realm }
+					   { Origin-Host }
+					   { Origin-Realm }
+					   { Auth-Request-Type }
+					   [ Destination-Host ]
+					   [ Origin-State-Id ]
+					   [ NAS-Identifier ]
+					   [ NAS-IP-Address ]
+					   [ NAS-IPv6-Address ]
+					   [ NAS-Port-Type ]
+					   [ Called-Station-Id ]
+					   [ Calling-Station-Id ]
+					   [ MIP6-Feature-Vector ]
+					   { MIP6-Auth-Mode }
+					   [ MIP-MN-AAA-SPI ]
+					   [ MIP-MN-HA-SPI ]
+					1*2{ MIP-Mobile-Node-Address }
+					   { MIP6-Agent-Info }
+					   { MIP-Careof-Address }
+					   [ MIP-Authenticator ]
+					   [ MIP-MAC-Mobility-Data ]
+					   [ MIP-Timestamp ]
+					   [ QoS-Capability ]
+					 * [ QoS-Resources ]
+					   [ Chargeable-User-Identity ]
+					   [ Service-Selection ]
+					   [ Authorization-Lifetime ]
+					   [ Auth-Session-State ]
+					 * [ Proxy-Info ]
+					 * [ Route-Record ]
+					 * [ AVP ]
+
+			If the MN is both authenticated and authorized for the mobility
+			service, then the Auth-Request-Type AVP is set to the value
+			AUTHORIZE_AUTHENTICATE.  This is the case when the MIP6-Auth-Mode is
+			set to the value MIP6_AUTH_MN_AAA.
+
+			*/
+			struct dict_object * cmd;
+			struct dict_cmd_data data = {
+					325, 					/* Code */
+					"MIP6-Request", 			/* Name */
+					CMD_FLAG_REQUEST | CMD_FLAG_PROXIABLE | CMD_FLAG_ERROR, 	/* Fixed flags */
+					CMD_FLAG_REQUEST | CMD_FLAG_PROXIABLE 						/* Fixed flag values */
+					};
+			struct local_rules_definition rules[] =
+						{ 	 {  "Session-Id", 			RULE_FIXED_HEAD, -1, 1 }
+							,{  "Auth-Application-Id", 		RULE_REQUIRED,   -1, 1 }
+							,{  "User-Name", 			RULE_REQUIRED,   -1, 1 }
+							,{  "Destination-Realm", 		RULE_REQUIRED,   -1, 1 }
+							,{  "Origin-Host", 			RULE_REQUIRED,   -1, 1 }
+							,{  "Origin-Realm", 			RULE_REQUIRED,   -1, 1 }
+							,{  "Auth-Request-Type", 		RULE_REQUIRED,   -1, 1 }
+							,{  "Destination-Host", 		RULE_OPTIONAL,   -1, 1 }
+							,{  "Origin-State-Id",	 		RULE_OPTIONAL,   -1, 1 }
+							,{  "NAS-Identifier", 			RULE_OPTIONAL,   -1, 1 }
+							,{  "NAS-IP-Address", 			RULE_OPTIONAL,   -1, 1 }
+							,{  "NAS-IPv6-Address", 		RULE_OPTIONAL,   -1, 1 }
+							,{  "NAS-Port-Type", 			RULE_OPTIONAL,   -1, 1 }
+							,{  "Called-Station-Id", 		RULE_OPTIONAL,   -1, 1 }
+							,{  "Calling-Station-Id", 		RULE_OPTIONAL,   -1, 1 }
+							,{  "MIP6-Feature-Vector", 		RULE_OPTIONAL,   -1, 1 }
+							,{  "MIP6-Auth-Mode", 			RULE_OPTIONAL,   -1, 1 }
+							,{  "MIP-MN-AAA-SPI", 			RULE_OPTIONAL,   -1, 1 }
+							,{  "MIP-MN-HA-SPI", 			RULE_OPTIONAL,   -1, 1 }
+							,{  "MIP-Mobile-Node-Address", 		RULE_OPTIONAL,    1, 2 }
+							,{  "MIP6-Agent-Info", 			RULE_OPTIONAL,   -1, 1 }
+							,{  "MIP-Careof-Address", 		RULE_OPTIONAL,   -1, 1 }
+							,{  "MIP-Authenticator", 		RULE_OPTIONAL,   -1, 1 }
+							,{  "MIP-MAC-Mobility-Data", 		RULE_OPTIONAL,   -1, 1 }
+							,{  "MIP-Timestamp", 			RULE_OPTIONAL,   -1, 1 }
+							,{  "QoS-Capability", 			RULE_OPTIONAL,   -1, 1 }
+							,{  "QoS-Resources", 			RULE_OPTIONAL,   -1, -1 }
+							,{  "Chargeable-User-Identity", 	RULE_OPTIONAL,   -1, 1 }
+							,{  "Service-Selection", 		RULE_OPTIONAL,   -1, 1 }
+							,{  "Authorization-Lifetime", 		RULE_OPTIONAL,   -1, 1 }
+							,{  "Auth-Session-State", 		RULE_OPTIONAL,   -1, 1 }
+							,{  "Proxy-Info", 			RULE_OPTIONAL,   -1, -1 }
+							,{  "Route-Record", 			RULE_OPTIONAL,   -1, -1 }
+						};
+
+			CHECK_dict_new( DICT_COMMAND, &data, mip6a, &cmd);
+			PARSE_loc_rules( rules, cmd );
+		}
+
+		/* MIP6-Answer (MIA) */
+		{
+			/*
+
+			The MIP6-Answer (MIA) message, indicated by the Command-Code field
+			set to 325 and the 'R' bit cleared in the Command Flags field, is
+			sent by the Diameter server in response to the MIP6-Request message.
+
+			The User-Name AVP MAY be included in the MIA if it is present in the
+			MIR.  The Result-Code AVP MAY contain one of the values defined in
+			Section 7, in addition to the values defined in [RFC3588].
+
+			An MIA message with the Result-Code AVP set to DIAMETER_SUCCESS MUST
+			include the MIP-Mobile-Node-Address AVP.
+
+			The message format is shown below.
+
+			<MIP6-Answer> ::= < Diameter Header: 325, PXY >
+					  < Session-Id >
+					  { Auth-Application-Id }
+					  { Result-Code }
+					  { Origin-Host }
+					  { Origin-Realm }
+					  { Auth-Request-Type }
+					  [ User-Name ]
+					  [ Authorization-Lifetime ]
+					  [ Auth-Session-State ]
+					  [ Error-Message ]
+					  [ Error-Reporting-Host ]
+					  [ Re-Auth-Request-Type ]
+					  [ MIP6-Feature-Vector ]
+					  [ MIP6-Agent-Info ]
+					*2[ MIP-Mobile-Node-Address ]
+					  [ MIP-MN-HA-MSA ]
+					* [ QoS-Resources ]
+					  [ Chargeable-User-Identity ]
+					  [ Service-Selection ]
+					  [ Origin-State-Id ]
+					* [ Proxy-Info ]
+					* [ Redirect-Host ]
+					  [ Redirect-Host-Usage ]
+					  [ Redirect-Max-Cache-Time ]
+					* [ Failed-AVP ]
+					* [ AVP ]
+
+			*/
+			struct dict_object * cmd;
+			struct dict_cmd_data data = {
+					325, 					/* Code */
+					"MIP6-Answer", 				/* Name */
+					CMD_FLAG_REQUEST | CMD_FLAG_PROXIABLE | CMD_FLAG_ERROR, 	/* Fixed flags */
+					CMD_FLAG_PROXIABLE 			/* Fixed flag values */
+					};
+			struct local_rules_definition rules[] =
+						{ 	 {  "Session-Id", 			RULE_FIXED_HEAD, -1, 1 }
+							,{  "Auth-Application-Id", 		RULE_REQUIRED,   -1, 1 }
+							,{  "Result-Code", 			RULE_REQUIRED,   -1, 1 }
+							,{  "Origin-Host", 			RULE_REQUIRED,   -1, 1 }
+							,{  "Origin-Realm", 			RULE_REQUIRED,   -1, 1 }
+							,{  "Auth-Request-Type", 		RULE_REQUIRED,   -1, 1 }
+							,{  "User-Name", 			RULE_OPTIONAL,   -1, 1 }
+							,{  "Authorization-Lifetime", 		RULE_OPTIONAL,   -1, 1 }
+							,{  "Auth-Session-State", 		RULE_OPTIONAL,   -1, 1 }
+							,{  "Error-Message", 			RULE_OPTIONAL,   -1, 1 }
+							,{  "Error-Reporting-Host", 		RULE_OPTIONAL,   -1, 1 }
+							,{  "Re-Auth-Request-Type", 		RULE_OPTIONAL,   -1, 1 }
+							,{  "MIP6-Feature-Vector", 		RULE_OPTIONAL,   -1, 1 }
+							,{  "MIP6-Agent-Info", 			RULE_OPTIONAL,   -1, 1 }
+							,{  "MIP-Mobile-Node-Address", 		RULE_OPTIONAL,   -1, 2 }
+							,{  "MIP-MN-HA-MSA", 			RULE_OPTIONAL,   -1, 1 }
+							,{  "QoS-Resources", 			RULE_OPTIONAL,   -1, -1 }
+							,{  "Chargeable-User-Identity",		RULE_OPTIONAL,   -1, 1 }
+							,{  "Service-Selection", 		RULE_OPTIONAL,   -1, 1 }
+							,{  "Origin-State-Id", 			RULE_OPTIONAL,   -1, 1 }
+							,{  "Proxy-Info", 			RULE_OPTIONAL,   -1, -1 }
+							,{  "Redirect-Host", 			RULE_OPTIONAL,   -1, -1 }
+							,{  "Redirect-Host-Usage", 		RULE_OPTIONAL,   -1, 1 }
+							,{  "Redirect-Max-Cache-Time", 		RULE_OPTIONAL,   -1, 1 }
+							,{  "Failed-AVP", 			RULE_OPTIONAL,   -1, -1 }
+						};
+
+			CHECK_dict_new( DICT_COMMAND, &data, mip6a, &cmd);
+			PARSE_loc_rules( rules, cmd );
+		}
+	}
+	LOG_D( "Dictionary Extension 'Diameter Mobile IPv6 Auth (MIP6A)' initialized");
+	return 0;
+}
+EXTENSION_ENTRY("dict_mip6a", dict_mip6a_init, "dict_rfc5777");
diff --git a/extensions/dict_mip6i/CMakeLists.txt b/extensions/dict_mip6i/CMakeLists.txt
new file mode 100644
index 0000000..15d0c24
--- /dev/null
+++ b/extensions/dict_mip6i/CMakeLists.txt
@@ -0,0 +1,13 @@
+# The dict_mip6i extension
+PROJECT("Diameter Mobile IPv6 IKE (MIP6I) Dictionary Definition" C)
+
+# Compile as a module
+FD_ADD_EXTENSION(dict_mip6i dict_mip6i.c)
+
+
+####
+## INSTALL section ##
+
+INSTALL(TARGETS dict_mip6i
+	LIBRARY DESTINATION ${INSTALL_EXTENSIONS_SUFFIX}
+	COMPONENT freeDiameter-dictionary-mip6)
diff --git a/extensions/dict_mip6i/dict_mip6i.c b/extensions/dict_mip6i/dict_mip6i.c
new file mode 100644
index 0000000..7977ccc
--- /dev/null
+++ b/extensions/dict_mip6i/dict_mip6i.c
@@ -0,0 +1,1137 @@
+/*********************************************************************************************************
+* Software License Agreement (BSD License)                                                               *
+* Author: Francois Bard <francois@tera.ics.keio.ac.jp>							 *
+*													 *
+* Copyright (c) 2010, Teraoka Laboratory, Keio University						 *
+* All rights reserved.											 *
+* 													 *
+* Redistribution and use of this software in source and binary forms, with or without modification, are  *
+* permitted provided that the following conditions are met:						 *
+* 													 *
+* * Redistributions of source code must retain the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer.										 *
+*    													 *
+* * Redistributions in binary form must reproduce the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer in the documentation and/or other						 *
+*   materials provided with the distribution.								 *
+* 													 *
+* * Neither the name of the Teraoka Laboratory nor the 							 *
+*   names of its contributors may be used to endorse or 						 *
+*   promote products derived from this software without 						 *
+*   specific prior written permission of Teraoka Laboratory 						 *
+*   													 *
+* 													 *
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED *
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
+* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR *
+* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 	 *
+* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 	 *
+* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR *
+* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF   *
+* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.								 *
+*********************************************************************************************************/
+
+/*
+
+The following table complete the one in RFC 5778, page 18. The AVPs are implemented below following the order of this table.
+We try to keep the structure of the grouped AVP by declaring the contained AVPs just before the grouped AVP they depend on.
+The number of '+' indicates the depth of the contained AVP.
+
+DEPTH	NAME					AVP	RFC		TYPE			NOTES
+	
+	MIP6-Feature-Vector			124	5447		Unsigned64
+	MIP-Mobile-Node-Address			333	4004		Address
++	MIP-Home-Agent-Address			334	4004		Address
+++	Destination-Host			293	3588		DiameterIdentity
+++	Destination-Realm			283	3588		DiameterIdentity
++	MIP-Home-Agent-Host			348	4004		Grouped
++	MIP6-Home-Link-Prefix			125	5447		OctetString
+	MIP6-Agent-Info				486	5447		Grouped
+	User-Name				1	3588		UTF8String
+	Service-Selection			493	5778		UTF8String
++	MIP-Replay-Mode				346	4004		Enumerated
++	MIP-Algorithm-Type			345	4004		Enumerated
++	MIP-MN-HA-SPI				491	5778		Unsigned32
++	MIP-MSA-Lifetime			367	4004		Unsigned32
++	MIP-Session-Key				343	4004		OctetString
+	MIP-MN-HA-MSA				492	5778		Grouped			different from MIP-MN-to-HA-MSA (331)
+	Chargeable-User-Identity		89	5778		OctetString
+
+QoS AVPs (RFC 5777 - implemented in the corresponding dictionary)
+
+	QoS-Capability				578	5777		Grouped
+	QoS-Resources				508	5777		Grouped
+
+ACCOUNTING AVPs (section 6.21)
+
+	Accounting-Input-Octets			363	4004, 4005	Unsigned64
+	Accounting-Output-Octets		364	4004, 4005	Unsigned64
+	Accounting-Input-Packets		365	4004, 4005	Unsigned64
+	Accounting-Output-Packets		366	4004, 4005	Unsigned64
+	Acct-Multi-Session-Id			50	3588		UTF8String
+	Acct-Session-Time			46	2866, 4004	Unsigned32
+	MIP6-Feature-Vector			----------------------------------
+	MIP-Mobile-Node-Address			----------------------------------
+	MIP6-Agent-Info				----------------------------------
+	Chargeable-User-Identity		----------------------------------
+	Service-Selection			----------------------------------
+	QoS-Resources				----------------------------------
+	QoS-Capability				----------------------------------
+	MIP-Careof-Address			487	5778		Address			needed (appears in MIR/MIA)
+
+REST OF THE AVPs IN THE MIR & MIA EXCLUDING *[AVP] (as written on page 19 of RFC 5778)
+
+MIP6-Request
+
+	Session-ID				263	3588
+	Auth-Application-Id			258	3588
+	User-Name				1	3588
+	Destination-Realm			283	3588
+	Origin-Host				264	3588
+	Origin-Realm				296	3588
+	Auth-Request-Type			274	3588
+	Origin-State-Id				278	3588
+	NAS-Identifier				32	2865		radius (see avp)        needed (radius)
+	NAS-IP-Address				4	2865            radius (see avp)        needed (radius)
+	NAS-IPv6-Address			95	3162            radius (see avp)        needed (radius)
+	NAS-Port-Type				61	2865            radius (see avp) 	needed (radius)
+	Called-Station-Id			30	2865            radius (see avp) 	needed (radius)
+	Calling-Station-Id			31	2865            radius (see avp)  	needed (radius)
+	MIP6-Feature-Vector			------------
+	MIP6-Auth-Mode				494	5778		Enumerated		needed (mip6a)
+	MIP-MN-AAA-SPI				341	5778		Unsigned32		needed (mip6a)
+	MIP-MN-HA-SPI				------------
+	MIP-Mobile-Node-Address			------------
+	MIP6-Agent-Info				------------
+	MIP-Careof-Address			------------
+	MIP-Authenticator			488	5778		OctetString		needed (mip6a)
+	MIP-MAC-Mobility-Data			489	5778		OctetString		needed (mip6a)
+	MIP-Timestamp				490	5778		OctetString		needed (mip6a)
+	QoS-Capability				------------
+	QoS-Resources				------------
+	Chargeable-User-Identity		------------
+	Service-Selection			------------
+	Authorization-Lifetime			291	3588
+	Auth-Session-State			277	3588
+	Proxy-Info				284	3588
+	Route-Record				282	3588
+
+MIP6-Answer - All of them are already implemented as base protocol AVPs or implemented earlier.
+
+*/
+
+/****************************************************************************************************************************************
+*																	*
+* This table is a copy of the registry named "MIP6 Authentication Mode Registry" and managed by IANA.					*
+* source : http://www.iana.org/assignments/aaa-parameters/aaa-parameters.txt								*
+* up to date on october 2010														*
+*																	*
+*      Value          Token       Reference												*
+*        0       Reserved         [RFC5778]												*
+*        1       MIP6_AUTH_MN_AAA [RFC5778]												*
+*   2-4294967295 Unassigned														*
+*																	*
+****************************************************************************************************************************************/
+
+
+/*
+
+NOTES
+
+check for omissions !
+
+*/
+
+#include <freeDiameter/extension.h>
+
+#define CHECK_dict_new( _type, _data, _parent, _ref )	\
+	CHECK_FCT(  fd_dict_new( fd_g_config->cnf_dict, (_type), (_data), (_parent), (_ref))  );
+
+#define CHECK_dict_search( _type, _criteria, _what, _result )	\
+	CHECK_FCT(  fd_dict_search( fd_g_config->cnf_dict, (_type), (_criteria), (_what), (_result), ENOENT) );
+
+struct local_rules_definition {
+	char 			*avp_name;
+	enum rule_position	position;
+	int 			min;
+	int			max;
+};
+
+#define RULE_ORDER( _position ) ((((_position) == RULE_FIXED_HEAD) || ((_position) == RULE_FIXED_TAIL)) ? 1 : 0 )
+
+#define PARSE_loc_rules( _rulearray, _parent) {								\
+	int __ar;											\
+	for (__ar=0; __ar < sizeof(_rulearray) / sizeof((_rulearray)[0]); __ar++) {			\
+		struct dict_rule_data __data = { NULL, 							\
+			(_rulearray)[__ar].position,							\
+			0, 										\
+			(_rulearray)[__ar].min,								\
+			(_rulearray)[__ar].max};							\
+		__data.rule_order = RULE_ORDER(__data.rule_position);					\
+		CHECK_FCT(  fd_dict_search( 								\
+			fd_g_config->cnf_dict,								\
+			DICT_AVP, 									\
+			AVP_BY_NAME, 									\
+			(_rulearray)[__ar].avp_name, 							\
+			&__data.rule_avp, 0 ) );							\
+		if ( !__data.rule_avp ) {								\
+			TRACE_DEBUG(INFO, "AVP Not found: '%s'", (_rulearray)[__ar].avp_name );		\
+			return ENOENT;									\
+		}											\
+		CHECK_FCT_DO( fd_dict_new( fd_g_config->cnf_dict, DICT_RULE, &__data, _parent, NULL),	\
+			{							        		\
+				TRACE_DEBUG(INFO, "Error on rule with AVP '%s'",      			\
+					 (_rulearray)[__ar].avp_name );		      			\
+				return EINVAL;					      			\
+			} );							      			\
+	}									      			\
+}
+
+#define enumval_def_u32( _val_, _str_ ) \
+		{ _str_, 		{ .u32 = _val_ }}
+
+#define enumval_def_os( _len_, _val_, _str_ ) \
+		{ _str_, 		{ .os = { .data = (unsigned char *)_val_, .len = _len_ }}}
+
+
+
+/* Defines if there are any */
+
+//New Result-Code for MIP (RFC5778, Section 7.*)
+#define DIAMETER_SUCCESS_RELOCATE_HA 2009
+#define DIAMETER_ERROR_MIP6_AUTH_MODE 5041
+
+//others
+#define MIP6_AUTH_MN_AAA 1
+
+/* Dictionary */
+
+int dict_mip6i_init(char * conffile)
+{
+	struct dict_object * mip6i;
+	{
+		struct dict_application_data data  = { 	7, "Diameter Mobile IPv6 IKE (MIP6I) Application" };
+		CHECK_dict_new( DICT_APPLICATION, &data , NULL, &mip6i);
+	}
+
+	/***************/
+	/* AVP section */
+	/***************/
+	{
+		/* Loading all the derived data formats */
+
+		struct dict_object * Address_type;
+		struct dict_object * UTF8String_type;
+		struct dict_object * DiameterIdentity_type;
+		struct dict_object * DiameterURI_type;
+		struct dict_object * Time_type;
+
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "Address", &Address_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "UTF8String", &UTF8String_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "DiameterIdentity", &DiameterIdentity_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "DiameterURI", &DiameterURI_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "Time", &Time_type);
+
+		/* MIP6-Feature-Vector - RFC 5447 */
+		{
+			/*
+
+			*/
+
+			struct dict_avp_data data = {
+					124, 					/* Code */
+					0, 					/* Vendor */
+					"MIP6-Feature-Vector", 			/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,		 	/* Fixed flag values */
+					AVP_TYPE_UNSIGNED64			/* base type of data */
+					};
+
+			CHECK_dict_new( DICT_AVP, &data , NULL, NULL);
+		}
+
+		/* MIP-Mobile-Node-Address - RFC 4004 */
+		{
+			/*
+
+			*/
+
+			struct dict_avp_data data = {
+					333, 					/* Code */
+					0, 					/* Vendor */
+					"MIP-Mobile-Node-Address",		/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,		 	/* Fixed flag values */
+					AVP_TYPE_OCTETSTRING			/* base type of data */
+					};
+
+			CHECK_dict_new( DICT_AVP, &data , Address_type, NULL);
+		}
+
+		/* MIP-Home-Agent-Address - RFC 4004 */
+		{
+			/*
+
+			*/
+
+			struct dict_avp_data data = {
+					334, 					/* Code */
+					0, 					/* Vendor */
+					"MIP-Home-Agent-Address",		/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,		 	/* Fixed flag values */
+					AVP_TYPE_OCTETSTRING			/* base type of data */
+					};
+
+			CHECK_dict_new( DICT_AVP, &data , Address_type, NULL);
+		}
+
+		/* Destination-Host - Base Protocol */
+
+			/*
+			Implemented in the base protocol
+			*/
+
+		/* Destination-Realm - Base Protocol */
+
+			/*
+			Implemented in the base protocol
+			*/
+
+		/* MIP-Home-Agent-Host - RFC 4004 */
+		{
+			/*
+
+			*/
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+					348, 					/* Code */
+					0, 					/* Vendor */
+					"MIP-Home-Agent-Host",			/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,		 	/* Fixed flag values */
+					AVP_TYPE_GROUPED 			/* base type of data */
+					};
+
+			struct local_rules_definition rules[] =
+						{ 	 {  "Destination-Realm",	RULE_REQUIRED,	-1, 1 }
+							,{  "Destination-Host",		RULE_REQUIRED,	-1, 1 }
+						};
+
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+			PARSE_loc_rules( rules, avp );
+		}
+
+		/* MIP6-Home-Link-Prefix - RFC 5447 */
+		{
+			/*
+
+			*/
+
+			struct dict_avp_data data = {
+					125, 					/* Code */
+					0, 					/* Vendor */
+					"MIP6-Home-Link-Prefix", 		/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,		 	/* Fixed flag values */
+					AVP_TYPE_OCTETSTRING			/* base type of data */
+					};
+
+			CHECK_dict_new( DICT_AVP, &data , NULL, NULL);
+		}
+
+		/* MIP6-Agent-Info - RFC 5447 */
+		{
+			/*
+
+			*/
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+					486, 					/* Code */
+					0, 					/* Vendor */
+					"MIP6-Agent-Info",			/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,		 	/* Fixed flag values */
+					AVP_TYPE_GROUPED 			/* base type of data */
+					};
+
+			struct local_rules_definition rules[] =
+						{ 	 {  "MIP-Home-Agent-Address", 		RULE_OPTIONAL, -1, 2 }
+							,{  "MIP-Home-Agent-Host",		RULE_OPTIONAL, -1, 1 }
+							,{  "MIP6-Home-Link-Prefix",		RULE_OPTIONAL, -1, 1 }
+						};
+
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+			PARSE_loc_rules( rules, avp );
+		}
+
+		/* User-Name - RFC 3588 */
+
+			/*
+			Implemented in the base protocol
+			*/
+
+		/* Service-Selection - RFC 5778 */
+		{
+			/*
+
+			*/
+
+			struct dict_avp_data data = {
+					493, 					/* Code */
+					0, 					/* Vendor */
+					"Service-Selection",			/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,		 	/* Fixed flag values */
+					AVP_TYPE_OCTETSTRING 			/* base type of data */
+					};
+
+			CHECK_dict_new( DICT_AVP, &data , UTF8String_type, NULL);
+		}
+
+		/* MIP-Replay-Mode - RFC 5778 */
+		{
+			/*
+
+			*/
+			struct dict_object 	* 	type;
+			struct dict_type_data	 	tdata = { AVP_TYPE_INTEGER32,	"Enumerated(MIP-Replay-Mode)"	, NULL, NULL, NULL };
+			struct dict_enumval_data 	t_1 = { "None",		{ .i32 = 1 }};
+			struct dict_enumval_data 	t_2 = { "Timestamp", 	{ .i32 = 2 }};
+
+			struct dict_avp_data 	data = {
+					346, 					/* Code */
+					0, 					/* Vendor */
+					"MIP-Replay-Mode",			/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,			/* Fixed flag values */
+					AVP_TYPE_INTEGER32 			/* base type of data */
+					};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata , NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1 , type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2 , type, NULL);
+			CHECK_dict_new( DICT_AVP, &data , type, NULL);
+		}
+
+		/* MIP-Algorithm-Type - RFC 5778 */
+		{
+			/*
+			The MIP-Algorithm-Type AVP (AVP Code 345) is of type Enumerated and
+			contains the Algorithm identifier for the associated Mobile IPv6
+			MN-HA Authentication Option.  The Diameter server selects the
+			algorithm type.  Existing algorithm types are defined in [RFC4004]
+			that also fulfill current RFC 4285 requirements. This AVP is reused
+			from [RFC4004].
+			*/
+			struct dict_object 	* 	type;
+			struct dict_type_data	 	tdata = { AVP_TYPE_INTEGER32,	"Enumerated(MIP-Algorithm-Type)"	, NULL, NULL, NULL };
+			struct dict_enumval_data 	t_2 = { "HMAC-SHA-1 [HMAC]",	{ .i32 = 2 }};
+
+			struct dict_avp_data 	data = {
+					345, 					/* Code */
+					0, 					/* Vendor */
+					"MIP-Algorithm-Type",			/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,			/* Fixed flag values */
+					AVP_TYPE_INTEGER32 			/* base type of data */
+					};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata , NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2 , type, NULL);
+			CHECK_dict_new( DICT_AVP, &data , type, NULL);
+		}
+
+		/* MIP-MN-HA-SPI - RFC 5778 */
+		{
+			/*
+
+			*/
+			struct dict_avp_data data = {
+					491, 					/* Code */
+					0, 					/* Vendor */
+					"MIP-MN-HA-SPI",			/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,		 	/* Fixed flag values */
+					AVP_TYPE_UNSIGNED32 			/* base type of data */
+					};
+
+			CHECK_dict_new( DICT_AVP, &data , NULL, NULL);
+		}
+
+		/* MIP-MSA-Lifetime - RFC 5778 */
+		{
+			/*
+
+			*/
+			struct dict_avp_data data = {
+					367, 					/* Code */
+					0, 					/* Vendor */
+					"MIP-MSA-Lifetime",			/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,		 	/* Fixed flag values */
+					AVP_TYPE_UNSIGNED32 			/* base type of data */
+					};
+
+			CHECK_dict_new( DICT_AVP, &data , NULL, NULL);
+		}
+
+		/* MIP-Session-Key - RFC 5778 */
+		{
+			/*
+
+			*/
+			struct dict_avp_data data = {
+					343, 					/* Code */
+					0, 					/* Vendor */
+					"MIP-Session-Key",			/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,		 	/* Fixed flag values */
+					AVP_TYPE_OCTETSTRING 			/* base type of data */
+					};
+
+			CHECK_dict_new( DICT_AVP, &data , NULL, NULL);
+		}
+
+		/* MIP-MN-HA-MSA - RFC 5778 */
+		{
+			/*
+
+			*/
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+					492, 					/* Code */
+					0, 					/* Vendor */
+					"MIP-MN-HA-MSA",			/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,		 	/* Fixed flag values */
+					AVP_TYPE_GROUPED 			/* base type of data */
+					};
+
+			struct local_rules_definition rules[] =
+						{ 	 {  "MIP-Session-Key", 		RULE_REQUIRED, -1, 1 }
+							,{  "MIP-MSA-Lifetime", 	RULE_REQUIRED, -1, 1 }
+							,{  "MIP-MN-HA-SPI", 		RULE_OPTIONAL, -1, 1 }
+							,{  "MIP-Algorithm-Type", 	RULE_OPTIONAL, -1, 1 }
+							,{  "MIP-Replay-Mode", 		RULE_OPTIONAL, -1, 1 }
+						};
+
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+			PARSE_loc_rules( rules, avp );
+		}
+
+		/* Chargeable-User-Identity - RFC 5778 */
+		{
+			/*
+
+			*/
+			struct dict_avp_data data = {
+					89, 					/* Code */
+					0, 					/* Vendor */
+					"Chargeable-User-Identity",		/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,		 	/* Fixed flag values */
+					AVP_TYPE_OCTETSTRING 			/* base type of data */
+					};
+
+			CHECK_dict_new( DICT_AVP, &data , NULL, NULL);
+		}
+
+	//////////////
+	/* QoS AVPs */
+	//////////////
+
+		/* QoS-Capability */
+
+			/*
+			Implemented in RFC 5777
+			*/
+
+		/* QoS-Resources */
+
+			/*
+			Implemented in RFC 5777
+			*/
+
+	/////////////////////
+	/* Accounting AVPs */
+	/////////////////////
+
+		/* Accounting-Input-Octets - RFC 4004 */
+		{
+			/*
+
+			*/
+			struct dict_avp_data data = {
+					363, 					/* Code */
+					0, 					/* Vendor */
+					"Accounting-Input-Octets",		/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,		 	/* Fixed flag values */
+					AVP_TYPE_UNSIGNED64 			/* base type of data */
+					};
+
+			CHECK_dict_new( DICT_AVP, &data , NULL, NULL);
+		}
+
+		/* Accounting-Output-Octets - RFC 4004 */
+		{
+			/*
+
+			*/
+			struct dict_avp_data data = {
+					364, 					/* Code */
+					0, 					/* Vendor */
+					"Accounting-Output-Octets",		/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,		 	/* Fixed flag values */
+					AVP_TYPE_UNSIGNED64 			/* base type of data */
+					};
+
+			CHECK_dict_new( DICT_AVP, &data , NULL, NULL);
+		}
+
+		/* Accounting-Input-Packets - RFC 4004 */
+		{
+			/*
+
+			*/
+			struct dict_avp_data data = {
+					365, 					/* Code */
+					0, 					/* Vendor */
+					"Accounting-Input-Packets",		/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,		 	/* Fixed flag values */
+					AVP_TYPE_UNSIGNED64 			/* base type of data */
+					};
+
+			CHECK_dict_new( DICT_AVP, &data , NULL, NULL);
+		}
+
+		/* Accounting-Output-Packets - RFC 4004 */
+		{
+			/*
+
+			*/
+			struct dict_avp_data data = {
+					366, 					/* Code */
+					0, 					/* Vendor */
+					"Accounting-Output-Packets",		/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,		 	/* Fixed flag values */
+					AVP_TYPE_UNSIGNED64 			/* base type of data */
+					};
+
+			CHECK_dict_new( DICT_AVP, &data , NULL, NULL);
+		}
+
+		/* Acct-Multi-Session-Id - RFC 3588 */
+
+			/*
+			Implemented in the base protocol
+			*/
+
+		/* Acct-Session-Time - RFC 4004 */
+		{
+			/*
+
+			*/
+			struct dict_avp_data data = {
+					46, 					/* Code */
+					0, 					/* Vendor */
+					"Acct-Session-Time",			/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,		 	/* Fixed flag values */
+					AVP_TYPE_UNSIGNED32 			/* base type of data */
+					};
+
+			CHECK_dict_new( DICT_AVP, &data , NULL, NULL);
+		}
+
+		/* MIP-Careof-Address - RFC 5778 */
+		{
+			/*
+			This AVP is needed in MIP6I at least for implementation reasons
+			(it appears in a command)
+			*/
+
+			struct dict_avp_data data = {
+					487, 					/* Code */
+					0, 					/* Vendor */
+					"MIP-Careof-Address",			/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,		 	/* Fixed flag values */
+					AVP_TYPE_OCTETSTRING			/* base type of data */
+					};
+
+			CHECK_dict_new( DICT_AVP, &data , Address_type, NULL);
+		}
+
+	/////////////////////////////////////
+	/* Radius AVPs used in MIR & MIA */
+	/////////////////////////////////////
+
+	/*
+	We used the following correspondences for determining the type of the Radius AVPs
+
+		Radius		Diameter
+
+		text		UTF8Sting
+		string		OctetString
+		address		Address
+		integer		Unsigned32
+		time		Time
+	*/
+
+
+		/* NAS-Identifier				32	3575 */
+		{
+			/*
+			string -> OctetString
+			*/
+
+			struct dict_avp_data data = {
+					32, 					/* Code */
+					0, 					/* Vendor */
+					"NAS-Identifier",			/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,		 	/* Fixed flag values */
+					AVP_TYPE_OCTETSTRING			/* base type of data */
+					};
+
+			CHECK_dict_new( DICT_AVP, &data , NULL, NULL);
+		}
+
+		/* NAS-IP-Address				4	3575 */
+		{
+			/*
+			address -> Address
+			*/
+
+			struct dict_avp_data data = {
+					4, 					/* Code */
+					0, 					/* Vendor */
+					"NAS-IP-Address",			/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,		 	/* Fixed flag values */
+					AVP_TYPE_OCTETSTRING			/* base type of data */
+					};
+
+			CHECK_dict_new( DICT_AVP, &data , Address_type, NULL);
+		}
+
+		/* NAS-IPv6-Address			95	3162 */
+		{
+			/*
+			address -> Address
+			*/
+
+			struct dict_avp_data data = {
+					95, 					/* Code */
+					0, 					/* Vendor */
+					"NAS-IPv6-Address",			/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,		 	/* Fixed flag values */
+					AVP_TYPE_OCTETSTRING			/* base type of data */
+					};
+
+			CHECK_dict_new( DICT_AVP, &data , Address_type, NULL);
+		}
+
+		/* NAS-Port-Type			61	2865 */
+		{
+			/*
+			integer -> Unsigned32
+
+			   Value
+
+			      The Value field is four octets.  "Virtual" refers to a connection
+			      to the NAS via some transport protocol, instead of through a
+			      physical port.  For example, if a user telnetted into a NAS to
+			      authenticate himself as an Outbound-User, the Access-Request might
+			      include NAS-Port-Type = Virtual as a hint to the RADIUS server
+			      that the user was not on a physical port.
+
+			      0       Async
+			      1       Sync
+			      2       ISDN Sync
+			      3       ISDN Async V.120
+			      4       ISDN Async V.110
+			      5       Virtual
+			      6       PIAFS
+			      7       HDLC Clear Channel
+			      8       X.25
+			      9       X.75
+			      10      G.3 Fax
+			      11      SDSL - Symmetric DSL
+			      12      ADSL-CAP - Asymmetric DSL, Carrierless Amplitude Phase
+				      Modulation
+			      13      ADSL-DMT - Asymmetric DSL, Discrete Multi-Tone
+			      14      IDSL - ISDN Digital Subscriber Line
+			      15      Ethernet
+			      16      xDSL - Digital Subscriber Line of unknown type
+			      17      Cable
+			      18      Wireless - Other
+			      19      Wireless - IEEE 802.11
+
+			      PIAFS is a form of wireless ISDN commonly used in Japan, and
+			      stands for PHS (Personal Handyphone System) Internet Access Forum
+			      Standard (PIAFS).
+			*/
+
+			struct dict_avp_data data = {
+					61, 					/* Code */
+					0, 					/* Vendor */
+					"NAS-Port-Type",			/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,		 	/* Fixed flag values */
+					AVP_TYPE_UNSIGNED32			/* base type of data */
+					};
+
+			CHECK_dict_new( DICT_AVP, &data , NULL, NULL);
+		}
+
+		/* Called-Station-Id			30	2865 */
+		{
+			/*
+			string -> OctetString
+			*/
+
+			struct dict_avp_data data = {
+					30, 					/* Code */
+					0, 					/* Vendor */
+					"Called-Station-Id",			/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,		 	/* Fixed flag values */
+					AVP_TYPE_OCTETSTRING			/* base type of data */
+					};
+
+			CHECK_dict_new( DICT_AVP, &data , NULL, NULL);
+		}
+		/* Calling-Station-Id			31	2865 */
+		{
+			/*
+			string -> OctetString
+			*/
+
+			struct dict_avp_data data = {
+					31, 					/* Code */
+					0, 					/* Vendor */
+					"Calling-Station-Id",			/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,		 	/* Fixed flag values */
+					AVP_TYPE_OCTETSTRING			/* base type of data */
+					};
+
+			CHECK_dict_new( DICT_AVP, &data , NULL, NULL);
+		}
+
+	///////////////////////////////////////////////////////////
+	/* REST OF THE AVP IN THE MIR AND MIA EXCLUDING *[AVP]   */
+	///////////////////////////////////////////////////////////
+
+		/* MIP6-Auth-Mode - RFC 5778 */
+		{
+			/*
+
+			*/
+			struct dict_object * 	 type;
+			struct dict_type_data 	 tdata = { AVP_TYPE_INTEGER32, "Enumerated(MIP6-Auth-Mode)", NULL, NULL, NULL };
+			struct dict_enumval_data t_0 = { "None", 	{ .i32 = MIP6_AUTH_MN_AAA }};
+			struct dict_avp_data data = {
+					494, 					/* Code */
+					0, 					/* Vendor */
+					"MIP6-Auth-Mode",			/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,		 	/* Fixed flag values */
+					AVP_TYPE_INTEGER32 			/* base type of data */
+					};
+
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata , NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_0 , type, NULL);
+			CHECK_dict_new( DICT_AVP, &data , type, NULL);
+		}
+
+		/* MIP-MN-AAA-SPI - RFC 5778 */
+		{
+			/*
+
+			*/
+
+			struct dict_avp_data data = {
+					341, 					/* Code */
+					0, 					/* Vendor */
+					"MIP-MN-AAA-SPI",			/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,		 	/* Fixed flag values */
+					AVP_TYPE_UNSIGNED32 			/* base type of data */
+					};
+
+			CHECK_dict_new( DICT_AVP, &data , NULL, NULL);
+		}
+
+		/* MIP-Authenticator - RFC 5778 */
+		{
+			/*
+
+			*/
+			struct dict_avp_data data = {
+					488, 					/* Code */
+					0, 					/* Vendor */
+					"MIP-Authenticator",			/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,		 	/* Fixed flag values */
+					AVP_TYPE_OCTETSTRING 			/* base type of data */
+					};
+
+			CHECK_dict_new( DICT_AVP, &data , NULL, NULL);
+		}
+
+		/* MIP-MAC-Mobility-Data - RFC 5778 */
+		{
+			/*
+
+			*/
+			struct dict_avp_data data = {
+					489, 					/* Code */
+					0, 					/* Vendor */
+					"MIP-MAC-Mobility-Data",		/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,		 	/* Fixed flag values */
+					AVP_TYPE_OCTETSTRING 			/* base type of data */
+					};
+
+			CHECK_dict_new( DICT_AVP, &data , NULL, NULL);
+		}
+
+		/* MIP-Timestamp - RFC 5778 */
+		{
+			/*
+
+			*/
+			struct dict_avp_data data = {
+					490, 					/* Code */
+					0, 					/* Vendor */
+					"MIP-Timestamp",			/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,		 	/* Fixed flag values */
+					AVP_TYPE_OCTETSTRING 			/* base type of data */
+					};
+
+			CHECK_dict_new( DICT_AVP, &data , NULL, NULL);
+		}
+	}
+
+/*******************/
+/* Command section */
+/*******************/
+
+	{
+		/* Diameter-EAP-Request (DER) */
+
+			/*
+			Defined in dict_eap
+			*/
+
+		/* Diameter-EAP-Answer (DEA) - COPIED FROM dict_eap.c, SEE IT FOR MORE REFERENCE */
+
+			/*
+			Defined in dict_eap
+			*/
+
+		/* MIP6-Request (MIR) */
+		{
+			/*
+
+			The MIP6-Request (MIR), indicated by the Command-Code field set to
+			325 and the 'R' bit set in the Command Flags field, is sent by the
+			HA, acting as a Diameter client, in order to request the
+			authentication and authorization of an MN.
+
+			Although the HA provides the Diameter server with replay protection-
+			related information, the HA is responsible for the replay protection.
+
+			The message format is shown below.
+
+			<MIP6-Request> ::= < Diameter Header: 325, REQ, PXY >
+					   < Session-ID >
+					   { Auth-Application-Id }
+					   { User-Name }
+					   { Destination-Realm }
+					   { Origin-Host }
+					   { Origin-Realm }
+					   { Auth-Request-Type }
+					   [ Destination-Host ]
+					   [ Origin-State-Id ]
+					   [ NAS-Identifier ]
+					   [ NAS-IP-Address ]
+					   [ NAS-IPv6-Address ]
+					   [ NAS-Port-Type ]
+					   [ Called-Station-Id ]
+					   [ Calling-Station-Id ]
+					   [ MIP6-Feature-Vector ]
+					   { MIP6-Auth-Mode }
+					   [ MIP-MN-AAA-SPI ]
+					   [ MIP-MN-HA-SPI ]
+					1*2{ MIP-Mobile-Node-Address }
+					   { MIP6-Agent-Info }
+					   { MIP-Careof-Address }
+					   [ MIP-Authenticator ]
+					   [ MIP-MAC-Mobility-Data ]
+					   [ MIP-Timestamp ]
+					   [ QoS-Capability ]
+					 * [ QoS-Resources ]
+					   [ Chargeable-User-Identity ]
+					   [ Service-Selection ]
+					   [ Authorization-Lifetime ]
+					   [ Auth-Session-State ]
+					 * [ Proxy-Info ]
+					 * [ Route-Record ]
+					 * [ AVP ]
+
+			If the MN is both authenticated and authorized for the mobility
+			service, then the Auth-Request-Type AVP is set to the value
+			AUTHORIZE_AUTHENTICATE.  This is the case when the MIP6-Auth-Mode is
+			set to the value MIP6_AUTH_MN_AAA.
+
+			*/
+			struct dict_object * cmd;
+			struct dict_cmd_data data = {
+					325, 					/* Code */
+					"MIP6-Request", 			/* Name */
+					CMD_FLAG_REQUEST | CMD_FLAG_PROXIABLE | CMD_FLAG_ERROR, 	/* Fixed flags */
+					CMD_FLAG_REQUEST | CMD_FLAG_PROXIABLE 						/* Fixed flag values */
+					};
+			struct local_rules_definition rules[] =
+						{ 	 {  "Session-Id", 			RULE_FIXED_HEAD, -1, 1 }
+						 	,{  "Auth-Application-Id", 		RULE_REQUIRED,   -1, 1 }
+							,{  "User-Name", 			RULE_REQUIRED,   -1, 1 }
+							,{  "Destination-Realm", 		RULE_REQUIRED,   -1, 1 }
+							,{  "Origin-Host", 			RULE_REQUIRED,   -1, 1 }
+							,{  "Origin-Realm", 			RULE_REQUIRED,   -1, 1 }
+							,{  "Auth-Request-Type", 		RULE_REQUIRED,   -1, 1 }
+							,{  "Destination-Host", 		RULE_OPTIONAL,   -1, 1 }
+							,{  "Origin-State-Id",	 		RULE_OPTIONAL,   -1, 1 }
+							,{  "NAS-Identifier", 			RULE_OPTIONAL,   -1, 1 }
+							,{  "NAS-IP-Address", 			RULE_OPTIONAL,   -1, 1 }
+							,{  "NAS-IPv6-Address", 		RULE_OPTIONAL,   -1, 1 }
+							,{  "NAS-Port-Type", 			RULE_OPTIONAL,   -1, 1 }
+							,{  "Called-Station-Id", 		RULE_OPTIONAL,   -1, 1 }
+							,{  "Calling-Station-Id", 		RULE_OPTIONAL,   -1, 1 }
+							,{  "MIP6-Feature-Vector", 		RULE_OPTIONAL,   -1, 1 }
+							,{  "MIP6-Auth-Mode", 			RULE_OPTIONAL,   -1, 1 }
+							,{  "MIP-MN-AAA-SPI", 			RULE_OPTIONAL,   -1, 1 }
+							,{  "MIP-MN-HA-SPI", 			RULE_OPTIONAL,   -1, 1 }
+							,{  "MIP-Mobile-Node-Address", 		RULE_OPTIONAL,    1, 2 }
+							,{  "MIP6-Agent-Info", 			RULE_OPTIONAL,   -1, 1 }
+							,{  "MIP-Careof-Address", 		RULE_OPTIONAL,   -1, 1 }
+							,{  "MIP-Authenticator", 		RULE_OPTIONAL,   -1, 1 }
+							,{  "MIP-MAC-Mobility-Data", 		RULE_OPTIONAL,   -1, 1 }
+							,{  "MIP-Timestamp", 			RULE_OPTIONAL,   -1, 1 }
+							,{  "QoS-Capability", 			RULE_OPTIONAL,   -1, 1 }
+							,{  "QoS-Resources", 			RULE_OPTIONAL,   -1, -1 }
+							,{  "Chargeable-User-Identity", 	RULE_OPTIONAL,   -1, 1 }
+							,{  "Service-Selection", 		RULE_OPTIONAL,   -1, 1 }
+							,{  "Authorization-Lifetime", 		RULE_OPTIONAL,   -1, 1 }
+							,{  "Auth-Session-State", 		RULE_OPTIONAL,   -1, 1 }
+							,{  "Proxy-Info", 			RULE_OPTIONAL,   -1, -1 }
+							,{  "Route-Record", 			RULE_OPTIONAL,   -1, -1 }
+						};
+
+			CHECK_dict_new( DICT_COMMAND, &data, mip6i, &cmd);
+			PARSE_loc_rules( rules, cmd );
+		}
+
+		/* MIP6-Answer (MIA) */
+		{
+			/*
+
+			The MIP6-Answer (MIA) message, indicated by the Command-Code field
+			set to 325 and the 'R' bit cleared in the Command Flags field, is
+			sent by the Diameter server in response to the MIP6-Request message.
+
+			The User-Name AVP MAY be included in the MIA if it is present in the
+			MIR.  The Result-Code AVP MAY contain one of the values defined in
+			Section 7, in addition to the values defined in [RFC3588].
+
+			An MIA message with the Result-Code AVP set to DIAMETER_SUCCESS MUST
+			include the MIP-Mobile-Node-Address AVP.
+
+			The message format is shown below.
+
+			<MIP6-Answer> ::= < Diameter Header: 325, PXY >
+					  < Session-Id >
+					  { Auth-Application-Id }
+					  { Result-Code }
+					  { Origin-Host }
+					  { Origin-Realm }
+					  { Auth-Request-Type }
+					  [ User-Name ]
+					  [ Authorization-Lifetime ]
+					  [ Auth-Session-State ]
+					  [ Error-Message ]
+					  [ Error-Reporting-Host ]
+					  [ Re-Auth-Request-Type ]
+					  [ MIP6-Feature-Vector ]
+					  [ MIP6-Agent-Info ]
+					*2[ MIP-Mobile-Node-Address ]
+					  [ MIP-MN-HA-MSA ]
+					* [ QoS-Resources ]
+					  [ Chargeable-User-Identity ]
+					  [ Service-Selection ]
+					  [ Origin-State-Id ]
+					* [ Proxy-Info ]
+					* [ Redirect-Host ]
+					  [ Redirect-Host-Usage ]
+					  [ Redirect-Max-Cache-Time ]
+					* [ Failed-AVP ]
+					* [ AVP ]
+
+			*/
+			struct dict_object * cmd;
+			struct dict_cmd_data data = {
+					325, 					/* Code */
+					"MIP6-Answer", 				/* Name */
+					CMD_FLAG_REQUEST | CMD_FLAG_PROXIABLE | CMD_FLAG_ERROR, 	/* Fixed flags */
+					CMD_FLAG_PROXIABLE 			/* Fixed flag values */
+					};
+			struct local_rules_definition rules[] =
+						{ 	 {  "Session-Id", 			RULE_FIXED_HEAD, -1, 1 }
+						 	,{  "Auth-Application-Id", 		RULE_REQUIRED,   -1, 1 }
+							,{  "Result-Code", 			RULE_REQUIRED,   -1, 1 }
+							,{  "Origin-Host", 			RULE_REQUIRED,   -1, 1 }
+							,{  "Origin-Realm", 			RULE_REQUIRED,   -1, 1 }
+							,{  "Auth-Request-Type", 		RULE_REQUIRED,   -1, 1 }
+							,{  "User-Name", 			RULE_OPTIONAL,   -1, 1 }
+							,{  "Authorization-Lifetime", 		RULE_OPTIONAL,   -1, 1 }
+							,{  "Auth-Session-State", 		RULE_OPTIONAL,   -1, 1 }
+							,{  "Error-Message", 			RULE_OPTIONAL,   -1, 1 }
+							,{  "Error-Reporting-Host", 		RULE_OPTIONAL,   -1, 1 }
+							,{  "Re-Auth-Request-Type", 		RULE_OPTIONAL,   -1, 1 }
+							,{  "MIP6-Feature-Vector", 		RULE_OPTIONAL,   -1, 1 }
+							,{  "MIP6-Agent-Info", 			RULE_OPTIONAL,   -1, 1 }
+							,{  "MIP-Mobile-Node-Address", 		RULE_OPTIONAL,   -1, 2 }
+							,{  "MIP-MN-HA-MSA", 			RULE_OPTIONAL,   -1, 1 }
+							,{  "QoS-Resources", 			RULE_OPTIONAL,   -1, -1 }
+							,{  "Chargeable-User-Identity",		RULE_OPTIONAL,   -1, 1 }
+							,{  "Service-Selection", 		RULE_OPTIONAL,   -1, 1 }
+							,{  "Origin-State-Id", 			RULE_OPTIONAL,   -1, 1 }
+							,{  "Proxy-Info", 			RULE_OPTIONAL,   -1, -1 }
+							,{  "Redirect-Host", 			RULE_OPTIONAL,   -1, -1 }
+							,{  "Redirect-Host-Usage", 		RULE_OPTIONAL,   -1, 1 }
+							,{  "Redirect-Max-Cache-Time", 		RULE_OPTIONAL,   -1, 1 }
+							,{  "Failed-AVP", 			RULE_OPTIONAL,   -1, -1 }
+						};
+
+			CHECK_dict_new( DICT_COMMAND, &data, mip6i, &cmd);
+			PARSE_loc_rules( rules, cmd );
+		}
+	}
+
+	LOG_D( "Dictionary Extension 'Diameter Mobile IPv6 IKE (MIP6I)' initialized");
+	return 0;
+}
+EXTENSION_ENTRY("dict_mip6i", dict_mip6i_init, "dict_rfc5777");
diff --git a/extensions/dict_nas_mipv6/CMakeLists.txt b/extensions/dict_nas_mipv6/CMakeLists.txt
new file mode 100644
index 0000000..517e948
--- /dev/null
+++ b/extensions/dict_nas_mipv6/CMakeLists.txt
@@ -0,0 +1,13 @@
+# The dict_nas_mipv6 extension
+PROJECT("MIPv6 NAS-to-HAAA Interaction Dictionary Definition" C)
+
+# Compile as a module
+FD_ADD_EXTENSION(dict_nas_mipv6 dict_nas_mipv6.c)
+
+
+####
+## INSTALL section ##
+
+INSTALL(TARGETS dict_nas_mipv6
+	LIBRARY DESTINATION ${INSTALL_EXTENSIONS_SUFFIX}
+	COMPONENT freeDiameter-dictionary-mip6)
diff --git a/extensions/dict_nas_mipv6/dict_nas_mipv6.c b/extensions/dict_nas_mipv6/dict_nas_mipv6.c
new file mode 100644
index 0000000..438e596
--- /dev/null
+++ b/extensions/dict_nas_mipv6/dict_nas_mipv6.c
@@ -0,0 +1,258 @@
+/*********************************************************************************************************
+* Software License Agreement (BSD License)                                                               *
+* Author: Francois Bard <francois@tera.ics.keio.ac.jp>							 *
+*													 *
+* Copyright (c) 2010, Teraoka Laboratory, Keio University						 *
+* All rights reserved.											 *
+* 													 *
+* Redistribution and use of this software in source and binary forms, with or without modification, are  *
+* permitted provided that the following conditions are met:						 *
+* 													 *
+* * Redistributions of source code must retain the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer.										 *
+*    													 *
+* * Redistributions in binary form must reproduce the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer in the documentation and/or other						 *
+*   materials provided with the distribution.								 *
+* 													 *
+* * Neither the name of the Teraoka Laboratory nor the 							 *
+*   names of its contributors may be used to endorse or 						 *
+*   promote products derived from this software without 						 *
+*   specific prior written permission of Teraoka Laboratory 						 *
+*   													 *
+* 													 *
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED *
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
+* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR *
+* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 	 *
+* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 	 *
+* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR *
+* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF   *
+* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.								 *
+*********************************************************************************************************/
+
+/*
+
+The following table lists the AVPs needed for the NAS to HAAA server interaction.
+We try to keep the structure of the grouped AVP by declaring the contained AVPs just before the grouped AVP they depend on.
+The number of '+' indicates the depth of the contained AVP.
+
+DEPTH	NAME					AVP CODE	RFC	TYPE			IMPLEMENTED	NOTES
+	
+	MIP6-Feature-Vector			124		5447	Unsigned64		yes
++	MIP-Home-Agent-Address			334		4004	Address			not yet
+++	Destination-Host			293		3588	DiameterIdentity	no (Base)
+++	Destination-Realm			283		3588	DiameterIdentity	no (Base)
++	MIP-Home-Agent-Host			348		4004	Grouped			not yet
++	MIP6-Home-Link-Prefix			125		5447	OctetString		yes
+	MIP6-Agent-Info				486		5447	Grouped			yes
+
+*/
+
+
+
+#include <freeDiameter/extension.h>
+
+/* The content of this file follows the same structure as dict_base_proto.c */
+
+#define CHECK_dict_new( _type, _data, _parent, _ref )	\
+	CHECK_FCT(  fd_dict_new( fd_g_config->cnf_dict, (_type), (_data), (_parent), (_ref))  );
+
+#define CHECK_dict_search( _type, _criteria, _what, _result )	\
+	CHECK_FCT(  fd_dict_search( fd_g_config->cnf_dict, (_type), (_criteria), (_what), (_result), ENOENT) );
+
+struct local_rules_definition {
+	char 			*avp_name;
+	enum rule_position	position;
+	int 			min;
+	int			max;
+};
+
+#define RULE_ORDER( _position ) ((((_position) == RULE_FIXED_HEAD) || ((_position) == RULE_FIXED_TAIL)) ? 1 : 0 )
+
+#define PARSE_loc_rules( _rulearray, _parent) {								\
+	int __ar;											\
+	for (__ar=0; __ar < sizeof(_rulearray) / sizeof((_rulearray)[0]); __ar++) {			\
+		struct dict_rule_data __data = { NULL, 							\
+			(_rulearray)[__ar].position,							\
+			0, 										\
+			(_rulearray)[__ar].min,								\
+			(_rulearray)[__ar].max};							\
+		__data.rule_order = RULE_ORDER(__data.rule_position);					\
+		CHECK_FCT(  fd_dict_search( 								\
+			fd_g_config->cnf_dict,								\
+			DICT_AVP, 									\
+			AVP_BY_NAME, 									\
+			(_rulearray)[__ar].avp_name, 							\
+			&__data.rule_avp, 0 ) );							\
+		if ( !__data.rule_avp ) {								\
+			TRACE_DEBUG(INFO, "AVP Not found: '%s'", (_rulearray)[__ar].avp_name );		\
+			return ENOENT;									\
+		}											\
+		CHECK_FCT_DO( fd_dict_new( fd_g_config->cnf_dict, DICT_RULE, &__data, _parent, NULL),	\
+			{							        		\
+				TRACE_DEBUG(INFO, "Error on rule with AVP '%s'",      			\
+					 (_rulearray)[__ar].avp_name );		      			\
+				return EINVAL;					      			\
+			} );							      			\
+	}									      			\
+}
+
+#define enumval_def_u32( _val_, _str_ ) \
+		{ _str_, 		{ .u32 = _val_ }}
+
+#define enumval_def_os( _len_, _val_, _str_ ) \
+		{ _str_, 		{ .os = { .data = (unsigned char *)_val_, .len = _len_ }}}
+
+
+
+
+
+
+/* Defines if there are any */
+
+/* Define Flags for MIP6-Feature-Vector*/
+
+#define MIP6_INTEGRATED 0x0000000000000001
+#define LOCAL_HOME_AGENT_ASSIGNMENT 0x0000000000000002
+
+/* Dictionary */
+
+int dict_nas_mipv6_init(char * conffile)
+{
+	struct dict_object * nas_mipv6;
+	{
+		struct dict_application_data data = { 5447, "MIPv6 NAS-to-HAAA Interaction" };
+		CHECK_dict_new( DICT_APPLICATION, &data , NULL, &nas_mipv6);
+	}
+
+	/* AVP section */
+	{
+		/* Loading the derived data formats */
+
+		struct dict_object * Address_type;
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "Address", &Address_type);
+
+		/* MIP6-Feature-Vector */
+		{
+			/*
+
+			*/
+
+			struct dict_avp_data data = { 
+					124, 					/* Code */
+					0, 					/* Vendor */
+					"MIP6-Feature-Vector", 			/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,		 	/* Fixed flag values */
+					AVP_TYPE_UNSIGNED64			/* base type of data */
+					};
+			
+			CHECK_dict_new( DICT_AVP, &data , NULL, NULL);
+		}
+
+		/* MIP-Home-Agent-Address - RFC 4004 */
+		{
+			/*
+
+			*/
+
+			struct dict_avp_data data = {
+					334, 					/* Code */
+					0, 					/* Vendor */
+					"MIP-Home-Agent-Address",		/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,		 	/* Fixed flag values */
+					AVP_TYPE_OCTETSTRING			/* base type of data */
+					};
+
+			CHECK_dict_new( DICT_AVP, &data , Address_type, NULL);
+		}
+
+		/* Destination-Host - Base Protocol */
+
+		/* Destination-Realm - Base Protocol */	
+
+		/* MIP-Home-Agent-Host - RFC 4004 */
+		{
+			/*
+			The MIP-Home-Agent-Host AVP (AVP Code 348) is of type Grouped and
+			contains the identity of the assigned Home Agent.  If the MIP-Home-
+			Agent-Host AVP is present in the AMR, the AAAH MUST copy it into the
+			HAR.
+
+			 MIP-Home-Agent-Host ::= < AVP Header: 348 >
+						  { Destination-Realm }
+						  { Destination-Host }
+						* [ AVP ]
+			*/
+
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+					348, 					/* Code */
+					0, 					/* Vendor */
+					"MIP-Home-Agent-Host", 			/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,		 	/* Fixed flag values */
+					AVP_TYPE_GROUPED 			/* base type of data */
+					};
+
+			struct local_rules_definition rules[] =
+						{ 	 {  "Destination-Realm", 	RULE_REQUIRED, -1, 1 }
+							,{  "Destination-Host",		RULE_REQUIRED, -1, 1 }
+						};
+
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+			PARSE_loc_rules( rules, avp );
+		}
+
+		/* MIP6-Home-Link-Prefix */
+		{
+			/*
+
+			*/
+
+			struct dict_avp_data data = { 
+					125, 					/* Code */
+					0, 					/* Vendor */
+					"MIP6-Home-Link-Prefix", 		/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,		 	/* Fixed flag values */
+					AVP_TYPE_OCTETSTRING			/* base type of data */
+					};
+			
+			CHECK_dict_new( DICT_AVP, &data , NULL, NULL);
+		}
+
+		/* MIP6-Agent-Info */
+		{
+			/*
+			
+			*/
+			struct dict_object * avp;
+			struct dict_avp_data data = { 
+					486, 					/* Code */
+					0, 					/* Vendor */
+					"MIP6-Agent-Info", 			/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,		 	/* Fixed flag values */
+					AVP_TYPE_GROUPED 			/* base type of data */
+					};
+
+			struct local_rules_definition rules[] = 
+						{ 	 {  "MIP-Home-Agent-Address", 		RULE_OPTIONAL, -1, 2 }
+							,{  "MIP-Home-Agent-Host",		RULE_OPTIONAL, -1, 1 }
+							,{  "MIP6-Home-Link-Prefix",		RULE_OPTIONAL, -1, 1 }
+						};
+			
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+			PARSE_loc_rules( rules, avp );
+		}
+	}
+
+	LOG_D( "Dictionary Extension 'MIPv6 NAS-to-HAAA Interaction' initialized");
+	return 0;
+}
+EXTENSION_ENTRY("dict_nas_mipv6", dict_nas_mipv6_init);
diff --git a/extensions/dict_nasreq/CMakeLists.txt b/extensions/dict_nasreq/CMakeLists.txt
new file mode 100644
index 0000000..438e3c1
--- /dev/null
+++ b/extensions/dict_nasreq/CMakeLists.txt
@@ -0,0 +1,13 @@
+# The dict_nasreq extension
+PROJECT("Diameter NASREQ (RFC4005) dictionary definitions" C)
+
+# Compile as a module
+FD_ADD_EXTENSION(dict_nasreq dict_nasreq.c)
+
+
+####
+## INSTALL section ##
+
+INSTALL(TARGETS dict_nasreq
+	LIBRARY DESTINATION ${INSTALL_EXTENSIONS_SUFFIX}
+	COMPONENT freeDiameter-dictionary-RFC4005)
diff --git a/extensions/dict_nasreq/dict_nasreq.c b/extensions/dict_nasreq/dict_nasreq.c
new file mode 100644
index 0000000..a87907b
--- /dev/null
+++ b/extensions/dict_nasreq/dict_nasreq.c
@@ -0,0 +1,3735 @@
+/*********************************************************************************************************
+* Software License Agreement (BSD License)                                                               *
+* Author: Sebastien Decugis <sdecugis@freediameter.net>							 *
+*													 *
+* Copyright (c) 2013, WIDE Project and NICT								 *
+* All rights reserved.											 *
+* 													 *
+* Redistribution and use of this software in source and binary forms, with or without modification, are  *
+* permitted provided that the following conditions are met:						 *
+* 													 *
+* * Redistributions of source code must retain the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer.										 *
+*    													 *
+* * Redistributions in binary form must reproduce the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer in the documentation and/or other						 *
+*   materials provided with the distribution.								 *
+* 													 *
+* * Neither the name of the WIDE Project or NICT nor the 						 *
+*   names of its contributors may be used to endorse or 						 *
+*   promote products derived from this software without 						 *
+*   specific prior written permission of WIDE Project and 						 *
+*   NICT.												 *
+* 													 *
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED *
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
+* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR *
+* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 	 *
+* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 	 *
+* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR *
+* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF   *
+* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.								 *
+*********************************************************************************************************/
+
+/* 
+ * Dictionary definitions of objects specified in Diameter NASREQ (RFC4005).
+ */
+#include <freeDiameter/extension.h>
+
+/* The content of this file follows the same structure as dict_base_proto.c */
+
+#define CHECK_dict_new( _type, _data, _parent, _ref )	\
+	CHECK_FCT(  fd_dict_new( fd_g_config->cnf_dict, (_type), (_data), (_parent), (_ref))  );
+
+#define CHECK_dict_search( _type, _criteria, _what, _result )	\
+	CHECK_FCT(  fd_dict_search( fd_g_config->cnf_dict, (_type), (_criteria), (_what), (_result), ENOENT) );
+
+struct local_rules_definition {
+	char 			*avp_name;
+	enum rule_position	position;
+	int 			min;
+	int			max;
+};
+
+#define RULE_ORDER( _position ) ((((_position) == RULE_FIXED_HEAD) || ((_position) == RULE_FIXED_TAIL)) ? 1 : 0 )
+
+#define PARSE_loc_rules( _rulearray, _parent) {								\
+	int __ar;											\
+	for (__ar=0; __ar < sizeof(_rulearray) / sizeof((_rulearray)[0]); __ar++) {			\
+		struct dict_rule_data __data = { NULL, 							\
+			(_rulearray)[__ar].position,							\
+			0, 										\
+			(_rulearray)[__ar].min,								\
+			(_rulearray)[__ar].max};							\
+		__data.rule_order = RULE_ORDER(__data.rule_position);					\
+		CHECK_FCT(  fd_dict_search( 								\
+			fd_g_config->cnf_dict,								\
+			DICT_AVP, 									\
+			AVP_BY_NAME, 									\
+			(_rulearray)[__ar].avp_name, 							\
+			&__data.rule_avp, 0 ) );							\
+		if ( !__data.rule_avp ) {								\
+			TRACE_DEBUG(INFO, "AVP Not found: '%s'", (_rulearray)[__ar].avp_name );		\
+			return ENOENT;									\
+		}											\
+		CHECK_FCT_DO( fd_dict_new( fd_g_config->cnf_dict, DICT_RULE, &__data, _parent, NULL),	\
+			{							        		\
+				TRACE_DEBUG(INFO, "Error on rule with AVP '%s'",      			\
+					 (_rulearray)[__ar].avp_name );		      			\
+				return EINVAL;					      			\
+			} );							      			\
+	}									      			\
+}
+
+#define enumval_def_u32( _val_, _str_ ) \
+		{ _str_, 		{ .u32 = _val_ }}
+
+#define enumval_def_os( _len_, _val_, _str_ ) \
+		{ _str_, 		{ .os = { .data = (unsigned char *)_val_, .len = _len_ }}}
+
+
+static int dnr_entry(char * conffile)
+{
+	struct dict_object * nasreq;
+	TRACE_ENTRY("%p", conffile);
+	
+	/* No Vendors definitions */
+	
+	/* Applications section */
+	{
+		/* NASREQ (RFC 4005) */
+		{
+			struct dict_application_data data = {        1, "Diameter Network Access Server Application" 			};
+			CHECK_dict_new( DICT_APPLICATION, &data, NULL, &nasreq);
+		}
+	}
+	
+	/* Derived AVP types section */
+	{
+		/* QoSFilterRule */
+		{
+			/*
+				The QosFilterRule format is derived from the OctetString AVP Base
+				Format.  It uses the ASCII charset.  Packets may be marked or
+				metered based on the following information:
+
+				 Direction                          (in or out)
+				 Source and destination IP address  (possibly masked)
+				 Protocol
+				 Source and destination port        (lists or ranges)
+				 DSCP values                        (no mask or range)
+
+				Rules for the appropriate direction are evaluated in order; the
+				first matched rule terminates the evaluation.  Each packet is
+				evaluated once.  If no rule matches, the packet is treated as best
+				effort.  An access device unable to interpret or apply a QoS rule
+				SHOULD NOT terminate the session.
+
+				QoSFilterRule filters MUST follow the following format:
+
+				action dir proto from src to dst [options]
+
+        				tag    - Mark packet with a specific DSCP
+                				 [DIFFSERV].  The DSCP option MUST be
+                				 included.
+        				meter  - Meter traffic.  The metering options
+                				 MUST be included.
+
+				dir           The format is as described under IPFilterRule.
+
+				proto         The format is as described under IPFilterRule.
+
+				src and dst   The format is as described under IPFilterRule.
+
+				 options:
+
+				 DSCP <color>
+				       Color values as defined in [DIFFSERV].  Exact
+				       matching of DSCP values is required (no masks or
+				       ranges).
+
+				 metering <rate> <color_under> <color_over>
+				       The metering option provides Assured Forwarding,
+				       as defined in [DIFFSERVAF], and MUST be present
+				       if the action is set to meter.  The rate option is
+				       the throughput, in bits per second, used
+				       by the access device to mark packets.  Traffic
+				       over the rate is marked with the color_over
+				       codepoint, and traffic under the rate is marked
+				       with the color_under codepoint.  The color_under
+				       and color_over options contain the drop
+				       preferences and MUST conform to the recommended
+				       codepoint keywords described in [DIFFSERVAF]
+				       (e.g., AF13).
+
+				       The metering option also supports the strict
+				       limit on traffic required by Expedited
+				       Forwarding, as defined in [DIFFSERVEF].  The
+				       color_over option may contain the keyword "drop"
+				       to prevent forwarding of traffic that exceeds the
+				       rate parameter.
+
+				 The rule syntax is a modified subset of ipfw(8) from FreeBSD,
+				 and the ipfw.c code may provide a useful base for
+				 implementations.
+			*/
+			struct dict_type_data data = { AVP_TYPE_OCTETSTRING,	"QoSFilterRule"		, NULL			, NULL			};
+			CHECK_dict_new( DICT_TYPE, &data , NULL, NULL);
+		}
+		
+	}
+	
+	/* AVP section */
+	{
+		struct dict_object * UTF8String_type;
+		struct dict_object * IPFilterRule_type;
+		struct dict_object * QoSFilterRule_type;
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "UTF8String", &UTF8String_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "IPFilterRule", &IPFilterRule_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "QoSFilterRule", &QoSFilterRule_type);
+
+/********************************
+ *  NAS Session AVPs            *
+ ********************************/		
+		/* NAS-Port */
+		{
+			/*
+				The NAS-Port AVP (AVP Code 5) is of type Unsigned32 and contains the
+				physical or virtual port number of the NAS which is authenticating
+				the user.  Note that "port" is meant in its sense as a service
+				connection on the NAS, not as an IP protocol identifier.
+
+				Either NAS-Port or NAS-Port-Id (AVP Code 87) SHOULD be present in
+				AA-Request (AAR) commands if the NAS differentiates among its ports.
+			*/
+			struct dict_avp_data data = { 
+					5, 					/* Code */
+					0, 					/* Vendor */
+					"NAS-Port", 				/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,		 	/* Fixed flag values */
+					AVP_TYPE_UNSIGNED32 			/* base type of data */
+					};
+			CHECK_dict_new( DICT_AVP, &data , NULL, NULL);
+		}
+		
+		/* NAS-Port-Id */
+		{
+			/*
+				The NAS-Port-Id AVP (AVP Code 87) is of type UTF8String and consists
+				of ASCII text identifying the port of the NAS authenticating the
+				user.  Note that "port" is meant in its sense as a service connection
+				on the NAS, not as an IP protocol identifier.
+
+				Either NAS-Port or NAS-Port-Id SHOULD be present in AA-Request (AAR)
+				commands if the NAS differentiates among its ports.  NAS-Port-Id is
+				intended for use by NASes that cannot conveniently number their
+				ports.
+			*/
+			struct dict_avp_data data = { 
+					87, 					/* Code */
+					0, 					/* Vendor */
+					"NAS-Port-Id", 				/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,		 	/* Fixed flag values */
+					AVP_TYPE_OCTETSTRING 			/* base type of data */
+					};
+			CHECK_dict_new( DICT_AVP, &data , UTF8String_type, NULL);
+		}
+		
+		/* NAS-Port-Type */
+		{
+			/*
+				The NAS-Port-Type AVP (AVP Code 61) is of type Enumerated and
+				contains the type of the port on which the NAS is authenticating the
+				user.  This AVP SHOULD be present if the NAS uses the same NAS-Port
+				number ranges for different service types concurrently.
+
+				The supported values are defined in [RADIUSTypes].  The following
+				list is informational and subject to change by the IANA.
+				
+				http://www.iana.org/assignments/radius-types
+				Sub-registry: Values for RADIUS Attribute 61, NAS-Port-Type
+				Reference: [RFC2865]
+				
+				Extract on 2009.06.01:
+				0      Async                                                               [RFC2865]
+				1      Sync                                                                [RFC2865]
+				2      ISDN Sync                                                           [RFC2865]
+				3      ISDN Async V.120                                                    [RFC2865]
+				4      ISDN Async V.110                                                    [RFC2865]
+				5      Virtual                                                             [RFC2865]
+				6      PIAFS                                                               [RFC2865]
+				7      HDLC Clear Channel                                                  [RFC2865]
+				8      X.25                                                                [RFC2865]
+				9      X.75                                                                [RFC2865]
+				10     G.3 Fax                                                             [RFC2865]
+				11     SDSL - Symmetric DSL                                                [RFC2865]
+				12     ADSL-CAP - Asymmetric DSL, Carrierless Amplitude Phase Modulation   [RFC2865]
+				13     ADSL-DMT - Asymmetric DSL, Discrete Multi-Tone                      [RFC2865]
+				14     IDSL - ISDN Digital Subscriber Line                                 [RFC2865]
+				15     Ethernet                                                            [RFC2865]
+				16     xDSL - Digital Subscriber Line of unknown type                      [RFC2865]
+				17     Cable                                                               [RFC2865]
+				18     Wireless - Other                                                    [RFC2865]
+				19     Wireless - IEEE 802.11                                              [RFC2865]
+				20     Token-Ring                                                          [RFC3580] 
+				21     FDDI                                                                [RFC3580]
+				22     Wireless - CDMA2000                                                 [McCann] 
+				23     Wireless - UMTS                                                     [McCann]
+				24     Wireless - 1X-EV                                                    [McCann]
+				25     IAPP                                                                [IEEE 802.11F][Kerry]   
+				26     FTTP - Fiber to the Premises                                        [Nyce]
+				27     Wireless - IEEE 802.16                                              [IEEE 802.16]          12 December 2006
+				28     Wireless - IEEE 802.20                                              [IEEE 802.20]          12 December 2006
+				29     Wireless - IEEE 802.22                                              [IEEE 802.22]          12 December 2006		
+				30     PPPoA - PPP over ATM                                                [RFC4603]
+				31     PPPoEoA - PPP over Ethernet over ATM                                [RFC4603]
+				32     PPPoEoE - PPP over Ethernet over Ethernet                           [RFC4603]
+				33     PPPoEoVLAN - PPP over Ethernet over VLAN                            [RFC4603]
+				34     PPPoEoQinQ - PPP over Ethernet over IEEE 802.1QinQ                  [RFC4603]
+				35     xPON - Passive Optical Network                                      [Hublet][Yan]           19 June 2007
+			*/
+			
+			struct dict_object 	*type;
+			struct dict_type_data 	 tdata = { AVP_TYPE_UNSIGNED32,	"Enumerated(NAS-Port-Type)"	, NULL, NULL};
+			struct dict_enumval_data tvals[] = {
+				enumval_def_u32( 0, "Async [RFC2865]"),
+				enumval_def_u32( 1, "Sync [RFC2865]"),
+				enumval_def_u32( 2, "ISDN Sync [RFC2865]"),
+				enumval_def_u32( 3, "ISDN Async V.120 [RFC2865]"),
+				enumval_def_u32( 4, "ISDN Async V.110 [RFC2865]"),
+				enumval_def_u32( 5, "Virtual [RFC2865]"),
+				enumval_def_u32( 6, "PIAFS [RFC2865]"),
+				enumval_def_u32( 7, "HDLC Clear Channel [RFC2865]"),
+				enumval_def_u32( 8, "X.25 [RFC2865]"),
+				enumval_def_u32( 9, "X.75 [RFC2865]"),
+				enumval_def_u32(10, "G.3 Fax [RFC2865]"),
+				enumval_def_u32(11, "SDSL - Symmetric DSL [RFC2865]"),
+				enumval_def_u32(12, "ADSL-CAP - Asymmetric DSL, Carrierless Amplitude Phase Modulation [RFC2865]"),
+				enumval_def_u32(13, "ADSL-DMT - Asymmetric DSL, Discrete Multi-Tone [RFC2865]"),
+				enumval_def_u32(14, "IDSL - ISDN Digital Subscriber Line [RFC2865]"),
+				enumval_def_u32(15, "Ethernet [RFC2865]"),
+				enumval_def_u32(16, "xDSL - Digital Subscriber Line of unknown type [RFC2865]"),
+				enumval_def_u32(17, "Cable [RFC2865]"),
+				enumval_def_u32(18, "Wireless - Other [RFC2865]"),
+				enumval_def_u32(19, "Wireless - IEEE 802.11 [RFC2865]"),
+				enumval_def_u32(20, "Token-Ring [RFC3580]"),
+				enumval_def_u32(21, "FDDI [RFC3580]"),
+				enumval_def_u32(22, "Wireless - CDMA2000 [McCann]"),
+				enumval_def_u32(23, "Wireless - UMTS [McCann]"),
+				enumval_def_u32(24, "Wireless - 1X-EV [McCann]"),
+				enumval_def_u32(25, "IAPP [IEEE 802.11F][Kerry]"),
+				enumval_def_u32(26, "FTTP - Fiber to the Premises [Nyce]"),
+				enumval_def_u32(27, "Wireless - IEEE 802.16 [IEEE 802.16]"),
+				enumval_def_u32(28, "Wireless - IEEE 802.20 [IEEE 802.20]"),
+				enumval_def_u32(29, "Wireless - IEEE 802.22 [IEEE 802.22]"),
+				enumval_def_u32(30, "PPPoA - PPP over ATM [RFC4603]"),
+				enumval_def_u32(31, "PPPoEoA - PPP over Ethernet over ATM [RFC4603]"),
+				enumval_def_u32(32, "PPPoEoE - PPP over Ethernet over Ethernet [RFC4603]"),
+				enumval_def_u32(33, "PPPoEoVLAN - PPP over Ethernet over VLAN [RFC4603]"),
+				enumval_def_u32(34, "PPPoEoQinQ - PPP over Ethernet over IEEE 802.1QinQ [RFC4603]"),
+				enumval_def_u32(35, "xPON - Passive Optical Network [Hublet][Yan]")
+			};
+			struct dict_avp_data 	data = { 
+					61, 					/* Code */
+					0, 					/* Vendor */
+					"NAS-Port-Type", 			/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,			/* Fixed flag values */
+					AVP_TYPE_UNSIGNED32 			/* base type of data */
+					};
+			int i;
+			/* Create the Enumerated type, enumerated values, and the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata , NULL, &type);
+			for (i = 0; i < sizeof(tvals) / sizeof(tvals[0]); i++) {
+				CHECK_dict_new( DICT_ENUMVAL, &tvals[i], type, NULL);
+			}
+			CHECK_dict_new( DICT_AVP, &data , type, NULL);
+		}
+		
+		/* Called-Station-Id */
+		{
+			/*
+				The Called-Station-Id AVP (AVP Code 30) is of type UTF8String and
+				allows the NAS to send the ASCII string describing the layer 2
+				address the user contacted in the request.  For dialup access, this
+				can be a phone number obtained by using Dialed Number Identification
+				(DNIS) or a similar technology.  Note that this may be different from
+				the phone number the call comes in on.  For use with IEEE 802 access,
+				the Called-Station-Id MAY contain a MAC address formatted as
+				described in [RAD802.1X].  It SHOULD only be present in
+				authentication and/or authorization requests.
+
+				If the Auth-Request-Type AVP is set to authorization-only and the
+				User-Name AVP is absent, the Diameter Server MAY perform
+				authorization based on this field.  This can be used by a NAS to
+				request whether a call should be answered based on the DNIS.
+			*/
+			struct dict_avp_data data = { 
+					30, 					/* Code */
+					0, 					/* Vendor */
+					"Called-Station-Id", 			/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,		 	/* Fixed flag values */
+					AVP_TYPE_OCTETSTRING 			/* base type of data */
+					};
+			CHECK_dict_new( DICT_AVP, &data , UTF8String_type, NULL);
+		}
+		
+		/* Calling-Station-Id */
+		{
+			/*
+				The Calling-Station-Id AVP (AVP Code 31) is of type UTF8String and
+				allows the NAS to send the ASCII string describing the layer 2
+				address from which the user connected in the request.  For dialup
+				access, this is the phone number the call came from, using Automatic
+				Number Identification (ANI) or a similar technology.  For use with
+				IEEE 802 access, the Calling-Station-Id AVP MAY contain a MAC
+				address, formated as described in [RAD802.1X].  It SHOULD only be
+				present in authentication and/or authorization requests.
+
+				If the Auth-Request-Type AVP is set to authorization-only and the
+				User-Name AVP is absent, the Diameter Server MAY perform
+				authorization based on this field.  This can be used by a NAS to
+				request whether a call should be answered based on the layer 2
+				address (ANI, MAC Address, etc.)
+			*/
+			struct dict_avp_data data = { 
+					31, 					/* Code */
+					0, 					/* Vendor */
+					"Calling-Station-Id", 			/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,		 	/* Fixed flag values */
+					AVP_TYPE_OCTETSTRING 			/* base type of data */
+					};
+			CHECK_dict_new( DICT_AVP, &data , UTF8String_type, NULL);
+		}
+		
+		/* Connect-Info */
+		{
+			/*
+				The Connect-Info AVP (AVP Code 77) is of type UTF8String and is sent
+				in the AA-Request message or ACR STOP message.  When sent in the
+				Access-Request, it indicates the nature of the user's connection.
+				The connection speed SHOULD be included at the beginning of the first
+				Connect-Info AVP in the message.  If the transmit and receive
+				connection speeds differ, both may be included in the first AVP with
+				the transmit speed listed first (the speed the NAS modem transmits
+				at), then a slash (/), then the receive speed, and then other
+				optional information.
+
+				For example: "28800 V42BIS/LAPM" or "52000/31200 V90"
+
+				More than one Connect-Info attribute may be present in an
+				Accounting-Request packet to accommodate expected efforts by the ITU
+				to have modems report more connection information in a standard
+				format that might exceed 252 octets.
+
+				If sent in the ACR STOP, this attribute may summarize statistics
+				relating to session quality.  For example, in IEEE 802.11, the
+				Connect-Info attribute may contain information on the number of link
+				layer retransmissions.  The exact format of this attribute is
+				implementation specific.
+			*/
+			struct dict_avp_data data = { 
+					77, 					/* Code */
+					0, 					/* Vendor */
+					"Connect-Info", 			/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,		 	/* Fixed flag values */
+					AVP_TYPE_OCTETSTRING 			/* base type of data */
+					};
+			CHECK_dict_new( DICT_AVP, &data , UTF8String_type, NULL);
+		}
+		
+		/* Originating-Line-Info */
+		{
+			/*
+				The Originating-Line-Info AVP (AVP Code 94) is of type OctetString
+				and is sent by the NAS system to convey information about the origin
+				of the call from an SS7 system.
+
+				The originating line information (OLI) element indicates the nature
+				and/or characteristics of the line from which a call originated
+				(e.g., pay phone, hotel, cellular).  Telephone companies are starting
+				to offer OLI to their customers as an option over Primary Rate
+				Interface (PRI).  Internet Service Providers (ISPs) can use OLI in
+				addition to Called-Station-Id and Calling-Station-Id attributes to
+				differentiate customer calls and to define different services.
+
+				The Value field contains two octets (00 - 99).  ANSI T1.113 and
+				BELLCORE 394 can be used for additional information about these
+				values and their use.  For more information on current assignment
+				values, see [http://www.nanpa.com/number_resource_info/ani_ii_assignments.html].
+
+			*/
+			struct dict_object 	*type;
+			struct dict_type_data 	 tdata = { AVP_TYPE_OCTETSTRING,	"Enumerated(Originating-Line-Info)"	, NULL, NULL};
+			struct dict_enumval_data tvals[] = {
+				enumval_def_os( 2, "00", "Plain Old Telephone Service (POTS)"),
+				enumval_def_os( 2, "01", "Multiparty Line (more than 2)"),
+				enumval_def_os( 2, "02", "ANI Failure"),
+				enumval_def_os( 2, "06", "Station Level Rating"),
+				enumval_def_os( 2, "07", "Special Operator Handling Required"),
+				enumval_def_os( 2, "20", "Automatic Identified Outward Dialing (AIOD)"),
+				enumval_def_os( 2, "23", "Coin or Non-Coin"),
+				enumval_def_os( 2, "24", "Toll Free Service (Non-Pay Origination)"),
+				enumval_def_os( 2, "25", "Toll Free Service (Pay Origination)"),
+				enumval_def_os( 2, "27", "Toll Free Service (Coin Control Origination)"),
+				enumval_def_os( 2, "29", "Prison/Inmate Service"),
+				enumval_def_os( 2, "30", "Intercept (Blank)"),
+				enumval_def_os( 2, "31", "Intercept (Trouble)"),
+				enumval_def_os( 2, "32", "Intercept (Regular)"),
+				enumval_def_os( 2, "34", "Telco Operator Handled Call"),
+				enumval_def_os( 2, "52", "Outward Wide Area Telecommunications Service (OUTWATS)"),
+				enumval_def_os( 2, "60", "Telecommunications Relay Service (TRS)(Unrestricted)"),
+				enumval_def_os( 2, "61", "Cellular/Wireless PCS (Type 1)"),
+				enumval_def_os( 2, "62", "Cellular/Wireless PCS (Type 2)"),
+				enumval_def_os( 2, "63", "Cellular/Wireless PCS (Roaming)"),
+				enumval_def_os( 2, "66", "TRS (Hotel)"),
+				enumval_def_os( 2, "67", "TRS (Restricted)"),
+				enumval_def_os( 2, "70", "Pay Station, No Coin Control"),
+				enumval_def_os( 2, "93", "Access for Private Virtual Network Service")
+			};
+			struct dict_avp_data data = { 
+					94, 					/* Code */
+					0, 					/* Vendor */
+					"Originating-Line-Info", 		/* Name */
+					AVP_FLAG_VENDOR, 			/* Fixed flags */
+					0,		 			/* Fixed flag values */
+					AVP_TYPE_OCTETSTRING 			/* base type of data */
+					};
+			int i;
+			/* Create the Enumerated type, enumerated values, and the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata , NULL, &type);
+			for (i = 0; i < sizeof(tvals) / sizeof(tvals[0]); i++) {
+				CHECK_dict_new( DICT_ENUMVAL, &tvals[i], type, NULL);
+			}
+			CHECK_dict_new( DICT_AVP, &data , type, NULL);
+		}
+		
+		/* Reply-Message */
+		{
+			/*
+				The Reply-Message AVP (AVP Code 18) is of type UTF8String and
+				contains text that MAY be displayed to the user.  When used in an
+				AA-Answer message with a successful Result-Code AVP, it indicates
+				success.  When found in an AAA message with a Result-Code other than
+				DIAMETER_SUCCESS, the AVP contains a failure message.
+
+				The Reply-Message AVP MAY indicate dialog text to prompt the user
+				before another AA-Request attempt.  When used in an AA-Answer with a
+				Result-Code of DIAMETER_MULTI_ROUND_AUTH or in an Re-Auth-Request
+				message, it MAY contain a dialog text to prompt the user for a
+				response.
+
+				Multiple Reply-Messages MAY be included, and if any are displayed,
+				they MUST be displayed in the same order as they appear in the
+				Diameter message.
+			*/
+			struct dict_avp_data data = { 
+					18, 					/* Code */
+					0, 					/* Vendor */
+					"Reply-Message", 			/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,		 	/* Fixed flag values */
+					AVP_TYPE_OCTETSTRING 			/* base type of data */
+					};
+			CHECK_dict_new( DICT_AVP, &data , UTF8String_type, NULL);
+		}
+		
+/********************************
+ *  NAS Authentication AVPs     *
+ ********************************/		
+		/* User-Password */
+		{
+			/*
+				The User-Password AVP (AVP Code 2) is of type OctetString and
+				contains the password of the user to be authenticated, or the user's
+				input in a multi-round authentication exchange.
+
+				The User-Password AVP contains a user password or one-time password
+				and therefore represents sensitive information.  As required in
+				[BASE], Diameter messages are encrypted by using IPsec or TLS.
+				Unless this AVP is used for one-time passwords, the User-Password AVP
+				SHOULD NOT be used in untrusted proxy environments without encrypting
+				it by using end-to-end security techniques, such as the proposed CMS
+				Security [DiamCMS].
+
+				The clear-text password (prior to encryption) MUST NOT be longer than
+				128 bytes in length.
+			*/
+			struct dict_avp_data data = { 
+					2, 					/* Code */
+					0, 					/* Vendor */
+					"User-Password", 			/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,		 	/* Fixed flag values */
+					AVP_TYPE_OCTETSTRING 			/* base type of data */
+					};
+			CHECK_dict_new( DICT_AVP, &data , NULL, NULL);
+		}
+		
+		/* Password-Retry */
+		{
+			/*
+				The Password-Retry AVP (AVP Code 75) is of type Unsigned32 and MAY be
+				included in the AA-Answer if the Result-Code indicates an
+				authentication failure.  The value of this AVP indicates how many
+				authentication attempts a user is permitted before being
+				disconnected.  This AVP is primarily intended for use when the
+				Framed-Protocol AVP (see section 6.10.1) is set to ARAP.
+			*/
+			struct dict_avp_data data = { 
+					75, 					/* Code */
+					0, 					/* Vendor */
+					"Password-Retry", 			/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,		 	/* Fixed flag values */
+					AVP_TYPE_UNSIGNED32 			/* base type of data */
+					};
+			CHECK_dict_new( DICT_AVP, &data , NULL, NULL);
+		}
+		
+		/* Prompt */
+		{
+			/*
+				The Prompt AVP (AVP Code 76) is of type Enumerated and MAY be present
+				in the AA-Answer message.  When present, it is used by the NAS to
+				determine whether the user's response, when entered, should be
+				echoed.
+
+				The supported values are listed in http://www.iana.org/assignments/radius-types
+				Sub-registry: Values for RADIUS Attribute 76, Prompt
+				Reference: [RFC2869]
+			*/
+			struct dict_object 	*type;
+			struct dict_type_data 	 tdata = { AVP_TYPE_UNSIGNED32,	"Enumerated(Prompt)"	, NULL, NULL};
+			struct dict_enumval_data tvals[] = {
+				enumval_def_u32( 0, "No Echo [RFC2869]"),
+				enumval_def_u32( 1, "Echo [RFC2869]")
+			};
+			struct dict_avp_data data = { 
+					76, 					/* Code */
+					0, 					/* Vendor */
+					"Prompt", 			/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,		 	/* Fixed flag values */
+					AVP_TYPE_UNSIGNED32 			/* base type of data */
+					};
+			int i;
+			/* Create the Enumerated type, enumerated values, and the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata , NULL, &type);
+			for (i = 0; i < sizeof(tvals) / sizeof(tvals[0]); i++) {
+				CHECK_dict_new( DICT_ENUMVAL, &tvals[i], type, NULL);
+			}
+			CHECK_dict_new( DICT_AVP, &data , type, NULL);
+		}
+		
+		/* CHAP-Algorithm */
+		{
+			/*
+				The CHAP-Algorithm AVP (AVP Code 403) is of type Enumerated and
+				contains the algorithm identifier used in the computation of the CHAP
+				response [PPPCHAP].  The following values are currently supported:
+
+				CHAP with MD5       5
+				 The CHAP response is computed by using the procedure described
+				 in [PPPCHAP].  This algorithm requires that the CHAP-Response
+				 AVP MUST be present in the CHAP-Auth AVP.
+			*/
+			struct dict_object 	*type;
+			struct dict_type_data 	 tdata = { AVP_TYPE_UNSIGNED32,	"Enumerated(CHAP-Algorithm)"	, NULL, NULL};
+			struct dict_enumval_data tvals[] = {
+				enumval_def_u32( 5, "CHAP with MD5")
+			};
+			struct dict_avp_data adata = { 
+					403, 					/* Code */
+					0, 					/* Vendor */
+					"CHAP-Algorithm", 			/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,			/* Fixed flag values */
+					AVP_TYPE_UNSIGNED32 			/* base type of data */
+					};
+			int i;
+			CHECK_dict_new( DICT_TYPE, &tdata , NULL, &type);
+			for (i = 0; i < sizeof(tvals) / sizeof(tvals[0]); i++) {
+				CHECK_dict_new( DICT_ENUMVAL, &tvals[i], type, NULL);
+			}
+			CHECK_dict_new( DICT_AVP, &adata , type, NULL);
+		}
+		
+		/* CHAP-Ident */
+		{
+			/*
+				The CHAP-Ident AVP (AVP Code 404) is of type OctetString and contains
+				the 1 octet CHAP Identifier used in the computation of the CHAP
+				response [PPPCHAP].
+			*/
+			struct dict_avp_data adata = { 
+					404, 					/* Code */
+					0, 					/* Vendor */
+					"CHAP-Ident", 				/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,			/* Fixed flag values */
+					AVP_TYPE_OCTETSTRING 			/* base type of data */
+					};
+			CHECK_dict_new( DICT_AVP, &adata , NULL, NULL);
+		}
+			
+		/* CHAP-Response */
+		{
+			/*
+				The CHAP-Response AVP (AVP Code 405) is of type OctetString and
+				contains the 16 octet authentication data provided by the user in
+				response to the CHAP challenge [PPPCHAP].
+			*/
+			struct dict_avp_data adata = { 
+					405, 					/* Code */
+					0, 					/* Vendor */
+					"CHAP-Response", 			/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,			/* Fixed flag values */
+					AVP_TYPE_OCTETSTRING 			/* base type of data */
+					};
+			CHECK_dict_new( DICT_AVP, &adata , NULL, NULL);
+		}
+			
+		/* CHAP-Auth */
+		{
+			/*
+				The CHAP-Auth AVP (AVP Code 402) is of type Grouped and contains the
+				information necessary to authenticate a user using the PPP
+				Challenge-Handshake Authentication Protocol (CHAP) [PPPCHAP].  If the
+				CHAP-Auth AVP is found in a message, the CHAP-Challenge AVP MUST be
+				present as well.  The optional AVPs containing the CHAP response
+				depend upon the value of the CHAP-Algorithm AVP.  The grouped AVP has
+				the following ABNF grammar:
+
+				CHAP-Auth  ::= < AVP Header: 402 >
+        				     { CHAP-Algorithm }
+        				     { CHAP-Ident }
+        				     [ CHAP-Response ]
+        				   * [ AVP ]
+			*/
+			struct dict_object * avp;
+			struct dict_avp_data data = { 
+					402, 					/* Code */
+					0, 					/* Vendor */
+					"CHAP-Auth", 				/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,			/* Fixed flag values */
+					AVP_TYPE_GROUPED 			/* base type of data */
+					};
+			struct local_rules_definition rules[] = 
+						{ 	 {  "CHAP-Algorithm", 			RULE_REQUIRED, -1, 1 }
+							,{  "CHAP-Ident",			RULE_REQUIRED, -1, 1 }
+							,{  "CHAP-Response",			RULE_OPTIONAL, -1, 1 }
+						};
+			
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+			PARSE_loc_rules( rules, avp );
+		}
+		
+		/* CHAP-Challenge */
+		{
+			/*
+				The CHAP-Challenge AVP (AVP Code 60) is of type OctetString and
+				contains the CHAP Challenge sent by the NAS to the CHAP peer
+				[PPPCHAP].
+			*/
+			struct dict_avp_data data = { 
+					60, 					/* Code */
+					0, 					/* Vendor */
+					"CHAP-Challenge", 			/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,		 	/* Fixed flag values */
+					AVP_TYPE_OCTETSTRING 			/* base type of data */
+					};
+			CHECK_dict_new( DICT_AVP, &data , NULL, NULL);
+		}
+		
+		/* ARAP-Password */
+		{
+			/*
+				The ARAP-Password AVP (AVP Code 70) is of type OctetString and is
+				only present when the Framed-Protocol AVP (see section 6.10.1) is
+				included in the message and is set to ARAP.  This AVP MUST NOT be
+				present if either the User-Password or the CHAP-Auth AVP is present.
+				See [RADIUSExt] for more information on the contents of this AVP.
+			*/
+			struct dict_avp_data data = { 
+					70, 					/* Code */
+					0, 					/* Vendor */
+					"ARAP-Password", 			/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,		 	/* Fixed flag values */
+					AVP_TYPE_OCTETSTRING 			/* base type of data */
+					};
+			CHECK_dict_new( DICT_AVP, &data , NULL, NULL);
+		}
+		
+		/* ARAP-Challenge-Response */
+		{
+			/*
+				The ARAP-Challenge-Response AVP (AVP Code 84) is of type OctetString
+				and is only present when the Framed-Protocol AVP (see section 6.10.1)
+				is included in the message and is set to ARAP.  This AVP contains an
+				8 octet response to the dial-in client's challenge.  The RADIUS
+				server calculates this value by taking the dial-in client's challenge
+				from the high-order 8 octets of the ARAP-Password AVP and performing
+				DES encryption on this value with the authenticating user's password
+				as the key.  If the user's password is fewer than 8 octets in length,
+				the password is padded at the end with NULL octets to a length of 8
+				before it is used as a key.
+			*/
+			struct dict_avp_data data = { 
+					84, 					/* Code */
+					0, 					/* Vendor */
+					"ARAP-Challenge-Response", 		/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,		 	/* Fixed flag values */
+					AVP_TYPE_OCTETSTRING 			/* base type of data */
+					};
+			CHECK_dict_new( DICT_AVP, &data , NULL, NULL);
+		}
+		
+		/* ARAP-Security */
+		{
+			/*
+				The ARAP-Security AVP (AVP Code 73) is of type Unsigned32 and MAY be
+				present in the AA-Answer message if the Framed-Protocol AVP (see
+				section 6.10.1) is set to the value of ARAP, and the Result-Code AVP
+				is set to DIAMETER_MULTI_ROUND_AUTH.  See [RADIUSExt] for more
+				information on the format of this AVP.
+			*/
+			struct dict_avp_data data = { 
+					73, 					/* Code */
+					0, 					/* Vendor */
+					"ARAP-Security", 			/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,		 	/* Fixed flag values */
+					AVP_TYPE_UNSIGNED32 			/* base type of data */
+					};
+			CHECK_dict_new( DICT_AVP, &data , NULL, NULL);
+		}
+		
+		/* ARAP-Security-Data */
+		{
+			/*
+				The ARAP-Security-Data AVP (AVP Code 74) is of type OctetString and MAY be
+				present in the AA-Request or AA-Answer message if the Framed-Protocol
+				AVP is set to the value of ARAP, and the Result-Code AVP is set to
+				DIAMETER_MULTI_ROUND_AUTH.  This AVP contains the security module
+				challenge or response associated with the ARAP Security Module
+				specified in ARAP-Security.
+			*/
+			struct dict_avp_data data = { 
+					74, 					/* Code */
+					0, 					/* Vendor */
+					"ARAP-Security-Data", 			/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,		 	/* Fixed flag values */
+					AVP_TYPE_OCTETSTRING 			/* base type of data */
+					};
+			CHECK_dict_new( DICT_AVP, &data , NULL, NULL);
+		}
+		
+/********************************
+ *  NAS Authorization AVPs      *
+ ********************************/		
+		/* Service-Type */
+		{
+			/*
+				The Service-Type AVP (AVP Code 6) is of type Enumerated and contains
+				the type of service the user has requested or the type of service to
+				be provided.  One such AVP MAY be present in an authentication and/or
+				authorization request or response.  A NAS is not required to
+				implement all of these service types.  It MUST treat unknown or
+				unsupported Service-Types received in a response as a failure and end
+				the session with a DIAMETER_INVALID_AVP_VALUE Result-Code.
+
+				When used in a request, the Service-Type AVP SHOULD be considered a
+				hint to the server that the NAS believes the user would prefer the
+				kind of service indicated.  The server is not required to honor the
+				hint.  Furthermore, if the service specified by the server is
+				supported, but not compatible with the current mode of access, the
+				NAS MUST fail to start the session.  The NAS MUST also generate the
+				appropriate error message(s).
+
+				The following values have been defined for the Service-Type AVP.  The
+				complete list of defined values can be found in [RADIUS] and
+				[RADIUSTypes].
+
+				Registry Name: Radius Attribute Values
+				Reference: [RFC2865][RFC3575]
+
+				Sub-registry: Values for RADIUS Attribute 6, Service-Type
+				Reference: [RFC2865][RFC3575]
+
+				1  Login
+				2  Framed
+				3  Callback Login
+				4  Callback Framed
+				5  Outbound
+				6  Administrative
+				7  NAS Prompt
+				8  Authenticate Only
+				9  Callback NAS Prompt
+				10  Call Check
+				11  Callback Administrative
+				12  Voice           [Chiba]
+				13  Fax             [Chiba]
+				14  Modem Relay	    [Chiba]
+				15  IAPP-Register   [IEEE 802.11f][Kerry]
+				16  IAPP-AP-Check   [IEEE 802.11f][Kerry]
+				17  Authorize Only  [RFC3576]
+
+				The following values are further qualified:
+
+				Login               1
+				 The user should be connected to a host.  The message MAY
+				 include additional AVPs defined in sections 6.16 or 6.17.
+
+				Framed              2
+				 A Framed Protocol, such as PPP or SLIP, should be started for
+				 the User.  The message MAY include additional AVPs defined in
+				 section 6.10, or section 7 for tunneling services.
+
+				Callback Login      3
+				 The user should be disconnected and called back, then connected
+				 to a host.  The message MAY include additional AVPs defined in
+				 this section.
+
+				Callback Framed     4
+				 The user should be disconnected and called back, and then a
+				 Framed Protocol, such as PPP or SLIP, should be started for the
+				 User.  The message MAY include additional AVPs defined in
+				 section 6.10, or in section 7 for tunneling services.
+
+			*/
+			struct dict_object 	*type;
+			struct dict_type_data 	 tdata = { AVP_TYPE_UNSIGNED32,	"Enumerated(Service-Type)"	, NULL, NULL};
+			struct dict_enumval_data tvals[] = {
+				enumval_def_u32( 1, "Login"),
+				enumval_def_u32( 2, "Framed"),
+				enumval_def_u32( 3, "Callback Login"),
+				enumval_def_u32( 4, "Callback Framed"),
+				enumval_def_u32( 5, "Outbound"),
+				enumval_def_u32( 6, "Administrative"),
+				enumval_def_u32( 7, "NAS Prompt"),
+				enumval_def_u32( 8, "Authenticate Only"),
+				enumval_def_u32( 9, "Callback NAS Prompt"),
+				enumval_def_u32(10, "Call Check"),
+				enumval_def_u32(11, "Callback Administrative"),
+				enumval_def_u32(12, "Voice [Chiba]"),
+				enumval_def_u32(13, "Fax [Chiba]"),
+				enumval_def_u32(14, "Modem Relay [Chiba]"),
+				enumval_def_u32(15, "IAPP-Register [IEEE 802.11f][Kerry]"),
+				enumval_def_u32(16, "IAPP-AP-Check [IEEE 802.11f][Kerry]"),
+				enumval_def_u32(17, "Authorize Only [RFC3576]")
+			};
+			struct dict_avp_data data = { 
+					6, 					/* Code */
+					0, 					/* Vendor */
+					"Service-Type", 			/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,		 	/* Fixed flag values */
+					AVP_TYPE_UNSIGNED32 			/* base type of data */
+					};
+			int i;
+			/* Create the Enumerated type, enumerated values, and the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata , NULL, &type);
+			for (i = 0; i < sizeof(tvals) / sizeof(tvals[0]); i++) {
+				CHECK_dict_new( DICT_ENUMVAL, &tvals[i], type, NULL);
+			}
+			CHECK_dict_new( DICT_AVP, &data , type, NULL);
+		}
+		
+		/* Callback-Number */
+		{
+			/*
+				The Callback-Number AVP (AVP Code 19) is of type UTF8String and
+				contains a dialing string to be used for callback.  It MAY be used in
+				an authentication and/or authorization request as a hint to the
+				server that a Callback service is desired, but the server is not
+				required to honor the hint in the corresponding response.
+			*/
+			struct dict_avp_data data = { 
+					19, 					/* Code */
+					0, 					/* Vendor */
+					"Callback-Number", 			/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,		 	/* Fixed flag values */
+					AVP_TYPE_OCTETSTRING 			/* base type of data */
+					};
+			CHECK_dict_new( DICT_AVP, &data , UTF8String_type, NULL);
+		}
+		
+		/* Callback-Id */
+		{
+			/*
+				The Callback-Id AVP (AVP Code 20) is of type UTF8String and contains
+				the name of a place to be called, to be interpreted by the NAS.  This
+				AVP MAY be present in an authentication and/or authorization
+				response.
+
+				This AVP is not roaming-friendly as it assumes that the Callback-Id
+				is configured on the NAS.  Using the Callback-Number AVP therefore
+				preferable.
+			*/
+			struct dict_avp_data data = { 
+					20, 					/* Code */
+					0, 					/* Vendor */
+					"Callback-Id", 				/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,		 	/* Fixed flag values */
+					AVP_TYPE_OCTETSTRING 			/* base type of data */
+					};
+			CHECK_dict_new( DICT_AVP, &data , UTF8String_type, NULL);
+		}
+		
+		/* Idle-Timeout */
+		{
+			/*
+				The Idle-Timeout AVP (AVP Code 28) is of type Unsigned32 and sets the
+				maximum number of consecutive seconds of idle connection allowable to
+				the user before termination of the session or before a prompt is
+				issued.  The default is none, or system specific.
+			*/
+			struct dict_avp_data data = { 
+					28, 					/* Code */
+					0, 					/* Vendor */
+					"Idle-Timeout", 			/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,		 	/* Fixed flag values */
+					AVP_TYPE_UNSIGNED32 			/* base type of data */
+					};
+			CHECK_dict_new( DICT_AVP, &data , NULL, NULL);
+		}
+		
+		/* Port-Limit */
+		{
+			/*
+				The Port-Limit AVP (AVP Code 62) is of type Unsigned32 and sets the
+				maximum number of ports the NAS provides to the user.  It MAY be used
+				in an authentication and/or authorization request as a hint to the
+				server that multilink PPP [PPPMP] service is desired, but the server
+				is not required to honor the hint in the corresponding response.
+			*/
+			struct dict_avp_data data = { 
+					62, 					/* Code */
+					0, 					/* Vendor */
+					"Port-Limit", 				/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,		 	/* Fixed flag values */
+					AVP_TYPE_UNSIGNED32 			/* base type of data */
+					};
+			CHECK_dict_new( DICT_AVP, &data , NULL, NULL);
+		}
+		
+		/* NAS-Filter-Rule */
+		{
+			/*
+				The NAS-Filter-Rule AVP (AVP Code 400) is of type IPFilterRule and
+				provides filter rules that need to be configured on the NAS for the
+				user.  One or more of these AVPs MAY be present in an authorization
+				response.
+			*/
+			struct dict_avp_data data = { 
+					400, 					/* Code */
+					0, 					/* Vendor */
+					"NAS-Filter-Rule", 			/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,		 	/* Fixed flag values */
+					AVP_TYPE_OCTETSTRING 			/* base type of data */
+					};
+			CHECK_dict_new( DICT_AVP, &data , IPFilterRule_type, NULL);
+		}
+		
+		/* Filter-Id */
+		{
+			/*
+				The Filter-Id AVP (AVP Code 11) is of type UTF8String and contains
+				the name of the filter list for this user.  Zero or more Filter-Id
+				AVPs MAY be sent in an authorization answer.
+
+				Identifying a filter list by name allows the filter to be used on
+				different NASes without regard to filter-list implementation details.
+				However, this AVP is not roaming friendly, as filter naming differs
+				from one service provider to another.
+
+				In non-RADIUS environments, it is RECOMMENDED that the NAS-Filter-
+				Rule AVP be used instead.
+			*/
+			struct dict_avp_data data = { 
+					11, 					/* Code */
+					0, 					/* Vendor */
+					"Filter-Id", 				/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,		 	/* Fixed flag values */
+					AVP_TYPE_OCTETSTRING 			/* base type of data */
+					};
+			CHECK_dict_new( DICT_AVP, &data , UTF8String_type, NULL);
+		}
+		
+		/* Configuration-Token */
+		{
+			/*
+				The Configuration-Token AVP (AVP Code 78) is of type OctetString and
+				is sent by a Diameter Server to a Diameter Proxy Agent or Translation
+				Agent in an AA-Answer command to indicate a type of user profile to
+				be used.  It should not be sent to a Diameter Client (NAS).
+
+				The format of the Data field of this AVP is site specific.
+			*/
+			struct dict_avp_data data = { 
+					78, 					/* Code */
+					0, 					/* Vendor */
+					"Configuration-Token", 			/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,		 	/* Fixed flag values */
+					AVP_TYPE_OCTETSTRING 			/* base type of data */
+					};
+			CHECK_dict_new( DICT_AVP, &data , NULL, NULL);
+		}
+		
+		/* QoS-Filter-Rule */
+		{
+			/*
+				The QoS-Filter-Rule AVP (AVP Code 407) is of type QoSFilterRule and
+				provides QoS filter rules that need to be configured on the NAS for
+				the user.  One or more such AVPs MAY be present in an authorization
+				response.
+			*/
+			struct dict_avp_data data = { 
+					407, 					/* Code */
+					0, 					/* Vendor */
+					"QoS-Filter-Rule", 			/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,		 	/* Fixed flag values */
+					AVP_TYPE_OCTETSTRING 			/* base type of data */
+					};
+			CHECK_dict_new( DICT_AVP, &data , QoSFilterRule_type, NULL);
+		}
+		
+/***  Framed Access Authorization AVPs  ***/
+		
+		/* Framed-Protocol */
+		{
+			/*
+				The Framed-Protocol AVP (AVP Code 7) is of type Enumerated and
+				contains the framing to be used for framed access.  This AVP MAY be
+				present in both requests and responses.  The supported values are
+				listed in [RADIUSTypes].
+
+				Sub-registry: Values for RADIUS Attribute 7, Framed-Protocol
+				Reference: [RFC2865]
+			*/
+			struct dict_object 	*type;
+			struct dict_type_data 	 tdata = { AVP_TYPE_UNSIGNED32,	"Enumerated(Framed-Protocol)"	, NULL, NULL};
+			struct dict_enumval_data tvals[] = {
+				enumval_def_u32( 1, "PPP"),
+				enumval_def_u32( 2, "SLIP"),
+				enumval_def_u32( 3, "AppleTalk Remote Access Protocol (ARAP)"),
+				enumval_def_u32( 4, "Gandalf proprietary SingleLink/MultiLink protocol"),
+				enumval_def_u32( 5, "Xylogics proprietary IPX/SLIP"),
+				enumval_def_u32( 6, "X.75 Synchronous"),
+				enumval_def_u32( 7, "GPRS PDP Context [Moore]")
+			};
+			struct dict_avp_data data = { 
+					7, 					/* Code */
+					0, 					/* Vendor */
+					"Framed-Protocol", 			/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,		 	/* Fixed flag values */
+					AVP_TYPE_UNSIGNED32 			/* base type of data */
+					};
+			int i;
+			/* Create the Enumerated type, enumerated values, and the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata , NULL, &type);
+			for (i = 0; i < sizeof(tvals) / sizeof(tvals[0]); i++) {
+				CHECK_dict_new( DICT_ENUMVAL, &tvals[i], type, NULL);
+			}
+			CHECK_dict_new( DICT_AVP, &data , type, NULL);
+		}
+		
+		/* Framed-Routing */
+		{
+			/*
+				The Framed-Routing AVP (AVP Code 10) is of type Enumerated and
+				contains the routing method for the user when the user is a router to
+				a network.  This AVP SHOULD only be present in authorization
+				responses.  The supported values are listed in [RADIUSTypes].
+
+				Sub-registry: Values for RADIUS Attribute 10, Framed-Routing
+				Reference: [RFC2865]
+			*/
+			struct dict_object 	*type;
+			struct dict_type_data 	 tdata = { AVP_TYPE_UNSIGNED32,	"Enumerated(Framed-Routing)"	, NULL, NULL};
+			struct dict_enumval_data tvals[] = {
+				enumval_def_u32( 0, "None"),
+				enumval_def_u32( 1, "Send routing packets"),
+				enumval_def_u32( 2, "Listen for routing packets"),
+				enumval_def_u32( 3, "Send and Listen")
+			};
+			struct dict_avp_data data = { 
+					10, 					/* Code */
+					0, 					/* Vendor */
+					"Framed-Routing", 			/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,		 	/* Fixed flag values */
+					AVP_TYPE_UNSIGNED32 			/* base type of data */
+					};
+			int i;
+			/* Create the Enumerated type, enumerated values, and the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata , NULL, &type);
+			for (i = 0; i < sizeof(tvals) / sizeof(tvals[0]); i++) {
+				CHECK_dict_new( DICT_ENUMVAL, &tvals[i], type, NULL);
+			}
+			CHECK_dict_new( DICT_AVP, &data , type, NULL);
+		}
+		
+		/* Framed-MTU */
+		{
+			/*
+				The Framed-MTU AVP (AVP Code 12) is of type Unsigned32 and contains
+				the Maximum Transmission Unit to be configured for the user, when it
+				is not negotiated by some other means (such as PPP).  This AVP SHOULD
+				only be present in authorization responses.  The MTU value MUST be in
+				the range from 64 to 65535.
+			*/
+			struct dict_avp_data data = { 
+					12, 					/* Code */
+					0, 					/* Vendor */
+					"Framed-MTU", 				/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,		 	/* Fixed flag values */
+					AVP_TYPE_UNSIGNED32 			/* base type of data */
+					};
+			CHECK_dict_new( DICT_AVP, &data , NULL, NULL);
+		}
+		
+		/* Framed-Compression */
+		{
+			/*
+				The Framed-Compression AVP (AVP Code 13) is of type Enumerated and
+				contains the compression protocol to be used for the link.  It MAY be
+				used in an authorization request as a hint to the server that a
+				specific compression type is desired, but the server is not required
+				to honor the hint in the corresponding response.
+
+				More than one compression protocol AVP MAY be sent.  The NAS is
+				responsible for applying the proper compression protocol to the
+				appropriate link traffic.
+
+				The supported values are listed in [RADIUSTypes].
+				Sub-registry: Values for RADIUS Attribute 13, Framed-Compression
+				Reference: [RFC2865]
+			*/
+			struct dict_object 	*type;
+			struct dict_type_data 	 tdata = { AVP_TYPE_UNSIGNED32,	"Enumerated(Framed-Compression)"	, NULL, NULL};
+			struct dict_enumval_data tvals[] = {
+				enumval_def_u32( 0, "None"),
+				enumval_def_u32( 1, "VJ TCP/IP header compression"),
+				enumval_def_u32( 2, "IPX header compression"),
+				enumval_def_u32( 3, "Stac-LZS compression")
+			};
+			struct dict_avp_data data = { 
+					13, 					/* Code */
+					0, 					/* Vendor */
+					"Framed-Compression", 			/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,		 	/* Fixed flag values */
+					AVP_TYPE_UNSIGNED32 			/* base type of data */
+					};
+			int i;
+			/* Create the Enumerated type, enumerated values, and the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata , NULL, &type);
+			for (i = 0; i < sizeof(tvals) / sizeof(tvals[0]); i++) {
+				CHECK_dict_new( DICT_ENUMVAL, &tvals[i], type, NULL);
+			}
+			CHECK_dict_new( DICT_AVP, &data , type, NULL);
+		}
+		
+/***  IP Access Authorization AVPs  ***/
+		
+		/* Framed-IP-Address */
+		{
+			/*
+				The Framed-IP-Address AVP (AVP Code 8) [RADIUS] is of type
+				OctetString and contains an IPv4 address of the type specified in the
+				attribute value to be configured for the user.  It MAY be used in an
+				authorization request as a hint to the server that a specific address
+				is desired, but the server is not required to honor the hint in the
+				corresponding response.
+
+				Two values have special significance: 0xFFFFFFFF and 0xFFFFFFFE.  The
+				value 0xFFFFFFFF indicates that the NAS should allow the user to
+				select an address (i.e., negotiated).  The value 0xFFFFFFFE indicates
+				that the NAS should select an address for the user (e.g., assigned
+				from a pool of addresses kept by the NAS).
+			*/
+			struct dict_avp_data data = { 
+					8, 					/* Code */
+					0, 					/* Vendor */
+					"Framed-IP-Address", 			/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,		 	/* Fixed flag values */
+					AVP_TYPE_OCTETSTRING 			/* base type of data */
+					};
+			CHECK_dict_new( DICT_AVP, &data , NULL, NULL);
+		}
+		
+		/* Framed-IP-Netmask */
+		{
+			/*
+				The Framed-IP-Netmask AVP (AVP Code 9) is of type OctetString and
+				contains the four octets of the IPv4 netmask to be configured for the
+				user when the user is a router to a network.  It MAY be used in an
+				authorization request as a hint to the server that a specific netmask
+				is desired, but the server is not required to honor the hint in the
+				corresponding response.  This AVP MUST be present in a response if
+				the request included this AVP with a value of 0xFFFFFFFF.
+			*/
+			struct dict_avp_data data = { 
+					9, 					/* Code */
+					0, 					/* Vendor */
+					"Framed-IP-Netmask", 			/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,		 	/* Fixed flag values */
+					AVP_TYPE_OCTETSTRING 			/* base type of data */
+					};
+			CHECK_dict_new( DICT_AVP, &data , NULL, NULL);
+		}
+		
+		/* Framed-Route */
+		{
+			/*
+				The Framed-Route AVP (AVP Code 22) is of type UTF8String and contains
+				the ASCII routing information to be configured for the user on the
+				NAS.  Zero or more of these AVPs MAY be present in an authorization
+				response.
+
+				The string MUST contain a destination prefix in dotted quad form
+				optionally followed by a slash and a decimal length specifier stating
+				how many high-order bits of the prefix should be used.  This is
+				followed by a space, a gateway address in dotted quad form, a space,
+				and one or more metrics separated by spaces; for example,
+
+				"192.168.1.0/24 192.168.1.1 1".
+
+				The length specifier may be omitted, in which case it should default
+				to 8 bits for class A prefixes, to 16 bits for class B prefixes, and
+				to 24 bits for class C prefixes; for example,
+
+				"192.168.1.0 192.168.1.1 1".
+
+				Whenever the gateway address is specified as "0.0.0.0" the IP address
+				of the user SHOULD be used as the gateway address.
+			*/
+			struct dict_avp_data data = { 
+					22, 					/* Code */
+					0, 					/* Vendor */
+					"Framed-Route", 			/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,		 	/* Fixed flag values */
+					AVP_TYPE_OCTETSTRING 			/* base type of data */
+					};
+			CHECK_dict_new( DICT_AVP, &data , UTF8String_type, NULL);
+		}
+		
+		/* Framed-Pool */
+		{
+			/*
+				The Framed-Pool AVP (AVP Code 88) is of type OctetString and contains
+				the name of an assigned address pool that SHOULD be used to assign an
+				address for the user.  If a NAS does not support multiple address
+				pools, the NAS SHOULD ignore this AVP.  Address pools are usually
+				used for IP addresses but can be used for other protocols if the NAS
+				supports pools for those protocols.
+
+				Although specified as type OctetString for compatibility with RADIUS
+				[RADIUSExt], the encoding of the Data field SHOULD also conform to
+				the rules for the UTF8String Data Format.
+			*/
+			struct dict_avp_data data = { 
+					88, 					/* Code */
+					0, 					/* Vendor */
+					"Framed-Pool", 				/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,		 	/* Fixed flag values */
+					AVP_TYPE_OCTETSTRING 			/* base type of data */
+					};
+			CHECK_dict_new( DICT_AVP, &data , NULL, NULL);
+		}
+		
+		/* Framed-Interface-Id */
+		{
+			/*
+				The Framed-Interface-Id AVP (AVP Code 96) is of type Unsigned64 and
+				contains the IPv6 interface identifier to be configured for the user.
+				It MAY be used in authorization requests as a hint to the server that
+				a specific interface id is desired, but the server is not required to
+				honor the hint in the corresponding response.
+			*/
+			struct dict_avp_data data = { 
+					96, 					/* Code */
+					0, 					/* Vendor */
+					"Framed-Interface-Id", 			/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,		 	/* Fixed flag values */
+					AVP_TYPE_UNSIGNED64 			/* base type of data */
+					};
+			CHECK_dict_new( DICT_AVP, &data , NULL, NULL);
+		}
+		
+		/* Framed-IPv6-Prefix */
+		{
+			/*
+				The Framed-IPv6-Prefix AVP (AVP Code 97) is of type OctetString and
+				contains the IPv6 prefix to be configured for the user.  One or more
+				AVPs MAY be used in authorization requests as a hint to the server
+				that specific IPv6 prefixes are desired, but the server is not
+				required to honor the hint in the corresponding response.
+			*/
+			struct dict_avp_data data = { 
+					97, 					/* Code */
+					0, 					/* Vendor */
+					"Framed-IPv6-Prefix", 			/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,		 	/* Fixed flag values */
+					AVP_TYPE_OCTETSTRING 			/* base type of data */
+					};
+			CHECK_dict_new( DICT_AVP, &data , NULL, NULL);
+		}
+		
+		/* Framed-IPv6-Route */
+		{
+			/*
+				The Framed-IPv6-Route AVP (AVP Code 99) is of type UTF8String and
+				contains the ASCII routing information to be configured for the user
+				on the NAS.  Zero or more of these AVPs MAY be present in an
+				authorization response.
+
+				The string MUST contain an IPv6 address prefix followed by a slash
+				and a decimal length specifier stating how many high order bits of
+				the prefix should be used.  This is followed by a space, a gateway
+				address in hexadecimal notation, a space, and one or more metrics
+				separated by spaces; for example,
+
+				"2000:0:0:106::/64 2000::106:a00:20ff:fe99:a998 1".
+
+				Whenever the gateway address is the IPv6 unspecified address, the IP
+				address of the user SHOULD be used as the gateway address, such as
+				in:
+
+				"2000:0:0:106::/64 :: 1".
+			*/
+			struct dict_avp_data data = { 
+					99, 					/* Code */
+					0, 					/* Vendor */
+					"Framed-IPv6-Route", 			/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,		 	/* Fixed flag values */
+					AVP_TYPE_OCTETSTRING 			/* base type of data */
+					};
+			CHECK_dict_new( DICT_AVP, &data , UTF8String_type, NULL);
+		}
+		
+		/* Framed-IPv6-Pool */
+		{
+			/*
+				The Framed-IPv6-Pool AVP (AVP Code 100) is of type OctetString and
+				contains the name of an assigned pool that SHOULD be used to assign
+				an IPv6 prefix for the user.  If the access device does not support
+				multiple prefix pools, it MUST ignore this AVP.
+
+				Although specified as type OctetString for compatibility with RADIUS
+				[RADIUSIPv6], the encoding of the Data field SHOULD also conform to
+				the rules for the UTF8String Data Format.
+			*/
+			struct dict_avp_data data = { 
+					100, 					/* Code */
+					0, 					/* Vendor */
+					"Framed-IPv6-Pool", 			/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,		 	/* Fixed flag values */
+					AVP_TYPE_OCTETSTRING 			/* base type of data */
+					};
+			CHECK_dict_new( DICT_AVP, &data , NULL, NULL);
+		}
+		
+/***  IPX Access  ***/
+		
+		/* Framed-IPX-Network */
+		{
+			/*
+				The Framed-IPX-Network AVP (AVP Code 23) is of type Unsigned32 and
+				contains the IPX Network number to be configured for the user.  It
+				MAY be used in an authorization request as a hint to the server that
+				a specific address is desired, but the server is not required to
+				honor the hint in the corresponding response.
+
+				Two addresses have special significance: 0xFFFFFFFF and 0xFFFFFFFE.
+				The value 0xFFFFFFFF indicates that the NAS should allow the user to
+				select an address (i.e., Negotiated).  The value 0xFFFFFFFE indicates
+				that the NAS should select an address for the user (e.g., assign it
+				from a pool of one or more IPX networks kept by the NAS).
+			*/
+			struct dict_avp_data data = { 
+					23, 					/* Code */
+					0, 					/* Vendor */
+					"Framed-IPX-Network", 			/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,		 	/* Fixed flag values */
+					AVP_TYPE_UNSIGNED32 			/* base type of data */
+					};
+			CHECK_dict_new( DICT_AVP, &data , NULL, NULL);
+		}
+		
+/***  AppleTalk Network Access  ***/
+		
+		/* Framed-AppleTalk-Link */
+		{
+			/*
+				The Framed-AppleTalk-Link AVP (AVP Code 37) is of type Unsigned32 and
+				contains the AppleTalk network number that should be used for the
+				serial link to the user, which is another AppleTalk router.  This AVP
+				MUST only be present in an authorization response and is never used
+				when the user is not another router.
+
+				Despite the size of the field, values range from 0 to 65,535.  The
+				special value of 0 indicates an unnumbered serial link.  A value of 1
+				to 65,535 means that the serial line between the NAS and the user
+				should be assigned that value as an AppleTalk network number.
+			*/
+			struct dict_avp_data data = { 
+					37, 					/* Code */
+					0, 					/* Vendor */
+					"Framed-AppleTalk-Link", 		/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,		 	/* Fixed flag values */
+					AVP_TYPE_UNSIGNED32 			/* base type of data */
+					};
+			CHECK_dict_new( DICT_AVP, &data , NULL, NULL);
+		}
+		
+		/* Framed-AppleTalk-Network */
+		{
+			/*
+				The Framed-AppleTalk-Network AVP (AVP Code 38) is of type Unsigned32
+				and contains the AppleTalk Network number that the NAS should probe
+				to allocate an AppleTalk node for the user.  This AVP MUST only be
+				present in an authorization response and is never used when the user
+				is not another router.  Multiple instances of this AVP indicate that
+				the NAS may probe, using any of the network numbers specified.
+
+				Despite the size of the field, values range from 0 to 65,535.  The
+				special value 0 indicates that the NAS should assign a network for
+				the user, using its default cable range.  A value between 1 and
+				65,535 (inclusive) indicates to the AppleTalk Network that the NAS
+				should probe to find an address for the user.
+			*/
+			struct dict_avp_data data = { 
+					38, 					/* Code */
+					0, 					/* Vendor */
+					"Framed-AppleTalk-Network", 		/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,		 	/* Fixed flag values */
+					AVP_TYPE_UNSIGNED32 			/* base type of data */
+					};
+			CHECK_dict_new( DICT_AVP, &data , NULL, NULL);
+		}
+		
+		/* Framed-AppleTalk-Zone */
+		{
+			/*
+				The Framed-AppleTalk-Zone AVP (AVP Code 39) is of type OctetString
+				and contains the AppleTalk Default Zone to be used for this user.
+				This AVP MUST only be present in an authorization response.  Multiple
+				instances of this AVP in the same message are not allowed.
+
+				The codification of this field's allowed range is outside the scope
+				of this specification.
+			*/
+			struct dict_avp_data data = { 
+					39, 					/* Code */
+					0, 					/* Vendor */
+					"Framed-AppleTalk-Zone", 		/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,		 	/* Fixed flag values */
+					AVP_TYPE_OCTETSTRING 			/* base type of data */
+					};
+			CHECK_dict_new( DICT_AVP, &data , NULL, NULL);
+		}
+		
+/***  AppleTalk Remote Access [RFC2869] ***/
+		
+		/* ARAP-Features */
+		{
+			/*
+				The ARAP-Features AVP (AVP Code 71) is of type OctetString and MAY be
+				present in the AA-Accept message if the Framed-Protocol AVP is set to
+				the value of ARAP.  See [RADIUSExt] for more information about the
+				format of this AVP.
+			*/
+			struct dict_avp_data data = { 
+					71, 					/* Code */
+					0, 					/* Vendor */
+					"ARAP-Features", 			/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,		 	/* Fixed flag values */
+					AVP_TYPE_OCTETSTRING 			/* base type of data */
+					};
+			CHECK_dict_new( DICT_AVP, &data , NULL, NULL);
+		}
+		
+		/* ARAP-Zone-Access */
+		{
+			/*
+				The ARAP-Zone-Access AVP (AVP Code 72) is of type Enumerated and MAY
+				be present in the AA-Accept message if the Framed-Protocol AVP is set
+				to the value of ARAP.
+
+				The supported values are listed in [RADIUSTypes] and defined in
+				[RADIUSExt].
+				Sub-registry: Values for RADIUS Attribute 72, ARAP-Zone-Access 
+				Reference: [RFC2869]
+			*/
+			struct dict_object 	*type;
+			struct dict_type_data 	 tdata = { AVP_TYPE_UNSIGNED32,	"Enumerated(ARAP-Zone-Access)"	, NULL, NULL};
+			struct dict_enumval_data tvals[] = {
+				enumval_def_u32( 1, "Only allow access to default zone [RFC2869]"),
+				enumval_def_u32( 2, "Use zone filter inclusively [RFC2869]"),
+				enumval_def_u32( 3, "Not used [RFC2869]"),
+				enumval_def_u32( 4, "Use zone filter exclusively [RFC2869]")
+			};
+			struct dict_avp_data data = { 
+					72, 					/* Code */
+					0, 					/* Vendor */
+					"ARAP-Zone-Access", 			/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,		 	/* Fixed flag values */
+					AVP_TYPE_UNSIGNED32 			/* base type of data */
+					};
+			int i;
+			/* Create the Enumerated type, enumerated values, and the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata , NULL, &type);
+			for (i = 0; i < sizeof(tvals) / sizeof(tvals[0]); i++) {
+				CHECK_dict_new( DICT_ENUMVAL, &tvals[i], type, NULL);
+			}
+			CHECK_dict_new( DICT_AVP, &data , type, NULL);
+		}
+		
+/***  Non-Framed Access Authorization AVPs ***/
+		
+		/* Login-IP-Host */
+		{
+			/*
+				The Login-IP-Host AVP (AVP Code 14) [RADIUS] is of type OctetString
+				and contains the IPv4 address of a host with which to connect the
+				user when the Login-Service AVP is included.  It MAY be used in an
+				AA-Request command as a hint to the Diameter Server that a specific
+				host is desired, but the Diameter Server is not required to honor the
+				hint in the AA-Answer.
+
+				Two addresses have special significance: all ones and 0.  The value
+				of all ones indicates that the NAS SHOULD allow the user to select an
+				address.  The value 0 indicates that the NAS SHOULD select a host to
+				connect the user to.
+			*/
+			struct dict_object 	*type;
+			uint32_t		 allzeros = 0;
+			uint32_t		 allones  = (uint32_t) -1;
+			struct dict_type_data 	 tdata = { AVP_TYPE_OCTETSTRING,	"Enumerated(Login-IP-Host)"	, NULL, NULL};
+			struct dict_enumval_data tvals[] = {
+				enumval_def_os( 4, &allzeros, "(0) NAS selects the host"),
+				enumval_def_os( 4, &allones , "(1) User selects the address")
+			};
+			struct dict_avp_data data = { 
+					14, 					/* Code */
+					0, 					/* Vendor */
+					"Login-IP-Host", 			/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,		 	/* Fixed flag values */
+					AVP_TYPE_OCTETSTRING 			/* base type of data */
+					};
+			int i;
+			/* Create the Enumerated type, enumerated values, and the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata , NULL, &type);
+			for (i = 0; i < sizeof(tvals) / sizeof(tvals[0]); i++) {
+				CHECK_dict_new( DICT_ENUMVAL, &tvals[i], type, NULL);
+			}
+			CHECK_dict_new( DICT_AVP, &data , type, NULL);
+		}
+		
+		/* Login-IPv6-Host */
+		{
+			/*
+				The Login-IPv6-Host AVP (AVP Code 98) [RADIUSIPv6] is of type
+				OctetString and contains the IPv6 address of a host with which to
+				connect the user when the Login-Service AVP is included.  It MAY be
+				used in an AA-Request command as a hint to the Diameter Server that a
+				specific host is desired, but the Diameter Server is not required to
+				honor the hint in the AA-Answer.
+
+				Two addresses have special significance:
+
+				0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF and 0.  The value
+				0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF indicates that the NAS SHOULD
+				allow the user to select an address.  The value 0 indicates that the
+				NAS SHOULD select a host to connect the user to.
+
+			*/
+			struct dict_object 	*type;
+			unsigned char 		 allzeros[16];
+			unsigned char		 allones[16];
+			struct dict_type_data 	 tdata = { AVP_TYPE_OCTETSTRING,	"Enumerated(Login-IPv6-Host)"	, NULL, NULL};
+			struct dict_enumval_data tvals[] = {
+				enumval_def_os( 16, &allzeros, "(0) NAS selects the host"),
+				enumval_def_os( 16, &allones , "(1) User selects the address")
+			};
+			struct dict_avp_data data = { 
+					98, 					/* Code */
+					0, 					/* Vendor */
+					"Login-IPv6-Host", 			/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,		 	/* Fixed flag values */
+					AVP_TYPE_OCTETSTRING 			/* base type of data */
+					};
+			int i;
+			memset(allzeros, 0,   sizeof(allzeros));
+			memset(allones, 0xff, sizeof(allones));
+			/* Create the Enumerated type, enumerated values, and the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata , NULL, &type);
+			for (i = 0; i < sizeof(tvals) / sizeof(tvals[0]); i++) {
+				CHECK_dict_new( DICT_ENUMVAL, &tvals[i], type, NULL);
+			}
+			CHECK_dict_new( DICT_AVP, &data , type, NULL);
+		}
+		
+		/* Login-Service */
+		{
+			/*
+				The Login-Service AVP (AVP Code 15) is of type Enumerated and
+				contains the service that should be used to connect the user to the
+				login host.  This AVP SHOULD only be present in authorization
+				responses.
+
+				The supported values are listed in [RADIUSTypes].
+				Sub-registry: Values for RADIUS Attribute 15, Login-Service
+				Reference: [RFC2865]
+   			*/
+			struct dict_object 	*type;
+			struct dict_type_data 	 tdata = { AVP_TYPE_UNSIGNED32,	"Enumerated(Login-Service)"	, NULL, NULL};
+			struct dict_enumval_data tvals[] = {
+				enumval_def_u32( 0, "Telnet"),
+				enumval_def_u32( 1, "Rlogin"),
+				enumval_def_u32( 2, "TCP Clear"),
+				enumval_def_u32( 3, "PortMaster (proprietary)"),
+				enumval_def_u32( 4, "LAT"),
+				enumval_def_u32( 5, "X25-PAD"),
+				enumval_def_u32( 6, "X25-T3POS"),
+				enumval_def_u32( 8, "TCP Clear Quiet (suppresses any NAS-generated connect string)")
+			};
+			struct dict_avp_data data = { 
+					15, 					/* Code */
+					0, 					/* Vendor */
+					"Login-Service", 			/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,		 	/* Fixed flag values */
+					AVP_TYPE_UNSIGNED32 			/* base type of data */
+					};
+			int i;
+			/* Create the Enumerated type, enumerated values, and the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata , NULL, &type);
+			for (i = 0; i < sizeof(tvals) / sizeof(tvals[0]); i++) {
+				CHECK_dict_new( DICT_ENUMVAL, &tvals[i], type, NULL);
+			}
+			CHECK_dict_new( DICT_AVP, &data , type, NULL);
+		}
+		
+/***  TCP Services  ***/
+		
+		/* Login-TCP-Port */
+		{
+			/*
+				The Login-TCP-Port AVP (AVP Code 16) is of type Unsigned32 and
+				contains the TCP port with which the user is to be connected when the
+				Login-Service AVP is also present.  This AVP SHOULD only be present
+				in authorization responses.  The value MUST NOT be greater than
+				65,535.
+			*/
+			struct dict_avp_data data = { 
+					16, 					/* Code */
+					0, 					/* Vendor */
+					"Login-TCP-Port", 			/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,		 	/* Fixed flag values */
+					AVP_TYPE_UNSIGNED32 			/* base type of data */
+					};
+			CHECK_dict_new( DICT_AVP, &data , NULL, NULL);
+		}
+		
+/***  LAT Services  ***/
+		
+		/* Login-LAT-Service */
+		{
+			/*
+				The Login-LAT-Service AVP (AVP Code 34) is of type OctetString and
+				contains the system with which the user is to be connected by LAT.
+				It MAY be used in an authorization request as a hint to the server
+				that a specific service is desired, but the server is not required to
+				honor the hint in the corresponding response.  This AVP MUST only be
+				present in the response if the Login-Service AVP states that LAT is
+				desired.
+
+				Administrators use this service attribute when dealing with clustered
+				systems, such as a VAX or Alpha cluster.  In these environments,
+				several different time-sharing hosts share the same resources (disks,
+				printers, etc.), and administrators often configure each host to
+				offer access (service) to each of the shared resources.  In this
+				case, each host in the cluster advertises its services through LAT
+				broadcasts.
+
+				Sophisticated users often know which service providers (machines) are
+				faster and tend to use a node name when initiating a LAT connection.
+				Some administrators want particular users to use certain machines as
+				a primitive form of load balancing (although LAT knows how to do load
+				balancing itself).
+
+				The String field contains the identity of the LAT service to use.
+				The LAT Architecture allows this string to contain $ (dollar), -
+				(hyphen), . (period), _ (underscore), numerics, upper- and lowercase
+				alphabetics, and the ISO Latin-1 character set extension [ISOLatin].
+				All LAT string comparisons are case insensitive.
+			*/
+			struct dict_avp_data data = { 
+					34, 					/* Code */
+					0, 					/* Vendor */
+					"Login-LAT-Service", 			/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,		 	/* Fixed flag values */
+					AVP_TYPE_OCTETSTRING 			/* base type of data */
+					};
+			CHECK_dict_new( DICT_AVP, &data , NULL, NULL);
+		}
+		
+		/* Login-LAT-Node */
+		{
+			/*
+				The Login-LAT-Node AVP (AVP Code 35) is of type OctetString and
+				contains the Node with which the user is to be automatically
+				connected by LAT.  It MAY be used in an authorization request as a
+				hint to the server that a specific LAT node is desired, but the
+				server is not required to honor the hint in the corresponding
+				response.  This AVP MUST only be present in a response if the Login-
+				Service-Type AVP is set to LAT.
+
+				The String field contains the identity of the LAT service to use.
+				The LAT Architecture allows this string to contain $ (dollar), -
+				(hyphen), . (period), _ (underscore), numerics, upper- and lowercase
+				alphabetics, and the ISO Latin-1 character set extension [ISOLatin].
+				All LAT string comparisons are case insensitive.
+			*/
+			struct dict_avp_data data = { 
+					35, 					/* Code */
+					0, 					/* Vendor */
+					"Login-LAT-Node", 			/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,		 	/* Fixed flag values */
+					AVP_TYPE_OCTETSTRING 			/* base type of data */
+					};
+			CHECK_dict_new( DICT_AVP, &data , NULL, NULL);
+		}
+		
+		/* Login-LAT-Group */
+		{
+			/*
+				The Login-LAT-Group AVP (AVP Code 36) is of type OctetString and
+				contains a string identifying the LAT group codes this user is
+				authorized to use.  It MAY be used in an authorization request as a
+				hint to the server that a specific group is desired, but the server
+				is not required to honor the hint in the corresponding response.
+				This AVP MUST only be present in a response if the Login-Service-Type
+				AVP is set to LAT.
+
+				LAT supports 256 different group codes, which LAT uses as a form of
+				access rights.  LAT encodes the group codes as a 256-bit bitmap.
+
+				Administrators can assign one or more of the group code bits at the
+				LAT service provider; it will only accept LAT connections that have
+				these group codes set in the bitmap.  The administrators assign a
+				bitmap of authorized group codes to each user.  LAT gets these from
+				the operating system and uses them in its requests to the service
+				providers.
+
+				The codification of the range of allowed usage of this field is
+				outside the scope of this specification.
+			*/
+			struct dict_avp_data data = { 
+					36, 					/* Code */
+					0, 					/* Vendor */
+					"Login-LAT-Group", 			/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,		 	/* Fixed flag values */
+					AVP_TYPE_OCTETSTRING 			/* base type of data */
+					};
+			CHECK_dict_new( DICT_AVP, &data , NULL, NULL);
+		}
+		
+		/* Login-LAT-Port */
+		{
+			/*
+				The Login-LAT-Port AVP (AVP Code 63) is of type OctetString and
+				contains the Port with which the user is to be connected by LAT.  It
+				MAY be used in an authorization request as a hint to the server that
+				a specific port is desired, but the server is not required to honor
+				the hint in the corresponding response.  This AVP MUST only be
+				present in a response if the Login-Service-Type AVP is set to LAT.
+
+				The String field contains the identity of the LAT service to use.
+				The LAT Architecture allows this string to contain $ (dollar), -
+				(hyphen), . (period), _ (underscore), numerics, upper- and lower-case
+				alphabetics, and the ISO Latin-1 character set extension [ISOLatin].
+				All LAT string comparisons are case insensitive.
+			*/
+			struct dict_avp_data data = { 
+					63, 					/* Code */
+					0, 					/* Vendor */
+					"Login-LAT-Port", 			/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,		 	/* Fixed flag values */
+					AVP_TYPE_OCTETSTRING 			/* base type of data */
+					};
+			CHECK_dict_new( DICT_AVP, &data , NULL, NULL);
+		}
+		
+/********************************
+ *  NAS Tunneling AVPs          *
+ ********************************/		
+		/* Tunnel-Type */
+		{
+			/*
+				The Tunnel-Type AVP (AVP Code 64) is of type Enumerated and contains
+				the tunneling protocol(s) to be used (in the case of a tunnel
+				initiator) or in use (in the case of a tunnel terminator).  It MAY be
+				used in an authorization request as a hint to the server that a
+				specific tunnel type is desired, but the server is not required to
+				honor the hint in the corresponding response.
+
+				The Tunnel-Type AVP SHOULD also be included in Accounting-Request
+				messages.
+
+				A tunnel initiator is not required to implement any of these tunnel
+				types.  If a tunnel initiator receives a response that contains only
+				unknown or unsupported Tunnel-Types, the tunnel initiator MUST behave
+				as though a response were received with the Result-Code indicating a
+				failure.
+
+				The supported values are listed in [RADIUSTypes].
+				Sub-registry: Values for RADIUS Attribute 64, Tunnel-Type 
+				Reference: [RFC2868]
+			*/
+			struct dict_object 	*type;
+			struct dict_type_data 	 tdata = { AVP_TYPE_UNSIGNED32,	"Enumerated(Tunnel-Type)"	, NULL, NULL};
+			struct dict_enumval_data tvals[] = {
+				enumval_def_u32( 1, "Point-to-Point Tunneling Protocol (PPTP) [RFC2868]"),
+				enumval_def_u32( 2, "Layer Two Forwarding (L2F) [RFC2868]"),
+				enumval_def_u32( 3, "Layer Two Tunneling Protocol (L2TP) [RFC2868]"),
+				enumval_def_u32( 4, "Ascend Tunnel Management Protocol (ATMP) [RFC2868]"),
+				enumval_def_u32( 5, "Virtual Tunneling Protocol (VTP) [RFC2868]"),
+				enumval_def_u32( 6, "IP Authentication Header in the Tunnel-mode (AH) [RFC2868]"),
+				enumval_def_u32( 7, "IP-in-IP Encapsulation (IP-IP) [RFC2868]"),
+				enumval_def_u32( 8, "Minimal IP-in-IP Encapsulation (MIN-IP-IP) [RFC2868]"),
+				enumval_def_u32( 9, "IP Encapsulating Security Payload in the Tunnel-mode (ESP) [RFC2868]"),
+				enumval_def_u32(10, "Generic Route Encapsulation (GRE) [RFC2868]"),
+				enumval_def_u32(11, "Bay Dial Virtual Services (DVS) [RFC2868]"),
+				enumval_def_u32(12, "IP-in-IP Tunneling [RFC2868]"),
+				enumval_def_u32(13, "Virtual LANs (VLAN) [RFC3580]")
+			};
+			struct dict_avp_data adata = { 
+					64, 					/* Code */
+					0, 					/* Vendor */
+					"Tunnel-Type", 				/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,			/* Fixed flag values */
+					AVP_TYPE_UNSIGNED32 			/* base type of data */
+					};
+			int i;
+			CHECK_dict_new( DICT_TYPE, &tdata , NULL, &type);
+			for (i = 0; i < sizeof(tvals) / sizeof(tvals[0]); i++) {
+				CHECK_dict_new( DICT_ENUMVAL, &tvals[i], type, NULL);
+			}
+			CHECK_dict_new( DICT_AVP, &adata , type, NULL);
+		}
+		
+		/* Tunnel-Medium-Type */
+		{
+			/*
+				The Tunnel-Medium-Type AVP (AVP Code 65) is of type Enumerated and
+				contains the transport medium to use when creating a tunnel for
+				protocols (such as L2TP) that can operate over multiple transports.
+				It MAY be used in an authorization request as a hint to the server
+				that a specific medium is desired, but the server is not required to
+				honor the hint in the corresponding response.
+
+				The supported values are listed in [RADIUSTypes].
+				Sub-registry: Values for RADIUS Attribute 65, Tunnel-Medium-Type
+				Reference: [RFC2868]
+			*/
+			struct dict_object 	*type;
+			struct dict_type_data 	 tdata = { AVP_TYPE_UNSIGNED32,	"Enumerated(Tunnel-Medium-Type)"	, NULL, NULL};
+			struct dict_enumval_data tvals[] = {
+				enumval_def_u32( 1, "IPv4 (IP version 4) [RFC2868]"),
+				enumval_def_u32( 2, "IPv6 (IP version 6) [RFC2868]"),
+				enumval_def_u32( 3, "NSAP [RFC2868]"),
+				enumval_def_u32( 4, "HDLC (8-bit multidrop) [RFC2868]"),
+				enumval_def_u32( 5, "BBN 1822 [RFC2868]"),
+				enumval_def_u32( 6, "802 (includes all 802 media plus Ethernet \"canonical format\") [RFC2868]"),
+				enumval_def_u32( 7, "E.163 (POTS) [RFC2868]"),
+				enumval_def_u32( 8, "E.164 (SMDS, Frame Relay, ATM) [RFC2868]"),
+				enumval_def_u32( 9, "F.69 (Telex) [RFC2868]"),
+				enumval_def_u32(10, "X.121 (X.25, Frame Relay) [RFC2868]"),
+				enumval_def_u32(11, "IPX [RFC2868]"),
+				enumval_def_u32(12, "Appletalk [RFC2868]"),
+				enumval_def_u32(13, "Decnet IV [RFC2868]"),
+				enumval_def_u32(14, "Banyan Vines [RFC2868]"),
+				enumval_def_u32(15, "E.164 with NSAP format subaddress [RFC2868]")
+			};
+			struct dict_avp_data adata = { 
+					65, 					/* Code */
+					0, 					/* Vendor */
+					"Tunnel-Medium-Type", 			/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,			/* Fixed flag values */
+					AVP_TYPE_UNSIGNED32 			/* base type of data */
+					};
+			int i;
+			CHECK_dict_new( DICT_TYPE, &tdata , NULL, &type);
+			for (i = 0; i < sizeof(tvals) / sizeof(tvals[0]); i++) {
+				CHECK_dict_new( DICT_ENUMVAL, &tvals[i], type, NULL);
+			}
+			CHECK_dict_new( DICT_AVP, &adata , type, NULL);
+		}
+		
+		/* Tunnel-Client-Endpoint */
+		{
+			/*
+				The Tunnel-Client-Endpoint AVP (AVP Code 66) is of type UTF8String
+				and contains the address of the initiator end of the tunnel.  It MAY
+				be used in an authorization request as a hint to the server that a
+				specific endpoint is desired, but the server is not required to honor
+				the hint in the corresponding response.
+
+				This AVP SHOULD be included in the corresponding Accounting-Request
+				messages, in which case it indicates the address from which the
+				tunnel was initiated.  This AVP, along with the Tunnel-Server-
+				Endpoint and Session-Id AVP [BASE], MAY be used to provide a globally
+				unique means to identify a tunnel for accounting and auditing
+				purposes.
+
+				If Tunnel-Medium-Type is IPv4 (1), then this string is either the
+				fully qualified domain name (FQDN) of the tunnel client machine, or a
+				"dotted-decimal" IP address.  Implementations MUST support the
+				dotted-decimal format and SHOULD support the FQDN format for IP
+				addresses.
+
+				If Tunnel-Medium-Type is IPv6 (2), then this string is either the
+				FQDN of the tunnel client machine, or a text representation of the
+				address in either the preferred or alternate form [IPv6Addr].
+				Conforming implementations MUST support the preferred form and SHOULD
+				support both the alternate text form and the FQDN format for IPv6
+				addresses.
+
+				If Tunnel-Medium-Type is neither IPv4 nor IPv6, then this string is a
+				tag referring to configuration data local to the Diameter client that
+				describes the interface or medium-specific client address to use.
+   			*/
+			struct dict_avp_data adata = { 
+					66, 					/* Code */
+					0, 					/* Vendor */
+					"Tunnel-Client-Endpoint", 		/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,			/* Fixed flag values */
+					AVP_TYPE_OCTETSTRING 			/* base type of data */
+					};
+			CHECK_dict_new( DICT_AVP, &adata , UTF8String_type, NULL);
+		}
+		
+		/* Tunnel-Server-Endpoint */
+		{
+			/*
+				The Tunnel-Server-Endpoint AVP (AVP Code 67) is of type UTF8String
+				and contains the address of the server end of the tunnel.  It MAY be
+				used in an authorization request as a hint to the server that a
+				specific endpoint is desired, but the server is not required to honor
+				the hint in the corresponding response.
+
+				This AVP SHOULD be included in the corresponding Accounting-Request
+				messages, in which case it indicates the address from which the
+				tunnel was initiated.  This AVP, along with the Tunnel-Client-
+				Endpoint and Session-Id AVP [BASE], MAY be used to provide a globally
+				unique means to identify a tunnel for accounting and auditing
+				purposes.
+
+				If Tunnel-Medium-Type is IPv4 (1), then this string is either the
+				fully qualified domain name (FQDN) of the tunnel server machine, or a
+				"dotted-decimal" IP address.  Implementations MUST support the
+				dotted-decimal format and SHOULD support the FQDN format for IP
+				addresses.
+
+				If Tunnel-Medium-Type is IPv6 (2), then this string is either the
+				FQDN of the tunnel server machine, or a text representation of the
+				address in either the preferred or alternate form [IPv6Addr].
+				Implementations MUST support the preferred form and SHOULD support
+				both the alternate text form and the FQDN format for IPv6 addresses.
+
+				If Tunnel-Medium-Type is not IPv4 or IPv6, this string is a tag
+				referring to configuration data local to the Diameter client that
+				describes the interface or medium-specific server address to use.
+   			*/
+			struct dict_avp_data adata = { 
+					67, 					/* Code */
+					0, 					/* Vendor */
+					"Tunnel-Server-Endpoint", 		/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,			/* Fixed flag values */
+					AVP_TYPE_OCTETSTRING 			/* base type of data */
+					};
+			CHECK_dict_new( DICT_AVP, &adata , UTF8String_type, NULL);
+		}
+		
+		/* Tunnel-Password */
+		{
+			/*
+				The Tunnel-Password AVP (AVP Code 69) is of type OctetString and may
+				contain a password to be used to authenticate to a remote server.
+				The Tunnel-Password AVP contains sensitive information.  This value
+				is not protected in the same manner as RADIUS [RADTunnels].
+
+				As required in [BASE], Diameter messages are encrypted by using IPsec
+				or TLS.  The Tunnel-Password AVP SHOULD NOT be used in untrusted
+				proxy environments without encrypting it by using end-to-end security
+				techniques, such as CMS Security [DiamCMS].
+   			*/
+			struct dict_avp_data adata = { 
+					69, 					/* Code */
+					0, 					/* Vendor */
+					"Tunnel-Password", 			/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,			/* Fixed flag values */
+					AVP_TYPE_OCTETSTRING 			/* base type of data */
+					};
+			CHECK_dict_new( DICT_AVP, &adata , NULL, NULL);
+		}
+		
+		/* Tunnel-Private-Group-Id */
+		{
+			/*
+				The Tunnel-Private-Group-Id AVP (AVP Code 81) is of type OctetString
+				and contains the group Id for a particular tunneled session.  The
+				Tunnel-Private-Group-Id AVP MAY be included in an authorization
+				request if the tunnel initiator can predetermine the group resulting
+				from a particular connection.  It SHOULD be included in the
+				authorization response if this tunnel session is to be treated as
+				belonging to a particular private group.  Private groups may be used
+				to associate a tunneled session with a particular group of users.
+				For example, it MAY be used to facilitate routing of unregistered IP
+				addresses through a particular interface.  This AVP SHOULD be
+				included in the Accounting-Request messages that pertain to the
+				tunneled session.
+   			*/
+			struct dict_avp_data adata = { 
+					81, 					/* Code */
+					0, 					/* Vendor */
+					"Tunnel-Private-Group-Id", 		/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,			/* Fixed flag values */
+					AVP_TYPE_OCTETSTRING 			/* base type of data */
+					};
+			CHECK_dict_new( DICT_AVP, &adata , NULL, NULL);
+		}
+		
+		/* Tunnel-Assignment-Id */
+		{
+			/*
+				The Tunnel-Assignment-Id AVP (AVP Code 82) is of type OctetString and
+				is used to indicate to the tunnel initiator the particular tunnel to
+				which a session is to be assigned.  Some tunneling protocols, such as
+				[PPTP] and [L2TP], allow for sessions between the same two tunnel
+				endpoints to be multiplexed over the same tunnel and also for a given
+				session to use its own dedicated tunnel.  This attribute provides a
+				mechanism for Diameter to inform the tunnel initiator (e.g., PAC,
+				LAC) whether to assign the session to a multiplexed tunnel or to a
+				separate tunnel.  Furthermore, it allows for sessions sharing
+				multiplexed tunnels to be assigned to different multiplexed tunnels.
+
+				A particular tunneling implementation may assign differing
+				characteristics to particular tunnels.  For example, different
+				tunnels may be assigned different QoS parameters.  Such tunnels may
+				be used to carry either individual or multiple sessions.  The
+				Tunnel-Assignment-Id attribute thus allows the Diameter server to
+				indicate that a particular session is to be assigned to a tunnel
+				providing an appropriate level of service.  It is expected that any
+				QoS-related Diameter tunneling attributes defined in the future
+				accompanying this one will be associated by the tunnel initiator with
+				the Id given by this attribute.  In the meantime, any semantic given
+				to a particular Id string is a matter left to local configuration in
+				the tunnel initiator.
+
+				The Tunnel-Assignment-Id AVP is of significance only to Diameter and
+				the tunnel initiator.  The Id it specifies is only intended to be of
+				local use to Diameter and the tunnel initiator.  The Id assigned by
+				the tunnel initiator is not conveyed to the tunnel peer.
+
+				This attribute MAY be included in authorization responses.  The
+				tunnel initiator receiving this attribute MAY choose to ignore it and
+				to assign the session to an arbitrary multiplexed or non-multiplexed
+				tunnel between the desired endpoints.  This AVP SHOULD also be
+				included in the Accounting-Request messages pertaining to the
+				tunneled session.
+
+				If a tunnel initiator supports the Tunnel-Assignment-Id AVP, then it
+				should assign a session to a tunnel in the following manner:
+
+				-  If this AVP is present and a tunnel exists between the
+				 specified endpoints with the specified Id, then the session
+				 should be assigned to that tunnel.
+
+				-  If this AVP is present and no tunnel exists between the
+				 specified endpoints with the specified Id, then a new tunnel
+				 should be established for the session and the specified Id
+				 should be associated with the new tunnel.
+
+				-  If this AVP is not present, then the session is assigned to an
+				 unnamed tunnel.  If an unnamed tunnel does not yet exist
+				 between the specified endpoints, then it is established and
+				 used for this session and for subsequent ones established
+				 without the Tunnel-Assignment-Id attribute.  A tunnel initiator
+				 MUST NOT assign a session for which a Tunnel-Assignment-Id AVP
+				 was not specified to a named tunnel (i.e., one that was
+				 initiated by a session specifying this AVP).
+
+				Note that the same Id may be used to name different tunnels if these
+				tunnels are between different endpoints.
+
+   			*/
+			struct dict_avp_data adata = { 
+					82, 					/* Code */
+					0, 					/* Vendor */
+					"Tunnel-Assignment-Id", 		/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,			/* Fixed flag values */
+					AVP_TYPE_OCTETSTRING 			/* base type of data */
+					};
+			CHECK_dict_new( DICT_AVP, &adata , NULL, NULL);
+		}
+		
+		/* Tunnel-Preference */
+		{
+			/*
+				The Tunnel-Preference AVP (AVP Code 83) is of type Unsigned32 and is
+				used to identify the relative preference assigned to each tunnel when
+				more than one set of tunneling AVPs is returned within separate
+				Grouped-AVP AVPs.  It MAY be used in an authorization request as a
+				hint to the server that a specific preference is desired, but the
+				server is not required to honor the hint in the corresponding
+				response.
+
+				For example, suppose that AVPs describing two tunnels are returned by
+				the server, one with a Tunnel-Type of PPTP and the other with a
+				Tunnel-Type of L2TP.  If the tunnel initiator supports only one of
+				the Tunnel-Types returned, it will initiate a tunnel of that type.
+				If, however, it supports both tunnel protocols, it SHOULD use the
+				value of the Tunnel-Preference AVP to decide which tunnel should be
+				started.  The tunnel with the lowest numerical value in the Value
+				field of this AVP SHOULD be given the highest preference.  The values
+				assigned to two or more instances of the Tunnel-Preference AVP within
+				a given authorization response MAY be identical.  In this case, the
+				tunnel initiator SHOULD use locally configured metrics to decide
+				which set of AVPs to use.
+   			*/
+			struct dict_avp_data adata = { 
+					83, 					/* Code */
+					0, 					/* Vendor */
+					"Tunnel-Preference", 			/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,			/* Fixed flag values */
+					AVP_TYPE_UNSIGNED32 			/* base type of data */
+					};
+			CHECK_dict_new( DICT_AVP, &adata , NULL, NULL);
+		}
+		
+		/* Tunnel-Client-Auth-Id */
+		{
+			/*
+				The Tunnel-Client-Auth-Id AVP (AVP Code 90) is of type UTF8String and
+				specifies the name used by the tunnel initiator during the
+				authentication phase of tunnel establishment.  It MAY be used in an
+				authorization request as a hint to the server that a specific
+				preference is desired, but the server is not required to honor the
+				hint in the corresponding response.  This AVP MUST be present in the
+				authorization response if an authentication name other than the
+				default is desired.  This AVP SHOULD be included in the Accounting-
+				Request messages pertaining to the tunneled session.
+   			*/
+			struct dict_avp_data adata = { 
+					90, 					/* Code */
+					0, 					/* Vendor */
+					"Tunnel-Client-Auth-Id", 		/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,			/* Fixed flag values */
+					AVP_TYPE_OCTETSTRING 			/* base type of data */
+					};
+			CHECK_dict_new( DICT_AVP, &adata , UTF8String_type, NULL);
+		}
+		
+		/* Tunnel-Server-Auth-Id */
+		{
+			/*
+				The Tunnel-Server-Auth-Id AVP (AVP Code 91) is of type UTF8String and
+				specifies the name used by the tunnel terminator during the
+				authentication phase of tunnel establishment.  It MAY be used in an
+				authorization request as a hint to the server that a specific
+				preference is desired, but the server is not required to honor the
+				hint in the corresponding response.  This AVP MUST be present in the
+				authorization response if an authentication name other than the
+				default is desired.  This AVP SHOULD be included in the Accounting-
+				Request messages pertaining to the tunneled session.
+   			*/
+			struct dict_avp_data adata = { 
+					91, 					/* Code */
+					0, 					/* Vendor */
+					"Tunnel-Server-Auth-Id", 		/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,			/* Fixed flag values */
+					AVP_TYPE_OCTETSTRING 			/* base type of data */
+					};
+			CHECK_dict_new( DICT_AVP, &adata , UTF8String_type, NULL);
+		}
+		
+		/* Tunneling */
+		{
+			/*
+				The Tunneling AVP (AVP Code 401) is of type Grouped and contains the
+				following AVPs, used to describe a compulsory tunnel service:
+				[RADTunnels], [RADTunlAcct].  Its data field has the following ABNF
+				grammar:
+
+				Tunneling     ::= < AVP Header: 401 >
+                				{ Tunnel-Type }
+                				{ Tunnel-Medium-Type }
+                				{ Tunnel-Client-Endpoint }
+                				{ Tunnel-Server-Endpoint }
+                				[ Tunnel-Preference ]
+                				[ Tunnel-Client-Auth-Id ]
+                				[ Tunnel-Server-Auth-Id ]
+                				[ Tunnel-Assignment-Id ]
+                				[ Tunnel-Password ]
+                				[ Tunnel-Private-Group-Id ]
+			*/
+			struct dict_object * avp;
+			struct dict_avp_data data = { 
+					401, 					/* Code */
+					0, 					/* Vendor */
+					"Tunneling", 				/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,			/* Fixed flag values */
+					AVP_TYPE_GROUPED 			/* base type of data */
+					};
+			struct local_rules_definition rules[] = 
+						{ 	 {  "Tunnel-Type", 			RULE_REQUIRED, -1, 1 }
+							,{  "Tunnel-Medium-Type",		RULE_OPTIONAL, -1, 1 }
+							,{  "Tunnel-Client-Endpoint",		RULE_OPTIONAL, -1, 1 }
+							,{  "Tunnel-Server-Endpoint",		RULE_OPTIONAL, -1, 1 }
+							,{  "Tunnel-Preference",		RULE_OPTIONAL, -1, 1 }
+							,{  "Tunnel-Client-Auth-Id",		RULE_OPTIONAL, -1, 1 }
+							,{  "Tunnel-Server-Auth-Id",		RULE_OPTIONAL, -1, 1 }
+							,{  "Tunnel-Assignment-Id",		RULE_OPTIONAL, -1, 1 }
+							,{  "Tunnel-Password",			RULE_OPTIONAL, -1, 1 }
+							,{  "Tunnel-Private-Group-Id",		RULE_OPTIONAL, -1, 1 }
+						};
+			
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+			PARSE_loc_rules( rules, avp );
+		}
+		
+/********************************
+ *  NAS Accounting AVPs         *
+ ********************************/		
+		/* Accounting-Input-Octets */
+		{
+			/*
+				The Accounting-Input-Octets AVP (AVP Code 363) is of type Unsigned64
+				and contains the number of octets received from the user.
+				
+				For NAS usage, this AVP indicates how many octets have been received
+				from the port in the course of this session.  It can only be present
+				in ACR messages with an Accounting-Record-Type of INTERIM_RECORD or
+				STOP_RECORD.
+			*/
+			struct dict_avp_data data = { 
+					363, 					/* Code */
+					0, 					/* Vendor */
+					"Accounting-Input-Octets", 		/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,		 	/* Fixed flag values */
+					AVP_TYPE_UNSIGNED64 			/* base type of data */
+					};
+			CHECK_dict_new( DICT_AVP, &data , NULL, NULL);
+		}
+		
+		/* Accounting-Output-Octets */
+		{
+			/*
+				The Accounting-Output-Octets AVP (AVP Code 364) is of type Unsigned64
+				and contains the number of octets sent to the user.
+
+				For NAS usage, this AVP indicates how many octets have been sent to
+				the port in the course of this session.  It can only be present in
+				ACR messages with an Accounting-Record-Type of INTERIM_RECORD or
+				STOP_RECORD.
+			*/
+			struct dict_avp_data data = { 
+					364, 					/* Code */
+					0, 					/* Vendor */
+					"Accounting-Output-Octets", 		/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,		 	/* Fixed flag values */
+					AVP_TYPE_UNSIGNED64 			/* base type of data */
+					};
+			CHECK_dict_new( DICT_AVP, &data , NULL, NULL);
+		}
+		
+		/* Accounting-Input-Packets */
+		{
+			/*
+				The Accounting-Input-Packets (AVP Code 365) is of type Unsigned64 and
+				contains the number of packets received from the user.
+
+				For NAS usage, this AVP indicates how many packets have been received
+				from the port over the course of a session being provided to a Framed
+				User.  It can only be present in ACR messages with an Accounting-
+				Record-Type of INTERIM_RECORD or STOP_RECORD.
+			*/
+			struct dict_avp_data data = { 
+					365, 					/* Code */
+					0, 					/* Vendor */
+					"Accounting-Input-Packets", 		/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,		 	/* Fixed flag values */
+					AVP_TYPE_UNSIGNED64 			/* base type of data */
+					};
+			CHECK_dict_new( DICT_AVP, &data , NULL, NULL);
+		}
+		
+		/* Accounting-Output-Packets */
+		{
+			/*
+				The Accounting-Output-Packets (AVP Code 366) is of type Unsigned64
+				and contains the number of IP packets sent to the user.
+
+				For NAS usage, this AVP indicates how many packets have been sent to
+				the port over the course of a session being provided to a Framed
+				User.  It can only be present in ACR messages with an Accounting-
+				Record-Type of INTERIM_RECORD or STOP_RECORD.
+			*/
+			struct dict_avp_data data = { 
+					366, 					/* Code */
+					0, 					/* Vendor */
+					"Accounting-Output-Packets", 		/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,		 	/* Fixed flag values */
+					AVP_TYPE_UNSIGNED64 			/* base type of data */
+					};
+			CHECK_dict_new( DICT_AVP, &data , NULL, NULL);
+		}
+		
+		/* Acct-Session-Time */
+		{
+			/*
+				The Acct-Session-Time AVP (AVP Code 46) is of type Unsigned32 and
+				indicates the length of the current session in seconds.  It can only
+				be present in ACR messages with an Accounting-Record-Type of
+				INTERIM_RECORD or STOP_RECORD.
+			*/
+			struct dict_avp_data data = { 
+					46, 					/* Code */
+					0, 					/* Vendor */
+					"Acct-Session-Time", 			/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,		 	/* Fixed flag values */
+					AVP_TYPE_UNSIGNED32 			/* base type of data */
+					};
+			CHECK_dict_new( DICT_AVP, &data , NULL, NULL);
+		}
+		
+		/* Acct-Authentic */
+		{
+			/*
+				The Acct-Authentic AVP (AVP Code 45) is of type Enumerated and
+				specifies how the user was authenticated.  The supported values are
+				listed in [RADIUSTypes].
+				Sub-registry: Values for RADIUS Attribute 45, Acct-Authentic
+				Reference: [RFC2866]
+			*/
+			struct dict_object 	*type;
+			struct dict_type_data 	 tdata = { AVP_TYPE_UNSIGNED32,	"Enumerated(Acct-Authentic)"	, NULL, NULL};
+			struct dict_enumval_data tvals[] = {
+				enumval_def_u32( 1, "RADIUS"),
+				enumval_def_u32( 2, "Local"),
+				enumval_def_u32( 3, "Remote"),
+				enumval_def_u32( 4, "Diameter")
+			};
+			struct dict_avp_data data = { 
+					45, 					/* Code */
+					0, 					/* Vendor */
+					"Acct-Authentic", 			/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,		 	/* Fixed flag values */
+					AVP_TYPE_UNSIGNED32 			/* base type of data */
+					};
+			int i;
+			/* Create the Enumerated type, enumerated values, and the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata , NULL, &type);
+			for (i = 0; i < sizeof(tvals) / sizeof(tvals[0]); i++) {
+				CHECK_dict_new( DICT_ENUMVAL, &tvals[i], type, NULL);
+			}
+			CHECK_dict_new( DICT_AVP, &data , type, NULL);
+		}
+		
+		/* Accounting-Auth-Method */
+		{
+			/*
+				The Accounting-Auth-Method AVP (AVP Code 406) is of type Enumerated.
+				A NAS MAY include this AVP in an Accounting-Request message to
+				indicate the method used to authenticate the user.  (Note that this
+				is equivalent to the RADIUS MS-Acct-Auth-Type VSA attribute).
+
+				The following values are defined:
+
+				1  PAP
+				2  CHAP
+				3  MS-CHAP-1
+				4  MS-CHAP-2
+				5  EAP
+				7  None
+			*/
+			struct dict_object 	*type;
+			struct dict_type_data 	 tdata = { AVP_TYPE_UNSIGNED32,	"Enumerated(Accounting-Auth-Method)"	, NULL, NULL};
+			struct dict_enumval_data tvals[] = {
+				enumval_def_u32( 1, "PAP"),
+				enumval_def_u32( 2, "CHAP"),
+				enumval_def_u32( 3, "MS-CHAP-1"),
+				enumval_def_u32( 4, "MS-CHAP-2"),
+				enumval_def_u32( 5, "EAP"),
+				enumval_def_u32( 7, "None")
+			};
+			struct dict_avp_data data = { 
+					406, 					/* Code */
+					0, 					/* Vendor */
+					"Accounting-Auth-Method", 		/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,		 	/* Fixed flag values */
+					AVP_TYPE_UNSIGNED32 			/* base type of data */
+					};
+			int i;
+			/* Create the Enumerated type, enumerated values, and the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata , NULL, &type);
+			for (i = 0; i < sizeof(tvals) / sizeof(tvals[0]); i++) {
+				CHECK_dict_new( DICT_ENUMVAL, &tvals[i], type, NULL);
+			}
+			CHECK_dict_new( DICT_AVP, &data , type, NULL);
+		}
+		
+		/* Acct-Delay-Time */
+		{
+			/*
+				The Acct-Delay-Time AVP (AVP Code 41) is of type Unsigned32 and
+				indicates the number of seconds the Diameter client has been trying
+				to send the Accounting-Request (ACR).  The accounting server may
+				subtract this value from the time when the ACR arrives at the server
+				to calculate the approximate time of the event that caused the ACR to
+				be generated.
+
+				This AVP is not used for retransmissions at the transport level (TCP
+				or SCTP).  Rather, it may be used when an ACR command cannot be
+				transmitted because there is no appropriate peer to transmit it to or
+				was rejected because it could not be delivered.  In these cases, the
+				command MAY be buffered and transmitted later, when an appropriate
+				peer-connection is available or after sufficient time has passed that
+				the destination-host may be reachable and operational.  If the ACR is
+				resent in this way, the Acct-Delay-Time AVP SHOULD be included.  The
+				value of this AVP indicates the number of seconds that elapsed
+				between the time of the first attempt at transmission and the current
+				attempt.
+			*/
+			struct dict_avp_data data = { 
+					41, 					/* Code */
+					0, 					/* Vendor */
+					"Acct-Delay-Time", 			/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,		 	/* Fixed flag values */
+					AVP_TYPE_UNSIGNED32 			/* base type of data */
+					};
+			CHECK_dict_new( DICT_AVP, &data , NULL, NULL);
+		}
+		
+		/* Acct-Link-Count */
+		{
+			/*
+				The Acct-Link-Count AVP (AVP Code 51) is of type Unsigned32 and
+				indicates the total number of links that have been active (current or
+				closed) in a given multilink session at the time the accounting
+				record is generated.  This AVP MAY be included in Accounting-Requests
+				for any session that may be part of a multilink service.
+
+				The Acct-Link-Count AVP may be used to make it easier for an
+				accounting server to know when it has all the records for a given
+				multilink service.  When the number of Accounting-Requests received
+				with Accounting-Record-Type = STOP_RECORD and with the same Acct-
+				Multi-Session-Id and unique Session-Ids equals the largest value of
+				Acct-Link-Count seen in those Accounting-Requests, all STOP_RECORD
+				Accounting-Requests for that multilink service have been received.
+
+				The following example, showing eight Accounting-Requests, illustrates
+				how the Acct-Link-Count AVP is used.  In the table below, only the
+				relevant AVPs are shown, although additional AVPs containing
+				accounting information will be present in the Accounting-Requests.
+
+				Acct-Multi-                   Accounting-     Acct-
+				Session-Id     Session-Id     Record-Type     Link-Count
+				--------------------------------------------------------
+				"...10"        "...10"      START_RECORD        1
+				"...10"        "...11"      START_RECORD        2
+				"...10"        "...11"      STOP_RECORD         2
+				"...10"        "...12"      START_RECORD        3
+				"...10"        "...13"      START_RECORD        4
+				"...10"        "...12"      STOP_RECORD         4
+				"...10"        "...13"      STOP_RECORD         4
+				"...10"        "...10"      STOP_RECORD         4
+
+			*/
+			struct dict_avp_data data = { 
+					51, 					/* Code */
+					0, 					/* Vendor */
+					"Acct-Link-Count", 			/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,		 	/* Fixed flag values */
+					AVP_TYPE_UNSIGNED32 			/* base type of data */
+					};
+			CHECK_dict_new( DICT_AVP, &data , NULL, NULL);
+		}
+		
+		/* Acct-Tunnel-Connection */
+		{
+			/*
+				The Acct-Tunnel-Connection AVP (AVP Code 68) is of type OctetString
+				and contains the identifier assigned to the tunnel session.  This
+				AVP, along with the Tunnel-Client-Endpoint and Tunnel-Server-Endpoint
+				AVPs, may be used to provide a means to uniquely identify a tunnel
+				session for auditing purposes.
+
+				The format of the identifier in this AVP depends upon the value of
+				the Tunnel-Type AVP.  For example, to identify an L2TP tunnel
+				connection fully, the L2TP Tunnel Id and Call Id might be encoded in
+				this field.  The exact encoding of this field is implementation
+				dependent.
+			*/
+			struct dict_avp_data data = { 
+					68, 					/* Code */
+					0, 					/* Vendor */
+					"Acct-Tunnel-Connection", 		/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,		 	/* Fixed flag values */
+					AVP_TYPE_OCTETSTRING 			/* base type of data */
+					};
+			CHECK_dict_new( DICT_AVP, &data , NULL, NULL);
+		}
+		
+		/* Acct-Tunnel-Packets-Lost */
+		{
+			/*
+				The Acct-Tunnel-Packets-Lost AVP (AVP Code 86) is of type Unsigned32
+				and contains the number of packets lost on a given link.
+			*/
+			struct dict_avp_data data = { 
+					86, 					/* Code */
+					0, 					/* Vendor */
+					"Acct-Tunnel-Packets-Lost", 		/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,		 	/* Fixed flag values */
+					AVP_TYPE_UNSIGNED32 			/* base type of data */
+					};
+			CHECK_dict_new( DICT_AVP, &data , NULL, NULL);
+		}
+		
+/***********************************
+ *  Compatibility with RADIUS AVPs *
+ ***********************************/
+		/* NAS-Identifier */
+		{
+			/*
+				The NAS-Identifier AVP (AVP Code 32) [RADIUS] is of type UTF8String
+				and contains the identity of the NAS providing service to the user.
+				This AVP SHOULD only be added by a RADIUS/Diameter Translation Agent.
+				When this AVP is present, the Origin-Host AVP identifies the NAS
+				providing service to the user.
+
+				In RADIUS it would be possible for a rogue NAS to forge the NAS-
+				Identifier attribute.  Diameter/RADIUS translation agents SHOULD
+				attempt to check a received NAS-Identifier attribute against the
+				source address of the RADIUS packet, by doing an A/AAAA RR query.  If
+				the NAS-Identifier attribute contains an FQDN, then such a query
+				would resolve to an IP address matching the source address.  However,
+				the NAS-Identifier attribute is not required to contain an FQDN, so
+				such a query could fail.  If it fails, an error should be logged, but
+				no action should be taken, other than a reverse lookup on the source
+				address and insert the resulting FQDN into the Route-Record AVP.
+
+				Diameter agents and servers SHOULD check whether a NAS-Identifier AVP
+				corresponds to an entry in the Route-Record AVP.  If no match is
+				found, then an error is logged, but no other action is taken.
+			*/
+			struct dict_avp_data data = { 
+					32, 					/* Code */
+					0, 					/* Vendor */
+					"NAS-Identifier", 			/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,		 	/* Fixed flag values */
+					AVP_TYPE_OCTETSTRING 			/* base type of data */
+					};
+			CHECK_dict_new( DICT_AVP, &data , UTF8String_type, NULL);
+		}
+		
+		/* NAS-IP-Address */
+		{
+			/*
+				The NAS-IP-Address AVP (AVP Code 4) [RADIUS] is of type OctetString
+				and contains the IP Address of the NAS providing service to the user.
+				This AVP SHOULD only be added by a RADIUS/Diameter Translation Agent.
+				When this AVP is present, the Origin-Host AVP identifies the NAS
+				providing service to the user.
+
+				In RADIUS it would be possible for a rogue NAS to forge the NAS-IP-
+				Address attribute value.  Diameter/RADIUS translation agents MUST
+				check a received NAS-IP-Address or NAS-IPv6-Address attribute against
+				the source address of the RADIUS packet.  If they do not match and
+				the Diameter/RADIUS translation agent does not know whether the
+				packet was sent by a RADIUS proxy or NAS (e.g., no Proxy-State
+				attribute), then by default it is assumed that the source address
+				corresponds to a RADIUS proxy, and that the NAS Address is behind
+				that proxy, potentially with some additional RADIUS proxies in
+				between.  The Diameter/RADIUS translation agent MUST insert entries
+				in the Route-Record AVP corresponding to the apparent route.  This
+				implies doing a reverse lookup on the source address and NAS-IP-
+				Address or NAS-IPv6-Address attributes to determine the corresponding
+				FQDNs.
+
+				If the source address and the NAS-IP-Address or NAS-IPv6-Address do
+				not match, and the Diameter/RADIUS translation agent knows that it is
+				talking directly to the NAS (e.g., there are no RADIUS proxies
+				between it and the NAS), then the error should be logged, and the
+				packet MUST be discarded.
+
+				Diameter agents and servers MUST check whether the NAS-IP-Address AVP
+				corresponds to an entry in the Route-Record AVP.  This is done by
+				doing a reverse lookup (PTR RR) for the NAS-IP-Address to retrieve
+				the corresponding FQDN, and by checking for a match with the Route-
+				Record AVP.  If no match is found, then an error is logged, but no
+				other action is taken.
+			*/
+			struct dict_avp_data data = { 
+					4, 					/* Code */
+					0, 					/* Vendor */
+					"NAS-IP-Address", 			/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,		 	/* Fixed flag values */
+					AVP_TYPE_OCTETSTRING 			/* base type of data */
+					};
+			CHECK_dict_new( DICT_AVP, &data , NULL, NULL);
+		}
+		
+		/* NAS-IPv6-Address */
+		{
+			/*
+				The NAS-IPv6-Address AVP (AVP Code 95) [RADIUSIPv6] is of type
+				OctetString and contains the IPv6 Address of the NAS providing
+				service to the user.  This AVP SHOULD only be added by a
+				RADIUS/Diameter Translation Agent.  When this AVP is present, the
+				Origin-Host AVP identifies the NAS providing service to the user.
+
+				In RADIUS it would be possible for a rogue NAS to forge the NAS-
+				IPv6-Address attribute.  Diameter/RADIUS translation agents MUST
+				check a received NAS-IPv6-Address attribute against the source
+				address of the RADIUS packet.  If they do not match and the
+				Diameter/RADIUS translation agent does not know whether the packet
+				was sent by a RADIUS proxy or NAS (e.g., no Proxy-State attribute),
+				then by default it is assumed that the source address corresponds to
+				a RADIUS proxy, and that the NAS-IPv6-Address is behind that proxy,
+				potentially with some additional RADIUS proxies in between.  The
+				Diameter/RADIUS translation agent MUST insert entries in the Route-
+				Record AVP corresponding to the apparent route.  This implies doing a
+				reverse lookup on the source address and NAS-IPv6-Address attributes
+				to determine the corresponding FQDNs.
+
+				If the source address and the NAS-IPv6-Address do not match, and the
+				Diameter/RADIUS translation agent knows that it is talking directly
+				to the NAS (e.g., there are no RADIUS proxies between it and the
+				NAS), then the error should be logged, and the packet MUST be
+				discarded.
+
+				Diameter agents and servers MUST check whether the NAS-IPv6-Address
+				AVP corresponds to an entry in the Route-Record AVP.  This is done by
+				doing a reverse lookup (PTR RR) for the NAS-IPv6-Address to retrieve
+				the corresponding FQDN, and by checking for a match with the Record-
+				Route AVP.  If no match is found, then an error is logged, but no
+				other action is taken.
+			*/
+			struct dict_avp_data data = { 
+					95, 					/* Code */
+					0, 					/* Vendor */
+					"NAS-IPv6-Address", 			/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,		 	/* Fixed flag values */
+					AVP_TYPE_OCTETSTRING 			/* base type of data */
+					};
+			CHECK_dict_new( DICT_AVP, &data , NULL, NULL);
+		}
+		
+		/* State */
+		{
+			/*
+				The State AVP (AVP Code 24) [RADIUS] is of type OctetString and has
+				two uses in the Diameter NAS application.
+
+				The State AVP MAY be sent by a Diameter Server to a NAS in an AA-
+				Response command that contains a Result-Code of
+				DIAMETER_MULTI_ROUND_AUTH.  If so, the NAS MUST return it unmodified
+				in the subsequent AA-Request command.
+
+				The State AVP MAY also be sent by a Diameter Server to a NAS in an
+				AA-Response command that also includes a Termination-Action AVP with
+				the value of AA-REQUEST.  If the NAS performs the Termination-Action
+				by sending a new AA-Request command upon termination of the current
+				service, it MUST return the State AVP unmodified in the new request
+				command.
+
+				In either usage, the NAS MUST NOT interpret the AVP locally.  Usage
+				of the State AVP is implementation dependent.
+			*/
+			struct dict_avp_data data = { 
+					24, 					/* Code */
+					0, 					/* Vendor */
+					"State", 				/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,		 	/* Fixed flag values */
+					AVP_TYPE_OCTETSTRING 			/* base type of data */
+					};
+			CHECK_dict_new( DICT_AVP, &data , NULL, NULL);
+		}
+		
+		/* Termination-Cause mapping */
+		{
+			
+			struct dict_object 	*type;
+			struct dict_enumval_data tvals[] = {
+				enumval_def_u32(11, "[RADIUS] User Request"),
+				enumval_def_u32(12, "[RADIUS] Lost Carrier"),
+				enumval_def_u32(13, "[RADIUS] Lost Service"),
+				enumval_def_u32(14, "[RADIUS] Idle Timeout"),
+				enumval_def_u32(15, "[RADIUS] Session Timeout"),
+				enumval_def_u32(16, "[RADIUS] Admin Reset"),
+				enumval_def_u32(17, "[RADIUS] Admin Reboot"),
+				enumval_def_u32(18, "[RADIUS] Port Error"),
+				enumval_def_u32(19, "[RADIUS] NAS Error"),
+				enumval_def_u32(20, "[RADIUS] NAS Request"),
+				enumval_def_u32(21, "[RADIUS] NAS Reboot"),
+				enumval_def_u32(22, "[RADIUS] Port Unneeded"),
+				enumval_def_u32(23, "[RADIUS] Port Preempted"),
+				enumval_def_u32(24, "[RADIUS] Port Suspended"),
+				enumval_def_u32(25, "[RADIUS] Service Unavailable"),
+				enumval_def_u32(26, "[RADIUS] Callback"),
+				enumval_def_u32(27, "[RADIUS] User Error"),
+				enumval_def_u32(28, "[RADIUS] Host Request"),
+				enumval_def_u32(29, "[RADIUS] Supplicant Restart"),
+				enumval_def_u32(30, "[RADIUS] Reauthentication Failure"),
+				enumval_def_u32(31, "[RADIUS] Port Reinit"),
+				enumval_def_u32(32, "[RADIUS] Port Disabled")
+				};
+			int i;
+
+			CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "Enumerated(Termination-Cause)", &type);
+			for (i = 0; i < sizeof(tvals) / sizeof(tvals[0]); i++) {
+				CHECK_dict_new( DICT_ENUMVAL, &tvals[i], type, NULL);
+			}
+			
+		}
+		
+		/* Origin-AAA-Protocol */
+		{
+			/*
+				The Origin-AAA-Protocol AVP (AVP Code 408) is of the type Enumerated
+				and should be inserted in a Diameter message translated by a gateway
+				system from another AAA protocol, such as RADIUS.  It identifies the
+				source protocol of the message to the Diameter system receiving the
+				message.
+
+				The supported values are:
+
+				 1       RADIUS
+			*/
+			struct dict_object 	*type;
+			struct dict_type_data 	 tdata = { AVP_TYPE_UNSIGNED32,	"Enumerated(Origin-AAA-Protocol)"	, NULL, NULL};
+			struct dict_enumval_data tvals[] = {
+				enumval_def_u32( 1, "RADIUS")
+			};
+			struct dict_avp_data data = { 
+					408, 					/* Code */
+					0, 					/* Vendor */
+					"Origin-AAA-Protocol", 			/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,		 	/* Fixed flag values */
+					AVP_TYPE_UNSIGNED32 			/* base type of data */
+					};
+			int i;
+			/* Create the Enumerated type, enumerated values, and the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata , NULL, &type);
+			for (i = 0; i < sizeof(tvals) / sizeof(tvals[0]); i++) {
+				CHECK_dict_new( DICT_ENUMVAL, &tvals[i], type, NULL);
+			}
+			CHECK_dict_new( DICT_AVP, &data , type, NULL);
+		}
+		
+	}
+
+/********************/		
+/* Commands section */
+/********************/		
+	{
+		/* To avoid defining global variables for all the AVP that we use here, we do search the dictionary in each sub-block.
+		 * This is far from optimal, but the code is clearer like this, and the time it requires at execution is not noticeable.
+		 */
+		
+		/* AA-Request (AAR) Command */
+		{
+			/*
+				The AA-Request (AAR), which is indicated by setting the Command-Code
+				field to 265 and the 'R' bit in the Command Flags field, is used to
+				request authentication and/or authorization for a given NAS user.
+				The type of request is identified through the Auth-Request-Type AVP
+				[BASE].  The recommended value for most RADIUS interoperabily
+				situations is AUTHORIZE_AUTHENTICATE.
+
+				If Authentication is requested, the User-Name attribute SHOULD be
+				present, as well as any additional authentication AVPs that would
+				carry the password information.  A request for authorization SHOULD
+				only include the information from which the authorization will be
+				performed, such as the User-Name, Called-Station-Id, or Calling-
+				Station-Id AVPs.  All requests SHOULD contain AVPs uniquely
+				identifying the source of the call, such as Origin-Host and NAS-Port.
+				Certain networks MAY use different AVPs for authorization purposes.
+				A request for authorization will include some AVPs defined in section
+				6.
+
+				It is possible for a single session to be authorized first and then
+				for an authentication request to follow.
+
+				This AA-Request message MAY be the result of a multi-round
+				authentication exchange, which occurs when the AA-Answer message is
+				received with the Result-Code AVP set to DIAMETER_MULTI_ROUND_AUTH.
+				A subsequent AAR message SHOULD be sent, with the User-Password AVP
+				that includes the user's response to the prompt, and MUST include any
+				State AVPs that were present in the AAA message.
+
+				Message Format
+				<AA-Request> ::= < Diameter Header: 265, REQ, PXY >
+        				       < Session-Id >
+        				       { Auth-Application-Id }
+        				       { Origin-Host }
+        				       { Origin-Realm }
+        				       { Destination-Realm }
+        				       { Auth-Request-Type }
+        				       [ Destination-Host ]
+        				       [ NAS-Identifier ]
+        				       [ NAS-IP-Address ]
+        				       [ NAS-IPv6-Address ]
+        				       [ NAS-Port ]
+        				       [ NAS-Port-Id ]
+        				       [ NAS-Port-Type ]
+        				       [ Origin-AAA-Protocol ]
+        				       [ Origin-State-Id ]
+        				       [ Port-Limit ]
+        				       [ User-Name ]
+        				       [ User-Password ]
+        				       [ Service-Type ]
+        				       [ State ]
+        				       [ Authorization-Lifetime ]
+        				       [ Auth-Grace-Period ]
+        				       [ Auth-Session-State ]
+        				       [ Callback-Number ]
+        				       [ Called-Station-Id ]
+        				       [ Calling-Station-Id ]
+        				       [ Originating-Line-Info ]
+        				       [ Connect-Info ]
+        				       [ CHAP-Auth ]
+        				       [ CHAP-Challenge ]
+        				     * [ Framed-Compression ]
+        				       [ Framed-Interface-Id ]
+        				       [ Framed-IP-Address ]
+        				     * [ Framed-IPv6-Prefix ]
+        				       [ Framed-IP-Netmask ]
+        				       [ Framed-MTU ]
+        				       [ Framed-Protocol ]
+        				       [ ARAP-Password ]
+        				       [ ARAP-Security ]
+        				     * [ ARAP-Security-Data ]
+        				     * [ Login-IP-Host ]
+        				     * [ Login-IPv6-Host ]
+        				       [ Login-LAT-Group ]
+        				       [ Login-LAT-Node ]
+        				       [ Login-LAT-Port ]
+        				       [ Login-LAT-Service ]
+        				     * [ Tunneling ]
+        				     * [ Proxy-Info ]
+        				     * [ Route-Record ]
+        				     * [ AVP ]
+			*/
+			struct dict_object * cmd;
+			struct dict_cmd_data data = { 
+					265, 					/* Code */
+					"AA-Request", 				/* Name */
+					CMD_FLAG_REQUEST | CMD_FLAG_PROXIABLE | CMD_FLAG_ERROR, /* Fixed flags */
+					CMD_FLAG_REQUEST | CMD_FLAG_PROXIABLE 			/* Fixed flag values */
+					};
+			struct local_rules_definition rules[] = 
+						{ 	 {  "Session-Id", 			RULE_FIXED_HEAD, -1, 1 }
+						 	,{  "Auth-Application-Id", 		RULE_REQUIRED,   -1, 1 }
+						 	,{  "Origin-Host", 			RULE_REQUIRED,   -1, 1 }
+							,{  "Origin-Realm",			RULE_REQUIRED,   -1, 1 }
+							,{  "Destination-Realm",		RULE_REQUIRED,   -1, 1 }
+						 	,{  "Auth-Request-Type", 		RULE_REQUIRED,   -1, 1 }
+							,{  "Destination-Host",			RULE_OPTIONAL,   -1, 1 }
+							,{  "NAS-Identifier",			RULE_OPTIONAL,   -1, 1 }
+							,{  "NAS-IP-Address",			RULE_OPTIONAL,   -1, 1 }
+							,{  "NAS-IPv6-Address",			RULE_OPTIONAL,   -1, 1 }
+							,{  "NAS-Port",				RULE_OPTIONAL,   -1, 1 }
+							,{  "NAS-Port-Id",			RULE_OPTIONAL,   -1, 1 }
+							,{  "NAS-Port-Type",			RULE_OPTIONAL,   -1, 1 }
+							,{  "Origin-AAA-Protocol",		RULE_OPTIONAL,   -1, 1 }
+							,{  "Origin-State-Id",			RULE_OPTIONAL,   -1, 1 }
+							,{  "Port-Limit",			RULE_OPTIONAL,   -1, 1 }
+							,{  "User-Name",			RULE_OPTIONAL,   -1, 1 }
+							,{  "User-Password",			RULE_OPTIONAL,   -1, 1 }
+							,{  "Service-Type",			RULE_OPTIONAL,   -1, 1 }
+							,{  "State",				RULE_OPTIONAL,   -1, 1 }
+							,{  "Authorization-Lifetime",		RULE_OPTIONAL,   -1, 1 }
+							,{  "Auth-Grace-Period",		RULE_OPTIONAL,   -1, 1 }
+							,{  "Auth-Session-State",		RULE_OPTIONAL,   -1, 1 }
+							,{  "Callback-Number",			RULE_OPTIONAL,   -1, 1 }
+							,{  "Called-Station-Id",		RULE_OPTIONAL,   -1, 1 }
+							,{  "Calling-Station-Id",		RULE_OPTIONAL,   -1, 1 }
+							,{  "Originating-Line-Info",		RULE_OPTIONAL,   -1, 1 }
+							,{  "Connect-Info",			RULE_OPTIONAL,   -1, 1 }
+							,{  "CHAP-Auth",			RULE_OPTIONAL,   -1, 1 }
+							,{  "CHAP-Challenge",			RULE_OPTIONAL,   -1, 1 }
+							,{  "Framed-Compression",		RULE_OPTIONAL,   -1,-1 }
+							,{  "Framed-Interface-Id",		RULE_OPTIONAL,   -1, 1 }
+							,{  "Framed-IP-Address",		RULE_OPTIONAL,   -1, 1 }
+							,{  "Framed-IPv6-Prefix",		RULE_OPTIONAL,   -1,-1 }
+							,{  "Framed-IP-Netmask",		RULE_OPTIONAL,   -1, 1 }
+							,{  "Framed-MTU",			RULE_OPTIONAL,   -1, 1 }
+							,{  "Framed-Protocol",			RULE_OPTIONAL,   -1, 1 }
+							,{  "ARAP-Password",			RULE_OPTIONAL,   -1, 1 }
+							,{  "ARAP-Security",			RULE_OPTIONAL,   -1, 1 }
+							,{  "ARAP-Security-Data",		RULE_OPTIONAL,   -1,-1 }
+							,{  "Login-IP-Host",			RULE_OPTIONAL,   -1,-1 }
+							,{  "Login-IPv6-Host",			RULE_OPTIONAL,   -1,-1 }
+							,{  "Login-LAT-Group",			RULE_OPTIONAL,   -1, 1 }
+							,{  "Login-LAT-Node",			RULE_OPTIONAL,   -1, 1 }
+							,{  "Login-LAT-Port",			RULE_OPTIONAL,   -1, 1 }
+							,{  "Login-LAT-Service",		RULE_OPTIONAL,   -1, 1 }
+							,{  "Tunneling",			RULE_OPTIONAL,   -1,-1 }
+							,{  "Proxy-Info",			RULE_OPTIONAL,   -1,-1 }
+							,{  "Route-Record",			RULE_OPTIONAL,   -1,-1 }
+						};
+			
+			CHECK_dict_new( DICT_COMMAND, &data , nasreq, &cmd);
+			PARSE_loc_rules( rules, cmd );
+		}
+		
+		/* AA-Answer (AAA) Command */
+		{
+			/*
+				The AA-Answer (AAA) message is indicated by setting the Command-Code
+				field to 265 and clearing the 'R' bit in the Command Flags field.  It
+				is sent in response to the AA-Request (AAR) message.  If
+				authorization was requested, a successful response will include the
+				authorization AVPs appropriate for the service being provided, as
+				defined in section 6.
+
+				For authentication exchanges requiring more than a single round trip,
+				the server MUST set the Result-Code AVP to DIAMETER_MULTI_ROUND_AUTH.
+				An AAA message with this result code MAY include one Reply-Message or
+				more and MAY include zero or one State AVPs.
+
+				If the Reply-Message AVP was present, the network access server
+				SHOULD send the text to the user's client to display to the user,
+				instructing the client to prompt the user for a response.  For
+				example, this capability can be achieved in PPP via PAP.  If the
+				access client is unable to prompt the user for a new response, it
+				MUST treat the AA-Answer (AAA) with the Reply-Message AVP as an error
+				and deny access.
+
+				Message Format
+
+				<AA-Answer> ::= < Diameter Header: 265, PXY >
+        				      < Session-Id >
+        				      { Auth-Application-Id }
+        				      { Auth-Request-Type }
+        				      { Result-Code }
+        				      { Origin-Host }
+        				      { Origin-Realm }
+        				      [ User-Name ]
+        				      [ Service-Type ]
+        				    * [ Class ]
+        				    * [ Configuration-Token ]
+        				      [ Acct-Interim-Interval ]
+        				      [ Error-Message ]
+        				      [ Error-Reporting-Host ]
+        				    * [ Failed-AVP ]
+        				      [ Idle-Timeout ]
+        				      [ Authorization-Lifetime ]
+        				      [ Auth-Grace-Period ]
+        				      [ Auth-Session-State ]
+        				      [ Re-Auth-Request-Type ]
+        				      [ Multi-Round-Time-Out ]
+        				      [ Session-Timeout ]
+        				      [ State ]
+        				    * [ Reply-Message ]
+        				      [ Origin-AAA-Protocol ]
+        				      [ Origin-State-Id ]
+        				    * [ Filter-Id ]
+        				      [ Password-Retry ]
+        				      [ Port-Limit ]
+        				      [ Prompt ]
+        				      [ ARAP-Challenge-Response ]
+        				      [ ARAP-Features ]
+        				      [ ARAP-Security ]
+        				    * [ ARAP-Security-Data ]
+        				      [ ARAP-Zone-Access ]
+        				      [ Callback-Id ]
+        				      [ Callback-Number ]
+        				      [ Framed-Appletalk-Link ]
+        				    * [ Framed-Appletalk-Network ]
+        				      [ Framed-Appletalk-Zone ]
+        				    * [ Framed-Compression ]
+        				      [ Framed-Interface-Id ]
+        				      [ Framed-IP-Address ]
+        				    * [ Framed-IPv6-Prefix ]
+        				      [ Framed-IPv6-Pool ]
+        				    * [ Framed-IPv6-Route ]
+        				      [ Framed-IP-Netmask ]
+        				    * [ Framed-Route ]
+        				      [ Framed-Pool ]
+        				      [ Framed-IPX-Network ]
+        				      [ Framed-MTU ]
+        				      [ Framed-Protocol ]
+        				      [ Framed-Routing ]
+        				    * [ Login-IP-Host ]
+        				    * [ Login-IPv6-Host ]
+        				      [ Login-LAT-Group ]
+        				      [ Login-LAT-Node ]
+        				      [ Login-LAT-Port ]
+        				      [ Login-LAT-Service ]
+        				      [ Login-Service ]
+        				      [ Login-TCP-Port ]
+        				    * [ NAS-Filter-Rule ]
+        				    * [ QoS-Filter-Rule ]
+        				    * [ Tunneling ]
+        				    * [ Redirect-Host ]
+        				      [ Redirect-Host-Usage ]
+        				      [ Redirect-Max-Cache-Time ]
+        				    * [ Proxy-Info ]
+        				    * [ AVP ]
+			*/
+			struct dict_object * cmd;
+			struct dict_cmd_data data = { 
+					265, 					/* Code */
+					"AA-Answer", 				/* Name */
+					CMD_FLAG_REQUEST | CMD_FLAG_PROXIABLE,	/* Fixed flags */
+							   CMD_FLAG_PROXIABLE	/* Fixed flag values */
+					};
+			struct local_rules_definition rules[] = 
+						{ 	 {  "Session-Id", 			RULE_FIXED_HEAD, -1, 1 }
+						 	,{  "Auth-Application-Id", 		RULE_REQUIRED,   -1, 1 }
+						 	,{  "Auth-Request-Type", 		RULE_REQUIRED,   -1, 1 }
+						 	,{  "Result-Code", 			RULE_REQUIRED,   -1, 1 }
+						 	,{  "Origin-Host", 			RULE_REQUIRED,   -1, 1 }
+							,{  "Origin-Realm",			RULE_REQUIRED,   -1, 1 }
+							,{  "User-Name",			RULE_OPTIONAL,   -1, 1 }
+							,{  "Service-Type",			RULE_OPTIONAL,   -1, 1 }
+							,{  "Class",				RULE_OPTIONAL,   -1,-1 }
+							,{  "Configuration-Token",		RULE_OPTIONAL,   -1,-1 }
+							,{  "Acct-Interim-Interval",		RULE_OPTIONAL,   -1, 1 }
+							,{  "Error-Message",			RULE_OPTIONAL,   -1, 1 }
+							,{  "Error-Reporting-Host",		RULE_OPTIONAL,   -1, 1 }
+							,{  "Failed-AVP",			RULE_OPTIONAL,   -1,-1 }
+							,{  "Idle-Timeout",			RULE_OPTIONAL,   -1, 1 }
+							,{  "Authorization-Lifetime",		RULE_OPTIONAL,   -1, 1 }
+							,{  "Auth-Grace-Period",		RULE_OPTIONAL,   -1, 1 }
+							,{  "Auth-Session-State",		RULE_OPTIONAL,   -1, 1 }
+							,{  "Re-Auth-Request-Type",		RULE_OPTIONAL,   -1, 1 }
+							,{  "Multi-Round-Time-Out",		RULE_OPTIONAL,   -1, 1 }
+							,{  "Session-Timeout",			RULE_OPTIONAL,   -1, 1 }
+							,{  "State",				RULE_OPTIONAL,   -1, 1 }
+							,{  "Reply-Message",			RULE_OPTIONAL,   -1,-1 }
+							,{  "Origin-AAA-Protocol",		RULE_OPTIONAL,   -1, 1 }
+							,{  "Origin-State-Id",			RULE_OPTIONAL,   -1, 1 }
+							,{  "Filter-Id",			RULE_OPTIONAL,   -1,-1 }
+							,{  "Password-Retry",			RULE_OPTIONAL,   -1, 1 }
+							,{  "Port-Limit",			RULE_OPTIONAL,   -1, 1 }
+							,{  "Prompt",				RULE_OPTIONAL,   -1, 1 }
+							,{  "ARAP-Challenge-Response",		RULE_OPTIONAL,   -1, 1 }
+							,{  "ARAP-Features",			RULE_OPTIONAL,   -1, 1 }
+							,{  "ARAP-Security",			RULE_OPTIONAL,   -1, 1 }
+							,{  "ARAP-Security-Data",		RULE_OPTIONAL,   -1,-1 }
+							,{  "ARAP-Zone-Access",			RULE_OPTIONAL,   -1, 1 }
+							,{  "Callback-Id",			RULE_OPTIONAL,   -1, 1 }
+							,{  "Callback-Number",			RULE_OPTIONAL,   -1, 1 }
+							,{  "Framed-AppleTalk-Link",		RULE_OPTIONAL,   -1, 1 }
+							,{  "Framed-AppleTalk-Network",		RULE_OPTIONAL,   -1,-1 }
+							,{  "Framed-AppleTalk-Zone",		RULE_OPTIONAL,   -1, 1 }
+							,{  "Framed-Compression",		RULE_OPTIONAL,   -1,-1 }
+							,{  "Framed-Interface-Id",		RULE_OPTIONAL,   -1,-1 }
+							,{  "Framed-IP-Address",		RULE_OPTIONAL,   -1, 1 }
+							,{  "Framed-IPv6-Prefix",		RULE_OPTIONAL,   -1,-1 }
+							,{  "Framed-IPv6-Pool",			RULE_OPTIONAL,   -1, 1 }
+							,{  "Framed-IPv6-Route",		RULE_OPTIONAL,   -1,-1 }
+							,{  "Framed-IP-Netmask",		RULE_OPTIONAL,   -1,-1 }
+							,{  "Framed-Route",			RULE_OPTIONAL,   -1,-1 }
+							,{  "Framed-Pool",			RULE_OPTIONAL,   -1, 1 }
+							,{  "Framed-IPX-Network",		RULE_OPTIONAL,   -1, 1 }
+							,{  "Framed-MTU",			RULE_OPTIONAL,   -1, 1 }
+							,{  "Framed-Protocol",			RULE_OPTIONAL,   -1, 1 }
+							,{  "Framed-Routing",			RULE_OPTIONAL,   -1, 1 }
+							,{  "Login-IP-Host",			RULE_OPTIONAL,   -1,-1 }
+							,{  "Login-IPv6-Host",			RULE_OPTIONAL,   -1,-1 }
+							,{  "Login-LAT-Group",			RULE_OPTIONAL,   -1, 1 }
+							,{  "Login-LAT-Node",			RULE_OPTIONAL,   -1, 1 }
+							,{  "Login-LAT-Port",			RULE_OPTIONAL,   -1, 1 }
+							,{  "Login-LAT-Service",		RULE_OPTIONAL,   -1, 1 }
+							,{  "Login-Service",			RULE_OPTIONAL,   -1, 1 }
+							,{  "Login-TCP-Port",			RULE_OPTIONAL,   -1, 1 }
+							,{  "NAS-Filter-Rule",			RULE_OPTIONAL,   -1,-1 }
+							,{  "QoS-Filter-Rule",			RULE_OPTIONAL,   -1,-1 }
+							,{  "Tunneling",			RULE_OPTIONAL,   -1,-1 }
+							,{  "Redirect-Host",			RULE_OPTIONAL,   -1,-1 }
+							,{  "Redirect-Host-Usage",		RULE_OPTIONAL,   -1, 1 }
+							,{  "Redirect-Max-Cache-Time",		RULE_OPTIONAL,   -1, 1 }
+							,{  "Proxy-Info",			RULE_OPTIONAL,   -1,-1 }
+						};
+			
+			CHECK_dict_new( DICT_COMMAND, &data , nasreq, &cmd);
+			PARSE_loc_rules( rules, cmd );
+		}
+		
+		/* Re-Auth-Request */
+		{
+			/*
+				Add additional rules of the ABNF (compared to Base definition):
+				
+			<RA-Request>  ::= < Diameter Header: 258, REQ, PXY >
+        			       < Session-Id >
+        			       { Origin-Host }
+        			       { Origin-Realm }
+        			       { Destination-Realm }
+        			       { Destination-Host }
+        			       { Auth-Application-Id }
+        			       { Re-Auth-Request-Type }
+        			       [ User-Name ]
+        			       [ Origin-AAA-Protocol ]
+        			       [ Origin-State-Id ]
+        			       [ NAS-Identifier ]
+        			       [ NAS-IP-Address ]
+        			       [ NAS-IPv6-Address ]
+        			       [ NAS-Port ]
+        			       [ NAS-Port-Id ]
+        			       [ NAS-Port-Type ]
+        			       [ Service-Type ]
+        			       [ Framed-IP-Address ]
+        			       [ Framed-IPv6-Prefix ]
+        			       [ Framed-Interface-Id ]
+        			       [ Called-Station-Id ]
+        			       [ Calling-Station-Id ]
+        			       [ Originating-Line-Info ]
+        			       [ Acct-Session-Id ]
+        			       [ Acct-Multi-Session-Id ]
+        			       [ State ]
+        			     * [ Class ]
+        			       [ Reply-Message ]
+        			     * [ Proxy-Info ]
+        			     * [ Route-Record ]
+        			     * [ AVP ]
+			*/
+			struct dict_object * cmd;
+			struct local_rules_definition rules[] = 
+						{ 	 {  "Origin-AAA-Protocol",		RULE_OPTIONAL,   -1, 1 }
+							,{  "NAS-Identifier",			RULE_OPTIONAL,   -1, 1 }
+							,{  "NAS-IP-Address",			RULE_OPTIONAL,   -1, 1 }
+							,{  "NAS-IPv6-Address",			RULE_OPTIONAL,   -1, 1 }
+							,{  "NAS-Port",				RULE_OPTIONAL,   -1, 1 }
+							,{  "NAS-Port-Id",			RULE_OPTIONAL,   -1, 1 }
+							,{  "NAS-Port-Type",			RULE_OPTIONAL,   -1, 1 }
+							,{  "Service-Type",			RULE_OPTIONAL,   -1, 1 }
+							,{  "Framed-IP-Address",		RULE_OPTIONAL,   -1, 1 }
+							,{  "Framed-IPv6-Prefix",		RULE_OPTIONAL,   -1, 1 }
+							,{  "Framed-Interface-Id",		RULE_OPTIONAL,   -1, 1 }
+							,{  "Called-Station-Id",		RULE_OPTIONAL,   -1, 1 }
+							,{  "Calling-Station-Id",		RULE_OPTIONAL,   -1, 1 }
+							,{  "Originating-Line-Info",		RULE_OPTIONAL,   -1, 1 }
+							,{  "Acct-Session-Id",			RULE_OPTIONAL,   -1, 1 }
+							,{  "Acct-Multi-Session-Id",		RULE_OPTIONAL,   -1, 1 }
+							,{  "State",				RULE_OPTIONAL,   -1, 1 }
+							,{  "Class",				RULE_OPTIONAL,   -1,-1 }
+							,{  "Reply-Message",			RULE_OPTIONAL,   -1,-1 }
+						};
+			
+			CHECK_dict_search( DICT_COMMAND, CMD_BY_NAME, "Re-Auth-Request", &cmd);
+			PARSE_loc_rules( rules, cmd );
+		}
+		
+		/* Re-Auth-Answer */
+		{
+			/*
+				Add additional rules of the ABNF (compared to Base definition):
+				
+
+				<RA-Answer>  ::= < Diameter Header: 258, PXY >
+        				       < Session-Id >
+        				       { Result-Code }
+        				       { Origin-Host }
+        				       { Origin-Realm }
+        				       [ User-Name ]
+        				       [ Origin-AAA-Protocol ]
+        				       [ Origin-State-Id ]
+        				       [ Error-Message ]
+        				       [ Error-Reporting-Host ]
+        				     * [ Failed-AVP ]
+        				     * [ Redirected-Host ]
+        				       [ Redirected-Host-Usage ]
+        				       [ Redirected-Host-Cache-Time ]
+        				       [ Service-Type ]
+        				     * [ Configuration-Token ]
+        				       [ Idle-Timeout ]
+        				       [ Authorization-Lifetime ]
+        				       [ Auth-Grace-Period ]
+        				       [ Re-Auth-Request-Type ]
+        				       [ State ]
+        				     * [ Class ]
+        				     * [ Reply-Message ]
+        				       [ Prompt ]
+        				     * [ Proxy-Info ]
+        				     * [ AVP ]
+			*/
+			struct dict_object * cmd;
+			struct local_rules_definition rules[] = 
+						{ 	 {  "Origin-AAA-Protocol",		RULE_OPTIONAL,   -1, 1 }
+							,{  "Service-Type",			RULE_OPTIONAL,   -1, 1 }
+							,{  "Configuration-Token",		RULE_OPTIONAL,   -1,-1 }
+							,{  "Idle-Timeout",			RULE_OPTIONAL,   -1, 1 }
+							,{  "Authorization-Lifetime",		RULE_OPTIONAL,   -1, 1 }
+							,{  "Auth-Grace-Period",		RULE_OPTIONAL,   -1, 1 }
+							,{  "Re-Auth-Request-Type",		RULE_OPTIONAL,   -1, 1 }
+							,{  "State",				RULE_OPTIONAL,   -1, 1 }
+							,{  "Class",				RULE_OPTIONAL,   -1,-1 }
+							,{  "Reply-Message",			RULE_OPTIONAL,   -1,-1 }
+							,{  "Prompt",				RULE_OPTIONAL,   -1, 1 }
+						};
+			
+			CHECK_dict_search( DICT_COMMAND, CMD_BY_NAME, "Re-Auth-Answer", &cmd);
+			PARSE_loc_rules( rules, cmd );
+		}
+		
+		/* Session-Termination-Request */
+		{
+			/*
+				Add additional rules of the ABNF (compared to Base definition):
+				
+
+				<ST-Request> ::= < Diameter Header: 275, REQ, PXY >
+        				      < Session-Id >
+        				      { Origin-Host }
+        				      { Origin-Realm }
+        				      { Destination-Realm }
+        				      { Auth-Application-Id }
+        				      { Termination-Cause }
+        				      [ User-Name ]
+        				      [ Destination-Host ]
+        				    * [ Class ]
+        				      [ Origin-AAA-Protocol ]
+        				      [ Origin-State-Id ]
+        				    * [ Proxy-Info ]
+        				    * [ Route-Record ]
+        				    * [ AVP ]
+			*/
+			struct dict_object * cmd;
+			struct local_rules_definition rules[] = 
+						{ 	 {  "Origin-AAA-Protocol",		RULE_OPTIONAL,   -1, 1 }
+						};
+			
+			CHECK_dict_search( DICT_COMMAND, CMD_BY_NAME, "Session-Termination-Request", &cmd);
+			PARSE_loc_rules( rules, cmd );
+		}
+		
+		/* Session-Termination-Answer */
+		{
+			/*
+				Add additional rules of the ABNF (compared to Base definition):
+				
+				<ST-Answer>  ::= < Diameter Header: 275, PXY >
+        				       < Session-Id >
+        				       { Result-Code }
+        				       { Origin-Host }
+        				       { Origin-Realm }
+        				       [ User-Name ]
+        				     * [ Class ]
+        				       [ Error-Message ]
+        				       [ Error-Reporting-Host ]
+        				     * [ Failed-AVP ]
+        				       [ Origin-AAA-Protocol ]
+        				       [ Origin-State-Id ]
+        				     * [ Redirect-Host ]
+        				       [ Redirect-Host-Usase ]
+        				       [ Redirect-Max-Cache-Time ]
+        				     * [ Proxy-Info ]
+        				     * [ AVP ]
+			*/
+			struct dict_object * cmd;
+			struct local_rules_definition rules[] = 
+						{ 	 {  "Origin-AAA-Protocol",		RULE_OPTIONAL,   -1, 1 }
+						};
+			
+			CHECK_dict_search( DICT_COMMAND, CMD_BY_NAME, "Session-Termination-Answer", &cmd);
+			PARSE_loc_rules( rules, cmd );
+		}
+		
+		/* Abort-Session-Request */
+		{
+			/*
+				Add additional rules of the ABNF (compared to Base definition):
+				
+			<AS-Request>  ::= < Diameter Header: 274, REQ, PXY >
+        			       < Session-Id >
+        			       { Origin-Host }
+        			       { Origin-Realm }
+        			       { Destination-Realm }
+        			       { Destination-Host }
+        			       { Auth-Application-Id }
+        			       [ User-Name ]
+        			       [ Origin-AAA-Protocol ]
+        			       [ Origin-State-Id ]
+        			       [ NAS-Identifier ]
+        			       [ NAS-IP-Address ]
+        			       [ NAS-IPv6-Address ]
+        			       [ NAS-Port ]
+        			       [ NAS-Port-Id ]
+        			       [ NAS-Port-Type ]
+        			       [ Service-Type ]
+        			       [ Framed-IP-Address ]
+        			       [ Framed-IPv6-Prefix ]
+        			       [ Framed-Interface-Id ]
+        			       [ Called-Station-Id ]
+        			       [ Calling-Station-Id ]
+        			       [ Originating-Line-Info ]
+        			       [ Acct-Session-Id ]
+        			       [ Acct-Multi-Session-Id ]
+        			       [ State ]
+        			     * [ Class ]
+        			     * [ Reply-Message ]
+        			     * [ Proxy-Info ]
+        			     * [ Route-Record ]
+        			     * [ AVP ]
+				     
+			*/
+			struct dict_object * cmd;
+			struct local_rules_definition rules[] = 
+						{ 	 {  "Origin-AAA-Protocol",		RULE_OPTIONAL,   -1, 1 }
+							,{  "NAS-Identifier",			RULE_OPTIONAL,   -1, 1 }
+							,{  "NAS-IP-Address",			RULE_OPTIONAL,   -1, 1 }
+							,{  "NAS-IPv6-Address",			RULE_OPTIONAL,   -1, 1 }
+							,{  "NAS-Port",				RULE_OPTIONAL,   -1, 1 }
+							,{  "NAS-Port-Id",			RULE_OPTIONAL,   -1, 1 }
+							,{  "NAS-Port-Type",			RULE_OPTIONAL,   -1, 1 }
+							,{  "Service-Type",			RULE_OPTIONAL,   -1, 1 }
+							,{  "Framed-IP-Address",		RULE_OPTIONAL,   -1, 1 }
+							,{  "Framed-IPv6-Prefix",		RULE_OPTIONAL,   -1, 1 }
+							,{  "Framed-Interface-Id",		RULE_OPTIONAL,   -1, 1 }
+							,{  "Called-Station-Id",		RULE_OPTIONAL,   -1, 1 }
+							,{  "Calling-Station-Id",		RULE_OPTIONAL,   -1, 1 }
+							,{  "Originating-Line-Info",		RULE_OPTIONAL,   -1, 1 }
+							,{  "Acct-Session-Id",			RULE_OPTIONAL,   -1, 1 }
+							,{  "Acct-Multi-Session-Id",		RULE_OPTIONAL,   -1, 1 }
+							,{  "State",				RULE_OPTIONAL,   -1, 1 }
+							,{  "Class",				RULE_OPTIONAL,   -1,-1 }
+							,{  "Reply-Message",			RULE_OPTIONAL,   -1,-1 }
+						};
+			
+			CHECK_dict_search( DICT_COMMAND, CMD_BY_NAME, "Abort-Session-Request", &cmd);
+			PARSE_loc_rules( rules, cmd );
+		}
+		
+		/* Abort-Session-Answer */
+		{
+			/*
+				Add additional rules of the ABNF (compared to Base definition):
+
+				<AS-Answer>  ::= < Diameter Header: 274, PXY >
+        				       < Session-Id >
+        				       { Result-Code }
+        				       { Origin-Host }
+        				       { Origin-Realm }
+        				       [ User-Name ]
+        				       [ Origin-AAA-Protocol ]
+        				       [ Origin-State-Id ]
+        				       [ State]
+        				       [ Error-Message ]
+        				       [ Error-Reporting-Host ]
+        				     * [ Failed-AVP ]
+        				     * [ Redirected-Host ]
+        				       [ Redirected-Host-Usage ]
+        				       [ Redirected-Max-Cache-Time ]
+        				     * [ Proxy-Info ]
+        				     * [ AVP ]
+			*/
+			struct dict_object * cmd;
+			struct local_rules_definition rules[] = 
+						{ 	 {  "Origin-AAA-Protocol",		RULE_OPTIONAL,   -1, 1 }
+							,{  "State", 				RULE_OPTIONAL,   -1, 1 }
+						};
+			
+			CHECK_dict_search( DICT_COMMAND, CMD_BY_NAME, "Abort-Session-Answer", &cmd);
+			PARSE_loc_rules( rules, cmd );
+		}
+		
+		/* Accounting-Request */
+		{
+			/*
+				Add additional rules of the ABNF (compared to Base definition):
+
+				<AC-Request> ::= < Diameter Header: 271, REQ, PXY >
+        				      < Session-Id >
+        				      { Origin-Host }
+        				      { Origin-Realm }
+        				      { Destination-Realm }
+        				      { Accounting-Record-Type }
+        				      { Accounting-Record-Number }
+        				      [ Acct-Application-Id ]
+        				      [ Vendor-Specific-Application-Id ]
+        				      [ User-Name ]
+        				      [ Accounting-Sub-Session-Id ]
+        				      [ Acct-Session-Id ]
+        				      [ Acct-Multi-Session-Id ]
+        				      [ Origin-AAA-Protocol ]
+        				      [ Origin-State-Id ]
+        				      [ Destination-Host ]
+        				      [ Event-Timestamp ]
+        				      [ Acct-Delay-Time ]
+        				      [ NAS-Identifier ]
+        				      [ NAS-IP-Address ]
+        				      [ NAS-IPv6-Address ]
+        				      [ NAS-Port ]
+        				      [ NAS-Port-Id ]
+        				      [ NAS-Port-Type ]
+        				    * [ Class ]
+        				      [ Service-Type ]
+        				      [ Termination-Cause ]
+        				      [ Accounting-Input-Octets ]
+        				      [ Accounting-Input-Packets ]
+        				      [ Accounting-Output-Octets ]
+        				      [ Accounting-Output-Packets ]
+        				      [ Acct-Authentic ]
+        				      [ Accounting-Auth-Method ]
+        				      [ Acct-Link-Count ]
+        				      [ Acct-Session-Time ]
+        				      [ Acct-Tunnel-Connection ]
+        				      [ Acct-Tunnel-Packets-Lost ]
+        				      [ Callback-Id ]
+        				      [ Callback-Number ]
+        				      [ Called-Station-Id ]
+        				      [ Calling-Station-Id ]
+        				    * [ Connection-Info ]
+        				      [ Originating-Line-Info ]
+        				      [ Authorization-Lifetime ]
+        				      [ Session-Timeout ]
+        				      [ Idle-Timeout ]
+        				      [ Port-Limit ]
+        				      [ Accounting-Realtime-Required ]
+        				      [ Acct-Interim-Interval ]
+        				    * [ Filter-Id ]
+        				    * [ NAS-Filter-Rule ]
+        				    * [ Qos-Filter-Rule ]
+        				      [ Framed-AppleTalk-Link ]
+        				      [ Framed-AppleTalk-Network ]
+        				      [ Framed-AppleTalk-Zone ]
+        				      [ Framed-Compression ]
+        				      [ Framed-Interface-Id ]
+        				      [ Framed-IP-Address ]
+        				      [ Framed-IP-Netmask ]
+        				    * [ Framed-IPv6-Prefix ]
+        				      [ Framed-IPv6-Pool ]
+        				    * [ Framed-IPv6-Route ]
+        				      [ Framed-IPX-Network ]
+        				      [ Framed-MTU ]
+        				      [ Framed-Pool ]
+        				      [ Framed-Protocol ]
+        				    * [ Framed-Route ]
+        				      [ Framed-Routing ]
+        				    * [ Login-IP-Host ]
+        				    * [ Login-IPv6-Host ]
+        				      [ Login-LAT-Group ]
+        				      [ Login-LAT-Node ]
+        				      [ Login-LAT-Port ]
+        				      [ Login-LAT-Service ]
+        				      [ Login-Service ]
+        				      [ Login-TCP-Port ]
+        				    * [ Tunneling ]
+        				    * [ Proxy-Info ]
+        				    * [ Route-Record ]
+        				    * [ AVP ]
+			*/
+			struct dict_object * cmd;
+			struct local_rules_definition rules[] = 
+						{ 	 {  "Origin-AAA-Protocol",		RULE_OPTIONAL,   -1, 1 }
+							,{  "Acct-Delay-Time",			RULE_OPTIONAL,   -1, 1 }
+							,{  "NAS-Identifier",			RULE_OPTIONAL,   -1, 1 }
+							,{  "NAS-IP-Address",			RULE_OPTIONAL,   -1, 1 }
+							,{  "NAS-IPv6-Address",			RULE_OPTIONAL,   -1, 1 }
+							,{  "NAS-Port",				RULE_OPTIONAL,   -1, 1 }
+							,{  "NAS-Port-Id",			RULE_OPTIONAL,   -1, 1 }
+							,{  "NAS-Port-Type",			RULE_OPTIONAL,   -1, 1 }
+							,{  "Class",				RULE_OPTIONAL,   -1,-1 }
+							,{  "Service-Type",			RULE_OPTIONAL,   -1, 1 }
+							,{  "Termination-Cause",		RULE_OPTIONAL,   -1, 1 }
+							,{  "Accounting-Input-Octets",		RULE_OPTIONAL,   -1, 1 }
+							,{  "Accounting-Input-Packets",		RULE_OPTIONAL,   -1, 1 }
+							,{  "Accounting-Output-Octets",		RULE_OPTIONAL,   -1, 1 }
+							,{  "Accounting-Output-Packets",	RULE_OPTIONAL,   -1, 1 }
+							,{  "Acct-Authentic",			RULE_OPTIONAL,   -1, 1 }
+							,{  "Accounting-Auth-Method",		RULE_OPTIONAL,   -1, 1 }
+							,{  "Acct-Link-Count",			RULE_OPTIONAL,   -1, 1 }
+							,{  "Acct-Session-Time",		RULE_OPTIONAL,   -1, 1 }
+							,{  "Acct-Tunnel-Connection",		RULE_OPTIONAL,   -1, 1 }
+							,{  "Acct-Tunnel-Packets-Lost",		RULE_OPTIONAL,   -1, 1 }
+							,{  "Callback-Id",			RULE_OPTIONAL,   -1, 1 }
+							,{  "Callback-Number",			RULE_OPTIONAL,   -1, 1 }
+							,{  "Called-Station-Id",		RULE_OPTIONAL,   -1, 1 }
+							,{  "Calling-Station-Id",		RULE_OPTIONAL,   -1, 1 }
+							,{  "Connect-Info",			RULE_OPTIONAL,   -1,-1 }
+							,{  "Originating-Line-Info",		RULE_OPTIONAL,   -1, 1 }
+							,{  "Authorization-Lifetime",		RULE_OPTIONAL,   -1, 1 }
+							,{  "Session-Timeout",			RULE_OPTIONAL,   -1, 1 }
+							,{  "Idle-Timeout",			RULE_OPTIONAL,   -1, 1 }
+							,{  "Port-Limit",			RULE_OPTIONAL,   -1, 1 }
+							,{  "Filter-Id",			RULE_OPTIONAL,   -1,-1 }
+							,{  "NAS-Filter-Rule",			RULE_OPTIONAL,   -1,-1 }
+							,{  "QoS-Filter-Rule",			RULE_OPTIONAL,   -1,-1 }
+							,{  "Framed-AppleTalk-Link",		RULE_OPTIONAL,   -1, 1 }
+							,{  "Framed-AppleTalk-Network",		RULE_OPTIONAL,   -1, 1 }
+							,{  "Framed-AppleTalk-Zone",		RULE_OPTIONAL,   -1, 1 }
+							,{  "Framed-Compression",		RULE_OPTIONAL,   -1, 1 }
+							,{  "Framed-Interface-Id",		RULE_OPTIONAL,   -1, 1 }
+							,{  "Framed-IP-Address",		RULE_OPTIONAL,   -1, 1 }
+							,{  "Framed-IPv6-Prefix",		RULE_OPTIONAL,   -1,-1 }
+							,{  "Framed-IPv6-Pool",			RULE_OPTIONAL,   -1, 1 }
+							,{  "Framed-IPv6-Route",		RULE_OPTIONAL,   -1,-1 }
+							,{  "Framed-IP-Netmask",		RULE_OPTIONAL,   -1, 1 }
+							,{  "Framed-Route",			RULE_OPTIONAL,   -1,-1 }
+							,{  "Framed-Pool",			RULE_OPTIONAL,   -1, 1 }
+							,{  "Framed-IPX-Network",		RULE_OPTIONAL,   -1, 1 }
+							,{  "Framed-MTU",			RULE_OPTIONAL,   -1, 1 }
+							,{  "Framed-Protocol",			RULE_OPTIONAL,   -1, 1 }
+							,{  "Framed-Routing",			RULE_OPTIONAL,   -1, 1 }
+							,{  "Login-IP-Host",			RULE_OPTIONAL,   -1,-1 }
+							,{  "Login-IPv6-Host",			RULE_OPTIONAL,   -1,-1 }
+							,{  "Login-LAT-Group",			RULE_OPTIONAL,   -1, 1 }
+							,{  "Login-LAT-Node",			RULE_OPTIONAL,   -1, 1 }
+							,{  "Login-LAT-Port",			RULE_OPTIONAL,   -1, 1 }
+							,{  "Login-LAT-Service",		RULE_OPTIONAL,   -1, 1 }
+							,{  "Login-Service",			RULE_OPTIONAL,   -1, 1 }
+							,{  "Login-TCP-Port",			RULE_OPTIONAL,   -1, 1 }
+							,{  "Tunneling",			RULE_OPTIONAL,   -1,-1 }
+						};
+			
+			CHECK_dict_search( DICT_COMMAND, CMD_BY_NAME, "Accounting-Request", &cmd);
+			PARSE_loc_rules( rules, cmd );
+		}
+		
+		/* Accounting-Answer */
+		{
+			/*
+				Add additional rules of the ABNF (compared to Base definition):
+
+				<AC-Answer> ::= < Diameter Header: 271, PXY >
+        				      < Session-Id >
+        				      { Result-Code }
+        				      { Origin-Host }
+        				      { Origin-Realm }
+        				      { Accounting-Record-Type }
+        				      { Accounting-Record-Number }
+        				      [ Acct-Application-Id ]
+        				      [ Vendor-Specific-Application-Id ]
+        				      [ User-Name ]
+        				      [ Accounting-Sub-Session-Id ]
+        				      [ Acct-Session-Id ]
+        				      [ Acct-Multi-Session-Id ]
+        				      [ Event-Timestamp ]
+        				      [ Error-Message ]
+        				      [ Error-Reporting-Host ]
+        				    * [ Failed-AVP ]
+        				      [ Origin-AAA-Protocol ]
+        				      [ Origin-State-Id ]
+        				      [ NAS-Identifier ]
+        				      [ NAS-IP-Address ]
+        				      [ NAS-IPv6-Address ]
+        				      [ NAS-Port ]
+        				      [ NAS-Port-Id ]
+        				      [ NAS-Port-Type ]
+        				      [ Service-Type ]
+        				      [ Termination-Cause ]
+        				      [ Accounting-Realtime-Required ]
+        				      [ Acct-Interim-Interval ]
+        				    * [ Class ]
+        				    * [ Proxy-Info ]
+        				    * [ Route-Record ]
+        				    * [ AVP ]
+
+			*/
+			struct dict_object * cmd;
+			struct local_rules_definition rules[] = 
+						{ 	 {  "Origin-AAA-Protocol",		RULE_OPTIONAL,   -1, 1 }
+							,{  "NAS-Identifier", 			RULE_OPTIONAL,   -1, 1 }
+							,{  "NAS-IP-Address", 			RULE_OPTIONAL,   -1, 1 }
+							,{  "NAS-IPv6-Address", 		RULE_OPTIONAL,   -1, 1 }
+							,{  "NAS-Port", 			RULE_OPTIONAL,   -1, 1 }
+							,{  "NAS-Port-Id", 			RULE_OPTIONAL,   -1, 1 }
+							,{  "NAS-Port-Type", 			RULE_OPTIONAL,   -1, 1 }
+							,{  "Service-Type", 			RULE_OPTIONAL,   -1, 1 }
+							,{  "Termination-Cause", 		RULE_OPTIONAL,   -1, 1 }
+						};
+			
+			CHECK_dict_search( DICT_COMMAND, CMD_BY_NAME, "Accounting-Answer", &cmd);
+			PARSE_loc_rules( rules, cmd );
+		}
+	}
+	
+	LOG_D( "Extension 'Dictionary definitions for NASREQ' initialized");
+	return 0;
+}
+
+EXTENSION_ENTRY("dict_nasreq", dnr_entry);
diff --git a/extensions/dict_rfc4004_avps/CMakeLists.txt b/extensions/dict_rfc4004_avps/CMakeLists.txt
new file mode 100644
index 0000000..43b6936
--- /dev/null
+++ b/extensions/dict_rfc4004_avps/CMakeLists.txt
@@ -0,0 +1,16 @@
+# The dict_rfc4004_avps extension
+PROJECT("dict_rfc4004_avps library generated by FdGen " C)
+
+# Compile as a module
+FD_ADD_EXTENSION(dict_rfc4004_avps dict_rfc4004_avps.c)
+
+
+####
+## INSTALL section ##
+
+INSTALL(TARGETS dict_rfc4004_avps
+	LIBRARY DESTINATION ${INSTALL_EXTENSIONS_SUFFIX}
+COMPONENT freeDiameter-dictionary-RFC4004_AVPS)
+
+
+
diff --git a/extensions/dict_rfc4004_avps/dict_rfc4004_avps.c b/extensions/dict_rfc4004_avps/dict_rfc4004_avps.c
new file mode 100644
index 0000000..d030c42
--- /dev/null
+++ b/extensions/dict_rfc4004_avps/dict_rfc4004_avps.c
@@ -0,0 +1,655 @@
+/*
+* Copyright (c) 2017 Sprint
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*    http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+/****************
+ Generated By: fdtool enhancements to diafuzzer
+ License: same as freeDiameter
+****************/
+
+
+/* 
+ * Dictionary definitions of objects specified in rfc4004_avps.
+ */
+#include <freeDiameter/extension.h>
+
+#define PROTO_VER "unspecified"
+#define GEN_DATE  1506697143.43
+
+const char *rfc4004_avps_proto_ver = PROTO_VER;
+const double rfc4004_avps_gen_date = GEN_DATE;
+
+/* The content of this file follows the same structure as dict_base_proto.c */
+
+#define CHECK_dict_new( _type, _data, _parent, _ref )                                     \
+{                                                                                         \
+    int _ret = fd_dict_new( fd_g_config->cnf_dict, (_type), (_data), (_parent), (_ref) ); \
+    if ( _ret != 0 && _ret != EEXIST )                                                    \
+       return _ret;                                                                       \
+}
+
+#define CHECK_dict_search( _type, _criteria, _what, _result )		\
+    CHECK_FCT(  fd_dict_search( fd_g_config->cnf_dict, (_type), (_criteria), (_what), (_result), ENOENT) );
+
+struct local_rules_definition {
+    struct dict_avp_request avp_vendor_plus_name;
+    enum rule_position	position;
+    int 			min;
+    int			max;
+};
+
+#define RULE_ORDER( _position ) ((((_position) == RULE_FIXED_HEAD) || ((_position) == RULE_FIXED_TAIL)) ? 1 : 0 )
+
+/* Attention! This version of the macro uses AVP_BY_NAME_AND_VENDOR, in contrast to most other copies! */
+#define PARSE_loc_rules( _rulearray, _parent) {                                                         \
+        int __ar;                                                                                       \
+        for (__ar=0; __ar < sizeof(_rulearray) / sizeof((_rulearray)[0]); __ar++) {                     \
+                struct dict_rule_data __data = { NULL,                                                  \
+                        (_rulearray)[__ar].position,                                                    \
+                        0,                                                                              \
+                        (_rulearray)[__ar].min,                                                         \
+                        (_rulearray)[__ar].max};                                                        \
+                __data.rule_order = RULE_ORDER(__data.rule_position);                                   \
+                CHECK_FCT(  fd_dict_search(                                                             \
+                        fd_g_config->cnf_dict,                                                          \
+                        DICT_AVP,                                                                       \
+                        AVP_BY_NAME_AND_VENDOR,                                                         \
+                        &(_rulearray)[__ar].avp_vendor_plus_name,                                       \
+                        &__data.rule_avp, 0 ) );                                                        \
+                if ( !__data.rule_avp ) {                                                               \
+                        TRACE_DEBUG(INFO, "AVP Not found: '%s'", (_rulearray)[__ar].avp_vendor_plus_name.avp_name);             \
+                        return ENOENT;                                                                  \
+                }                                                                                       \
+                {                                                                                       \
+                         int _ret = fd_dict_new( fd_g_config->cnf_dict, DICT_RULE, &(__data), (_parent), NULL ); \
+                         if ( _ret != 0 && _ret != EEXIST )      {                                      \
+                                TRACE_DEBUG(INFO, "Error on rule with AVP '%s'",                        \
+                                            (_rulearray)[__ar].avp_vendor_plus_name.avp_name);          \
+                                return EINVAL;                                                          \
+                         }                                                                              \
+                }                                                                                       \
+        }                                                                                               \
+}
+
+#define CHECK_vendor_new( _data ) { \
+        struct dict_object * vendor_found; \
+        if (fd_dict_search(fd_g_config->cnf_dict,DICT_VENDOR,VENDOR_BY_ID,&_data.vendor_id,&vendor_found,ENOENT) == ENOENT) { \
+                CHECK_FCT(fd_dict_new(fd_g_config->cnf_dict, DICT_VENDOR, &_data, NULL, NULL)); \
+        } \
+}
+
+#define enumval_def_u32( _val_, _str_ )		\
+    { _str_, 		{ .u32 = _val_ }}
+
+#define enumval_def_os( _len_, _val_, _str_ )				\
+    { _str_, 		{ .os = { .data = (unsigned char *)_val_, .len = _len_ }}}
+
+
+static int dict_rfc4004_avps_load_defs(char * conffile)
+{
+   TRACE_ENTRY("%p", conffile);
+
+   /* AVP section */
+   {
+		struct dict_object * Address_type;
+		struct dict_object * UTF8String_type;
+		struct dict_object * DiameterIdentity_type;
+		struct dict_object * DiameterURI_type;
+		struct dict_object * Time_type;
+		struct dict_object * IPFilterRule_type;
+
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "Address", &Address_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "UTF8String", &UTF8String_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "DiameterIdentity", &DiameterIdentity_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "DiameterURI", &DiameterURI_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "Time", &Time_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "IPFilterRule", &IPFilterRule_type);
+		/* MIP-Reg-Request */
+		{
+			struct dict_avp_data data = {
+				320,	/* Code */
+				0,	/* Vendor */
+				"MIP-Reg-Request",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* MIP-Reg-Reply */
+		{
+			struct dict_avp_data data = {
+				321,	/* Code */
+				0,	/* Vendor */
+				"MIP-Reg-Reply",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* MIP-Mobile-Node-Address */
+		{
+			struct dict_avp_data data = {
+				333,	/* Code */
+				0,	/* Vendor */
+				"MIP-Mobile-Node-Address",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, Address_type, NULL);
+		};
+		/* MIP-Home-Agent-Address */
+		{
+			struct dict_avp_data data = {
+				334,	/* Code */
+				0,	/* Vendor */
+				"MIP-Home-Agent-Address",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, Address_type, NULL);
+		};
+		/* MIP-Candidate-Home-Agent-Host */
+		{
+			struct dict_avp_data data = {
+				336,	/* Code */
+				0,	/* Vendor */
+				"MIP-Candidate-Home-Agent-Host",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, DiameterIdentity_type, NULL);
+		};
+		/* MIP-Feature-Vector */
+		{
+			struct dict_avp_data data = {
+				337,	/* Code */
+				0,	/* Vendor */
+				"MIP-Feature-Vector",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* MIP-Auth-Input-Data-Length */
+		{
+			struct dict_avp_data data = {
+				338,	/* Code */
+				0,	/* Vendor */
+				"MIP-Auth-Input-Data-Length",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* MIP-Authenticator-Length */
+		{
+			struct dict_avp_data data = {
+				339,	/* Code */
+				0,	/* Vendor */
+				"MIP-Authenticator-Length",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* MIP-Authenticator-Offset */
+		{
+			struct dict_avp_data data = {
+				340,	/* Code */
+				0,	/* Vendor */
+				"MIP-Authenticator-Offset",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* MIP-MN-AAA-SPI */
+		{
+			struct dict_avp_data data = {
+				341,	/* Code */
+				0,	/* Vendor */
+				"MIP-MN-AAA-SPI",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* MIP-Filter-Rule */
+		{
+			struct dict_avp_data data = {
+				342,	/* Code */
+				0,	/* Vendor */
+				"MIP-Filter-Rule",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, IPFilterRule_type, NULL);
+		};
+		/* MIP-FA-Challenge */
+		{
+			struct dict_avp_data data = {
+				344,	/* Code */
+				0,	/* Vendor */
+				"MIP-FA-Challenge",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* MIP-Home-Agent-Host */
+		{
+			struct dict_avp_data data = {
+				348,	/* Code */
+				0,	/* Vendor */
+				"MIP-Home-Agent-Host",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, DiameterIdentity_type, NULL);
+		};
+		/* MIP-FA-to-HA-SPI */
+		{
+			struct dict_avp_data data = {
+				318,	/* Code */
+				0,	/* Vendor */
+				"MIP-FA-to-HA-SPI",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* MIP-FA-to-MN-SPI */
+		{
+			struct dict_avp_data data = {
+				319,	/* Code */
+				0,	/* Vendor */
+				"MIP-FA-to-MN-SPI",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* MIP-HA-to-FA-SPI */
+		{
+			struct dict_avp_data data = {
+				323,	/* Code */
+				0,	/* Vendor */
+				"MIP-HA-to-FA-SPI",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* MIP-Nonce */
+		{
+			struct dict_avp_data data = {
+				335,	/* Code */
+				0,	/* Vendor */
+				"MIP-Nonce",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* MIP-Session-Key */
+		{
+			struct dict_avp_data data = {
+				343,	/* Code */
+				0,	/* Vendor */
+				"MIP-Session-Key",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* MIP-Algorithm-Type */
+		{
+			struct dict_avp_data data = {
+				345,	/* Code */
+				0,	/* Vendor */
+				"MIP-Algorithm-Type",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "Enumerated(MIP-Algorithm-Type)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "HMAC-SHA-1", { .i32=2 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* MIP-Replay-Mode */
+		{
+			struct dict_avp_data data = {
+				346,	/* Code */
+				0,	/* Vendor */
+				"MIP-Replay-Mode",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "Enumerated(MIP-Replay-Mode)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "None", { .i32=1 }};
+			struct dict_enumval_data        t_2 = { "Timestamps", { .i32=2 }};
+			struct dict_enumval_data        t_3 = { "Nonces", { .i32=3 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_3, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* MIP-MSA-Lifetime */
+		{
+			struct dict_avp_data data = {
+				367,	/* Code */
+				0,	/* Vendor */
+				"MIP-MSA-Lifetime",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* MIP-FA-to-HA-MSA */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				328,	/* Code */
+				0,	/* Vendor */
+				"MIP-FA-to-HA-MSA",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* MIP-MN-to-FA-MSA */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				325,	/* Code */
+				0,	/* Vendor */
+				"MIP-MN-to-FA-MSA",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* MIP-Originating-Foreign-AAA */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				347,	/* Code */
+				0,	/* Vendor */
+				"MIP-Originating-Foreign-AAA",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* MIP-HA-to-MN-MSA */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				332,	/* Code */
+				0,	/* Vendor */
+				"MIP-HA-to-MN-MSA",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* MIP-MN-AAA-Auth */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				322,	/* Code */
+				0,	/* Vendor */
+				"MIP-MN-AAA-Auth",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* MIP-FA-to-MN-MSA */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				326,	/* Code */
+				0,	/* Vendor */
+				"MIP-FA-to-MN-MSA",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* MIP-HA-to-FA-MSA */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				329,	/* Code */
+				0,	/* Vendor */
+				"MIP-HA-to-FA-MSA",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* MIP-MN-to-HA-MSA */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				331,	/* Code */
+				0,	/* Vendor */
+				"MIP-MN-to-HA-MSA",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+
+	
+   }
+
+   /* Commands section */
+   {
+
+   }
+
+   return 0;
+}
+
+static int dict_rfc4004_avps_load_rules(char * conffile)
+{
+   /* Grouped AVP section */
+   {
+	  /* MIP-FA-to-HA-MSA */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 0, .avp_name = "MIP-FA-to-HA-MSA"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 0, .avp_name = "MIP-FA-to-HA-SPI"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "MIP-Algorithm-Type"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "MIP-Session-Key"}, RULE_REQUIRED, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* MIP-MN-to-FA-MSA */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 0, .avp_name = "MIP-MN-to-FA-MSA"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 0, .avp_name = "MIP-Algorithm-Type"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "MIP-Nonce"}, RULE_REQUIRED, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* MIP-Originating-Foreign-AAA */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 0, .avp_name = "MIP-Originating-Foreign-AAA"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 0, .avp_name = "Origin-Realm"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Origin-Host"}, RULE_REQUIRED, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* MIP-HA-to-MN-MSA */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 0, .avp_name = "MIP-HA-to-MN-MSA"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 0, .avp_name = "MIP-Algorithm-Type"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "MIP-Replay-Mode"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "MIP-Session-Key"}, RULE_REQUIRED, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* MIP-MN-AAA-Auth */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 0, .avp_name = "MIP-MN-AAA-Auth"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 0, .avp_name = "MIP-MN-AAA-SPI"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "MIP-Auth-Input-Data-Length"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "MIP-Authenticator-Length"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "MIP-Authenticator-Offset"}, RULE_REQUIRED, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* MIP-FA-to-MN-MSA */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 0, .avp_name = "MIP-FA-to-MN-MSA"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 0, .avp_name = "MIP-FA-to-MN-SPI"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "MIP-Algorithm-Type"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "MIP-Session-Key"}, RULE_REQUIRED, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* MIP-HA-to-FA-MSA */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 0, .avp_name = "MIP-HA-to-FA-MSA"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 0, .avp_name = "MIP-HA-to-FA-SPI"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "MIP-Algorithm-Type"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "MIP-Session-Key"}, RULE_REQUIRED, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* MIP-MN-to-HA-MSA */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 0, .avp_name = "MIP-MN-to-HA-MSA"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 0, .avp_name = "MIP-Algorithm-Type"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "MIP-Replay-Mode"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "MIP-Nonce"}, RULE_REQUIRED, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+
+   }	
+
+   /* Commands section */
+   {
+
+   }
+
+   LOG_D( "Extension 'Dictionary definitions for rfc4004_avps (None)' initialized");
+   return 0;
+}
+
+int dict_entry(char * conffile)
+{
+	dict_rfc4004_avps_load_defs(conffile);
+	return dict_rfc4004_avps_load_rules(conffile);
+}
+
+const char* dict_rfc4004_avps_proto_ver(char * conffile) {
+	return rfc4004_avps_proto_ver;
+}
+
+const double dict_rfc4004_avps_gen_ts(char * conffile) {
+	return rfc4004_avps_gen_date;
+}
+
+EXTENSION_ENTRY2("dict_rfc4004_avps", dict_rfc4004_avps_load_defs, dict_rfc4004_avps_load_rules);
+
+
+
diff --git a/extensions/dict_rfc4004_avps/rfc4004_avps.did b/extensions/dict_rfc4004_avps/rfc4004_avps.did
new file mode 100644
index 0000000..5c6effd
--- /dev/null
+++ b/extensions/dict_rfc4004_avps/rfc4004_avps.did
@@ -0,0 +1 @@
+dict_rfc4004_avps
diff --git a/extensions/dict_rfc4006bis_avps/CMakeLists.txt b/extensions/dict_rfc4006bis_avps/CMakeLists.txt
new file mode 100644
index 0000000..9302ae9
--- /dev/null
+++ b/extensions/dict_rfc4006bis_avps/CMakeLists.txt
@@ -0,0 +1,16 @@
+# The dict_rfc4006bis_avps extension
+PROJECT("dict_rfc4006bis_avps library generated by FdGen " C)
+
+# Compile as a module
+FD_ADD_EXTENSION(dict_rfc4006bis_avps dict_rfc4006bis_avps.c)
+
+
+####
+## INSTALL section ##
+
+INSTALL(TARGETS dict_rfc4006bis_avps
+	LIBRARY DESTINATION ${INSTALL_EXTENSIONS_SUFFIX}
+COMPONENT freeDiameter-dictionary-RFC4006BIS_AVPS)
+
+
+
diff --git a/extensions/dict_rfc4006bis_avps/dict_rfc4006bis_avps.c b/extensions/dict_rfc4006bis_avps/dict_rfc4006bis_avps.c
new file mode 100644
index 0000000..45ec31e
--- /dev/null
+++ b/extensions/dict_rfc4006bis_avps/dict_rfc4006bis_avps.c
@@ -0,0 +1,1419 @@
+/*
+* Copyright (c) 2017 Sprint
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*    http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+/****************
+ Generated By: fdtool enhancements to diafuzzer
+ License: same as freeDiameter
+****************/
+
+
+/* 
+ * Dictionary definitions of objects specified in rfc4006bis_avps.
+ */
+#include <freeDiameter/extension.h>
+
+#define PROTO_VER "unspecified"
+#define GEN_DATE  1506697143.49
+
+const char *rfc4006bis_avps_proto_ver = PROTO_VER;
+const double rfc4006bis_avps_gen_date = GEN_DATE;
+
+/* The content of this file follows the same structure as dict_base_proto.c */
+
+#define CHECK_dict_new( _type, _data, _parent, _ref )                                     \
+{                                                                                         \
+    int _ret = fd_dict_new( fd_g_config->cnf_dict, (_type), (_data), (_parent), (_ref) ); \
+    if ( _ret != 0 && _ret != EEXIST )                                                    \
+       return _ret;                                                                       \
+}
+
+#define CHECK_dict_search( _type, _criteria, _what, _result )		\
+    CHECK_FCT(  fd_dict_search( fd_g_config->cnf_dict, (_type), (_criteria), (_what), (_result), ENOENT) );
+
+struct local_rules_definition {
+    struct dict_avp_request avp_vendor_plus_name;
+    enum rule_position	position;
+    int 			min;
+    int			max;
+};
+
+#define RULE_ORDER( _position ) ((((_position) == RULE_FIXED_HEAD) || ((_position) == RULE_FIXED_TAIL)) ? 1 : 0 )
+
+/* Attention! This version of the macro uses AVP_BY_NAME_AND_VENDOR, in contrast to most other copies! */
+#define PARSE_loc_rules( _rulearray, _parent) {                                                         \
+        int __ar;                                                                                       \
+        for (__ar=0; __ar < sizeof(_rulearray) / sizeof((_rulearray)[0]); __ar++) {                     \
+                struct dict_rule_data __data = { NULL,                                                  \
+                        (_rulearray)[__ar].position,                                                    \
+                        0,                                                                              \
+                        (_rulearray)[__ar].min,                                                         \
+                        (_rulearray)[__ar].max};                                                        \
+                __data.rule_order = RULE_ORDER(__data.rule_position);                                   \
+                CHECK_FCT(  fd_dict_search(                                                             \
+                        fd_g_config->cnf_dict,                                                          \
+                        DICT_AVP,                                                                       \
+                        AVP_BY_NAME_AND_VENDOR,                                                         \
+                        &(_rulearray)[__ar].avp_vendor_plus_name,                                       \
+                        &__data.rule_avp, 0 ) );                                                        \
+                if ( !__data.rule_avp ) {                                                               \
+                        TRACE_DEBUG(INFO, "AVP Not found: '%s'", (_rulearray)[__ar].avp_vendor_plus_name.avp_name);             \
+                        return ENOENT;                                                                  \
+                }                                                                                       \
+                {                                                                                       \
+                         int _ret = fd_dict_new( fd_g_config->cnf_dict, DICT_RULE, &(__data), (_parent), NULL ); \
+                         if ( _ret != 0 && _ret != EEXIST )      {                                      \
+                                TRACE_DEBUG(INFO, "Error on rule with AVP '%s'",                        \
+                                            (_rulearray)[__ar].avp_vendor_plus_name.avp_name);          \
+                                return EINVAL;                                                          \
+                         }                                                                              \
+                }                                                                                       \
+        }                                                                                               \
+}
+
+#define CHECK_vendor_new( _data ) { \
+        struct dict_object * vendor_found; \
+        if (fd_dict_search(fd_g_config->cnf_dict,DICT_VENDOR,VENDOR_BY_ID,&_data.vendor_id,&vendor_found,ENOENT) == ENOENT) { \
+                CHECK_FCT(fd_dict_new(fd_g_config->cnf_dict, DICT_VENDOR, &_data, NULL, NULL)); \
+        } \
+}
+
+#define enumval_def_u32( _val_, _str_ )		\
+    { _str_, 		{ .u32 = _val_ }}
+
+#define enumval_def_os( _len_, _val_, _str_ )				\
+    { _str_, 		{ .os = { .data = (unsigned char *)_val_, .len = _len_ }}}
+
+
+static int dict_rfc4006bis_avps_load_defs(char * conffile)
+{
+   TRACE_ENTRY("%p", conffile);
+
+   /* AVP section */
+   {
+		struct dict_object * Address_type;
+		struct dict_object * UTF8String_type;
+		struct dict_object * DiameterIdentity_type;
+		struct dict_object * DiameterURI_type;
+		struct dict_object * Time_type;
+		struct dict_object * IPFilterRule_type;
+
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "Address", &Address_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "UTF8String", &UTF8String_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "DiameterIdentity", &DiameterIdentity_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "DiameterURI", &DiameterURI_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "Time", &Time_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "IPFilterRule", &IPFilterRule_type);
+		/* CC-Correlation-Id */
+		{
+			struct dict_avp_data data = {
+				411,	/* Code */
+				0,	/* Vendor */
+				"CC-Correlation-Id",	/* Name */
+				AVP_FLAG_VENDOR,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* CC-Input-Octets */
+		{
+			struct dict_avp_data data = {
+				412,	/* Code */
+				0,	/* Vendor */
+				"CC-Input-Octets",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED64	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* CC-Output-Octets */
+		{
+			struct dict_avp_data data = {
+				414,	/* Code */
+				0,	/* Vendor */
+				"CC-Output-Octets",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED64	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* CC-Request-Number */
+		{
+			struct dict_avp_data data = {
+				415,	/* Code */
+				0,	/* Vendor */
+				"CC-Request-Number",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* CC-Request-Type */
+		{
+			struct dict_avp_data data = {
+				416,	/* Code */
+				0,	/* Vendor */
+				"CC-Request-Type",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "Enumerated(CC-Request-Type)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "INITIAL_REQUEST", { .i32=1 }};
+			struct dict_enumval_data        t_2 = { "UPDATE_REQUEST", { .i32=2 }};
+			struct dict_enumval_data        t_3 = { "TERMINATION_REQUEST", { .i32=3 }};
+			struct dict_enumval_data        t_4 = { "EVENT_REQUEST", { .i32=4 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_3, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_4, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* CC-Service-Specific-Units */
+		{
+			struct dict_avp_data data = {
+				417,	/* Code */
+				0,	/* Vendor */
+				"CC-Service-Specific-Units",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED64	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* CC-Session-Failover */
+		{
+			struct dict_avp_data data = {
+				418,	/* Code */
+				0,	/* Vendor */
+				"CC-Session-Failover",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "Enumerated(CC-Session-Failover)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "FAILOVER_NOT_SUPPORTED", { .i32=0 }};
+			struct dict_enumval_data        t_2 = { "FAILOVER_SUPPORTED", { .i32=1 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* CC-Sub-Session-Id */
+		{
+			struct dict_avp_data data = {
+				419,	/* Code */
+				0,	/* Vendor */
+				"CC-Sub-Session-Id",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED64	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* CC-Time */
+		{
+			struct dict_avp_data data = {
+				420,	/* Code */
+				0,	/* Vendor */
+				"CC-Time",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* CC-Total-Octets */
+		{
+			struct dict_avp_data data = {
+				421,	/* Code */
+				0,	/* Vendor */
+				"CC-Total-Octets",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED64	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* CC-Unit-Type */
+		{
+			struct dict_avp_data data = {
+				454,	/* Code */
+				0,	/* Vendor */
+				"CC-Unit-Type",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "Enumerated(CC-Unit-Type)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "TIME", { .i32=0 }};
+			struct dict_enumval_data        t_2 = { "MONEY", { .i32=1 }};
+			struct dict_enumval_data        t_3 = { "TOTAL_OCTETS", { .i32=2 }};
+			struct dict_enumval_data        t_4 = { "INPUT_OCTETS", { .i32=3 }};
+			struct dict_enumval_data        t_5 = { "OUTPUT_OCTETS", { .i32=4 }};
+			struct dict_enumval_data        t_6 = { "SERVICE_SPECIFIC_UNITS", { .i32=5 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_3, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_4, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_5, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_6, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* Check-Balance-Result */
+		{
+			struct dict_avp_data data = {
+				422,	/* Code */
+				0,	/* Vendor */
+				"Check-Balance-Result",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "Enumerated(Check-Balance-Result)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "ENOUGH_CREDIT", { .i32=0 }};
+			struct dict_enumval_data        t_2 = { "NO_CREDIT", { .i32=1 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* Cost-Unit */
+		{
+			struct dict_avp_data data = {
+				424,	/* Code */
+				0,	/* Vendor */
+				"Cost-Unit",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, UTF8String_type, NULL);
+		};
+		/* Credit-Control */
+		{
+			struct dict_avp_data data = {
+				426,	/* Code */
+				0,	/* Vendor */
+				"Credit-Control",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "Enumerated(Credit-Control)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "CREDIT_AUTHORIZATION", { .i32=0 }};
+			struct dict_enumval_data        t_2 = { "RE_AUTHORIZATION", { .i32=1 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* Credit-Control-Failure-Handling */
+		{
+			struct dict_avp_data data = {
+				427,	/* Code */
+				0,	/* Vendor */
+				"Credit-Control-Failure-Handling",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "Enumerated(Credit-Control-Failure-Handling)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "TERMINATE", { .i32=0 }};
+			struct dict_enumval_data        t_2 = { "CONTINUE", { .i32=1 }};
+			struct dict_enumval_data        t_3 = { "RETRY_AND_TERMINATE", { .i32=2 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_3, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* Currency-Code */
+		{
+			struct dict_avp_data data = {
+				425,	/* Code */
+				0,	/* Vendor */
+				"Currency-Code",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Direct-Debiting-Failure-Handling */
+		{
+			struct dict_avp_data data = {
+				428,	/* Code */
+				0,	/* Vendor */
+				"Direct-Debiting-Failure-Handling",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "Enumerated(Direct-Debiting-Failure-Handling)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "TERMINATE_OR_BUFFER", { .i32=0 }};
+			struct dict_enumval_data        t_2 = { "CONTINUE", { .i32=1 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* Exponent */
+		{
+			struct dict_avp_data data = {
+				429,	/* Code */
+				0,	/* Vendor */
+				"Exponent",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Final-Unit-Action */
+		{
+			struct dict_avp_data data = {
+				449,	/* Code */
+				0,	/* Vendor */
+				"Final-Unit-Action",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "Enumerated(Final-Unit-Action)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "TERMINATE", { .i32=0 }};
+			struct dict_enumval_data        t_2 = { "REDIRECT", { .i32=1 }};
+			struct dict_enumval_data        t_3 = { "RESTRICT_ACCESS", { .i32=2 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_3, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* G-S-U-Pool-Identifier */
+		{
+			struct dict_avp_data data = {
+				453,	/* Code */
+				0,	/* Vendor */
+				"G-S-U-Pool-Identifier",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Multiple-Services-Indicator */
+		{
+			struct dict_avp_data data = {
+				455,	/* Code */
+				0,	/* Vendor */
+				"Multiple-Services-Indicator",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "Enumerated(Multiple-Services-Indicator)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "MULTIPLE_SERVICES_NOT_SUPPORTED", { .i32=0 }};
+			struct dict_enumval_data        t_2 = { "MULTIPLE_SERVICES_SUPPORTED", { .i32=1 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* Rating-Group */
+		{
+			struct dict_avp_data data = {
+				432,	/* Code */
+				0,	/* Vendor */
+				"Rating-Group",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Redirect-Address-Type */
+		{
+			struct dict_avp_data data = {
+				433,	/* Code */
+				0,	/* Vendor */
+				"Redirect-Address-Type",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "Enumerated(Redirect-Address-Type)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "IPv4_Address", { .i32=0 }};
+			struct dict_enumval_data        t_2 = { "IPv6_Address", { .i32=1 }};
+			struct dict_enumval_data        t_3 = { "URL", { .i32=2 }};
+			struct dict_enumval_data        t_4 = { "SIP_URI", { .i32=3 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_3, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_4, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* Redirect-Server-Address */
+		{
+			struct dict_avp_data data = {
+				435,	/* Code */
+				0,	/* Vendor */
+				"Redirect-Server-Address",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, UTF8String_type, NULL);
+		};
+		/* Redirect-Address-IPAddress */
+		{
+			struct dict_avp_data data = {
+				99996,	/* Code */
+				0,	/* Vendor */
+				"Redirect-Address-IPAddress",	/* Name */
+				AVP_FLAG_VENDOR,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, Address_type, NULL);
+		};
+		/* Redirect-Address-URL */
+		{
+			struct dict_avp_data data = {
+				99997,	/* Code */
+				0,	/* Vendor */
+				"Redirect-Address-URL",	/* Name */
+				AVP_FLAG_VENDOR,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, UTF8String_type, NULL);
+		};
+		/* Redirect-Address-SIP-URI */
+		{
+			struct dict_avp_data data = {
+				99998,	/* Code */
+				0,	/* Vendor */
+				"Redirect-Address-SIP-URI",	/* Name */
+				AVP_FLAG_VENDOR,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, UTF8String_type, NULL);
+		};
+		/* Requested-Action */
+		{
+			struct dict_avp_data data = {
+				436,	/* Code */
+				0,	/* Vendor */
+				"Requested-Action",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "Enumerated(Requested-Action)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "DIRECT_DEBITING", { .i32=0 }};
+			struct dict_enumval_data        t_2 = { "REFUND_ACCOUNT", { .i32=1 }};
+			struct dict_enumval_data        t_3 = { "CHECK_BALANCE", { .i32=2 }};
+			struct dict_enumval_data        t_4 = { "PRICE_ENQUIRY", { .i32=3 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_3, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_4, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* Restriction-Filter-Rule */
+		{
+			struct dict_avp_data data = {
+				438,	/* Code */
+				0,	/* Vendor */
+				"Restriction-Filter-Rule",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, IPFilterRule_type, NULL);
+		};
+		/* Service-Context-Id */
+		{
+			struct dict_avp_data data = {
+				461,	/* Code */
+				0,	/* Vendor */
+				"Service-Context-Id",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, UTF8String_type, NULL);
+		};
+		/* Service-Identifier */
+		{
+			struct dict_avp_data data = {
+				439,	/* Code */
+				0,	/* Vendor */
+				"Service-Identifier",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Service-Parameter-Type */
+		{
+			struct dict_avp_data data = {
+				441,	/* Code */
+				0,	/* Vendor */
+				"Service-Parameter-Type",	/* Name */
+				AVP_FLAG_VENDOR,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Service-Parameter-Value */
+		{
+			struct dict_avp_data data = {
+				442,	/* Code */
+				0,	/* Vendor */
+				"Service-Parameter-Value",	/* Name */
+				AVP_FLAG_VENDOR,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Subscription-Id-Data */
+		{
+			struct dict_avp_data data = {
+				444,	/* Code */
+				0,	/* Vendor */
+				"Subscription-Id-Data",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, UTF8String_type, NULL);
+		};
+		/* Subscription-Id-Type */
+		{
+			struct dict_avp_data data = {
+				450,	/* Code */
+				0,	/* Vendor */
+				"Subscription-Id-Type",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "Enumerated(Subscription-Id-Type)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "END_USER_E164", { .i32=0 }};
+			struct dict_enumval_data        t_2 = { "END_USER_IMSI", { .i32=1 }};
+			struct dict_enumval_data        t_3 = { "END_USER_SIP_URI", { .i32=2 }};
+			struct dict_enumval_data        t_4 = { "END_USER_NAI", { .i32=3 }};
+			struct dict_enumval_data        t_5 = { "END_USER_PRIVATE", { .i32=4 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_3, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_4, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_5, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* Subscription-Id-E164 */
+		{
+			struct dict_avp_data data = {
+				99990,	/* Code */
+				0,	/* Vendor */
+				"Subscription-Id-E164",	/* Name */
+				AVP_FLAG_VENDOR,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, UTF8String_type, NULL);
+		};
+		/* Subscription-Id-IMSI */
+		{
+			struct dict_avp_data data = {
+				99991,	/* Code */
+				0,	/* Vendor */
+				"Subscription-Id-IMSI",	/* Name */
+				AVP_FLAG_VENDOR,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, UTF8String_type, NULL);
+		};
+		/* Subscription-Id-SIP-URI */
+		{
+			struct dict_avp_data data = {
+				99992,	/* Code */
+				0,	/* Vendor */
+				"Subscription-Id-SIP-URI",	/* Name */
+				AVP_FLAG_VENDOR,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, UTF8String_type, NULL);
+		};
+		/* Subscription-Id-NAI */
+		{
+			struct dict_avp_data data = {
+				99993,	/* Code */
+				0,	/* Vendor */
+				"Subscription-Id-NAI",	/* Name */
+				AVP_FLAG_VENDOR,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, UTF8String_type, NULL);
+		};
+		/* Subscription-Id-Private */
+		{
+			struct dict_avp_data data = {
+				99994,	/* Code */
+				0,	/* Vendor */
+				"Subscription-Id-Private",	/* Name */
+				AVP_FLAG_VENDOR,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, UTF8String_type, NULL);
+		};
+		/* Tariff-Change-Usage */
+		{
+			struct dict_avp_data data = {
+				452,	/* Code */
+				0,	/* Vendor */
+				"Tariff-Change-Usage",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "Enumerated(Tariff-Change-Usage)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "UNIT_BEFORE_TARIFF_CHANGE", { .i32=0 }};
+			struct dict_enumval_data        t_2 = { "UNIT_AFTER_TARIFF_CHANGE", { .i32=1 }};
+			struct dict_enumval_data        t_3 = { "UNIT_INDETERMINATE", { .i32=2 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_3, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* Tariff-Time-Change */
+		{
+			struct dict_avp_data data = {
+				451,	/* Code */
+				0,	/* Vendor */
+				"Tariff-Time-Change",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, Time_type, NULL);
+		};
+		/* User-Equipment-Info-Type */
+		{
+			struct dict_avp_data data = {
+				459,	/* Code */
+				0,	/* Vendor */
+				"User-Equipment-Info-Type",	/* Name */
+				AVP_FLAG_VENDOR,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "Enumerated(User-Equipment-Info-Type)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "IMEISV", { .i32=0 }};
+			struct dict_enumval_data        t_2 = { "MAC", { .i32=1 }};
+			struct dict_enumval_data        t_3 = { "EUI64", { .i32=2 }};
+			struct dict_enumval_data        t_4 = { "MODIFIED_EUI64", { .i32=3 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_3, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_4, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* User-Equipment-Info-Value */
+		{
+			struct dict_avp_data data = {
+				460,	/* Code */
+				0,	/* Vendor */
+				"User-Equipment-Info-Value",	/* Name */
+				AVP_FLAG_VENDOR,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* User-Equipment-Info-IMEISV */
+		{
+			struct dict_avp_data data = {
+				99984,	/* Code */
+				0,	/* Vendor */
+				"User-Equipment-Info-IMEISV",	/* Name */
+				AVP_FLAG_VENDOR,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* User-Equipment-Info-MAC */
+		{
+			struct dict_avp_data data = {
+				99985,	/* Code */
+				0,	/* Vendor */
+				"User-Equipment-Info-MAC",	/* Name */
+				AVP_FLAG_VENDOR,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* User-Equipment-Info-EUI64 */
+		{
+			struct dict_avp_data data = {
+				99986,	/* Code */
+				0,	/* Vendor */
+				"User-Equipment-Info-EUI64",	/* Name */
+				AVP_FLAG_VENDOR,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* User-Equipment-Info-ModifiedEUI64 */
+		{
+			struct dict_avp_data data = {
+				99987,	/* Code */
+				0,	/* Vendor */
+				"User-Equipment-Info-ModifiedEUI64",	/* Name */
+				AVP_FLAG_VENDOR,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* User-Equipment-Info-IMEI */
+		{
+			struct dict_avp_data data = {
+				99988,	/* Code */
+				0,	/* Vendor */
+				"User-Equipment-Info-IMEI",	/* Name */
+				AVP_FLAG_VENDOR,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Value-Digits */
+		{
+			struct dict_avp_data data = {
+				447,	/* Code */
+				0,	/* Vendor */
+				"Value-Digits",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_INTEGER64	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Validity-Time */
+		{
+			struct dict_avp_data data = {
+				448,	/* Code */
+				0,	/* Vendor */
+				"Validity-Time",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Subscription-Id-Extension */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				99989,	/* Code */
+				0,	/* Vendor */
+				"Subscription-Id-Extension",	/* Name */
+				AVP_FLAG_VENDOR,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* Subscription-Id */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				443,	/* Code */
+				0,	/* Vendor */
+				"Subscription-Id",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* Service-Parameter-Info */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				440,	/* Code */
+				0,	/* Vendor */
+				"Service-Parameter-Info",	/* Name */
+				AVP_FLAG_VENDOR,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* User-Equipment-Info */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				458,	/* Code */
+				0,	/* Vendor */
+				"User-Equipment-Info",	/* Name */
+				AVP_FLAG_VENDOR,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* Unit-Value */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				445,	/* Code */
+				0,	/* Vendor */
+				"Unit-Value",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* Redirect-Server-Extension */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				99995,	/* Code */
+				0,	/* Vendor */
+				"Redirect-Server-Extension",	/* Name */
+				AVP_FLAG_VENDOR,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* Redirect-Server */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				434,	/* Code */
+				0,	/* Vendor */
+				"Redirect-Server",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* User-Equipment-Info-Extension */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				99983,	/* Code */
+				0,	/* Vendor */
+				"User-Equipment-Info-Extension",	/* Name */
+				AVP_FLAG_VENDOR,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* G-S-U-Pool-Reference */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				457,	/* Code */
+				0,	/* Vendor */
+				"G-S-U-Pool-Reference",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* Final-Unit-Indication */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				430,	/* Code */
+				0,	/* Vendor */
+				"Final-Unit-Indication",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* CC-Money */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				413,	/* Code */
+				0,	/* Vendor */
+				"CC-Money",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* Cost-Information */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				423,	/* Code */
+				0,	/* Vendor */
+				"Cost-Information",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* Used-Service-Unit */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				446,	/* Code */
+				0,	/* Vendor */
+				"Used-Service-Unit",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* Requested-Service-Unit */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				437,	/* Code */
+				0,	/* Vendor */
+				"Requested-Service-Unit",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* Granted-Service-Unit */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				431,	/* Code */
+				0,	/* Vendor */
+				"Granted-Service-Unit",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* QoS-Final-Unit-Indication */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				99999,	/* Code */
+				0,	/* Vendor */
+				"QoS-Final-Unit-Indication",	/* Name */
+				AVP_FLAG_VENDOR,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* Multiple-Services-Credit-Control */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				456,	/* Code */
+				0,	/* Vendor */
+				"Multiple-Services-Credit-Control",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+
+	
+   }
+
+   /* Commands section */
+   {
+
+   }
+
+   return 0;
+}
+
+static int dict_rfc4006bis_avps_load_rules(char * conffile)
+{
+   /* Grouped AVP section */
+   {
+	  /* Subscription-Id-Extension */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 0, .avp_name = "Subscription-Id-Extension"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 0, .avp_name = "Subscription-Id-E164"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Subscription-Id-IMSI"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Subscription-Id-SIP-URI"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Subscription-Id-NAI"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Subscription-Id-Private"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* Subscription-Id */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 0, .avp_name = "Subscription-Id"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 0, .avp_name = "Subscription-Id-Type"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Subscription-Id-Data"}, RULE_REQUIRED, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* Service-Parameter-Info */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 0, .avp_name = "Service-Parameter-Info"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 0, .avp_name = "Service-Parameter-Type"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Service-Parameter-Value"}, RULE_REQUIRED, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* User-Equipment-Info */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 0, .avp_name = "User-Equipment-Info"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 0, .avp_name = "User-Equipment-Info-Type"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "User-Equipment-Info-Value"}, RULE_REQUIRED, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* Unit-Value */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 0, .avp_name = "Unit-Value"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 0, .avp_name = "Value-Digits"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Exponent"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* Redirect-Server-Extension */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 0, .avp_name = "Redirect-Server-Extension"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 0, .avp_name = "Redirect-Address-IPAddress"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Redirect-Address-URL"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Redirect-Address-SIP-URI"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* Redirect-Server */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 0, .avp_name = "Redirect-Server"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 0, .avp_name = "Redirect-Address-Type"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Redirect-Server-Address"}, RULE_REQUIRED, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* User-Equipment-Info-Extension */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 0, .avp_name = "User-Equipment-Info-Extension"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 0, .avp_name = "User-Equipment-Info-IMEISV"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "User-Equipment-Info-MAC"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "User-Equipment-Info-EUI64"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "User-Equipment-Info-ModifiedEUI64"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "User-Equipment-Info-IMEI"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* G-S-U-Pool-Reference */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 0, .avp_name = "G-S-U-Pool-Reference"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 0, .avp_name = "G-S-U-Pool-Identifier"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "CC-Unit-Type"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Unit-Value"}, RULE_REQUIRED, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* Final-Unit-Indication */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 0, .avp_name = "Final-Unit-Indication"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 0, .avp_name = "Final-Unit-Action"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Restriction-Filter-Rule"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Filter-Id"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Redirect-Server"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* CC-Money */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 0, .avp_name = "CC-Money"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 0, .avp_name = "Unit-Value"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Currency-Code"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* Cost-Information */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 0, .avp_name = "Cost-Information"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 0, .avp_name = "Unit-Value"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Currency-Code"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Cost-Unit"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* Used-Service-Unit */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 0, .avp_name = "Used-Service-Unit"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 0, .avp_name = "Tariff-Change-Usage"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "CC-Time"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "CC-Money"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "CC-Total-Octets"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "CC-Input-Octets"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "CC-Output-Octets"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "CC-Service-Specific-Units"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* Requested-Service-Unit */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 0, .avp_name = "Requested-Service-Unit"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 0, .avp_name = "CC-Time"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "CC-Money"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "CC-Total-Octets"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "CC-Input-Octets"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "CC-Output-Octets"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "CC-Service-Specific-Units"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* Granted-Service-Unit */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 0, .avp_name = "Granted-Service-Unit"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 0, .avp_name = "Tariff-Time-Change"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "CC-Time"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "CC-Money"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "CC-Total-Octets"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "CC-Input-Octets"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "CC-Output-Octets"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "CC-Service-Specific-Units"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* QoS-Final-Unit-Indication */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 0, .avp_name = "QoS-Final-Unit-Indication"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 0, .avp_name = "Final-Unit-Action"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Filter-Rule"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Filter-Id"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Redirect-Server-Extension"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* Multiple-Services-Credit-Control */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 0, .avp_name = "Multiple-Services-Credit-Control"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 0, .avp_name = "Granted-Service-Unit"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Requested-Service-Unit"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Used-Service-Unit"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Tariff-Change-Usage"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Service-Identifier"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Rating-Group"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "G-S-U-Pool-Reference"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Validity-Time"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Result-Code"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Final-Unit-Indication"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "QoS-Final-Unit-Indication"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+
+   }	
+
+   /* Commands section */
+   {
+
+   }
+
+   LOG_D( "Extension 'Dictionary definitions for rfc4006bis_avps (None)' initialized");
+   return 0;
+}
+
+int dict_entry(char * conffile)
+{
+	dict_rfc4006bis_avps_load_defs(conffile);
+	return dict_rfc4006bis_avps_load_rules(conffile);
+}
+
+const char* dict_rfc4006bis_avps_proto_ver(char * conffile) {
+	return rfc4006bis_avps_proto_ver;
+}
+
+const double dict_rfc4006bis_avps_gen_ts(char * conffile) {
+	return rfc4006bis_avps_gen_date;
+}
+
+EXTENSION_ENTRY2("dict_rfc4006bis_avps", dict_rfc4006bis_avps_load_defs, dict_rfc4006bis_avps_load_rules, "dict_rfc7155_avps", "dict_rfc5777_avps");
+
+
+
diff --git a/extensions/dict_rfc4006bis_avps/rfc4006bis_avps.did b/extensions/dict_rfc4006bis_avps/rfc4006bis_avps.did
new file mode 100644
index 0000000..0aad557
--- /dev/null
+++ b/extensions/dict_rfc4006bis_avps/rfc4006bis_avps.did
@@ -0,0 +1,4 @@
+dict_rfc4004_avps
+dict_rfc7155_avps
+dict_rfc5777_avps
+dict_rfc4006bis_avps
diff --git a/extensions/dict_rfc4072_avps/CMakeLists.txt b/extensions/dict_rfc4072_avps/CMakeLists.txt
new file mode 100644
index 0000000..d694a90
--- /dev/null
+++ b/extensions/dict_rfc4072_avps/CMakeLists.txt
@@ -0,0 +1,16 @@
+# The dict_rfc4072_avps extension
+PROJECT("dict_rfc4072_avps library generated by FdGen " C)
+
+# Compile as a module
+FD_ADD_EXTENSION(dict_rfc4072_avps dict_rfc4072_avps.c)
+
+
+####
+## INSTALL section ##
+
+INSTALL(TARGETS dict_rfc4072_avps
+	LIBRARY DESTINATION ${INSTALL_EXTENSIONS_SUFFIX}
+COMPONENT freeDiameter-dictionary-RFC4072_AVPS)
+
+
+
diff --git a/extensions/dict_rfc4072_avps/dict_rfc4072_avps.c b/extensions/dict_rfc4072_avps/dict_rfc4072_avps.c
new file mode 100644
index 0000000..69d705d
--- /dev/null
+++ b/extensions/dict_rfc4072_avps/dict_rfc4072_avps.c
@@ -0,0 +1,224 @@
+/*
+* Copyright (c) 2017 Sprint
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*    http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+/****************
+ Generated By: fdtool enhancements to diafuzzer
+ License: same as freeDiameter
+****************/
+
+
+/* 
+ * Dictionary definitions of objects specified in rfc4072_avps.
+ */
+#include <freeDiameter/extension.h>
+
+#define PROTO_VER "unspecified"
+#define GEN_DATE  1506697143.65
+
+const char *rfc4072_avps_proto_ver = PROTO_VER;
+const double rfc4072_avps_gen_date = GEN_DATE;
+
+/* The content of this file follows the same structure as dict_base_proto.c */
+
+#define CHECK_dict_new( _type, _data, _parent, _ref )                                     \
+{                                                                                         \
+    int _ret = fd_dict_new( fd_g_config->cnf_dict, (_type), (_data), (_parent), (_ref) ); \
+    if ( _ret != 0 && _ret != EEXIST )                                                    \
+       return _ret;                                                                       \
+}
+
+#define CHECK_dict_search( _type, _criteria, _what, _result )		\
+    CHECK_FCT(  fd_dict_search( fd_g_config->cnf_dict, (_type), (_criteria), (_what), (_result), ENOENT) );
+
+struct local_rules_definition {
+    struct dict_avp_request avp_vendor_plus_name;
+    enum rule_position	position;
+    int 			min;
+    int			max;
+};
+
+#define RULE_ORDER( _position ) ((((_position) == RULE_FIXED_HEAD) || ((_position) == RULE_FIXED_TAIL)) ? 1 : 0 )
+
+/* Attention! This version of the macro uses AVP_BY_NAME_AND_VENDOR, in contrast to most other copies! */
+#define PARSE_loc_rules( _rulearray, _parent) {                                                         \
+        int __ar;                                                                                       \
+        for (__ar=0; __ar < sizeof(_rulearray) / sizeof((_rulearray)[0]); __ar++) {                     \
+                struct dict_rule_data __data = { NULL,                                                  \
+                        (_rulearray)[__ar].position,                                                    \
+                        0,                                                                              \
+                        (_rulearray)[__ar].min,                                                         \
+                        (_rulearray)[__ar].max};                                                        \
+                __data.rule_order = RULE_ORDER(__data.rule_position);                                   \
+                CHECK_FCT(  fd_dict_search(                                                             \
+                        fd_g_config->cnf_dict,                                                          \
+                        DICT_AVP,                                                                       \
+                        AVP_BY_NAME_AND_VENDOR,                                                         \
+                        &(_rulearray)[__ar].avp_vendor_plus_name,                                       \
+                        &__data.rule_avp, 0 ) );                                                        \
+                if ( !__data.rule_avp ) {                                                               \
+                        TRACE_DEBUG(INFO, "AVP Not found: '%s'", (_rulearray)[__ar].avp_vendor_plus_name.avp_name);             \
+                        return ENOENT;                                                                  \
+                }                                                                                       \
+                {                                                                                       \
+                         int _ret = fd_dict_new( fd_g_config->cnf_dict, DICT_RULE, &(__data), (_parent), NULL ); \
+                         if ( _ret != 0 && _ret != EEXIST )      {                                      \
+                                TRACE_DEBUG(INFO, "Error on rule with AVP '%s'",                        \
+                                            (_rulearray)[__ar].avp_vendor_plus_name.avp_name);          \
+                                return EINVAL;                                                          \
+                         }                                                                              \
+                }                                                                                       \
+        }                                                                                               \
+}
+
+#define CHECK_vendor_new( _data ) { \
+        struct dict_object * vendor_found; \
+        if (fd_dict_search(fd_g_config->cnf_dict,DICT_VENDOR,VENDOR_BY_ID,&_data.vendor_id,&vendor_found,ENOENT) == ENOENT) { \
+                CHECK_FCT(fd_dict_new(fd_g_config->cnf_dict, DICT_VENDOR, &_data, NULL, NULL)); \
+        } \
+}
+
+#define enumval_def_u32( _val_, _str_ )		\
+    { _str_, 		{ .u32 = _val_ }}
+
+#define enumval_def_os( _len_, _val_, _str_ )				\
+    { _str_, 		{ .os = { .data = (unsigned char *)_val_, .len = _len_ }}}
+
+
+static int dict_rfc4072_avps_load_defs(char * conffile)
+{
+   TRACE_ENTRY("%p", conffile);
+
+   /* AVP section */
+   {
+		struct dict_object * Address_type;
+		struct dict_object * UTF8String_type;
+		struct dict_object * DiameterIdentity_type;
+		struct dict_object * DiameterURI_type;
+		struct dict_object * Time_type;
+		struct dict_object * IPFilterRule_type;
+
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "Address", &Address_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "UTF8String", &UTF8String_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "DiameterIdentity", &DiameterIdentity_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "DiameterURI", &DiameterURI_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "Time", &Time_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "IPFilterRule", &IPFilterRule_type);
+		/* EAP-Payload */
+		{
+			struct dict_avp_data data = {
+				462,	/* Code */
+				0,	/* Vendor */
+				"EAP-Payload",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* EAP-Reissued-Payload */
+		{
+			struct dict_avp_data data = {
+				463,	/* Code */
+				0,	/* Vendor */
+				"EAP-Reissued-Payload",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* EAP-Master-Session-Key */
+		{
+			struct dict_avp_data data = {
+				464,	/* Code */
+				0,	/* Vendor */
+				"EAP-Master-Session-Key",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* EAP-Key-Name */
+		{
+			struct dict_avp_data data = {
+				102,	/* Code */
+				0,	/* Vendor */
+				"EAP-Key-Name",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Accounting-EAP-Auth-Method */
+		{
+			struct dict_avp_data data = {
+				465,	/* Code */
+				0,	/* Vendor */
+				"Accounting-EAP-Auth-Method",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED64	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+
+	
+   }
+
+   /* Commands section */
+   {
+
+   }
+
+   return 0;
+}
+
+static int dict_rfc4072_avps_load_rules(char * conffile)
+{
+   /* Grouped AVP section */
+   {
+
+   }	
+
+   /* Commands section */
+   {
+
+   }
+
+   LOG_D( "Extension 'Dictionary definitions for rfc4072_avps (None)' initialized");
+   return 0;
+}
+
+int dict_entry(char * conffile)
+{
+	dict_rfc4072_avps_load_defs(conffile);
+	return dict_rfc4072_avps_load_rules(conffile);
+}
+
+const char* dict_rfc4072_avps_proto_ver(char * conffile) {
+	return rfc4072_avps_proto_ver;
+}
+
+const double dict_rfc4072_avps_gen_ts(char * conffile) {
+	return rfc4072_avps_gen_date;
+}
+
+EXTENSION_ENTRY2("dict_rfc4072_avps", dict_rfc4072_avps_load_defs, dict_rfc4072_avps_load_rules, "dict_rfc7155_avps");
+
+
+
diff --git a/extensions/dict_rfc4072_avps/rfc4072_avps.did b/extensions/dict_rfc4072_avps/rfc4072_avps.did
new file mode 100644
index 0000000..feaf759
--- /dev/null
+++ b/extensions/dict_rfc4072_avps/rfc4072_avps.did
@@ -0,0 +1,3 @@
+dict_rfc4004_avps
+dict_rfc7155_avps
+dict_rfc4072_avps
diff --git a/extensions/dict_rfc4590_avps/CMakeLists.txt b/extensions/dict_rfc4590_avps/CMakeLists.txt
new file mode 100644
index 0000000..c755961
--- /dev/null
+++ b/extensions/dict_rfc4590_avps/CMakeLists.txt
@@ -0,0 +1,16 @@
+# The dict_rfc4590_avps extension
+PROJECT("dict_rfc4590_avps library generated by FdGen " C)
+
+# Compile as a module
+FD_ADD_EXTENSION(dict_rfc4590_avps dict_rfc4590_avps.c)
+
+
+####
+## INSTALL section ##
+
+INSTALL(TARGETS dict_rfc4590_avps
+	LIBRARY DESTINATION ${INSTALL_EXTENSIONS_SUFFIX}
+COMPONENT freeDiameter-dictionary-RFC4590_AVPS)
+
+
+
diff --git a/extensions/dict_rfc4590_avps/dict_rfc4590_avps.c b/extensions/dict_rfc4590_avps/dict_rfc4590_avps.c
new file mode 100644
index 0000000..a09901d
--- /dev/null
+++ b/extensions/dict_rfc4590_avps/dict_rfc4590_avps.c
@@ -0,0 +1,416 @@
+/*
+* Copyright (c) 2017 Sprint
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*    http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+/****************
+ Generated By: fdtool enhancements to diafuzzer
+ License: same as freeDiameter
+****************/
+
+
+/* 
+ * Dictionary definitions of objects specified in rfc4590_avps.
+ */
+#include <freeDiameter/extension.h>
+
+#define PROTO_VER "unspecified"
+#define GEN_DATE  1506697143.52
+
+const char *rfc4590_avps_proto_ver = PROTO_VER;
+const double rfc4590_avps_gen_date = GEN_DATE;
+
+/* The content of this file follows the same structure as dict_base_proto.c */
+
+#define CHECK_dict_new( _type, _data, _parent, _ref )                                     \
+{                                                                                         \
+    int _ret = fd_dict_new( fd_g_config->cnf_dict, (_type), (_data), (_parent), (_ref) ); \
+    if ( _ret != 0 && _ret != EEXIST )                                                    \
+       return _ret;                                                                       \
+}
+
+#define CHECK_dict_search( _type, _criteria, _what, _result )		\
+    CHECK_FCT(  fd_dict_search( fd_g_config->cnf_dict, (_type), (_criteria), (_what), (_result), ENOENT) );
+
+struct local_rules_definition {
+    struct dict_avp_request avp_vendor_plus_name;
+    enum rule_position	position;
+    int 			min;
+    int			max;
+};
+
+#define RULE_ORDER( _position ) ((((_position) == RULE_FIXED_HEAD) || ((_position) == RULE_FIXED_TAIL)) ? 1 : 0 )
+
+/* Attention! This version of the macro uses AVP_BY_NAME_AND_VENDOR, in contrast to most other copies! */
+#define PARSE_loc_rules( _rulearray, _parent) {                                                         \
+        int __ar;                                                                                       \
+        for (__ar=0; __ar < sizeof(_rulearray) / sizeof((_rulearray)[0]); __ar++) {                     \
+                struct dict_rule_data __data = { NULL,                                                  \
+                        (_rulearray)[__ar].position,                                                    \
+                        0,                                                                              \
+                        (_rulearray)[__ar].min,                                                         \
+                        (_rulearray)[__ar].max};                                                        \
+                __data.rule_order = RULE_ORDER(__data.rule_position);                                   \
+                CHECK_FCT(  fd_dict_search(                                                             \
+                        fd_g_config->cnf_dict,                                                          \
+                        DICT_AVP,                                                                       \
+                        AVP_BY_NAME_AND_VENDOR,                                                         \
+                        &(_rulearray)[__ar].avp_vendor_plus_name,                                       \
+                        &__data.rule_avp, 0 ) );                                                        \
+                if ( !__data.rule_avp ) {                                                               \
+                        TRACE_DEBUG(INFO, "AVP Not found: '%s'", (_rulearray)[__ar].avp_vendor_plus_name.avp_name);             \
+                        return ENOENT;                                                                  \
+                }                                                                                       \
+                {                                                                                       \
+                         int _ret = fd_dict_new( fd_g_config->cnf_dict, DICT_RULE, &(__data), (_parent), NULL ); \
+                         if ( _ret != 0 && _ret != EEXIST )      {                                      \
+                                TRACE_DEBUG(INFO, "Error on rule with AVP '%s'",                        \
+                                            (_rulearray)[__ar].avp_vendor_plus_name.avp_name);          \
+                                return EINVAL;                                                          \
+                         }                                                                              \
+                }                                                                                       \
+        }                                                                                               \
+}
+
+#define CHECK_vendor_new( _data ) { \
+        struct dict_object * vendor_found; \
+        if (fd_dict_search(fd_g_config->cnf_dict,DICT_VENDOR,VENDOR_BY_ID,&_data.vendor_id,&vendor_found,ENOENT) == ENOENT) { \
+                CHECK_FCT(fd_dict_new(fd_g_config->cnf_dict, DICT_VENDOR, &_data, NULL, NULL)); \
+        } \
+}
+
+#define enumval_def_u32( _val_, _str_ )		\
+    { _str_, 		{ .u32 = _val_ }}
+
+#define enumval_def_os( _len_, _val_, _str_ )				\
+    { _str_, 		{ .os = { .data = (unsigned char *)_val_, .len = _len_ }}}
+
+
+static int dict_rfc4590_avps_load_defs(char * conffile)
+{
+   TRACE_ENTRY("%p", conffile);
+
+   /* AVP section */
+   {
+		struct dict_object * Address_type;
+		struct dict_object * UTF8String_type;
+		struct dict_object * DiameterIdentity_type;
+		struct dict_object * DiameterURI_type;
+		struct dict_object * Time_type;
+		struct dict_object * IPFilterRule_type;
+
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "Address", &Address_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "UTF8String", &UTF8String_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "DiameterIdentity", &DiameterIdentity_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "DiameterURI", &DiameterURI_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "Time", &Time_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "IPFilterRule", &IPFilterRule_type);
+		/* Message-Authenticator */
+		{
+			struct dict_avp_data data = {
+				80,	/* Code */
+				0,	/* Vendor */
+				"Message-Authenticator",	/* Name */
+				0,	/* Fixed flags */
+				0,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Digest-Response */
+		{
+			struct dict_avp_data data = {
+				103,	/* Code */
+				0,	/* Vendor */
+				"Digest-Response",	/* Name */
+				0,	/* Fixed flags */
+				0,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Digest-Realm */
+		{
+			struct dict_avp_data data = {
+				104,	/* Code */
+				0,	/* Vendor */
+				"Digest-Realm",	/* Name */
+				0,	/* Fixed flags */
+				0,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Digest-Nonce */
+		{
+			struct dict_avp_data data = {
+				105,	/* Code */
+				0,	/* Vendor */
+				"Digest-Nonce",	/* Name */
+				0,	/* Fixed flags */
+				0,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Digest-Response-Auth */
+		{
+			struct dict_avp_data data = {
+				106,	/* Code */
+				0,	/* Vendor */
+				"Digest-Response-Auth",	/* Name */
+				0,	/* Fixed flags */
+				0,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Digest-Nextnonce */
+		{
+			struct dict_avp_data data = {
+				107,	/* Code */
+				0,	/* Vendor */
+				"Digest-Nextnonce",	/* Name */
+				0,	/* Fixed flags */
+				0,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Digest-Method */
+		{
+			struct dict_avp_data data = {
+				108,	/* Code */
+				0,	/* Vendor */
+				"Digest-Method",	/* Name */
+				0,	/* Fixed flags */
+				0,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Digest-URI */
+		{
+			struct dict_avp_data data = {
+				109,	/* Code */
+				0,	/* Vendor */
+				"Digest-URI",	/* Name */
+				0,	/* Fixed flags */
+				0,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Digest-QoP */
+		{
+			struct dict_avp_data data = {
+				110,	/* Code */
+				0,	/* Vendor */
+				"Digest-QoP",	/* Name */
+				0,	/* Fixed flags */
+				0,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Digest-Algorithm */
+		{
+			struct dict_avp_data data = {
+				111,	/* Code */
+				0,	/* Vendor */
+				"Digest-Algorithm",	/* Name */
+				0,	/* Fixed flags */
+				0,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Digest-Entity-Body-Hash */
+		{
+			struct dict_avp_data data = {
+				112,	/* Code */
+				0,	/* Vendor */
+				"Digest-Entity-Body-Hash",	/* Name */
+				0,	/* Fixed flags */
+				0,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Digest-CNonce */
+		{
+			struct dict_avp_data data = {
+				113,	/* Code */
+				0,	/* Vendor */
+				"Digest-CNonce",	/* Name */
+				0,	/* Fixed flags */
+				0,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Digest-Nonce-Count */
+		{
+			struct dict_avp_data data = {
+				114,	/* Code */
+				0,	/* Vendor */
+				"Digest-Nonce-Count",	/* Name */
+				0,	/* Fixed flags */
+				0,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Digest-Username */
+		{
+			struct dict_avp_data data = {
+				115,	/* Code */
+				0,	/* Vendor */
+				"Digest-Username",	/* Name */
+				0,	/* Fixed flags */
+				0,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Digest-Opaque */
+		{
+			struct dict_avp_data data = {
+				116,	/* Code */
+				0,	/* Vendor */
+				"Digest-Opaque",	/* Name */
+				0,	/* Fixed flags */
+				0,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Digest-Auth-Param */
+		{
+			struct dict_avp_data data = {
+				117,	/* Code */
+				0,	/* Vendor */
+				"Digest-Auth-Param",	/* Name */
+				0,	/* Fixed flags */
+				0,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Digest-AKA-Auts */
+		{
+			struct dict_avp_data data = {
+				118,	/* Code */
+				0,	/* Vendor */
+				"Digest-AKA-Auts",	/* Name */
+				0,	/* Fixed flags */
+				0,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Digest-Domain */
+		{
+			struct dict_avp_data data = {
+				119,	/* Code */
+				0,	/* Vendor */
+				"Digest-Domain",	/* Name */
+				0,	/* Fixed flags */
+				0,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Digest-Stale */
+		{
+			struct dict_avp_data data = {
+				120,	/* Code */
+				0,	/* Vendor */
+				"Digest-Stale",	/* Name */
+				0,	/* Fixed flags */
+				0,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Digest-HA1 */
+		{
+			struct dict_avp_data data = {
+				121,	/* Code */
+				0,	/* Vendor */
+				"Digest-HA1",	/* Name */
+				0,	/* Fixed flags */
+				0,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* SIP-AOR */
+		{
+			struct dict_avp_data data = {
+				122,	/* Code */
+				0,	/* Vendor */
+				"SIP-AOR",	/* Name */
+				0,	/* Fixed flags */
+				0,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+
+	
+   }
+
+   /* Commands section */
+   {
+
+   }
+
+   return 0;
+}
+
+static int dict_rfc4590_avps_load_rules(char * conffile)
+{
+   /* Grouped AVP section */
+   {
+
+   }	
+
+   /* Commands section */
+   {
+
+   }
+
+   LOG_D( "Extension 'Dictionary definitions for rfc4590_avps (None)' initialized");
+   return 0;
+}
+
+int dict_entry(char * conffile)
+{
+	dict_rfc4590_avps_load_defs(conffile);
+	return dict_rfc4590_avps_load_rules(conffile);
+}
+
+const char* dict_rfc4590_avps_proto_ver(char * conffile) {
+	return rfc4590_avps_proto_ver;
+}
+
+const double dict_rfc4590_avps_gen_ts(char * conffile) {
+	return rfc4590_avps_gen_date;
+}
+
+EXTENSION_ENTRY2("dict_rfc4590_avps", dict_rfc4590_avps_load_defs, dict_rfc4590_avps_load_rules);
+
+
+
diff --git a/extensions/dict_rfc4590_avps/rfc4590_avps.did b/extensions/dict_rfc4590_avps/rfc4590_avps.did
new file mode 100644
index 0000000..0ef3e08
--- /dev/null
+++ b/extensions/dict_rfc4590_avps/rfc4590_avps.did
@@ -0,0 +1 @@
+dict_rfc4590_avps
diff --git a/extensions/dict_rfc5447_avps/CMakeLists.txt b/extensions/dict_rfc5447_avps/CMakeLists.txt
new file mode 100644
index 0000000..80425cd
--- /dev/null
+++ b/extensions/dict_rfc5447_avps/CMakeLists.txt
@@ -0,0 +1,16 @@
+# The dict_rfc5447_avps extension
+PROJECT("dict_rfc5447_avps library generated by FdGen " C)
+
+# Compile as a module
+FD_ADD_EXTENSION(dict_rfc5447_avps dict_rfc5447_avps.c)
+
+
+####
+## INSTALL section ##
+
+INSTALL(TARGETS dict_rfc5447_avps
+	LIBRARY DESTINATION ${INSTALL_EXTENSIONS_SUFFIX}
+COMPONENT freeDiameter-dictionary-RFC5447_AVPS)
+
+
+
diff --git a/extensions/dict_rfc5447_avps/dict_rfc5447_avps.c b/extensions/dict_rfc5447_avps/dict_rfc5447_avps.c
new file mode 100644
index 0000000..a665cf8
--- /dev/null
+++ b/extensions/dict_rfc5447_avps/dict_rfc5447_avps.c
@@ -0,0 +1,216 @@
+/*
+* Copyright (c) 2017 Sprint
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*    http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+/****************
+ Generated By: fdtool enhancements to diafuzzer
+ License: same as freeDiameter
+****************/
+
+
+/* 
+ * Dictionary definitions of objects specified in rfc5447_avps.
+ */
+#include <freeDiameter/extension.h>
+
+#define PROTO_VER "unspecified"
+#define GEN_DATE  1506697143.54
+
+const char *rfc5447_avps_proto_ver = PROTO_VER;
+const double rfc5447_avps_gen_date = GEN_DATE;
+
+/* The content of this file follows the same structure as dict_base_proto.c */
+
+#define CHECK_dict_new( _type, _data, _parent, _ref )                                     \
+{                                                                                         \
+    int _ret = fd_dict_new( fd_g_config->cnf_dict, (_type), (_data), (_parent), (_ref) ); \
+    if ( _ret != 0 && _ret != EEXIST )                                                    \
+       return _ret;                                                                       \
+}
+
+#define CHECK_dict_search( _type, _criteria, _what, _result )		\
+    CHECK_FCT(  fd_dict_search( fd_g_config->cnf_dict, (_type), (_criteria), (_what), (_result), ENOENT) );
+
+struct local_rules_definition {
+    struct dict_avp_request avp_vendor_plus_name;
+    enum rule_position	position;
+    int 			min;
+    int			max;
+};
+
+#define RULE_ORDER( _position ) ((((_position) == RULE_FIXED_HEAD) || ((_position) == RULE_FIXED_TAIL)) ? 1 : 0 )
+
+/* Attention! This version of the macro uses AVP_BY_NAME_AND_VENDOR, in contrast to most other copies! */
+#define PARSE_loc_rules( _rulearray, _parent) {                                                         \
+        int __ar;                                                                                       \
+        for (__ar=0; __ar < sizeof(_rulearray) / sizeof((_rulearray)[0]); __ar++) {                     \
+                struct dict_rule_data __data = { NULL,                                                  \
+                        (_rulearray)[__ar].position,                                                    \
+                        0,                                                                              \
+                        (_rulearray)[__ar].min,                                                         \
+                        (_rulearray)[__ar].max};                                                        \
+                __data.rule_order = RULE_ORDER(__data.rule_position);                                   \
+                CHECK_FCT(  fd_dict_search(                                                             \
+                        fd_g_config->cnf_dict,                                                          \
+                        DICT_AVP,                                                                       \
+                        AVP_BY_NAME_AND_VENDOR,                                                         \
+                        &(_rulearray)[__ar].avp_vendor_plus_name,                                       \
+                        &__data.rule_avp, 0 ) );                                                        \
+                if ( !__data.rule_avp ) {                                                               \
+                        TRACE_DEBUG(INFO, "AVP Not found: '%s'", (_rulearray)[__ar].avp_vendor_plus_name.avp_name);             \
+                        return ENOENT;                                                                  \
+                }                                                                                       \
+                {                                                                                       \
+                         int _ret = fd_dict_new( fd_g_config->cnf_dict, DICT_RULE, &(__data), (_parent), NULL ); \
+                         if ( _ret != 0 && _ret != EEXIST )      {                                      \
+                                TRACE_DEBUG(INFO, "Error on rule with AVP '%s'",                        \
+                                            (_rulearray)[__ar].avp_vendor_plus_name.avp_name);          \
+                                return EINVAL;                                                          \
+                         }                                                                              \
+                }                                                                                       \
+        }                                                                                               \
+}
+
+#define CHECK_vendor_new( _data ) { \
+        struct dict_object * vendor_found; \
+        if (fd_dict_search(fd_g_config->cnf_dict,DICT_VENDOR,VENDOR_BY_ID,&_data.vendor_id,&vendor_found,ENOENT) == ENOENT) { \
+                CHECK_FCT(fd_dict_new(fd_g_config->cnf_dict, DICT_VENDOR, &_data, NULL, NULL)); \
+        } \
+}
+
+#define enumval_def_u32( _val_, _str_ )		\
+    { _str_, 		{ .u32 = _val_ }}
+
+#define enumval_def_os( _len_, _val_, _str_ )				\
+    { _str_, 		{ .os = { .data = (unsigned char *)_val_, .len = _len_ }}}
+
+
+static int dict_rfc5447_avps_load_defs(char * conffile)
+{
+   TRACE_ENTRY("%p", conffile);
+
+   /* AVP section */
+   {
+		struct dict_object * Address_type;
+		struct dict_object * UTF8String_type;
+		struct dict_object * DiameterIdentity_type;
+		struct dict_object * DiameterURI_type;
+		struct dict_object * Time_type;
+		struct dict_object * IPFilterRule_type;
+
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "Address", &Address_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "UTF8String", &UTF8String_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "DiameterIdentity", &DiameterIdentity_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "DiameterURI", &DiameterURI_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "Time", &Time_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "IPFilterRule", &IPFilterRule_type);
+		/* MIP6-Feature-Vector */
+		{
+			struct dict_avp_data data = {
+				124,	/* Code */
+				0,	/* Vendor */
+				"MIP6-Feature-Vector",	/* Name */
+				AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* MIP6-Home-Link-Prefix */
+		{
+			struct dict_avp_data data = {
+				125,	/* Code */
+				0,	/* Vendor */
+				"MIP6-Home-Link-Prefix",	/* Name */
+				AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* MIP6-Agent-Info */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				486,	/* Code */
+				0,	/* Vendor */
+				"MIP6-Agent-Info",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+
+	
+   }
+
+   /* Commands section */
+   {
+
+   }
+
+   return 0;
+}
+
+static int dict_rfc5447_avps_load_rules(char * conffile)
+{
+   /* Grouped AVP section */
+   {
+	  /* MIP6-Agent-Info */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 0, .avp_name = "MIP6-Agent-Info"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 0, .avp_name = "MIP-Home-Agent-Address"}, RULE_OPTIONAL, -1, 2 },
+			{ { .avp_vendor = 0, .avp_name = "MIP-Home-Agent-Host"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "MIP6-Home-Link-Prefix"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+
+   }	
+
+   /* Commands section */
+   {
+
+   }
+
+   LOG_D( "Extension 'Dictionary definitions for rfc5447_avps (None)' initialized");
+   return 0;
+}
+
+int dict_entry(char * conffile)
+{
+	dict_rfc5447_avps_load_defs(conffile);
+	return dict_rfc5447_avps_load_rules(conffile);
+}
+
+const char* dict_rfc5447_avps_proto_ver(char * conffile) {
+	return rfc5447_avps_proto_ver;
+}
+
+const double dict_rfc5447_avps_gen_ts(char * conffile) {
+	return rfc5447_avps_gen_date;
+}
+
+EXTENSION_ENTRY2("dict_rfc5447_avps", dict_rfc5447_avps_load_defs, dict_rfc5447_avps_load_rules, "dict_rfc4004_avps");
+
+
+
diff --git a/extensions/dict_rfc5447_avps/rfc5447_avps.did b/extensions/dict_rfc5447_avps/rfc5447_avps.did
new file mode 100644
index 0000000..8225d5d
--- /dev/null
+++ b/extensions/dict_rfc5447_avps/rfc5447_avps.did
@@ -0,0 +1,2 @@
+dict_rfc4004_avps
+dict_rfc5447_avps
diff --git a/extensions/dict_rfc5580_avps/CMakeLists.txt b/extensions/dict_rfc5580_avps/CMakeLists.txt
new file mode 100644
index 0000000..f1f5034
--- /dev/null
+++ b/extensions/dict_rfc5580_avps/CMakeLists.txt
@@ -0,0 +1,16 @@
+# The dict_rfc5580_avps extension
+PROJECT("dict_rfc5580_avps library generated by FdGen " C)
+
+# Compile as a module
+FD_ADD_EXTENSION(dict_rfc5580_avps dict_rfc5580_avps.c)
+
+
+####
+## INSTALL section ##
+
+INSTALL(TARGETS dict_rfc5580_avps
+	LIBRARY DESTINATION ${INSTALL_EXTENSIONS_SUFFIX}
+COMPONENT freeDiameter-dictionary-RFC5580_AVPS)
+
+
+
diff --git a/extensions/dict_rfc5580_avps/dict_rfc5580_avps.c b/extensions/dict_rfc5580_avps/dict_rfc5580_avps.c
new file mode 100644
index 0000000..10f55c1
--- /dev/null
+++ b/extensions/dict_rfc5580_avps/dict_rfc5580_avps.c
@@ -0,0 +1,260 @@
+/*
+* Copyright (c) 2017 Sprint
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*    http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+/****************
+ Generated By: fdtool enhancements to diafuzzer
+ License: same as freeDiameter
+****************/
+
+
+/* 
+ * Dictionary definitions of objects specified in rfc5580_avps.
+ */
+#include <freeDiameter/extension.h>
+
+#define PROTO_VER "unspecified"
+#define GEN_DATE  1506697191.32
+
+const char *rfc5580_avps_proto_ver = PROTO_VER;
+const double rfc5580_avps_gen_date = GEN_DATE;
+
+/* The content of this file follows the same structure as dict_base_proto.c */
+
+#define CHECK_dict_new( _type, _data, _parent, _ref )                                     \
+{                                                                                         \
+    int _ret = fd_dict_new( fd_g_config->cnf_dict, (_type), (_data), (_parent), (_ref) ); \
+    if ( _ret != 0 && _ret != EEXIST )                                                    \
+       return _ret;                                                                       \
+}
+
+#define CHECK_dict_search( _type, _criteria, _what, _result )		\
+    CHECK_FCT(  fd_dict_search( fd_g_config->cnf_dict, (_type), (_criteria), (_what), (_result), ENOENT) );
+
+struct local_rules_definition {
+    struct dict_avp_request avp_vendor_plus_name;
+    enum rule_position	position;
+    int 			min;
+    int			max;
+};
+
+#define RULE_ORDER( _position ) ((((_position) == RULE_FIXED_HEAD) || ((_position) == RULE_FIXED_TAIL)) ? 1 : 0 )
+
+/* Attention! This version of the macro uses AVP_BY_NAME_AND_VENDOR, in contrast to most other copies! */
+#define PARSE_loc_rules( _rulearray, _parent) {                                                         \
+        int __ar;                                                                                       \
+        for (__ar=0; __ar < sizeof(_rulearray) / sizeof((_rulearray)[0]); __ar++) {                     \
+                struct dict_rule_data __data = { NULL,                                                  \
+                        (_rulearray)[__ar].position,                                                    \
+                        0,                                                                              \
+                        (_rulearray)[__ar].min,                                                         \
+                        (_rulearray)[__ar].max};                                                        \
+                __data.rule_order = RULE_ORDER(__data.rule_position);                                   \
+                CHECK_FCT(  fd_dict_search(                                                             \
+                        fd_g_config->cnf_dict,                                                          \
+                        DICT_AVP,                                                                       \
+                        AVP_BY_NAME_AND_VENDOR,                                                         \
+                        &(_rulearray)[__ar].avp_vendor_plus_name,                                       \
+                        &__data.rule_avp, 0 ) );                                                        \
+                if ( !__data.rule_avp ) {                                                               \
+                        TRACE_DEBUG(INFO, "AVP Not found: '%s'", (_rulearray)[__ar].avp_vendor_plus_name.avp_name);             \
+                        return ENOENT;                                                                  \
+                }                                                                                       \
+                {                                                                                       \
+                         int _ret = fd_dict_new( fd_g_config->cnf_dict, DICT_RULE, &(__data), (_parent), NULL ); \
+                         if ( _ret != 0 && _ret != EEXIST )      {                                      \
+                                TRACE_DEBUG(INFO, "Error on rule with AVP '%s'",                        \
+                                            (_rulearray)[__ar].avp_vendor_plus_name.avp_name);          \
+                                return EINVAL;                                                          \
+                         }                                                                              \
+                }                                                                                       \
+        }                                                                                               \
+}
+
+#define CHECK_vendor_new( _data ) { \
+        struct dict_object * vendor_found; \
+        if (fd_dict_search(fd_g_config->cnf_dict,DICT_VENDOR,VENDOR_BY_ID,&_data.vendor_id,&vendor_found,ENOENT) == ENOENT) { \
+                CHECK_FCT(fd_dict_new(fd_g_config->cnf_dict, DICT_VENDOR, &_data, NULL, NULL)); \
+        } \
+}
+
+#define enumval_def_u32( _val_, _str_ )		\
+    { _str_, 		{ .u32 = _val_ }}
+
+#define enumval_def_os( _len_, _val_, _str_ )				\
+    { _str_, 		{ .os = { .data = (unsigned char *)_val_, .len = _len_ }}}
+
+
+static int dict_rfc5580_avps_load_defs(char * conffile)
+{
+   TRACE_ENTRY("%p", conffile);
+
+   /* AVP section */
+   {
+		struct dict_object * Address_type;
+		struct dict_object * UTF8String_type;
+		struct dict_object * DiameterIdentity_type;
+		struct dict_object * DiameterURI_type;
+		struct dict_object * Time_type;
+		struct dict_object * IPFilterRule_type;
+
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "Address", &Address_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "UTF8String", &UTF8String_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "DiameterIdentity", &DiameterIdentity_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "DiameterURI", &DiameterURI_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "Time", &Time_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "IPFilterRule", &IPFilterRule_type);
+		/* Operator-Name */
+		{
+			struct dict_avp_data data = {
+				126,	/* Code */
+				0,	/* Vendor */
+				"Operator-Name",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Location-Information */
+		{
+			struct dict_avp_data data = {
+				127,	/* Code */
+				0,	/* Vendor */
+				"Location-Information",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Location-Data */
+		{
+			struct dict_avp_data data = {
+				128,	/* Code */
+				0,	/* Vendor */
+				"Location-Data",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Basic-Location-Policy-Rules */
+		{
+			struct dict_avp_data data = {
+				129,	/* Code */
+				0,	/* Vendor */
+				"Basic-Location-Policy-Rules",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Extended-Location-Policy-Rules */
+		{
+			struct dict_avp_data data = {
+				130,	/* Code */
+				0,	/* Vendor */
+				"Extended-Location-Policy-Rules",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Location-Capable */
+		{
+			struct dict_avp_data data = {
+				131,	/* Code */
+				0,	/* Vendor */
+				"Location-Capable",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Requested-Location-Info */
+		{
+			struct dict_avp_data data = {
+				132,	/* Code */
+				0,	/* Vendor */
+				"Requested-Location-Info",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Error-Cause */
+		{
+			struct dict_avp_data data = {
+				101,	/* Code */
+				0,	/* Vendor */
+				"Error-Cause",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+
+	
+   }
+
+   /* Commands section */
+   {
+
+   }
+
+   return 0;
+}
+
+static int dict_rfc5580_avps_load_rules(char * conffile)
+{
+   /* Grouped AVP section */
+   {
+
+   }	
+
+   /* Commands section */
+   {
+
+   }
+
+   LOG_D( "Extension 'Dictionary definitions for rfc5580_avps (None)' initialized");
+   return 0;
+}
+
+int dict_entry(char * conffile)
+{
+	dict_rfc5580_avps_load_defs(conffile);
+	return dict_rfc5580_avps_load_rules(conffile);
+}
+
+const char* dict_rfc5580_avps_proto_ver(char * conffile) {
+	return rfc5580_avps_proto_ver;
+}
+
+const double dict_rfc5580_avps_gen_ts(char * conffile) {
+	return rfc5580_avps_gen_date;
+}
+
+EXTENSION_ENTRY2("dict_rfc5580_avps", dict_rfc5580_avps_load_defs, dict_rfc5580_avps_load_rules);
+
+
+
diff --git a/extensions/dict_rfc5580_avps/rfc5580_avps.did b/extensions/dict_rfc5580_avps/rfc5580_avps.did
new file mode 100644
index 0000000..40ca6fb
--- /dev/null
+++ b/extensions/dict_rfc5580_avps/rfc5580_avps.did
@@ -0,0 +1 @@
+dict_rfc5580_avps
diff --git a/extensions/dict_rfc5777_avps/CMakeLists.txt b/extensions/dict_rfc5777_avps/CMakeLists.txt
new file mode 100644
index 0000000..d0573c4
--- /dev/null
+++ b/extensions/dict_rfc5777_avps/CMakeLists.txt
@@ -0,0 +1,16 @@
+# The dict_rfc5777_avps extension
+PROJECT("dict_rfc5777_avps library generated by FdGen " C)
+
+# Compile as a module
+FD_ADD_EXTENSION(dict_rfc5777_avps dict_rfc5777_avps.c)
+
+
+####
+## INSTALL section ##
+
+INSTALL(TARGETS dict_rfc5777_avps
+	LIBRARY DESTINATION ${INSTALL_EXTENSIONS_SUFFIX}
+COMPONENT freeDiameter-dictionary-RFC5777_AVPS)
+
+
+
diff --git a/extensions/dict_rfc5777_avps/dict_rfc5777_avps.c b/extensions/dict_rfc5777_avps/dict_rfc5777_avps.c
new file mode 100644
index 0000000..f287963
--- /dev/null
+++ b/extensions/dict_rfc5777_avps/dict_rfc5777_avps.c
@@ -0,0 +1,2077 @@
+/*
+* Copyright (c) 2017 Sprint
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*    http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+/****************
+ Generated By: fdtool enhancements to diafuzzer
+ License: same as freeDiameter
+****************/
+
+
+/* 
+ * Dictionary definitions of objects specified in rfc5777_avps.
+ */
+#include <freeDiameter/extension.h>
+
+#define PROTO_VER "unspecified"
+#define GEN_DATE  1506697143.56
+
+const char *rfc5777_avps_proto_ver = PROTO_VER;
+const double rfc5777_avps_gen_date = GEN_DATE;
+
+/* The content of this file follows the same structure as dict_base_proto.c */
+
+#define CHECK_dict_new( _type, _data, _parent, _ref )                                     \
+{                                                                                         \
+    int _ret = fd_dict_new( fd_g_config->cnf_dict, (_type), (_data), (_parent), (_ref) ); \
+    if ( _ret != 0 && _ret != EEXIST )                                                    \
+       return _ret;                                                                       \
+}
+
+#define CHECK_dict_search( _type, _criteria, _what, _result )		\
+    CHECK_FCT(  fd_dict_search( fd_g_config->cnf_dict, (_type), (_criteria), (_what), (_result), ENOENT) );
+
+struct local_rules_definition {
+    struct dict_avp_request avp_vendor_plus_name;
+    enum rule_position	position;
+    int 			min;
+    int			max;
+};
+
+#define RULE_ORDER( _position ) ((((_position) == RULE_FIXED_HEAD) || ((_position) == RULE_FIXED_TAIL)) ? 1 : 0 )
+
+/* Attention! This version of the macro uses AVP_BY_NAME_AND_VENDOR, in contrast to most other copies! */
+#define PARSE_loc_rules( _rulearray, _parent) {                                                         \
+        int __ar;                                                                                       \
+        for (__ar=0; __ar < sizeof(_rulearray) / sizeof((_rulearray)[0]); __ar++) {                     \
+                struct dict_rule_data __data = { NULL,                                                  \
+                        (_rulearray)[__ar].position,                                                    \
+                        0,                                                                              \
+                        (_rulearray)[__ar].min,                                                         \
+                        (_rulearray)[__ar].max};                                                        \
+                __data.rule_order = RULE_ORDER(__data.rule_position);                                   \
+                CHECK_FCT(  fd_dict_search(                                                             \
+                        fd_g_config->cnf_dict,                                                          \
+                        DICT_AVP,                                                                       \
+                        AVP_BY_NAME_AND_VENDOR,                                                         \
+                        &(_rulearray)[__ar].avp_vendor_plus_name,                                       \
+                        &__data.rule_avp, 0 ) );                                                        \
+                if ( !__data.rule_avp ) {                                                               \
+                        TRACE_DEBUG(INFO, "AVP Not found: '%s'", (_rulearray)[__ar].avp_vendor_plus_name.avp_name);             \
+                        return ENOENT;                                                                  \
+                }                                                                                       \
+                {                                                                                       \
+                         int _ret = fd_dict_new( fd_g_config->cnf_dict, DICT_RULE, &(__data), (_parent), NULL ); \
+                         if ( _ret != 0 && _ret != EEXIST )      {                                      \
+                                TRACE_DEBUG(INFO, "Error on rule with AVP '%s'",                        \
+                                            (_rulearray)[__ar].avp_vendor_plus_name.avp_name);          \
+                                return EINVAL;                                                          \
+                         }                                                                              \
+                }                                                                                       \
+        }                                                                                               \
+}
+
+#define CHECK_vendor_new( _data ) { \
+        struct dict_object * vendor_found; \
+        if (fd_dict_search(fd_g_config->cnf_dict,DICT_VENDOR,VENDOR_BY_ID,&_data.vendor_id,&vendor_found,ENOENT) == ENOENT) { \
+                CHECK_FCT(fd_dict_new(fd_g_config->cnf_dict, DICT_VENDOR, &_data, NULL, NULL)); \
+        } \
+}
+
+#define enumval_def_u32( _val_, _str_ )		\
+    { _str_, 		{ .u32 = _val_ }}
+
+#define enumval_def_os( _len_, _val_, _str_ )				\
+    { _str_, 		{ .os = { .data = (unsigned char *)_val_, .len = _len_ }}}
+
+
+static int dict_rfc5777_avps_load_defs(char * conffile)
+{
+   TRACE_ENTRY("%p", conffile);
+
+   /* AVP section */
+   {
+		struct dict_object * Address_type;
+		struct dict_object * UTF8String_type;
+		struct dict_object * DiameterIdentity_type;
+		struct dict_object * DiameterURI_type;
+		struct dict_object * Time_type;
+		struct dict_object * IPFilterRule_type;
+
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "Address", &Address_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "UTF8String", &UTF8String_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "DiameterIdentity", &DiameterIdentity_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "DiameterURI", &DiameterURI_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "Time", &Time_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "IPFilterRule", &IPFilterRule_type);
+		/* Filter-Rule-Precedence */
+		{
+			struct dict_avp_data data = {
+				510,	/* Code */
+				0,	/* Vendor */
+				"Filter-Rule-Precedence",	/* Name */
+				0,	/* Fixed flags */
+				0,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Classifier-ID */
+		{
+			struct dict_avp_data data = {
+				512,	/* Code */
+				0,	/* Vendor */
+				"Classifier-ID",	/* Name */
+				0,	/* Fixed flags */
+				0,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Protocol */
+		{
+			struct dict_avp_data data = {
+				513,	/* Code */
+				0,	/* Vendor */
+				"Protocol",	/* Name */
+				0,	/* Fixed flags */
+				0,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "Enumerated(Protocol)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "HOPOPT", { .i32=0 }};
+			struct dict_enumval_data        t_2 = { "ICMP", { .i32=1 }};
+			struct dict_enumval_data        t_3 = { "IGMP", { .i32=2 }};
+			struct dict_enumval_data        t_4 = { "GGP", { .i32=3 }};
+			struct dict_enumval_data        t_5 = { "IPv4", { .i32=4 }};
+			struct dict_enumval_data        t_6 = { "ST", { .i32=5 }};
+			struct dict_enumval_data        t_7 = { "TCP", { .i32=6 }};
+			struct dict_enumval_data        t_8 = { "CBT", { .i32=7 }};
+			struct dict_enumval_data        t_9 = { "EGP", { .i32=8 }};
+			struct dict_enumval_data        t_10 = { "IGP", { .i32=9 }};
+			struct dict_enumval_data        t_11 = { "BBN-RCC-MON", { .i32=10 }};
+			struct dict_enumval_data        t_12 = { "NVP-II", { .i32=11 }};
+			struct dict_enumval_data        t_13 = { "PUP", { .i32=12 }};
+			struct dict_enumval_data        t_14 = { "ARGUS", { .i32=13 }};
+			struct dict_enumval_data        t_15 = { "EMCON", { .i32=14 }};
+			struct dict_enumval_data        t_16 = { "XNET", { .i32=15 }};
+			struct dict_enumval_data        t_17 = { "CHAOS", { .i32=16 }};
+			struct dict_enumval_data        t_18 = { "UDP", { .i32=17 }};
+			struct dict_enumval_data        t_19 = { "MUX", { .i32=18 }};
+			struct dict_enumval_data        t_20 = { "DCN-MEAS", { .i32=19 }};
+			struct dict_enumval_data        t_21 = { "HMP", { .i32=20 }};
+			struct dict_enumval_data        t_22 = { "PRM", { .i32=21 }};
+			struct dict_enumval_data        t_23 = { "XNS-IDP", { .i32=22 }};
+			struct dict_enumval_data        t_24 = { "TRUNK-1", { .i32=23 }};
+			struct dict_enumval_data        t_25 = { "TRUNK-2", { .i32=24 }};
+			struct dict_enumval_data        t_26 = { "LEAF-1", { .i32=25 }};
+			struct dict_enumval_data        t_27 = { "LEAF-2", { .i32=26 }};
+			struct dict_enumval_data        t_28 = { "RDP", { .i32=27 }};
+			struct dict_enumval_data        t_29 = { "IRTP", { .i32=28 }};
+			struct dict_enumval_data        t_30 = { "ISO-TP4", { .i32=29 }};
+			struct dict_enumval_data        t_31 = { "NETBLT", { .i32=30 }};
+			struct dict_enumval_data        t_32 = { "MFE-NSP", { .i32=31 }};
+			struct dict_enumval_data        t_33 = { "MERIT-INP", { .i32=32 }};
+			struct dict_enumval_data        t_34 = { "DCCP", { .i32=33 }};
+			struct dict_enumval_data        t_35 = { "3PC", { .i32=34 }};
+			struct dict_enumval_data        t_36 = { "IDPR", { .i32=35 }};
+			struct dict_enumval_data        t_37 = { "XTP", { .i32=36 }};
+			struct dict_enumval_data        t_38 = { "DDP", { .i32=37 }};
+			struct dict_enumval_data        t_39 = { "IDPR-CMTP", { .i32=38 }};
+			struct dict_enumval_data        t_40 = { "TPplusplus", { .i32=39 }};
+			struct dict_enumval_data        t_41 = { "IL", { .i32=40 }};
+			struct dict_enumval_data        t_42 = { "IPv6", { .i32=41 }};
+			struct dict_enumval_data        t_43 = { "SDRP", { .i32=42 }};
+			struct dict_enumval_data        t_44 = { "IPv6-Route", { .i32=43 }};
+			struct dict_enumval_data        t_45 = { "IPv6-Frag", { .i32=44 }};
+			struct dict_enumval_data        t_46 = { "IDRP", { .i32=45 }};
+			struct dict_enumval_data        t_47 = { "RSVP", { .i32=46 }};
+			struct dict_enumval_data        t_48 = { "GRE", { .i32=47 }};
+			struct dict_enumval_data        t_49 = { "DSR", { .i32=48 }};
+			struct dict_enumval_data        t_50 = { "BNA", { .i32=49 }};
+			struct dict_enumval_data        t_51 = { "ESP", { .i32=50 }};
+			struct dict_enumval_data        t_52 = { "AH", { .i32=51 }};
+			struct dict_enumval_data        t_53 = { "I-NLSP", { .i32=52 }};
+			struct dict_enumval_data        t_54 = { "SWIPE", { .i32=53 }};
+			struct dict_enumval_data        t_55 = { "NARP", { .i32=54 }};
+			struct dict_enumval_data        t_56 = { "MOBILE", { .i32=55 }};
+			struct dict_enumval_data        t_57 = { "TLSP", { .i32=56 }};
+			struct dict_enumval_data        t_58 = { "SKIP", { .i32=57 }};
+			struct dict_enumval_data        t_59 = { "IPv6-ICMP", { .i32=58 }};
+			struct dict_enumval_data        t_60 = { "IPv6-NoNxt", { .i32=59 }};
+			struct dict_enumval_data        t_61 = { "IPv6-Opts", { .i32=60 }};
+			struct dict_enumval_data        t_62 = { "CFTP", { .i32=62 }};
+			struct dict_enumval_data        t_63 = { "SAT-EXPAK", { .i32=64 }};
+			struct dict_enumval_data        t_64 = { "KRYPTOLAN", { .i32=65 }};
+			struct dict_enumval_data        t_65 = { "RVD", { .i32=66 }};
+			struct dict_enumval_data        t_66 = { "IPPC", { .i32=67 }};
+			struct dict_enumval_data        t_67 = { "SAT-MON", { .i32=69 }};
+			struct dict_enumval_data        t_68 = { "VISA", { .i32=70 }};
+			struct dict_enumval_data        t_69 = { "IPCV", { .i32=71 }};
+			struct dict_enumval_data        t_70 = { "CPNX", { .i32=72 }};
+			struct dict_enumval_data        t_71 = { "CPHB", { .i32=73 }};
+			struct dict_enumval_data        t_72 = { "WSN", { .i32=74 }};
+			struct dict_enumval_data        t_73 = { "PVP", { .i32=75 }};
+			struct dict_enumval_data        t_74 = { "BR-SAT-MON", { .i32=76 }};
+			struct dict_enumval_data        t_75 = { "SUN-ND", { .i32=77 }};
+			struct dict_enumval_data        t_76 = { "WB-MON", { .i32=78 }};
+			struct dict_enumval_data        t_77 = { "WB-EXPAK", { .i32=79 }};
+			struct dict_enumval_data        t_78 = { "ISO-IP", { .i32=80 }};
+			struct dict_enumval_data        t_79 = { "VMTP", { .i32=81 }};
+			struct dict_enumval_data        t_80 = { "SECURE-VMTP", { .i32=82 }};
+			struct dict_enumval_data        t_81 = { "VINES", { .i32=83 }};
+			struct dict_enumval_data        t_82 = { "TTP", { .i32=84 }};
+			struct dict_enumval_data        t_83 = { "IPTM", { .i32=84 }};
+			struct dict_enumval_data        t_84 = { "NSFNET-IGP", { .i32=85 }};
+			struct dict_enumval_data        t_85 = { "DGP", { .i32=86 }};
+			struct dict_enumval_data        t_86 = { "TCF", { .i32=87 }};
+			struct dict_enumval_data        t_87 = { "EIGRP", { .i32=88 }};
+			struct dict_enumval_data        t_88 = { "OSPFIGP", { .i32=89 }};
+			struct dict_enumval_data        t_89 = { "Sprite-RPC", { .i32=90 }};
+			struct dict_enumval_data        t_90 = { "LARP", { .i32=91 }};
+			struct dict_enumval_data        t_91 = { "MTP", { .i32=92 }};
+			struct dict_enumval_data        t_92 = { "AX_25", { .i32=93 }};
+			struct dict_enumval_data        t_93 = { "IPIP", { .i32=94 }};
+			struct dict_enumval_data        t_94 = { "MICP", { .i32=95 }};
+			struct dict_enumval_data        t_95 = { "SCC-SP", { .i32=96 }};
+			struct dict_enumval_data        t_96 = { "ETHERIP", { .i32=97 }};
+			struct dict_enumval_data        t_97 = { "ENCAP", { .i32=98 }};
+			struct dict_enumval_data        t_98 = { "GMTP", { .i32=100 }};
+			struct dict_enumval_data        t_99 = { "IFMP", { .i32=101 }};
+			struct dict_enumval_data        t_100 = { "PNNI", { .i32=102 }};
+			struct dict_enumval_data        t_101 = { "PIM", { .i32=103 }};
+			struct dict_enumval_data        t_102 = { "ARIS", { .i32=104 }};
+			struct dict_enumval_data        t_103 = { "SCPS", { .i32=105 }};
+			struct dict_enumval_data        t_104 = { "QNX", { .i32=106 }};
+			struct dict_enumval_data        t_105 = { "A_N", { .i32=107 }};
+			struct dict_enumval_data        t_106 = { "IPComp", { .i32=108 }};
+			struct dict_enumval_data        t_107 = { "SNP", { .i32=109 }};
+			struct dict_enumval_data        t_108 = { "Compaq-Peer", { .i32=110 }};
+			struct dict_enumval_data        t_109 = { "IPX-in-IP", { .i32=111 }};
+			struct dict_enumval_data        t_110 = { "VRRP", { .i32=112 }};
+			struct dict_enumval_data        t_111 = { "PGM", { .i32=113 }};
+			struct dict_enumval_data        t_112 = { "L2TP", { .i32=115 }};
+			struct dict_enumval_data        t_113 = { "DDX", { .i32=116 }};
+			struct dict_enumval_data        t_114 = { "IATP", { .i32=117 }};
+			struct dict_enumval_data        t_115 = { "STP", { .i32=118 }};
+			struct dict_enumval_data        t_116 = { "SRP", { .i32=119 }};
+			struct dict_enumval_data        t_117 = { "UTI", { .i32=120 }};
+			struct dict_enumval_data        t_118 = { "SMP", { .i32=121 }};
+			struct dict_enumval_data        t_119 = { "SM", { .i32=122 }};
+			struct dict_enumval_data        t_120 = { "PTP", { .i32=123 }};
+			struct dict_enumval_data        t_121 = { "ISISoverIPv4", { .i32=124 }};
+			struct dict_enumval_data        t_122 = { "FIRE", { .i32=125 }};
+			struct dict_enumval_data        t_123 = { "CRTP", { .i32=126 }};
+			struct dict_enumval_data        t_124 = { "CRUDP", { .i32=127 }};
+			struct dict_enumval_data        t_125 = { "SSCOPMCE", { .i32=128 }};
+			struct dict_enumval_data        t_126 = { "IPLT", { .i32=129 }};
+			struct dict_enumval_data        t_127 = { "SPS", { .i32=130 }};
+			struct dict_enumval_data        t_128 = { "PIPE", { .i32=131 }};
+			struct dict_enumval_data        t_129 = { "SCTP", { .i32=132 }};
+			struct dict_enumval_data        t_130 = { "FC", { .i32=133 }};
+			struct dict_enumval_data        t_131 = { "RSVP-E2E-IGNORE", { .i32=134 }};
+			struct dict_enumval_data        t_132 = { "MobilityHeader", { .i32=135 }};
+			struct dict_enumval_data        t_133 = { "UDPLite", { .i32=136 }};
+			struct dict_enumval_data        t_134 = { "MPLS-in-IP", { .i32=137 }};
+			struct dict_enumval_data        t_135 = { "manet", { .i32=138 }};
+			struct dict_enumval_data        t_136 = { "HIP", { .i32=139 }};
+			struct dict_enumval_data        t_137 = { "Shim6", { .i32=140 }};
+			struct dict_enumval_data        t_138 = { "WESP", { .i32=141 }};
+			struct dict_enumval_data        t_139 = { "ROHC", { .i32=142 }};
+			struct dict_enumval_data        t_140 = { "Reserved", { .i32=255 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_3, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_4, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_5, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_6, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_7, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_8, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_9, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_10, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_11, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_12, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_13, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_14, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_15, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_16, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_17, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_18, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_19, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_20, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_21, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_22, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_23, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_24, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_25, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_26, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_27, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_28, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_29, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_30, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_31, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_32, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_33, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_34, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_35, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_36, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_37, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_38, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_39, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_40, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_41, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_42, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_43, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_44, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_45, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_46, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_47, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_48, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_49, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_50, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_51, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_52, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_53, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_54, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_55, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_56, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_57, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_58, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_59, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_60, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_61, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_62, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_63, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_64, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_65, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_66, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_67, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_68, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_69, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_70, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_71, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_72, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_73, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_74, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_75, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_76, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_77, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_78, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_79, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_80, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_81, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_82, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_83, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_84, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_85, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_86, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_87, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_88, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_89, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_90, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_91, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_92, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_93, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_94, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_95, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_96, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_97, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_98, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_99, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_100, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_101, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_102, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_103, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_104, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_105, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_106, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_107, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_108, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_109, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_110, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_111, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_112, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_113, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_114, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_115, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_116, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_117, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_118, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_119, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_120, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_121, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_122, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_123, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_124, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_125, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_126, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_127, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_128, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_129, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_130, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_131, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_132, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_133, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_134, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_135, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_136, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_137, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_138, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_139, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_140, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* Direction */
+		{
+			struct dict_avp_data data = {
+				514,	/* Code */
+				0,	/* Vendor */
+				"Direction",	/* Name */
+				0,	/* Fixed flags */
+				0,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "Enumerated(Direction)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "IN", { .i32=0 }};
+			struct dict_enumval_data        t_2 = { "OUT", { .i32=1 }};
+			struct dict_enumval_data        t_3 = { "BOTH", { .i32=2 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_3, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* Negated */
+		{
+			struct dict_avp_data data = {
+				517,	/* Code */
+				0,	/* Vendor */
+				"Negated",	/* Name */
+				0,	/* Fixed flags */
+				0,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "Enumerated(Negated)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "False", { .i32=0 }};
+			struct dict_enumval_data        t_2 = { "True", { .i32=1 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* IP-Address */
+		{
+			struct dict_avp_data data = {
+				518,	/* Code */
+				0,	/* Vendor */
+				"IP-Address",	/* Name */
+				0,	/* Fixed flags */
+				0,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, Address_type, NULL);
+		};
+		/* IP-Address-Start */
+		{
+			struct dict_avp_data data = {
+				520,	/* Code */
+				0,	/* Vendor */
+				"IP-Address-Start",	/* Name */
+				0,	/* Fixed flags */
+				0,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, Address_type, NULL);
+		};
+		/* IP-Address-End */
+		{
+			struct dict_avp_data data = {
+				521,	/* Code */
+				0,	/* Vendor */
+				"IP-Address-End",	/* Name */
+				0,	/* Fixed flags */
+				0,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, Address_type, NULL);
+		};
+		/* IP-Bit-Mask-Width */
+		{
+			struct dict_avp_data data = {
+				523,	/* Code */
+				0,	/* Vendor */
+				"IP-Bit-Mask-Width",	/* Name */
+				0,	/* Fixed flags */
+				0,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* MAC-Address */
+		{
+			struct dict_avp_data data = {
+				524,	/* Code */
+				0,	/* Vendor */
+				"MAC-Address",	/* Name */
+				0,	/* Fixed flags */
+				0,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* MAC-Address-Mask-Pattern */
+		{
+			struct dict_avp_data data = {
+				526,	/* Code */
+				0,	/* Vendor */
+				"MAC-Address-Mask-Pattern",	/* Name */
+				0,	/* Fixed flags */
+				0,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* EUI64-Address */
+		{
+			struct dict_avp_data data = {
+				527,	/* Code */
+				0,	/* Vendor */
+				"EUI64-Address",	/* Name */
+				0,	/* Fixed flags */
+				0,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* EUI64-Address-Mask-Pattern */
+		{
+			struct dict_avp_data data = {
+				529,	/* Code */
+				0,	/* Vendor */
+				"EUI64-Address-Mask-Pattern",	/* Name */
+				0,	/* Fixed flags */
+				0,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Port */
+		{
+			struct dict_avp_data data = {
+				530,	/* Code */
+				0,	/* Vendor */
+				"Port",	/* Name */
+				0,	/* Fixed flags */
+				0,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Port-Start */
+		{
+			struct dict_avp_data data = {
+				532,	/* Code */
+				0,	/* Vendor */
+				"Port-Start",	/* Name */
+				0,	/* Fixed flags */
+				0,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Port-End */
+		{
+			struct dict_avp_data data = {
+				533,	/* Code */
+				0,	/* Vendor */
+				"Port-End",	/* Name */
+				0,	/* Fixed flags */
+				0,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Use-Assigned-Address */
+		{
+			struct dict_avp_data data = {
+				534,	/* Code */
+				0,	/* Vendor */
+				"Use-Assigned-Address",	/* Name */
+				0,	/* Fixed flags */
+				0,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "Enumerated(Use-Assigned-Address)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "False", { .i32=0 }};
+			struct dict_enumval_data        t_2 = { "True", { .i32=1 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* Diffserv-Code-Point */
+		{
+			struct dict_avp_data data = {
+				535,	/* Code */
+				0,	/* Vendor */
+				"Diffserv-Code-Point",	/* Name */
+				0,	/* Fixed flags */
+				0,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "Enumerated(Diffserv-Code-Point)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "CS0", { .i32=0 }};
+			struct dict_enumval_data        t_2 = { "CS1", { .i32=8 }};
+			struct dict_enumval_data        t_3 = { "CS2", { .i32=16 }};
+			struct dict_enumval_data        t_4 = { "CS3", { .i32=24 }};
+			struct dict_enumval_data        t_5 = { "CS4", { .i32=32 }};
+			struct dict_enumval_data        t_6 = { "CS5", { .i32=40 }};
+			struct dict_enumval_data        t_7 = { "CS6", { .i32=48 }};
+			struct dict_enumval_data        t_8 = { "CS7", { .i32=56 }};
+			struct dict_enumval_data        t_9 = { "AF11", { .i32=10 }};
+			struct dict_enumval_data        t_10 = { "AF12", { .i32=12 }};
+			struct dict_enumval_data        t_11 = { "AF13", { .i32=14 }};
+			struct dict_enumval_data        t_12 = { "AF21", { .i32=18 }};
+			struct dict_enumval_data        t_13 = { "AF22", { .i32=20 }};
+			struct dict_enumval_data        t_14 = { "AF23", { .i32=22 }};
+			struct dict_enumval_data        t_15 = { "AF31", { .i32=26 }};
+			struct dict_enumval_data        t_16 = { "AF32", { .i32=28 }};
+			struct dict_enumval_data        t_17 = { "AF33", { .i32=30 }};
+			struct dict_enumval_data        t_18 = { "AF41", { .i32=34 }};
+			struct dict_enumval_data        t_19 = { "AF42", { .i32=36 }};
+			struct dict_enumval_data        t_20 = { "AF43", { .i32=38 }};
+			struct dict_enumval_data        t_21 = { "EF", { .i32=46 }};
+			struct dict_enumval_data        t_22 = { "VOICE_ADMIT", { .i32=44 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_3, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_4, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_5, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_6, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_7, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_8, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_9, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_10, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_11, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_12, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_13, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_14, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_15, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_16, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_17, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_18, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_19, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_20, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_21, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_22, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* Fragmentation-Flag */
+		{
+			struct dict_avp_data data = {
+				536,	/* Code */
+				0,	/* Vendor */
+				"Fragmentation-Flag",	/* Name */
+				0,	/* Fixed flags */
+				0,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "Enumerated(Fragmentation-Flag)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "DF", { .i32=0 }};
+			struct dict_enumval_data        t_2 = { "MF", { .i32=1 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* IP-Option-Type */
+		{
+			struct dict_avp_data data = {
+				538,	/* Code */
+				0,	/* Vendor */
+				"IP-Option-Type",	/* Name */
+				0,	/* Fixed flags */
+				0,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "Enumerated(IP-Option-Type)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "EOOL", { .i32=0 }};
+			struct dict_enumval_data        t_2 = { "NOP", { .i32=1 }};
+			struct dict_enumval_data        t_3 = { "SEC", { .i32=2 }};
+			struct dict_enumval_data        t_4 = { "LSR", { .i32=3 }};
+			struct dict_enumval_data        t_5 = { "TS", { .i32=4 }};
+			struct dict_enumval_data        t_6 = { "E-SEC", { .i32=5 }};
+			struct dict_enumval_data        t_7 = { "CIPSO", { .i32=6 }};
+			struct dict_enumval_data        t_8 = { "RR", { .i32=7 }};
+			struct dict_enumval_data        t_9 = { "SID", { .i32=8 }};
+			struct dict_enumval_data        t_10 = { "SSR", { .i32=9 }};
+			struct dict_enumval_data        t_11 = { "ZSU", { .i32=10 }};
+			struct dict_enumval_data        t_12 = { "MTUP", { .i32=11 }};
+			struct dict_enumval_data        t_13 = { "MTUR", { .i32=12 }};
+			struct dict_enumval_data        t_14 = { "FINN", { .i32=13 }};
+			struct dict_enumval_data        t_15 = { "VISA", { .i32=14 }};
+			struct dict_enumval_data        t_16 = { "ENCODE", { .i32=15 }};
+			struct dict_enumval_data        t_17 = { "IMITD", { .i32=16 }};
+			struct dict_enumval_data        t_18 = { "EIP", { .i32=17 }};
+			struct dict_enumval_data        t_19 = { "TR", { .i32=18 }};
+			struct dict_enumval_data        t_20 = { "ADDEXT", { .i32=19 }};
+			struct dict_enumval_data        t_21 = { "RTRALT", { .i32=20 }};
+			struct dict_enumval_data        t_22 = { "SDB", { .i32=21 }};
+			struct dict_enumval_data        t_23 = { "DPS", { .i32=23 }};
+			struct dict_enumval_data        t_24 = { "UMP", { .i32=24 }};
+			struct dict_enumval_data        t_25 = { "QS", { .i32=25 }};
+			struct dict_enumval_data        t_26 = { "EXP", { .i32=30 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_3, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_4, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_5, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_6, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_7, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_8, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_9, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_10, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_11, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_12, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_13, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_14, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_15, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_16, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_17, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_18, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_19, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_20, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_21, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_22, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_23, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_24, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_25, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_26, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* IP-Option-Value */
+		{
+			struct dict_avp_data data = {
+				539,	/* Code */
+				0,	/* Vendor */
+				"IP-Option-Value",	/* Name */
+				0,	/* Fixed flags */
+				0,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* TCP-Option-Type */
+		{
+			struct dict_avp_data data = {
+				541,	/* Code */
+				0,	/* Vendor */
+				"TCP-Option-Type",	/* Name */
+				0,	/* Fixed flags */
+				0,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "Enumerated(TCP-Option-Type)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "EOL", { .i32=0 }};
+			struct dict_enumval_data        t_2 = { "NOP", { .i32=1 }};
+			struct dict_enumval_data        t_3 = { "MAX_SEG_SZ", { .i32=2 }};
+			struct dict_enumval_data        t_4 = { "Window_Scale", { .i32=3 }};
+			struct dict_enumval_data        t_5 = { "SACK_Permitted", { .i32=4 }};
+			struct dict_enumval_data        t_6 = { "SACK", { .i32=5 }};
+			struct dict_enumval_data        t_7 = { "Echo", { .i32=6 }};
+			struct dict_enumval_data        t_8 = { "Echo_Reply", { .i32=7 }};
+			struct dict_enumval_data        t_9 = { "Timestamps", { .i32=8 }};
+			struct dict_enumval_data        t_10 = { "PartialOrderConnectionPermitted", { .i32=9 }};
+			struct dict_enumval_data        t_11 = { "PartialOrderServiceProfile", { .i32=10 }};
+			struct dict_enumval_data        t_12 = { "CC", { .i32=11 }};
+			struct dict_enumval_data        t_13 = { "CC_NEW", { .i32=12 }};
+			struct dict_enumval_data        t_14 = { "CC_ECHO", { .i32=13 }};
+			struct dict_enumval_data        t_15 = { "TCP_Alternate_Checksum_Request", { .i32=14 }};
+			struct dict_enumval_data        t_16 = { "TCP_Alternate_Checksum_Data", { .i32=15 }};
+			struct dict_enumval_data        t_17 = { "Skeeter", { .i32=16 }};
+			struct dict_enumval_data        t_18 = { "Bubba", { .i32=17 }};
+			struct dict_enumval_data        t_19 = { "Trailer_Checksum_Option", { .i32=18 }};
+			struct dict_enumval_data        t_20 = { "MD5_Signature_Option", { .i32=19 }};
+			struct dict_enumval_data        t_21 = { "SCPS_Capabilities", { .i32=20 }};
+			struct dict_enumval_data        t_22 = { "Selective_Negative_Acknowledgements", { .i32=21 }};
+			struct dict_enumval_data        t_23 = { "Record_Boundaries", { .i32=22 }};
+			struct dict_enumval_data        t_24 = { "Corruption_experienced", { .i32=23 }};
+			struct dict_enumval_data        t_25 = { "SNAP", { .i32=24 }};
+			struct dict_enumval_data        t_26 = { "TCP_Compression_Filter", { .i32=26 }};
+			struct dict_enumval_data        t_27 = { "Quick-Start_Response", { .i32=27 }};
+			struct dict_enumval_data        t_28 = { "User_Timeout_Option", { .i32=28 }};
+			struct dict_enumval_data        t_29 = { "TCP_Authentication_Option", { .i32=29 }};
+			struct dict_enumval_data        t_30 = { "Multipath_TCP", { .i32=30 }};
+			struct dict_enumval_data        t_31 = { "Reserved1", { .i32=31 }};
+			struct dict_enumval_data        t_32 = { "Reserved2", { .i32=32 }};
+			struct dict_enumval_data        t_33 = { "Reserved3", { .i32=33 }};
+			struct dict_enumval_data        t_34 = { "TCP_Fast_Open_Cookie", { .i32=34 }};
+			struct dict_enumval_data        t_35 = { "Reserved4", { .i32=69 }};
+			struct dict_enumval_data        t_36 = { "Reserved5", { .i32=70 }};
+			struct dict_enumval_data        t_37 = { "Reserved6", { .i32=76 }};
+			struct dict_enumval_data        t_38 = { "Reserved7", { .i32=77 }};
+			struct dict_enumval_data        t_39 = { "Reserved8", { .i32=78 }};
+			struct dict_enumval_data        t_40 = { "RFC3692-style_Experiment_1", { .i32=253 }};
+			struct dict_enumval_data        t_41 = { "RFC3692-style_Experiment_2", { .i32=254 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_3, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_4, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_5, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_6, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_7, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_8, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_9, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_10, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_11, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_12, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_13, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_14, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_15, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_16, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_17, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_18, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_19, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_20, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_21, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_22, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_23, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_24, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_25, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_26, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_27, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_28, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_29, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_30, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_31, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_32, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_33, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_34, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_35, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_36, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_37, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_38, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_39, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_40, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_41, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* TCP-Option-Value */
+		{
+			struct dict_avp_data data = {
+				542,	/* Code */
+				0,	/* Vendor */
+				"TCP-Option-Value",	/* Name */
+				0,	/* Fixed flags */
+				0,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* TCP-Flag-Type */
+		{
+			struct dict_avp_data data = {
+				544,	/* Code */
+				0,	/* Vendor */
+				"TCP-Flag-Type",	/* Name */
+				0,	/* Fixed flags */
+				0,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* ICMP-Type-Number */
+		{
+			struct dict_avp_data data = {
+				546,	/* Code */
+				0,	/* Vendor */
+				"ICMP-Type-Number",	/* Name */
+				0,	/* Fixed flags */
+				0,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "Enumerated(ICMP-Type-Number)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "Echo_Reply", { .i32=0 }};
+			struct dict_enumval_data        t_2 = { "Destination_Unreachable", { .i32=3 }};
+			struct dict_enumval_data        t_3 = { "Source_Quench", { .i32=4 }};
+			struct dict_enumval_data        t_4 = { "Redirect", { .i32=5 }};
+			struct dict_enumval_data        t_5 = { "Alternate_Host_Address", { .i32=6 }};
+			struct dict_enumval_data        t_6 = { "Echo", { .i32=8 }};
+			struct dict_enumval_data        t_7 = { "Router_Advertisement", { .i32=9 }};
+			struct dict_enumval_data        t_8 = { "Router_Solicitation", { .i32=10 }};
+			struct dict_enumval_data        t_9 = { "Time_Exceeded", { .i32=11 }};
+			struct dict_enumval_data        t_10 = { "Parameter_Problem", { .i32=12 }};
+			struct dict_enumval_data        t_11 = { "Timestamp", { .i32=13 }};
+			struct dict_enumval_data        t_12 = { "Timestamp_Reply", { .i32=14 }};
+			struct dict_enumval_data        t_13 = { "Information_Request", { .i32=15 }};
+			struct dict_enumval_data        t_14 = { "Information_Reply", { .i32=16 }};
+			struct dict_enumval_data        t_15 = { "Address_Mask_Request", { .i32=17 }};
+			struct dict_enumval_data        t_16 = { "Address_Mask_Reply", { .i32=18 }};
+			struct dict_enumval_data        t_17 = { "Traceroute", { .i32=30 }};
+			struct dict_enumval_data        t_18 = { "Datagram_Conversion_Error", { .i32=31 }};
+			struct dict_enumval_data        t_19 = { "Mobile_Host_Redirect", { .i32=32 }};
+			struct dict_enumval_data        t_20 = { "IPv6_Where-Are-You", { .i32=33 }};
+			struct dict_enumval_data        t_21 = { "IPv6_I-Am-Here", { .i32=34 }};
+			struct dict_enumval_data        t_22 = { "Mobile_Registration_Request", { .i32=35 }};
+			struct dict_enumval_data        t_23 = { "Mobile_Registration_Reply", { .i32=36 }};
+			struct dict_enumval_data        t_24 = { "Domain_Name_Request", { .i32=37 }};
+			struct dict_enumval_data        t_25 = { "Domain_Name_Reply", { .i32=38 }};
+			struct dict_enumval_data        t_26 = { "SKIP", { .i32=39 }};
+			struct dict_enumval_data        t_27 = { "Photuris", { .i32=40 }};
+			struct dict_enumval_data        t_28 = { "ICMP_messages_utilized_by_experimental", { .i32=41 }};
+			struct dict_enumval_data        t_29 = { "RFC3692-style_Experiment_1", { .i32=253 }};
+			struct dict_enumval_data        t_30 = { "RFC3692-style_Experiment_2", { .i32=254 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_3, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_4, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_5, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_6, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_7, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_8, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_9, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_10, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_11, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_12, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_13, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_14, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_15, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_16, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_17, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_18, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_19, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_20, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_21, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_22, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_23, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_24, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_25, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_26, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_27, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_28, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_29, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_30, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* ICMP-Code */
+		{
+			struct dict_avp_data data = {
+				547,	/* Code */
+				0,	/* Vendor */
+				"ICMP-Code",	/* Name */
+				0,	/* Fixed flags */
+				0,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "Enumerated(ICMP-Code)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "Echo_Reply", { .i32=0 }};
+			struct dict_enumval_data        t_2 = { "Destination_Unreachable", { .i32=3 }};
+			struct dict_enumval_data        t_3 = { "Source_Quench", { .i32=4 }};
+			struct dict_enumval_data        t_4 = { "Redirect", { .i32=5 }};
+			struct dict_enumval_data        t_5 = { "Alternate_Host_Address", { .i32=6 }};
+			struct dict_enumval_data        t_6 = { "Echo", { .i32=8 }};
+			struct dict_enumval_data        t_7 = { "Router_Advertisement", { .i32=9 }};
+			struct dict_enumval_data        t_8 = { "Router_Solicitation", { .i32=10 }};
+			struct dict_enumval_data        t_9 = { "Time_Exceeded", { .i32=11 }};
+			struct dict_enumval_data        t_10 = { "Parameter_Problem", { .i32=12 }};
+			struct dict_enumval_data        t_11 = { "Timestamp", { .i32=13 }};
+			struct dict_enumval_data        t_12 = { "Timestamp_Reply", { .i32=14 }};
+			struct dict_enumval_data        t_13 = { "Information_Request", { .i32=15 }};
+			struct dict_enumval_data        t_14 = { "Information_Reply", { .i32=16 }};
+			struct dict_enumval_data        t_15 = { "Address_Mask_Request", { .i32=17 }};
+			struct dict_enumval_data        t_16 = { "Address_Mask_Reply", { .i32=18 }};
+			struct dict_enumval_data        t_17 = { "Traceroute", { .i32=30 }};
+			struct dict_enumval_data        t_18 = { "Datagram_Conversion_Error", { .i32=31 }};
+			struct dict_enumval_data        t_19 = { "Mobile_Host_Redirect", { .i32=32 }};
+			struct dict_enumval_data        t_20 = { "IPv6_Where-Are-You", { .i32=33 }};
+			struct dict_enumval_data        t_21 = { "IPv6_I-Am-Here", { .i32=34 }};
+			struct dict_enumval_data        t_22 = { "Mobile_Registration_Request", { .i32=35 }};
+			struct dict_enumval_data        t_23 = { "Mobile_Registration_Reply", { .i32=36 }};
+			struct dict_enumval_data        t_24 = { "Domain_Name_Request", { .i32=37 }};
+			struct dict_enumval_data        t_25 = { "Domain_Name_Reply", { .i32=38 }};
+			struct dict_enumval_data        t_26 = { "SKIP", { .i32=39 }};
+			struct dict_enumval_data        t_27 = { "Photuris", { .i32=40 }};
+			struct dict_enumval_data        t_28 = { "ICMP_messages_utilized_by_experimental", { .i32=41 }};
+			struct dict_enumval_data        t_29 = { "RFC3692-style_Experiment_1", { .i32=253 }};
+			struct dict_enumval_data        t_30 = { "RFC3692-style_Experiment_2", { .i32=254 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_3, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_4, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_5, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_6, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_7, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_8, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_9, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_10, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_11, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_12, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_13, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_14, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_15, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_16, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_17, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_18, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_19, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_20, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_21, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_22, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_23, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_24, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_25, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_26, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_27, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_28, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_29, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_30, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* ETH-Ether-Type */
+		{
+			struct dict_avp_data data = {
+				550,	/* Code */
+				0,	/* Vendor */
+				"ETH-Ether-Type",	/* Name */
+				0,	/* Fixed flags */
+				0,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* ETH-SAP */
+		{
+			struct dict_avp_data data = {
+				551,	/* Code */
+				0,	/* Vendor */
+				"ETH-SAP",	/* Name */
+				0,	/* Fixed flags */
+				0,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* S-VID-Start */
+		{
+			struct dict_avp_data data = {
+				553,	/* Code */
+				0,	/* Vendor */
+				"S-VID-Start",	/* Name */
+				0,	/* Fixed flags */
+				0,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* S-VID-End */
+		{
+			struct dict_avp_data data = {
+				554,	/* Code */
+				0,	/* Vendor */
+				"S-VID-End",	/* Name */
+				0,	/* Fixed flags */
+				0,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* C-VID-Start */
+		{
+			struct dict_avp_data data = {
+				555,	/* Code */
+				0,	/* Vendor */
+				"C-VID-Start",	/* Name */
+				0,	/* Fixed flags */
+				0,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* C-VID-End */
+		{
+			struct dict_avp_data data = {
+				556,	/* Code */
+				0,	/* Vendor */
+				"C-VID-End",	/* Name */
+				0,	/* Fixed flags */
+				0,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Low-User-Priority */
+		{
+			struct dict_avp_data data = {
+				558,	/* Code */
+				0,	/* Vendor */
+				"Low-User-Priority",	/* Name */
+				0,	/* Fixed flags */
+				0,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* High-User-Priority */
+		{
+			struct dict_avp_data data = {
+				559,	/* Code */
+				0,	/* Vendor */
+				"High-User-Priority",	/* Name */
+				0,	/* Fixed flags */
+				0,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Time-Of-Day-Start */
+		{
+			struct dict_avp_data data = {
+				561,	/* Code */
+				0,	/* Vendor */
+				"Time-Of-Day-Start",	/* Name */
+				0,	/* Fixed flags */
+				0,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Time-Of-Day-End */
+		{
+			struct dict_avp_data data = {
+				562,	/* Code */
+				0,	/* Vendor */
+				"Time-Of-Day-End",	/* Name */
+				0,	/* Fixed flags */
+				0,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Day-Of-Week-Mask */
+		{
+			struct dict_avp_data data = {
+				563,	/* Code */
+				0,	/* Vendor */
+				"Day-Of-Week-Mask",	/* Name */
+				0,	/* Fixed flags */
+				0,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Day-Of-Month-Mask */
+		{
+			struct dict_avp_data data = {
+				564,	/* Code */
+				0,	/* Vendor */
+				"Day-Of-Month-Mask",	/* Name */
+				0,	/* Fixed flags */
+				0,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Month-Of-Year-Mask */
+		{
+			struct dict_avp_data data = {
+				565,	/* Code */
+				0,	/* Vendor */
+				"Month-Of-Year-Mask",	/* Name */
+				0,	/* Fixed flags */
+				0,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Absolute-Start-Time */
+		{
+			struct dict_avp_data data = {
+				566,	/* Code */
+				0,	/* Vendor */
+				"Absolute-Start-Time",	/* Name */
+				0,	/* Fixed flags */
+				0,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, Time_type, NULL);
+		};
+		/* Absolute-Start-Fractional-Seconds */
+		{
+			struct dict_avp_data data = {
+				567,	/* Code */
+				0,	/* Vendor */
+				"Absolute-Start-Fractional-Seconds",	/* Name */
+				0,	/* Fixed flags */
+				0,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Absolute-End-Time */
+		{
+			struct dict_avp_data data = {
+				568,	/* Code */
+				0,	/* Vendor */
+				"Absolute-End-Time",	/* Name */
+				0,	/* Fixed flags */
+				0,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, Time_type, NULL);
+		};
+		/* Absolute-End-Fractional-Seconds */
+		{
+			struct dict_avp_data data = {
+				569,	/* Code */
+				0,	/* Vendor */
+				"Absolute-End-Fractional-Seconds",	/* Name */
+				0,	/* Fixed flags */
+				0,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Timezone-Flag */
+		{
+			struct dict_avp_data data = {
+				570,	/* Code */
+				0,	/* Vendor */
+				"Timezone-Flag",	/* Name */
+				0,	/* Fixed flags */
+				0,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "Enumerated(Timezone-Flag)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "UTC", { .i32=0 }};
+			struct dict_enumval_data        t_2 = { "LOCAL", { .i32=1 }};
+			struct dict_enumval_data        t_3 = { "OFFSET", { .i32=2 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_3, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* Timezone-Offset */
+		{
+			struct dict_avp_data data = {
+				571,	/* Code */
+				0,	/* Vendor */
+				"Timezone-Offset",	/* Name */
+				0,	/* Fixed flags */
+				0,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Treatment-Action */
+		{
+			struct dict_avp_data data = {
+				572,	/* Code */
+				0,	/* Vendor */
+				"Treatment-Action",	/* Name */
+				0,	/* Fixed flags */
+				0,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "Enumerated(Treatment-Action)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "drop", { .i32=0 }};
+			struct dict_enumval_data        t_2 = { "shape", { .i32=1 }};
+			struct dict_enumval_data        t_3 = { "mark", { .i32=2 }};
+			struct dict_enumval_data        t_4 = { "permit", { .i32=3 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_3, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_4, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* QoS-Profile-Id */
+		{
+			struct dict_avp_data data = {
+				573,	/* Code */
+				0,	/* Vendor */
+				"QoS-Profile-Id",	/* Name */
+				0,	/* Fixed flags */
+				0,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* QoS-Semantics */
+		{
+			struct dict_avp_data data = {
+				575,	/* Code */
+				0,	/* Vendor */
+				"QoS-Semantics",	/* Name */
+				0,	/* Fixed flags */
+				0,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "Enumerated(QoS-Semantics)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "QoS_Desired", { .i32=0 }};
+			struct dict_enumval_data        t_2 = { "QoS_Available", { .i32=1 }};
+			struct dict_enumval_data        t_3 = { "QoS_Delivered", { .i32=2 }};
+			struct dict_enumval_data        t_4 = { "Minimum_QoS", { .i32=3 }};
+			struct dict_enumval_data        t_5 = { "QoS_Authorized", { .i32=4 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_3, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_4, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_5, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* QoS-Parameters */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				576,	/* Code */
+				0,	/* Vendor */
+				"QoS-Parameters",	/* Name */
+				0,	/* Fixed flags */
+				0,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* ETH-Proto-Type */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				549,	/* Code */
+				0,	/* Vendor */
+				"ETH-Proto-Type",	/* Name */
+				0,	/* Fixed flags */
+				0,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* VLAN-ID-Range */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				552,	/* Code */
+				0,	/* Vendor */
+				"VLAN-ID-Range",	/* Name */
+				0,	/* Fixed flags */
+				0,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* IP-Option */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				537,	/* Code */
+				0,	/* Vendor */
+				"IP-Option",	/* Name */
+				0,	/* Fixed flags */
+				0,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* IP-Address-Mask */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				522,	/* Code */
+				0,	/* Vendor */
+				"IP-Address-Mask",	/* Name */
+				0,	/* Fixed flags */
+				0,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* Time-Of-Day-Condition */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				560,	/* Code */
+				0,	/* Vendor */
+				"Time-Of-Day-Condition",	/* Name */
+				0,	/* Fixed flags */
+				0,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* TCP-Option */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				540,	/* Code */
+				0,	/* Vendor */
+				"TCP-Option",	/* Name */
+				0,	/* Fixed flags */
+				0,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* MAC-Address-Mask */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				525,	/* Code */
+				0,	/* Vendor */
+				"MAC-Address-Mask",	/* Name */
+				0,	/* Fixed flags */
+				0,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* TCP-Flags */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				543,	/* Code */
+				0,	/* Vendor */
+				"TCP-Flags",	/* Name */
+				0,	/* Fixed flags */
+				0,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* Port-Range */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				531,	/* Code */
+				0,	/* Vendor */
+				"Port-Range",	/* Name */
+				0,	/* Fixed flags */
+				0,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* ICMP-Type */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				545,	/* Code */
+				0,	/* Vendor */
+				"ICMP-Type",	/* Name */
+				0,	/* Fixed flags */
+				0,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* User-Priority-Range */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				557,	/* Code */
+				0,	/* Vendor */
+				"User-Priority-Range",	/* Name */
+				0,	/* Fixed flags */
+				0,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* QoS-Profile-Template */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				574,	/* Code */
+				0,	/* Vendor */
+				"QoS-Profile-Template",	/* Name */
+				0,	/* Fixed flags */
+				0,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* IP-Address-Range */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				519,	/* Code */
+				0,	/* Vendor */
+				"IP-Address-Range",	/* Name */
+				0,	/* Fixed flags */
+				0,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* EUI64-Address-Mask */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				528,	/* Code */
+				0,	/* Vendor */
+				"EUI64-Address-Mask",	/* Name */
+				0,	/* Fixed flags */
+				0,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* From-Spec */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				515,	/* Code */
+				0,	/* Vendor */
+				"From-Spec",	/* Name */
+				0,	/* Fixed flags */
+				0,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* Excess-Treatment */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				577,	/* Code */
+				0,	/* Vendor */
+				"Excess-Treatment",	/* Name */
+				0,	/* Fixed flags */
+				0,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* ETH-Option */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				548,	/* Code */
+				0,	/* Vendor */
+				"ETH-Option",	/* Name */
+				0,	/* Fixed flags */
+				0,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* To-Spec */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				516,	/* Code */
+				0,	/* Vendor */
+				"To-Spec",	/* Name */
+				0,	/* Fixed flags */
+				0,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* QoS-Capability */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				578,	/* Code */
+				0,	/* Vendor */
+				"QoS-Capability",	/* Name */
+				0,	/* Fixed flags */
+				0,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* Classifier */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				511,	/* Code */
+				0,	/* Vendor */
+				"Classifier",	/* Name */
+				0,	/* Fixed flags */
+				0,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* Filter-Rule */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				509,	/* Code */
+				0,	/* Vendor */
+				"Filter-Rule",	/* Name */
+				0,	/* Fixed flags */
+				0,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* QoS-Resources */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				508,	/* Code */
+				0,	/* Vendor */
+				"QoS-Resources",	/* Name */
+				0,	/* Fixed flags */
+				0,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+
+	
+   }
+
+   /* Commands section */
+   {
+
+   }
+
+   return 0;
+}
+
+static int dict_rfc5777_avps_load_rules(char * conffile)
+{
+   /* Grouped AVP section */
+   {
+	  /* QoS-Parameters */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 0, .avp_name = "QoS-Parameters"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* ETH-Proto-Type */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 0, .avp_name = "ETH-Proto-Type"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 0, .avp_name = "ETH-Ether-Type"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "ETH-SAP"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* VLAN-ID-Range */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 0, .avp_name = "VLAN-ID-Range"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 0, .avp_name = "S-VID-Start"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "S-VID-End"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "C-VID-Start"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "C-VID-End"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* IP-Option */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 0, .avp_name = "IP-Option"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 0, .avp_name = "IP-Option-Type"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "IP-Option-Value"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Negated"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* IP-Address-Mask */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 0, .avp_name = "IP-Address-Mask"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 0, .avp_name = "IP-Address"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "IP-Bit-Mask-Width"}, RULE_REQUIRED, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* Time-Of-Day-Condition */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 0, .avp_name = "Time-Of-Day-Condition"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 0, .avp_name = "Time-Of-Day-Start"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Time-Of-Day-End"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Day-Of-Week-Mask"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Day-Of-Month-Mask"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Month-Of-Year-Mask"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Absolute-Start-Time"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Absolute-End-Time"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Timezone-Flag"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* TCP-Option */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 0, .avp_name = "TCP-Option"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 0, .avp_name = "TCP-Option-Type"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "TCP-Option-Value"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Negated"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* MAC-Address-Mask */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 0, .avp_name = "MAC-Address-Mask"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 0, .avp_name = "MAC-Address"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "MAC-Address-Mask-Pattern"}, RULE_REQUIRED, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* TCP-Flags */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 0, .avp_name = "TCP-Flags"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 0, .avp_name = "TCP-Flag-Type"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Negated"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* Port-Range */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 0, .avp_name = "Port-Range"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 0, .avp_name = "Port-Start"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Port-End"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* ICMP-Type */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 0, .avp_name = "ICMP-Type"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 0, .avp_name = "ICMP-Type-Number"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "ICMP-Code"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Negated"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* User-Priority-Range */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 0, .avp_name = "User-Priority-Range"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 0, .avp_name = "Low-User-Priority"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "High-User-Priority"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* QoS-Profile-Template */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 0, .avp_name = "QoS-Profile-Template"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 0, .avp_name = "Vendor-Id"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "QoS-Profile-Id"}, RULE_REQUIRED, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* IP-Address-Range */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 0, .avp_name = "IP-Address-Range"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 0, .avp_name = "IP-Address-Start"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "IP-Address-End"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* EUI64-Address-Mask */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 0, .avp_name = "EUI64-Address-Mask"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 0, .avp_name = "EUI64-Address"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "EUI64-Address-Mask-Pattern"}, RULE_REQUIRED, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* From-Spec */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 0, .avp_name = "From-Spec"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 0, .avp_name = "IP-Address"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "IP-Address-Range"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "IP-Address-Mask"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "MAC-Address"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "MAC-Address-Mask"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "EUI64-Address"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "EUI64-Address-Mask"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Port"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Port-Range"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Negated"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Use-Assigned-Address"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* Excess-Treatment */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 0, .avp_name = "Excess-Treatment"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 0, .avp_name = "Treatment-Action"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "QoS-Profile-Template"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "QoS-Parameters"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* ETH-Option */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 0, .avp_name = "ETH-Option"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 0, .avp_name = "ETH-Proto-Type"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "VLAN-ID-Range"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "User-Priority-Range"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* To-Spec */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 0, .avp_name = "To-Spec"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 0, .avp_name = "IP-Address"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "IP-Address-Range"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "IP-Address-Mask"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "MAC-Address"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "MAC-Address-Mask"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "EUI64-Address"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "EUI64-Address-Mask"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Port"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Port-Range"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Negated"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Use-Assigned-Address"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* QoS-Capability */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 0, .avp_name = "QoS-Capability"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 0, .avp_name = "QoS-Profile-Template"}, RULE_REQUIRED, 1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* Classifier */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 0, .avp_name = "Classifier"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 0, .avp_name = "Classifier-ID"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Protocol"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Direction"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "From-Spec"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "To-Spec"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Diffserv-Code-Point"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Fragmentation-Flag"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "IP-Option"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "TCP-Option"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "TCP-Flags"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "ICMP-Type"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "ETH-Option"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* Filter-Rule */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 0, .avp_name = "Filter-Rule"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 0, .avp_name = "Filter-Rule-Precedence"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Classifier"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Time-Of-Day-Condition"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Treatment-Action"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "QoS-Semantics"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "QoS-Profile-Template"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "QoS-Parameters"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Excess-Treatment"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* QoS-Resources */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 0, .avp_name = "QoS-Resources"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 0, .avp_name = "Filter-Rule"}, RULE_REQUIRED, 1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+
+   }	
+
+   /* Commands section */
+   {
+
+   }
+
+   LOG_D( "Extension 'Dictionary definitions for rfc5777_avps (None)' initialized");
+   return 0;
+}
+
+int dict_entry(char * conffile)
+{
+	dict_rfc5777_avps_load_defs(conffile);
+	return dict_rfc5777_avps_load_rules(conffile);
+}
+
+const char* dict_rfc5777_avps_proto_ver(char * conffile) {
+	return rfc5777_avps_proto_ver;
+}
+
+const double dict_rfc5777_avps_gen_ts(char * conffile) {
+	return rfc5777_avps_gen_date;
+}
+
+EXTENSION_ENTRY2("dict_rfc5777_avps", dict_rfc5777_avps_load_defs, dict_rfc5777_avps_load_rules);
+
+
+
diff --git a/extensions/dict_rfc5777_avps/rfc5777_avps.did b/extensions/dict_rfc5777_avps/rfc5777_avps.did
new file mode 100644
index 0000000..d94dddb
--- /dev/null
+++ b/extensions/dict_rfc5777_avps/rfc5777_avps.did
@@ -0,0 +1 @@
+dict_rfc5777_avps
diff --git a/extensions/dict_rfc5778_avps/CMakeLists.txt b/extensions/dict_rfc5778_avps/CMakeLists.txt
new file mode 100644
index 0000000..06abe56
--- /dev/null
+++ b/extensions/dict_rfc5778_avps/CMakeLists.txt
@@ -0,0 +1,16 @@
+# The dict_rfc5778_avps extension
+PROJECT("dict_rfc5778_avps library generated by FdGen " C)
+
+# Compile as a module
+FD_ADD_EXTENSION(dict_rfc5778_avps dict_rfc5778_avps.c)
+
+
+####
+## INSTALL section ##
+
+INSTALL(TARGETS dict_rfc5778_avps
+	LIBRARY DESTINATION ${INSTALL_EXTENSIONS_SUFFIX}
+COMPONENT freeDiameter-dictionary-RFC5778_AVPS)
+
+
+
diff --git a/extensions/dict_rfc5778_avps/dict_rfc5778_avps.c b/extensions/dict_rfc5778_avps/dict_rfc5778_avps.c
new file mode 100644
index 0000000..8d88569
--- /dev/null
+++ b/extensions/dict_rfc5778_avps/dict_rfc5778_avps.c
@@ -0,0 +1,286 @@
+/*
+* Copyright (c) 2017 Sprint
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*    http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+/****************
+ Generated By: fdtool enhancements to diafuzzer
+ License: same as freeDiameter
+****************/
+
+
+/* 
+ * Dictionary definitions of objects specified in rfc5778_avps.
+ */
+#include <freeDiameter/extension.h>
+
+#define PROTO_VER "unspecified"
+#define GEN_DATE  1506697143.61
+
+const char *rfc5778_avps_proto_ver = PROTO_VER;
+const double rfc5778_avps_gen_date = GEN_DATE;
+
+/* The content of this file follows the same structure as dict_base_proto.c */
+
+#define CHECK_dict_new( _type, _data, _parent, _ref )                                     \
+{                                                                                         \
+    int _ret = fd_dict_new( fd_g_config->cnf_dict, (_type), (_data), (_parent), (_ref) ); \
+    if ( _ret != 0 && _ret != EEXIST )                                                    \
+       return _ret;                                                                       \
+}
+
+#define CHECK_dict_search( _type, _criteria, _what, _result )		\
+    CHECK_FCT(  fd_dict_search( fd_g_config->cnf_dict, (_type), (_criteria), (_what), (_result), ENOENT) );
+
+struct local_rules_definition {
+    struct dict_avp_request avp_vendor_plus_name;
+    enum rule_position	position;
+    int 			min;
+    int			max;
+};
+
+#define RULE_ORDER( _position ) ((((_position) == RULE_FIXED_HEAD) || ((_position) == RULE_FIXED_TAIL)) ? 1 : 0 )
+
+/* Attention! This version of the macro uses AVP_BY_NAME_AND_VENDOR, in contrast to most other copies! */
+#define PARSE_loc_rules( _rulearray, _parent) {                                                         \
+        int __ar;                                                                                       \
+        for (__ar=0; __ar < sizeof(_rulearray) / sizeof((_rulearray)[0]); __ar++) {                     \
+                struct dict_rule_data __data = { NULL,                                                  \
+                        (_rulearray)[__ar].position,                                                    \
+                        0,                                                                              \
+                        (_rulearray)[__ar].min,                                                         \
+                        (_rulearray)[__ar].max};                                                        \
+                __data.rule_order = RULE_ORDER(__data.rule_position);                                   \
+                CHECK_FCT(  fd_dict_search(                                                             \
+                        fd_g_config->cnf_dict,                                                          \
+                        DICT_AVP,                                                                       \
+                        AVP_BY_NAME_AND_VENDOR,                                                         \
+                        &(_rulearray)[__ar].avp_vendor_plus_name,                                       \
+                        &__data.rule_avp, 0 ) );                                                        \
+                if ( !__data.rule_avp ) {                                                               \
+                        TRACE_DEBUG(INFO, "AVP Not found: '%s'", (_rulearray)[__ar].avp_vendor_plus_name.avp_name);             \
+                        return ENOENT;                                                                  \
+                }                                                                                       \
+                {                                                                                       \
+                         int _ret = fd_dict_new( fd_g_config->cnf_dict, DICT_RULE, &(__data), (_parent), NULL ); \
+                         if ( _ret != 0 && _ret != EEXIST )      {                                      \
+                                TRACE_DEBUG(INFO, "Error on rule with AVP '%s'",                        \
+                                            (_rulearray)[__ar].avp_vendor_plus_name.avp_name);          \
+                                return EINVAL;                                                          \
+                         }                                                                              \
+                }                                                                                       \
+        }                                                                                               \
+}
+
+#define CHECK_vendor_new( _data ) { \
+        struct dict_object * vendor_found; \
+        if (fd_dict_search(fd_g_config->cnf_dict,DICT_VENDOR,VENDOR_BY_ID,&_data.vendor_id,&vendor_found,ENOENT) == ENOENT) { \
+                CHECK_FCT(fd_dict_new(fd_g_config->cnf_dict, DICT_VENDOR, &_data, NULL, NULL)); \
+        } \
+}
+
+#define enumval_def_u32( _val_, _str_ )		\
+    { _str_, 		{ .u32 = _val_ }}
+
+#define enumval_def_os( _len_, _val_, _str_ )				\
+    { _str_, 		{ .os = { .data = (unsigned char *)_val_, .len = _len_ }}}
+
+
+static int dict_rfc5778_avps_load_defs(char * conffile)
+{
+   TRACE_ENTRY("%p", conffile);
+
+   /* AVP section */
+   {
+		struct dict_object * Address_type;
+		struct dict_object * UTF8String_type;
+		struct dict_object * DiameterIdentity_type;
+		struct dict_object * DiameterURI_type;
+		struct dict_object * Time_type;
+		struct dict_object * IPFilterRule_type;
+
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "Address", &Address_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "UTF8String", &UTF8String_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "DiameterIdentity", &DiameterIdentity_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "DiameterURI", &DiameterURI_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "Time", &Time_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "IPFilterRule", &IPFilterRule_type);
+		/* Service-Selection */
+		{
+			struct dict_avp_data data = {
+				493,	/* Code */
+				0,	/* Vendor */
+				"Service-Selection",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, UTF8String_type, NULL);
+		};
+		/* MIP-MN-HA-SPI */
+		{
+			struct dict_avp_data data = {
+				491,	/* Code */
+				0,	/* Vendor */
+				"MIP-MN-HA-SPI",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* MIP-Careof-Address */
+		{
+			struct dict_avp_data data = {
+				487,	/* Code */
+				0,	/* Vendor */
+				"MIP-Careof-Address",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, Address_type, NULL);
+		};
+		/* MIP-Authenticator */
+		{
+			struct dict_avp_data data = {
+				488,	/* Code */
+				0,	/* Vendor */
+				"MIP-Authenticator",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* MIP-MAC-Mobility-Data */
+		{
+			struct dict_avp_data data = {
+				489,	/* Code */
+				0,	/* Vendor */
+				"MIP-MAC-Mobility-Data",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* MIP-Timestamp */
+		{
+			struct dict_avp_data data = {
+				490,	/* Code */
+				0,	/* Vendor */
+				"MIP-Timestamp",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* MIP6-Auth-Mode */
+		{
+			struct dict_avp_data data = {
+				494,	/* Code */
+				0,	/* Vendor */
+				"MIP6-Auth-Mode",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "Enumerated(MIP6-Auth-Mode)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "MN_HA", { .i32=1 }};
+			struct dict_enumval_data        t_2 = { "MN_AAA", { .i32=2 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* MIP-MN-HA-MSA */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				492,	/* Code */
+				0,	/* Vendor */
+				"MIP-MN-HA-MSA",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+
+	
+   }
+
+   /* Commands section */
+   {
+
+   }
+
+   return 0;
+}
+
+static int dict_rfc5778_avps_load_rules(char * conffile)
+{
+   /* Grouped AVP section */
+   {
+	  /* MIP-MN-HA-MSA */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 0, .avp_name = "MIP-MN-HA-MSA"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 0, .avp_name = "MIP-Session-Key"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "MIP-MSA-Lifetime"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "MIP-MN-HA-SPI"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "MIP-Algorithm-Type"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "MIP-Replay-Mode"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+
+   }	
+
+   /* Commands section */
+   {
+
+   }
+
+   LOG_D( "Extension 'Dictionary definitions for rfc5778_avps (None)' initialized");
+   return 0;
+}
+
+int dict_entry(char * conffile)
+{
+	dict_rfc5778_avps_load_defs(conffile);
+	return dict_rfc5778_avps_load_rules(conffile);
+}
+
+const char* dict_rfc5778_avps_proto_ver(char * conffile) {
+	return rfc5778_avps_proto_ver;
+}
+
+const double dict_rfc5778_avps_gen_ts(char * conffile) {
+	return rfc5778_avps_gen_date;
+}
+
+EXTENSION_ENTRY2("dict_rfc5778_avps", dict_rfc5778_avps_load_defs, dict_rfc5778_avps_load_rules, "dict_rfc7155_avps", "dict_rfc5447_avps", "dict_rfc5777_avps", "dict_rfc4004_avps");
+
+
+
diff --git a/extensions/dict_rfc5778_avps/rfc5778_avps.did b/extensions/dict_rfc5778_avps/rfc5778_avps.did
new file mode 100644
index 0000000..0db426a
--- /dev/null
+++ b/extensions/dict_rfc5778_avps/rfc5778_avps.did
@@ -0,0 +1,5 @@
+dict_rfc7155_avps
+dict_rfc5777_avps
+dict_rfc5447_avps
+dict_rfc4004_avps
+dict_rfc5778_avps
diff --git a/extensions/dict_rfc6734_avps/CMakeLists.txt b/extensions/dict_rfc6734_avps/CMakeLists.txt
new file mode 100644
index 0000000..581d6f4
--- /dev/null
+++ b/extensions/dict_rfc6734_avps/CMakeLists.txt
@@ -0,0 +1,16 @@
+# The dict_rfc6734_avps extension
+PROJECT("dict_rfc6734_avps library generated by FdGen " C)
+
+# Compile as a module
+FD_ADD_EXTENSION(dict_rfc6734_avps dict_rfc6734_avps.c)
+
+
+####
+## INSTALL section ##
+
+INSTALL(TARGETS dict_rfc6734_avps
+	LIBRARY DESTINATION ${INSTALL_EXTENSIONS_SUFFIX}
+COMPONENT freeDiameter-dictionary-RFC6734_AVPS)
+
+
+
diff --git a/extensions/dict_rfc6734_avps/dict_rfc6734_avps.c b/extensions/dict_rfc6734_avps/dict_rfc6734_avps.c
new file mode 100644
index 0000000..c78dcd7
--- /dev/null
+++ b/extensions/dict_rfc6734_avps/dict_rfc6734_avps.c
@@ -0,0 +1,264 @@
+/*
+* Copyright (c) 2017 Sprint
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*    http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+/****************
+ Generated By: fdtool enhancements to diafuzzer
+ License: same as freeDiameter
+****************/
+
+
+/* 
+ * Dictionary definitions of objects specified in rfc6734_avps.
+ */
+#include <freeDiameter/extension.h>
+
+#define PROTO_VER "unspecified"
+#define GEN_DATE  1506697143.62
+
+const char *rfc6734_avps_proto_ver = PROTO_VER;
+const double rfc6734_avps_gen_date = GEN_DATE;
+
+/* The content of this file follows the same structure as dict_base_proto.c */
+
+#define CHECK_dict_new( _type, _data, _parent, _ref )                                     \
+{                                                                                         \
+    int _ret = fd_dict_new( fd_g_config->cnf_dict, (_type), (_data), (_parent), (_ref) ); \
+    if ( _ret != 0 && _ret != EEXIST )                                                    \
+       return _ret;                                                                       \
+}
+
+#define CHECK_dict_search( _type, _criteria, _what, _result )		\
+    CHECK_FCT(  fd_dict_search( fd_g_config->cnf_dict, (_type), (_criteria), (_what), (_result), ENOENT) );
+
+struct local_rules_definition {
+    struct dict_avp_request avp_vendor_plus_name;
+    enum rule_position	position;
+    int 			min;
+    int			max;
+};
+
+#define RULE_ORDER( _position ) ((((_position) == RULE_FIXED_HEAD) || ((_position) == RULE_FIXED_TAIL)) ? 1 : 0 )
+
+/* Attention! This version of the macro uses AVP_BY_NAME_AND_VENDOR, in contrast to most other copies! */
+#define PARSE_loc_rules( _rulearray, _parent) {                                                         \
+        int __ar;                                                                                       \
+        for (__ar=0; __ar < sizeof(_rulearray) / sizeof((_rulearray)[0]); __ar++) {                     \
+                struct dict_rule_data __data = { NULL,                                                  \
+                        (_rulearray)[__ar].position,                                                    \
+                        0,                                                                              \
+                        (_rulearray)[__ar].min,                                                         \
+                        (_rulearray)[__ar].max};                                                        \
+                __data.rule_order = RULE_ORDER(__data.rule_position);                                   \
+                CHECK_FCT(  fd_dict_search(                                                             \
+                        fd_g_config->cnf_dict,                                                          \
+                        DICT_AVP,                                                                       \
+                        AVP_BY_NAME_AND_VENDOR,                                                         \
+                        &(_rulearray)[__ar].avp_vendor_plus_name,                                       \
+                        &__data.rule_avp, 0 ) );                                                        \
+                if ( !__data.rule_avp ) {                                                               \
+                        TRACE_DEBUG(INFO, "AVP Not found: '%s'", (_rulearray)[__ar].avp_vendor_plus_name.avp_name);             \
+                        return ENOENT;                                                                  \
+                }                                                                                       \
+                {                                                                                       \
+                         int _ret = fd_dict_new( fd_g_config->cnf_dict, DICT_RULE, &(__data), (_parent), NULL ); \
+                         if ( _ret != 0 && _ret != EEXIST )      {                                      \
+                                TRACE_DEBUG(INFO, "Error on rule with AVP '%s'",                        \
+                                            (_rulearray)[__ar].avp_vendor_plus_name.avp_name);          \
+                                return EINVAL;                                                          \
+                         }                                                                              \
+                }                                                                                       \
+        }                                                                                               \
+}
+
+#define CHECK_vendor_new( _data ) { \
+        struct dict_object * vendor_found; \
+        if (fd_dict_search(fd_g_config->cnf_dict,DICT_VENDOR,VENDOR_BY_ID,&_data.vendor_id,&vendor_found,ENOENT) == ENOENT) { \
+                CHECK_FCT(fd_dict_new(fd_g_config->cnf_dict, DICT_VENDOR, &_data, NULL, NULL)); \
+        } \
+}
+
+#define enumval_def_u32( _val_, _str_ )		\
+    { _str_, 		{ .u32 = _val_ }}
+
+#define enumval_def_os( _len_, _val_, _str_ )				\
+    { _str_, 		{ .os = { .data = (unsigned char *)_val_, .len = _len_ }}}
+
+
+static int dict_rfc6734_avps_load_defs(char * conffile)
+{
+   TRACE_ENTRY("%p", conffile);
+
+   /* AVP section */
+   {
+		struct dict_object * Address_type;
+		struct dict_object * UTF8String_type;
+		struct dict_object * DiameterIdentity_type;
+		struct dict_object * DiameterURI_type;
+		struct dict_object * Time_type;
+		struct dict_object * IPFilterRule_type;
+
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "Address", &Address_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "UTF8String", &UTF8String_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "DiameterIdentity", &DiameterIdentity_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "DiameterURI", &DiameterURI_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "Time", &Time_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "IPFilterRule", &IPFilterRule_type);
+		/* Key-Type */
+		{
+			struct dict_avp_data data = {
+				582,	/* Code */
+				0,	/* Vendor */
+				"Key-Type",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "Enumerated(Key-Type)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "DSRK", { .i32=0 }};
+			struct dict_enumval_data        t_2 = { "rRK", { .i32=1 }};
+			struct dict_enumval_data        t_3 = { "rMSK", { .i32=2 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_3, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* Keying-Material */
+		{
+			struct dict_avp_data data = {
+				583,	/* Code */
+				0,	/* Vendor */
+				"Keying-Material",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Key-Lifetime */
+		{
+			struct dict_avp_data data = {
+				584,	/* Code */
+				0,	/* Vendor */
+				"Key-Lifetime",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Key-SPI */
+		{
+			struct dict_avp_data data = {
+				585,	/* Code */
+				0,	/* Vendor */
+				"Key-SPI",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Key-Name */
+		{
+			struct dict_avp_data data = {
+				586,	/* Code */
+				0,	/* Vendor */
+				"Key-Name",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Key */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				581,	/* Code */
+				0,	/* Vendor */
+				"Key",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+
+	
+   }
+
+   /* Commands section */
+   {
+
+   }
+
+   return 0;
+}
+
+static int dict_rfc6734_avps_load_rules(char * conffile)
+{
+   /* Grouped AVP section */
+   {
+	  /* Key */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 0, .avp_name = "Key"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 0, .avp_name = "Key-Type"}, RULE_FIXED_HEAD, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Keying-Material"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Key-Lifetime"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Key-Name"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Key-SPI"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+
+   }	
+
+   /* Commands section */
+   {
+
+   }
+
+   LOG_D( "Extension 'Dictionary definitions for rfc6734_avps (None)' initialized");
+   return 0;
+}
+
+int dict_entry(char * conffile)
+{
+	dict_rfc6734_avps_load_defs(conffile);
+	return dict_rfc6734_avps_load_rules(conffile);
+}
+
+const char* dict_rfc6734_avps_proto_ver(char * conffile) {
+	return rfc6734_avps_proto_ver;
+}
+
+const double dict_rfc6734_avps_gen_ts(char * conffile) {
+	return rfc6734_avps_gen_date;
+}
+
+EXTENSION_ENTRY2("dict_rfc6734_avps", dict_rfc6734_avps_load_defs, dict_rfc6734_avps_load_rules);
+
+
+
diff --git a/extensions/dict_rfc6734_avps/rfc6734_avps.did b/extensions/dict_rfc6734_avps/rfc6734_avps.did
new file mode 100644
index 0000000..efbfb52
--- /dev/null
+++ b/extensions/dict_rfc6734_avps/rfc6734_avps.did
@@ -0,0 +1 @@
+dict_rfc6734_avps
diff --git a/extensions/dict_rfc6942_avps/CMakeLists.txt b/extensions/dict_rfc6942_avps/CMakeLists.txt
new file mode 100644
index 0000000..efb9e5f
--- /dev/null
+++ b/extensions/dict_rfc6942_avps/CMakeLists.txt
@@ -0,0 +1,16 @@
+# The dict_rfc6942_avps extension
+PROJECT("dict_rfc6942_avps library generated by FdGen " C)
+
+# Compile as a module
+FD_ADD_EXTENSION(dict_rfc6942_avps dict_rfc6942_avps.c)
+
+
+####
+## INSTALL section ##
+
+INSTALL(TARGETS dict_rfc6942_avps
+	LIBRARY DESTINATION ${INSTALL_EXTENSIONS_SUFFIX}
+COMPONENT freeDiameter-dictionary-RFC6942_AVPS)
+
+
+
diff --git a/extensions/dict_rfc6942_avps/dict_rfc6942_avps.c b/extensions/dict_rfc6942_avps/dict_rfc6942_avps.c
new file mode 100644
index 0000000..8145e9e
--- /dev/null
+++ b/extensions/dict_rfc6942_avps/dict_rfc6942_avps.c
@@ -0,0 +1,202 @@
+/*
+* Copyright (c) 2017 Sprint
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*    http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+/****************
+ Generated By: fdtool enhancements to diafuzzer
+ License: same as freeDiameter
+****************/
+
+
+/* 
+ * Dictionary definitions of objects specified in rfc6942_avps.
+ */
+#include <freeDiameter/extension.h>
+
+#define PROTO_VER "unspecified"
+#define GEN_DATE  1506697191.32
+
+const char *rfc6942_avps_proto_ver = PROTO_VER;
+const double rfc6942_avps_gen_date = GEN_DATE;
+
+/* The content of this file follows the same structure as dict_base_proto.c */
+
+#define CHECK_dict_new( _type, _data, _parent, _ref )                                     \
+{                                                                                         \
+    int _ret = fd_dict_new( fd_g_config->cnf_dict, (_type), (_data), (_parent), (_ref) ); \
+    if ( _ret != 0 && _ret != EEXIST )                                                    \
+       return _ret;                                                                       \
+}
+
+#define CHECK_dict_search( _type, _criteria, _what, _result )		\
+    CHECK_FCT(  fd_dict_search( fd_g_config->cnf_dict, (_type), (_criteria), (_what), (_result), ENOENT) );
+
+struct local_rules_definition {
+    struct dict_avp_request avp_vendor_plus_name;
+    enum rule_position	position;
+    int 			min;
+    int			max;
+};
+
+#define RULE_ORDER( _position ) ((((_position) == RULE_FIXED_HEAD) || ((_position) == RULE_FIXED_TAIL)) ? 1 : 0 )
+
+/* Attention! This version of the macro uses AVP_BY_NAME_AND_VENDOR, in contrast to most other copies! */
+#define PARSE_loc_rules( _rulearray, _parent) {                                                         \
+        int __ar;                                                                                       \
+        for (__ar=0; __ar < sizeof(_rulearray) / sizeof((_rulearray)[0]); __ar++) {                     \
+                struct dict_rule_data __data = { NULL,                                                  \
+                        (_rulearray)[__ar].position,                                                    \
+                        0,                                                                              \
+                        (_rulearray)[__ar].min,                                                         \
+                        (_rulearray)[__ar].max};                                                        \
+                __data.rule_order = RULE_ORDER(__data.rule_position);                                   \
+                CHECK_FCT(  fd_dict_search(                                                             \
+                        fd_g_config->cnf_dict,                                                          \
+                        DICT_AVP,                                                                       \
+                        AVP_BY_NAME_AND_VENDOR,                                                         \
+                        &(_rulearray)[__ar].avp_vendor_plus_name,                                       \
+                        &__data.rule_avp, 0 ) );                                                        \
+                if ( !__data.rule_avp ) {                                                               \
+                        TRACE_DEBUG(INFO, "AVP Not found: '%s'", (_rulearray)[__ar].avp_vendor_plus_name.avp_name);             \
+                        return ENOENT;                                                                  \
+                }                                                                                       \
+                {                                                                                       \
+                         int _ret = fd_dict_new( fd_g_config->cnf_dict, DICT_RULE, &(__data), (_parent), NULL ); \
+                         if ( _ret != 0 && _ret != EEXIST )      {                                      \
+                                TRACE_DEBUG(INFO, "Error on rule with AVP '%s'",                        \
+                                            (_rulearray)[__ar].avp_vendor_plus_name.avp_name);          \
+                                return EINVAL;                                                          \
+                         }                                                                              \
+                }                                                                                       \
+        }                                                                                               \
+}
+
+#define CHECK_vendor_new( _data ) { \
+        struct dict_object * vendor_found; \
+        if (fd_dict_search(fd_g_config->cnf_dict,DICT_VENDOR,VENDOR_BY_ID,&_data.vendor_id,&vendor_found,ENOENT) == ENOENT) { \
+                CHECK_FCT(fd_dict_new(fd_g_config->cnf_dict, DICT_VENDOR, &_data, NULL, NULL)); \
+        } \
+}
+
+#define enumval_def_u32( _val_, _str_ )		\
+    { _str_, 		{ .u32 = _val_ }}
+
+#define enumval_def_os( _len_, _val_, _str_ )				\
+    { _str_, 		{ .os = { .data = (unsigned char *)_val_, .len = _len_ }}}
+
+
+static int dict_rfc6942_avps_load_defs(char * conffile)
+{
+   TRACE_ENTRY("%p", conffile);
+
+   /* AVP section */
+   {
+		struct dict_object * Address_type;
+		struct dict_object * UTF8String_type;
+		struct dict_object * DiameterIdentity_type;
+		struct dict_object * DiameterURI_type;
+		struct dict_object * Time_type;
+		struct dict_object * IPFilterRule_type;
+
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "Address", &Address_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "UTF8String", &UTF8String_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "DiameterIdentity", &DiameterIdentity_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "DiameterURI", &DiameterURI_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "Time", &Time_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "IPFilterRule", &IPFilterRule_type);
+		/* ERP-Realm */
+		{
+			struct dict_avp_data data = {
+				619,	/* Code */
+				0,	/* Vendor */
+				"ERP-Realm",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, DiameterIdentity_type, NULL);
+		};
+		/* ERP-RK-Request */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				618,	/* Code */
+				0,	/* Vendor */
+				"ERP-RK-Request",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+
+	
+   }
+
+   /* Commands section */
+   {
+
+   }
+
+   return 0;
+}
+
+static int dict_rfc6942_avps_load_rules(char * conffile)
+{
+   /* Grouped AVP section */
+   {
+	  /* ERP-RK-Request */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 0, .avp_name = "ERP-RK-Request"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 0, .avp_name = "ERP-Realm"}, RULE_REQUIRED, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+
+   }	
+
+   /* Commands section */
+   {
+
+   }
+
+   LOG_D( "Extension 'Dictionary definitions for rfc6942_avps (None)' initialized");
+   return 0;
+}
+
+int dict_entry(char * conffile)
+{
+	dict_rfc6942_avps_load_defs(conffile);
+	return dict_rfc6942_avps_load_rules(conffile);
+}
+
+const char* dict_rfc6942_avps_proto_ver(char * conffile) {
+	return rfc6942_avps_proto_ver;
+}
+
+const double dict_rfc6942_avps_gen_ts(char * conffile) {
+	return rfc6942_avps_gen_date;
+}
+
+EXTENSION_ENTRY2("dict_rfc6942_avps", dict_rfc6942_avps_load_defs, dict_rfc6942_avps_load_rules, "dict_rfc6734_avps");
+
+
+
diff --git a/extensions/dict_rfc6942_avps/rfc6942_avps.did b/extensions/dict_rfc6942_avps/rfc6942_avps.did
new file mode 100644
index 0000000..1724c7b
--- /dev/null
+++ b/extensions/dict_rfc6942_avps/rfc6942_avps.did
@@ -0,0 +1,2 @@
+dict_rfc6734_avps
+dict_rfc6942_avps
diff --git a/extensions/dict_rfc7155_avps/CMakeLists.txt b/extensions/dict_rfc7155_avps/CMakeLists.txt
new file mode 100644
index 0000000..ed14e01
--- /dev/null
+++ b/extensions/dict_rfc7155_avps/CMakeLists.txt
@@ -0,0 +1,16 @@
+# The dict_rfc7155_avps extension
+PROJECT("dict_rfc7155_avps library generated by FdGen " C)
+
+# Compile as a module
+FD_ADD_EXTENSION(dict_rfc7155_avps dict_rfc7155_avps.c)
+
+
+####
+## INSTALL section ##
+
+INSTALL(TARGETS dict_rfc7155_avps
+	LIBRARY DESTINATION ${INSTALL_EXTENSIONS_SUFFIX}
+COMPONENT freeDiameter-dictionary-RFC7155_AVPS)
+
+
+
diff --git a/extensions/dict_rfc7155_avps/dict_rfc7155_avps.c b/extensions/dict_rfc7155_avps/dict_rfc7155_avps.c
new file mode 100644
index 0000000..f8f3f17
--- /dev/null
+++ b/extensions/dict_rfc7155_avps/dict_rfc7155_avps.c
@@ -0,0 +1,1634 @@
+/*
+* Copyright (c) 2017 Sprint
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*    http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+/****************
+ Generated By: fdtool enhancements to diafuzzer
+ License: same as freeDiameter
+****************/
+
+
+/* 
+ * Dictionary definitions of objects specified in rfc7155_avps.
+ */
+#include <freeDiameter/extension.h>
+
+#define PROTO_VER "unspecified"
+#define GEN_DATE  1506697143.67
+
+const char *rfc7155_avps_proto_ver = PROTO_VER;
+const double rfc7155_avps_gen_date = GEN_DATE;
+
+/* The content of this file follows the same structure as dict_base_proto.c */
+
+#define CHECK_dict_new( _type, _data, _parent, _ref )                                     \
+{                                                                                         \
+    int _ret = fd_dict_new( fd_g_config->cnf_dict, (_type), (_data), (_parent), (_ref) ); \
+    if ( _ret != 0 && _ret != EEXIST )                                                    \
+       return _ret;                                                                       \
+}
+
+#define CHECK_dict_search( _type, _criteria, _what, _result )		\
+    CHECK_FCT(  fd_dict_search( fd_g_config->cnf_dict, (_type), (_criteria), (_what), (_result), ENOENT) );
+
+struct local_rules_definition {
+    struct dict_avp_request avp_vendor_plus_name;
+    enum rule_position	position;
+    int 			min;
+    int			max;
+};
+
+#define RULE_ORDER( _position ) ((((_position) == RULE_FIXED_HEAD) || ((_position) == RULE_FIXED_TAIL)) ? 1 : 0 )
+
+/* Attention! This version of the macro uses AVP_BY_NAME_AND_VENDOR, in contrast to most other copies! */
+#define PARSE_loc_rules( _rulearray, _parent) {                                                         \
+        int __ar;                                                                                       \
+        for (__ar=0; __ar < sizeof(_rulearray) / sizeof((_rulearray)[0]); __ar++) {                     \
+                struct dict_rule_data __data = { NULL,                                                  \
+                        (_rulearray)[__ar].position,                                                    \
+                        0,                                                                              \
+                        (_rulearray)[__ar].min,                                                         \
+                        (_rulearray)[__ar].max};                                                        \
+                __data.rule_order = RULE_ORDER(__data.rule_position);                                   \
+                CHECK_FCT(  fd_dict_search(                                                             \
+                        fd_g_config->cnf_dict,                                                          \
+                        DICT_AVP,                                                                       \
+                        AVP_BY_NAME_AND_VENDOR,                                                         \
+                        &(_rulearray)[__ar].avp_vendor_plus_name,                                       \
+                        &__data.rule_avp, 0 ) );                                                        \
+                if ( !__data.rule_avp ) {                                                               \
+                        TRACE_DEBUG(INFO, "AVP Not found: '%s'", (_rulearray)[__ar].avp_vendor_plus_name.avp_name);             \
+                        return ENOENT;                                                                  \
+                }                                                                                       \
+                {                                                                                       \
+                         int _ret = fd_dict_new( fd_g_config->cnf_dict, DICT_RULE, &(__data), (_parent), NULL ); \
+                         if ( _ret != 0 && _ret != EEXIST )      {                                      \
+                                TRACE_DEBUG(INFO, "Error on rule with AVP '%s'",                        \
+                                            (_rulearray)[__ar].avp_vendor_plus_name.avp_name);          \
+                                return EINVAL;                                                          \
+                         }                                                                              \
+                }                                                                                       \
+        }                                                                                               \
+}
+
+#define CHECK_vendor_new( _data ) { \
+        struct dict_object * vendor_found; \
+        if (fd_dict_search(fd_g_config->cnf_dict,DICT_VENDOR,VENDOR_BY_ID,&_data.vendor_id,&vendor_found,ENOENT) == ENOENT) { \
+                CHECK_FCT(fd_dict_new(fd_g_config->cnf_dict, DICT_VENDOR, &_data, NULL, NULL)); \
+        } \
+}
+
+#define enumval_def_u32( _val_, _str_ )		\
+    { _str_, 		{ .u32 = _val_ }}
+
+#define enumval_def_os( _len_, _val_, _str_ )				\
+    { _str_, 		{ .os = { .data = (unsigned char *)_val_, .len = _len_ }}}
+
+
+static int dict_rfc7155_avps_load_defs(char * conffile)
+{
+   TRACE_ENTRY("%p", conffile);
+
+	/* Derived AVP types section */
+	{
+		/* QoSFilterRule */
+		{
+			/*
+				The QosFilterRule format is derived from the OctetString AVP Base
+				Format.  It uses the ASCII charset.  Packets may be marked or
+				metered based on the following information:
+
+				 Direction                          (in or out)
+				 Source and destination IP address  (possibly masked)
+				 Protocol
+				 Source and destination port        (lists or ranges)
+				 DSCP values                        (no mask or range)
+
+				Rules for the appropriate direction are evaluated in order; the
+				first matched rule terminates the evaluation.  Each packet is
+				evaluated once.  If no rule matches, the packet is treated as best
+				effort.  An access device unable to interpret or apply a QoS rule
+				SHOULD NOT terminate the session.
+
+				QoSFilterRule filters MUST follow the following format:
+
+				action dir proto from src to dst [options]
+
+        				tag    - Mark packet with a specific DSCP
+                				 [DIFFSERV].  The DSCP option MUST be
+                				 included.
+        				meter  - Meter traffic.  The metering options
+                				 MUST be included.
+
+				dir           The format is as described under IPFilterRule.
+
+				proto         The format is as described under IPFilterRule.
+
+				src and dst   The format is as described under IPFilterRule.
+
+				 options:
+
+				 DSCP <color>
+				       Color values as defined in [DIFFSERV].  Exact
+				       matching of DSCP values is required (no masks or
+				       ranges).
+
+				 metering <rate> <color_under> <color_over>
+				       The metering option provides Assured Forwarding,
+				       as defined in [DIFFSERVAF], and MUST be present
+				       if the action is set to meter.  The rate option is
+				       the throughput, in bits per second, used
+				       by the access device to mark packets.  Traffic
+				       over the rate is marked with the color_over
+				       codepoint, and traffic under the rate is marked
+				       with the color_under codepoint.  The color_under
+				       and color_over options contain the drop
+				       preferences and MUST conform to the recommended
+				       codepoint keywords described in [DIFFSERVAF]
+				       (e.g., AF13).
+
+				       The metering option also supports the strict
+				       limit on traffic required by Expedited
+				       Forwarding, as defined in [DIFFSERVEF].  The
+				       color_over option may contain the keyword "drop"
+				       to prevent forwarding of traffic that exceeds the
+				       rate parameter.
+
+				 The rule syntax is a modified subset of ipfw(8) from FreeBSD,
+				 and the ipfw.c code may provide a useful base for
+				 implementations.
+			*/
+			struct dict_type_data data = { AVP_TYPE_OCTETSTRING,	"QoSFilterRule"		, NULL			, NULL			};
+			CHECK_dict_new( DICT_TYPE, &data , NULL, NULL);
+		}
+		
+	}
+	
+   /* AVP section */
+   {
+		struct dict_object * Address_type;
+		struct dict_object * UTF8String_type;
+		struct dict_object * DiameterIdentity_type;
+		struct dict_object * DiameterURI_type;
+		struct dict_object * Time_type;
+		struct dict_object * IPFilterRule_type;
+		struct dict_object * QoSFilterRule_type;
+
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "Address", &Address_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "UTF8String", &UTF8String_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "DiameterIdentity", &DiameterIdentity_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "DiameterURI", &DiameterURI_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "Time", &Time_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "IPFilterRule", &IPFilterRule_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "QoSFilterRule", &QoSFilterRule_type);
+		/* NAS-Port */
+		{
+			struct dict_avp_data data = {
+				5,	/* Code */
+				0,	/* Vendor */
+				"NAS-Port",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* NAS-Port-Id */
+		{
+			struct dict_avp_data data = {
+				87,	/* Code */
+				0,	/* Vendor */
+				"NAS-Port-Id",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, UTF8String_type, NULL);
+		};
+		/* NAS-Port-Type */
+		{
+			struct dict_avp_data data = {
+				61,	/* Code */
+				0,	/* Vendor */
+				"NAS-Port-Type",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "Enumerated(NAS-Port-Type)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "ASYNC", { .i32=0 }};
+			struct dict_enumval_data        t_2 = { "SYNC", { .i32=1 }};
+			struct dict_enumval_data        t_3 = { "ISDN_SYNC", { .i32=2 }};
+			struct dict_enumval_data        t_4 = { "ISDN_ASYNC_V120", { .i32=3 }};
+			struct dict_enumval_data        t_5 = { "ISDN_ASYNC_V110", { .i32=4 }};
+			struct dict_enumval_data        t_6 = { "VIRTUAL", { .i32=5 }};
+			struct dict_enumval_data        t_7 = { "PIAFS", { .i32=6 }};
+			struct dict_enumval_data        t_8 = { "HDLC_CLEAR_CHANNEL", { .i32=7 }};
+			struct dict_enumval_data        t_9 = { "X25", { .i32=8 }};
+			struct dict_enumval_data        t_10 = { "X75", { .i32=9 }};
+			struct dict_enumval_data        t_11 = { "G.3_FAX", { .i32=10 }};
+			struct dict_enumval_data        t_12 = { "SDSL_SYMMETRIC_DSL", { .i32=11 }};
+			struct dict_enumval_data        t_13 = { "IDSL_ISDN_DIGITAL_SUBSCRIBER_LINE", { .i32=14 }};
+			struct dict_enumval_data        t_14 = { "ETHERNET", { .i32=15 }};
+			struct dict_enumval_data        t_15 = { "XDSL_DIGITAL_SUBSCRIBER_LINE_OF_UNKNOWN_TYPE", { .i32=16 }};
+			struct dict_enumval_data        t_16 = { "CABLE", { .i32=17 }};
+			struct dict_enumval_data        t_17 = { "WIRELESS_OTHER", { .i32=18 }};
+			struct dict_enumval_data        t_18 = { "WIRELESS_IEEE_802.11", { .i32=19 }};
+			struct dict_enumval_data        t_19 = { "TOKEN_RING", { .i32=20 }};
+			struct dict_enumval_data        t_20 = { "FDDI", { .i32=21 }};
+			struct dict_enumval_data        t_21 = { "WIRELESS_CDMA2000", { .i32=22 }};
+			struct dict_enumval_data        t_22 = { "WIRELESS_UMTS", { .i32=23 }};
+			struct dict_enumval_data        t_23 = { "WIRELESS_1X_EV", { .i32=24 }};
+			struct dict_enumval_data        t_24 = { "IAPP", { .i32=25 }};
+			struct dict_enumval_data        t_25 = { "FTTP_FIBER_TO_THE_PREMISES", { .i32=26 }};
+			struct dict_enumval_data        t_26 = { "WIRELESS_IEEE_802.16", { .i32=27 }};
+			struct dict_enumval_data        t_27 = { "WIRELESS_IEEE_802.20", { .i32=28 }};
+			struct dict_enumval_data        t_28 = { "WIRELESS_IEEE_802.22", { .i32=29 }};
+			struct dict_enumval_data        t_29 = { "PPPOA_PPP_OVER_ATM", { .i32=30 }};
+			struct dict_enumval_data        t_30 = { "PPPOEOA_PPP_OVER_ETHERNET_OVER_ATM", { .i32=31 }};
+			struct dict_enumval_data        t_31 = { "PPPOEOE_PPP_OVER_ETHERNET_OVER_ETHERNET", { .i32=32 }};
+			struct dict_enumval_data        t_32 = { "PPPOEOVLAN_PPP_OVER_ETHERNET_OVER_VLAN", { .i32=33 }};
+			struct dict_enumval_data        t_33 = { "PPPOEOQINQ_PPP_OVER_ETHERNET_OVER_IEEE_802.1QINQ", { .i32=34 }};
+			struct dict_enumval_data        t_34 = { "XPON_PASSIVE_OPTICAL_NETWORK", { .i32=35 }};
+			struct dict_enumval_data        t_35 = { "WIRELESS_XGP", { .i32=36 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_3, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_4, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_5, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_6, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_7, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_8, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_9, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_10, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_11, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_12, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_13, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_14, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_15, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_16, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_17, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_18, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_19, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_20, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_21, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_22, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_23, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_24, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_25, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_26, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_27, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_28, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_29, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_30, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_31, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_32, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_33, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_34, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_35, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* Called-Station-Id */
+		{
+			struct dict_avp_data data = {
+				30,	/* Code */
+				0,	/* Vendor */
+				"Called-Station-Id",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, UTF8String_type, NULL);
+		};
+		/* Calling-Station-Id */
+		{
+			struct dict_avp_data data = {
+				31,	/* Code */
+				0,	/* Vendor */
+				"Calling-Station-Id",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, UTF8String_type, NULL);
+		};
+		/* Connect-Info */
+		{
+			struct dict_avp_data data = {
+				77,	/* Code */
+				0,	/* Vendor */
+				"Connect-Info",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, UTF8String_type, NULL);
+		};
+		/* Originating-Line-Info */
+		{
+			struct dict_avp_data data = {
+				94,	/* Code */
+				0,	/* Vendor */
+				"Originating-Line-Info",	/* Name */
+				AVP_FLAG_VENDOR,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Reply-Message */
+		{
+			struct dict_avp_data data = {
+				18,	/* Code */
+				0,	/* Vendor */
+				"Reply-Message",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, UTF8String_type, NULL);
+		};
+		/* User-Password */
+		{
+			struct dict_avp_data data = {
+				2,	/* Code */
+				0,	/* Vendor */
+				"User-Password",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Password-Retry */
+		{
+			struct dict_avp_data data = {
+				75,	/* Code */
+				0,	/* Vendor */
+				"Password-Retry",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Prompt */
+		{
+			struct dict_avp_data data = {
+				76,	/* Code */
+				0,	/* Vendor */
+				"Prompt",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "Enumerated(Prompt)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "NO_ECHO", { .i32=0 }};
+			struct dict_enumval_data        t_2 = { "ECHO", { .i32=1 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* CHAP-Algorithm */
+		{
+			struct dict_avp_data data = {
+				403,	/* Code */
+				0,	/* Vendor */
+				"CHAP-Algorithm",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "Enumerated(CHAP-Algorithm)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "CHAP_WITH_MD5", { .i32=5 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* CHAP-Ident */
+		{
+			struct dict_avp_data data = {
+				404,	/* Code */
+				0,	/* Vendor */
+				"CHAP-Ident",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* CHAP-Response */
+		{
+			struct dict_avp_data data = {
+				405,	/* Code */
+				0,	/* Vendor */
+				"CHAP-Response",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* CHAP-Challenge */
+		{
+			struct dict_avp_data data = {
+				60,	/* Code */
+				0,	/* Vendor */
+				"CHAP-Challenge",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* ARAP-Password */
+		{
+			struct dict_avp_data data = {
+				70,	/* Code */
+				0,	/* Vendor */
+				"ARAP-Password",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* ARAP-Challenge-Response */
+		{
+			struct dict_avp_data data = {
+				84,	/* Code */
+				0,	/* Vendor */
+				"ARAP-Challenge-Response",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* ARAP-Security */
+		{
+			struct dict_avp_data data = {
+				73,	/* Code */
+				0,	/* Vendor */
+				"ARAP-Security",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* ARAP-Security-Data */
+		{
+			struct dict_avp_data data = {
+				74,	/* Code */
+				0,	/* Vendor */
+				"ARAP-Security-Data",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Service-Type */
+		{
+			struct dict_avp_data data = {
+				6,	/* Code */
+				0,	/* Vendor */
+				"Service-Type",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "Enumerated(Service-Type)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "UNKNOWN", { .i32=0 }};
+			struct dict_enumval_data        t_2 = { "LOGIN", { .i32=1 }};
+			struct dict_enumval_data        t_3 = { "FRAMED", { .i32=2 }};
+			struct dict_enumval_data        t_4 = { "CALLBACK_LOGIN", { .i32=3 }};
+			struct dict_enumval_data        t_5 = { "CALLBACK_FRAMED", { .i32=4 }};
+			struct dict_enumval_data        t_6 = { "OUTBOUND", { .i32=5 }};
+			struct dict_enumval_data        t_7 = { "ADMINISTRATIVE", { .i32=6 }};
+			struct dict_enumval_data        t_8 = { "NAS_PROMPT", { .i32=7 }};
+			struct dict_enumval_data        t_9 = { "AUTHENTICATE_ONLY", { .i32=8 }};
+			struct dict_enumval_data        t_10 = { "CALLBACK_NAS_PROMPT", { .i32=9 }};
+			struct dict_enumval_data        t_11 = { "CALL_CHECK", { .i32=10 }};
+			struct dict_enumval_data        t_12 = { "CALLBACK_ADMINISTRATIVE", { .i32=11 }};
+			struct dict_enumval_data        t_13 = { "VOICE", { .i32=12 }};
+			struct dict_enumval_data        t_14 = { "FAX", { .i32=13 }};
+			struct dict_enumval_data        t_15 = { "MODEM_RELAY", { .i32=14 }};
+			struct dict_enumval_data        t_16 = { "IAPP_REGISTER", { .i32=15 }};
+			struct dict_enumval_data        t_17 = { "IAPP_AP_CHECK", { .i32=16 }};
+			struct dict_enumval_data        t_18 = { "AUTHORIZE_ONLY", { .i32=17 }};
+			struct dict_enumval_data        t_19 = { "FRAMED_MANAGEMENT", { .i32=18 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_3, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_4, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_5, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_6, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_7, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_8, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_9, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_10, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_11, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_12, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_13, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_14, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_15, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_16, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_17, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_18, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_19, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* Callback-Number */
+		{
+			struct dict_avp_data data = {
+				19,	/* Code */
+				0,	/* Vendor */
+				"Callback-Number",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, UTF8String_type, NULL);
+		};
+		/* Callback-Id */
+		{
+			struct dict_avp_data data = {
+				20,	/* Code */
+				0,	/* Vendor */
+				"Callback-Id",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, UTF8String_type, NULL);
+		};
+		/* Idle-Timeout */
+		{
+			struct dict_avp_data data = {
+				28,	/* Code */
+				0,	/* Vendor */
+				"Idle-Timeout",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Port-Limit */
+		{
+			struct dict_avp_data data = {
+				62,	/* Code */
+				0,	/* Vendor */
+				"Port-Limit",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* NAS-Filter-Rule */
+		{
+			struct dict_avp_data data = {
+				400,	/* Code */
+				0,	/* Vendor */
+				"NAS-Filter-Rule",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, IPFilterRule_type, NULL);
+		};
+		/* Filter-Id */
+		{
+			struct dict_avp_data data = {
+				11,	/* Code */
+				0,	/* Vendor */
+				"Filter-Id",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, UTF8String_type, NULL);
+		};
+		/* Configuration-Token */
+		{
+			struct dict_avp_data data = {
+				78,	/* Code */
+				0,	/* Vendor */
+				"Configuration-Token",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* QoS-Filter-Rule */
+		{
+			struct dict_avp_data data = {
+				407,	/* Code */
+				0,	/* Vendor */
+				"QoS-Filter-Rule",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, QoSFilterRule_type, NULL);
+		};
+		/* Framed-Protocol */
+		{
+			struct dict_avp_data data = {
+				7,	/* Code */
+				0,	/* Vendor */
+				"Framed-Protocol",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "Enumerated(Framed-Protocol)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "PPP", { .i32=1 }};
+			struct dict_enumval_data        t_2 = { "SLIP", { .i32=2 }};
+			struct dict_enumval_data        t_3 = { "ARAP", { .i32=3 }};
+			struct dict_enumval_data        t_4 = { "GANDALF", { .i32=4 }};
+			struct dict_enumval_data        t_5 = { "XYLOGICS", { .i32=5 }};
+			struct dict_enumval_data        t_6 = { "X.75", { .i32=6 }};
+			struct dict_enumval_data        t_7 = { "GPRS_PDP_CONTEXT", { .i32=7 }};
+			struct dict_enumval_data        t_8 = { "ASCEND_ARA", { .i32=255 }};
+			struct dict_enumval_data        t_9 = { "MPP", { .i32=256 }};
+			struct dict_enumval_data        t_10 = { "EURAW", { .i32=257 }};
+			struct dict_enumval_data        t_11 = { "EUUI", { .i32=258 }};
+			struct dict_enumval_data        t_12 = { "X25", { .i32=259 }};
+			struct dict_enumval_data        t_13 = { "COMB", { .i32=260 }};
+			struct dict_enumval_data        t_14 = { "FR", { .i32=261 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_3, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_4, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_5, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_6, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_7, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_8, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_9, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_10, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_11, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_12, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_13, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_14, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* Framed-Routing */
+		{
+			struct dict_avp_data data = {
+				10,	/* Code */
+				0,	/* Vendor */
+				"Framed-Routing",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "Enumerated(Framed-Routing)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "NONE", { .i32=0 }};
+			struct dict_enumval_data        t_2 = { "SEND_ROUTING_PACKETS", { .i32=1 }};
+			struct dict_enumval_data        t_3 = { "LISTEN_FOR_ROUTING_PACKETS", { .i32=2 }};
+			struct dict_enumval_data        t_4 = { "SEND_AND_LISTEN", { .i32=3 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_3, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_4, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* Framed-MTU */
+		{
+			struct dict_avp_data data = {
+				12,	/* Code */
+				0,	/* Vendor */
+				"Framed-MTU",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Framed-Compression */
+		{
+			struct dict_avp_data data = {
+				13,	/* Code */
+				0,	/* Vendor */
+				"Framed-Compression",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "Enumerated(Framed-Compression)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "NONE", { .i32=0 }};
+			struct dict_enumval_data        t_2 = { "IPX_HEADER_COMPRESSION", { .i32=2 }};
+			struct dict_enumval_data        t_3 = { "STAC_LZS_COMPRESSION", { .i32=3 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_3, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* Framed-IP-Address */
+		{
+			struct dict_avp_data data = {
+				8,	/* Code */
+				0,	/* Vendor */
+				"Framed-IP-Address",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Framed-IP-Netmask */
+		{
+			struct dict_avp_data data = {
+				9,	/* Code */
+				0,	/* Vendor */
+				"Framed-IP-Netmask",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Framed-Route */
+		{
+			struct dict_avp_data data = {
+				22,	/* Code */
+				0,	/* Vendor */
+				"Framed-Route",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, UTF8String_type, NULL);
+		};
+		/* Framed-Pool */
+		{
+			struct dict_avp_data data = {
+				88,	/* Code */
+				0,	/* Vendor */
+				"Framed-Pool",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Framed-Interface-Id */
+		{
+			struct dict_avp_data data = {
+				96,	/* Code */
+				0,	/* Vendor */
+				"Framed-Interface-Id",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED64	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Framed-IPv6-Prefix */
+		{
+			struct dict_avp_data data = {
+				97,	/* Code */
+				0,	/* Vendor */
+				"Framed-IPv6-Prefix",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Framed-IPv6-Route */
+		{
+			struct dict_avp_data data = {
+				99,	/* Code */
+				0,	/* Vendor */
+				"Framed-IPv6-Route",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, UTF8String_type, NULL);
+		};
+		/* Framed-IPv6-Pool */
+		{
+			struct dict_avp_data data = {
+				100,	/* Code */
+				0,	/* Vendor */
+				"Framed-IPv6-Pool",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Framed-IPX-Network */
+		{
+			struct dict_avp_data data = {
+				23,	/* Code */
+				0,	/* Vendor */
+				"Framed-IPX-Network",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, UTF8String_type, NULL);
+		};
+		/* Framed-Appletalk-Link */
+		{
+			struct dict_avp_data data = {
+				37,	/* Code */
+				0,	/* Vendor */
+				"Framed-Appletalk-Link",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Framed-Appletalk-Network */
+		{
+			struct dict_avp_data data = {
+				38,	/* Code */
+				0,	/* Vendor */
+				"Framed-Appletalk-Network",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Framed-Appletalk-Zone */
+		{
+			struct dict_avp_data data = {
+				39,	/* Code */
+				0,	/* Vendor */
+				"Framed-Appletalk-Zone",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* ARAP-Features */
+		{
+			struct dict_avp_data data = {
+				71,	/* Code */
+				0,	/* Vendor */
+				"ARAP-Features",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* ARAP-Zone-Access */
+		{
+			struct dict_avp_data data = {
+				72,	/* Code */
+				0,	/* Vendor */
+				"ARAP-Zone-Access",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "Enumerated(ARAP-Zone-Access)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "ONLY_ALLOW_ACCESS_TO_DEFAULT_ZONE", { .i32=1 }};
+			struct dict_enumval_data        t_2 = { "USE_ZONE_FILTER_INCLUSIVELY", { .i32=2 }};
+			struct dict_enumval_data        t_3 = { "USE_ZONE_FILTER_EXCLUSIVELY", { .i32=3 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_3, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* Login-IP-Host */
+		{
+			struct dict_avp_data data = {
+				14,	/* Code */
+				0,	/* Vendor */
+				"Login-IP-Host",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Login-IPv6-Host */
+		{
+			struct dict_avp_data data = {
+				98,	/* Code */
+				0,	/* Vendor */
+				"Login-IPv6-Host",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Login-Service */
+		{
+			struct dict_avp_data data = {
+				15,	/* Code */
+				0,	/* Vendor */
+				"Login-Service",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "Enumerated(Login-Service)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "TELNET", { .i32=0 }};
+			struct dict_enumval_data        t_2 = { "RLOGIN", { .i32=1 }};
+			struct dict_enumval_data        t_3 = { "TCP_CLEAR", { .i32=2 }};
+			struct dict_enumval_data        t_4 = { "PORTMASTER", { .i32=3 }};
+			struct dict_enumval_data        t_5 = { "LAT", { .i32=4 }};
+			struct dict_enumval_data        t_6 = { "X25_PAD", { .i32=5 }};
+			struct dict_enumval_data        t_7 = { "X25_T3POS", { .i32=6 }};
+			struct dict_enumval_data        t_8 = { "UNASSIGNED", { .i32=7 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_3, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_4, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_5, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_6, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_7, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_8, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* Login-TCP-Port */
+		{
+			struct dict_avp_data data = {
+				16,	/* Code */
+				0,	/* Vendor */
+				"Login-TCP-Port",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Login-LAT-Service */
+		{
+			struct dict_avp_data data = {
+				34,	/* Code */
+				0,	/* Vendor */
+				"Login-LAT-Service",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Login-LAT-Node */
+		{
+			struct dict_avp_data data = {
+				35,	/* Code */
+				0,	/* Vendor */
+				"Login-LAT-Node",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Login-LAT-Group */
+		{
+			struct dict_avp_data data = {
+				36,	/* Code */
+				0,	/* Vendor */
+				"Login-LAT-Group",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Login-LAT-Port */
+		{
+			struct dict_avp_data data = {
+				63,	/* Code */
+				0,	/* Vendor */
+				"Login-LAT-Port",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Tunnel-Type */
+		{
+			struct dict_avp_data data = {
+				64,	/* Code */
+				0,	/* Vendor */
+				"Tunnel-Type",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "Enumerated(Tunnel-Type)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "PPTP", { .i32=1 }};
+			struct dict_enumval_data        t_2 = { "L2F", { .i32=2 }};
+			struct dict_enumval_data        t_3 = { "L2TP", { .i32=3 }};
+			struct dict_enumval_data        t_4 = { "ATMP", { .i32=4 }};
+			struct dict_enumval_data        t_5 = { "VTP", { .i32=5 }};
+			struct dict_enumval_data        t_6 = { "AH", { .i32=6 }};
+			struct dict_enumval_data        t_7 = { "IP_IP_ENCAP", { .i32=7 }};
+			struct dict_enumval_data        t_8 = { "MIN_IP_IP", { .i32=8 }};
+			struct dict_enumval_data        t_9 = { "ESP", { .i32=9 }};
+			struct dict_enumval_data        t_10 = { "GRE", { .i32=10 }};
+			struct dict_enumval_data        t_11 = { "DVS", { .i32=11 }};
+			struct dict_enumval_data        t_12 = { "IP_IN_IP_TUNNELING", { .i32=12 }};
+			struct dict_enumval_data        t_13 = { "VLAN", { .i32=13 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_3, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_4, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_5, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_6, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_7, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_8, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_9, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_10, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_11, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_12, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_13, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* Tunnel-Medium-Type */
+		{
+			struct dict_avp_data data = {
+				65,	/* Code */
+				0,	/* Vendor */
+				"Tunnel-Medium-Type",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "Enumerated(Tunnel-Medium-Type)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "IPV4", { .i32=1 }};
+			struct dict_enumval_data        t_2 = { "IPV6", { .i32=2 }};
+			struct dict_enumval_data        t_3 = { "NSAP", { .i32=3 }};
+			struct dict_enumval_data        t_4 = { "HDLC", { .i32=4 }};
+			struct dict_enumval_data        t_5 = { "BBN", { .i32=5 }};
+			struct dict_enumval_data        t_6 = { "IEEE_802", { .i32=6 }};
+			struct dict_enumval_data        t_7 = { "E_163", { .i32=7 }};
+			struct dict_enumval_data        t_8 = { "E_164", { .i32=8 }};
+			struct dict_enumval_data        t_9 = { "F_69", { .i32=9 }};
+			struct dict_enumval_data        t_10 = { "X_121", { .i32=10 }};
+			struct dict_enumval_data        t_11 = { "IPX", { .i32=11 }};
+			struct dict_enumval_data        t_12 = { "APPLETALK_802", { .i32=12 }};
+			struct dict_enumval_data        t_13 = { "DECNET4", { .i32=13 }};
+			struct dict_enumval_data        t_14 = { "VINES", { .i32=14 }};
+			struct dict_enumval_data        t_15 = { "E_164_NSAP", { .i32=15 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_3, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_4, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_5, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_6, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_7, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_8, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_9, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_10, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_11, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_12, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_13, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_14, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_15, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* Tunnel-Client-Endpoint */
+		{
+			struct dict_avp_data data = {
+				66,	/* Code */
+				0,	/* Vendor */
+				"Tunnel-Client-Endpoint",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, UTF8String_type, NULL);
+		};
+		/* Tunnel-Server-Endpoint */
+		{
+			struct dict_avp_data data = {
+				67,	/* Code */
+				0,	/* Vendor */
+				"Tunnel-Server-Endpoint",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, UTF8String_type, NULL);
+		};
+		/* Tunnel-Password */
+		{
+			struct dict_avp_data data = {
+				69,	/* Code */
+				0,	/* Vendor */
+				"Tunnel-Password",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Tunnel-Private-Group-Id */
+		{
+			struct dict_avp_data data = {
+				81,	/* Code */
+				0,	/* Vendor */
+				"Tunnel-Private-Group-Id",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Tunnel-Assignment-Id */
+		{
+			struct dict_avp_data data = {
+				82,	/* Code */
+				0,	/* Vendor */
+				"Tunnel-Assignment-Id",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Tunnel-Preference */
+		{
+			struct dict_avp_data data = {
+				83,	/* Code */
+				0,	/* Vendor */
+				"Tunnel-Preference",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Tunnel-Client-Auth-Id */
+		{
+			struct dict_avp_data data = {
+				90,	/* Code */
+				0,	/* Vendor */
+				"Tunnel-Client-Auth-Id",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, UTF8String_type, NULL);
+		};
+		/* Tunnel-Server-Auth-Id */
+		{
+			struct dict_avp_data data = {
+				91,	/* Code */
+				0,	/* Vendor */
+				"Tunnel-Server-Auth-Id",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, UTF8String_type, NULL);
+		};
+		/* Accounting-Input-Octets */
+		{
+			struct dict_avp_data data = {
+				363,	/* Code */
+				0,	/* Vendor */
+				"Accounting-Input-Octets",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED64	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Accounting-Output-Octets */
+		{
+			struct dict_avp_data data = {
+				364,	/* Code */
+				0,	/* Vendor */
+				"Accounting-Output-Octets",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED64	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Accounting-Input-Packets */
+		{
+			struct dict_avp_data data = {
+				365,	/* Code */
+				0,	/* Vendor */
+				"Accounting-Input-Packets",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED64	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Accounting-Output-Packets */
+		{
+			struct dict_avp_data data = {
+				366,	/* Code */
+				0,	/* Vendor */
+				"Accounting-Output-Packets",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED64	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Acct-Session-Time */
+		{
+			struct dict_avp_data data = {
+				46,	/* Code */
+				0,	/* Vendor */
+				"Acct-Session-Time",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Acct-Authentic */
+		{
+			struct dict_avp_data data = {
+				45,	/* Code */
+				0,	/* Vendor */
+				"Acct-Authentic",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "Enumerated(Acct-Authentic)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "NONE", { .i32=0 }};
+			struct dict_enumval_data        t_2 = { "RADIUS", { .i32=1 }};
+			struct dict_enumval_data        t_3 = { "LOCAL", { .i32=2 }};
+			struct dict_enumval_data        t_4 = { "REMOTE", { .i32=3 }};
+			struct dict_enumval_data        t_5 = { "DIAMETER", { .i32=4 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_3, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_4, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_5, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* Accounting-Auth-Method */
+		{
+			struct dict_avp_data data = {
+				406,	/* Code */
+				0,	/* Vendor */
+				"Accounting-Auth-Method",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "Enumerated(Accounting-Auth-Method)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "PAP", { .i32=1 }};
+			struct dict_enumval_data        t_2 = { "CHAP", { .i32=2 }};
+			struct dict_enumval_data        t_3 = { "MS_CHAP_1", { .i32=3 }};
+			struct dict_enumval_data        t_4 = { "MS_CHAP_2", { .i32=4 }};
+			struct dict_enumval_data        t_5 = { "EAP", { .i32=5 }};
+			struct dict_enumval_data        t_6 = { "UNDEFINED", { .i32=6 }};
+			struct dict_enumval_data        t_7 = { "NONE", { .i32=7 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_3, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_4, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_5, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_6, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_7, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* Acct-Delay-Time */
+		{
+			struct dict_avp_data data = {
+				41,	/* Code */
+				0,	/* Vendor */
+				"Acct-Delay-Time",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Acct-Link-Count */
+		{
+			struct dict_avp_data data = {
+				51,	/* Code */
+				0,	/* Vendor */
+				"Acct-Link-Count",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Acct-Tunnel-Connection */
+		{
+			struct dict_avp_data data = {
+				68,	/* Code */
+				0,	/* Vendor */
+				"Acct-Tunnel-Connection",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Acct-Tunnel-Packets-Lost */
+		{
+			struct dict_avp_data data = {
+				86,	/* Code */
+				0,	/* Vendor */
+				"Acct-Tunnel-Packets-Lost",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* NAS-Identifier */
+		{
+			struct dict_avp_data data = {
+				32,	/* Code */
+				0,	/* Vendor */
+				"NAS-Identifier",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, UTF8String_type, NULL);
+		};
+		/* NAS-IP-Address */
+		{
+			struct dict_avp_data data = {
+				4,	/* Code */
+				0,	/* Vendor */
+				"NAS-IP-Address",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* NAS-IPv6-Address */
+		{
+			struct dict_avp_data data = {
+				95,	/* Code */
+				0,	/* Vendor */
+				"NAS-IPv6-Address",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Origin-AAA-Protocol */
+		{
+			struct dict_avp_data data = {
+				408,	/* Code */
+				0,	/* Vendor */
+				"Origin-AAA-Protocol",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "Enumerated(Origin-AAA-Protocol)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "RADIUS", { .i32=1 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* State */
+		{
+			struct dict_avp_data data = {
+				24,	/* Code */
+				0,	/* Vendor */
+				"State",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Redirect-Host */
+		{
+			struct dict_avp_data data = {
+				292,	/* Code */
+				0,	/* Vendor */
+				"Redirect-Host",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, DiameterURI_type, NULL);
+		};
+		/* Redirect-Host-Usage */
+		{
+			struct dict_avp_data data = {
+				261,	/* Code */
+				0,	/* Vendor */
+				"Redirect-Host-Usage",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "Enumerated(Redirect-Host-Usage)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "DONT_CACHE", { .i32=0 }};
+			struct dict_enumval_data        t_2 = { "ALL_SESSION", { .i32=1 }};
+			struct dict_enumval_data        t_3 = { "ALL_REALM", { .i32=2 }};
+			struct dict_enumval_data        t_4 = { "REALM_AND_APPLICATION", { .i32=3 }};
+			struct dict_enumval_data        t_5 = { "ALL_APPLICATION", { .i32=4 }};
+			struct dict_enumval_data        t_6 = { "ALL_HOST", { .i32=5 }};
+			struct dict_enumval_data        t_7 = { "ALL_USER", { .i32=6 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_3, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_4, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_5, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_6, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_7, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* Redirect-Max-Cache-Time */
+		{
+			struct dict_avp_data data = {
+				262,	/* Code */
+				0,	/* Vendor */
+				"Redirect-Max-Cache-Time",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Tunneling */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				401,	/* Code */
+				0,	/* Vendor */
+				"Tunneling",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* CHAP-Auth */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				402,	/* Code */
+				0,	/* Vendor */
+				"CHAP-Auth",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+
+	
+   }
+
+   /* Commands section */
+   {
+
+   }
+
+   return 0;
+}
+
+static int dict_rfc7155_avps_load_rules(char * conffile)
+{
+   /* Grouped AVP section */
+   {
+	  /* Tunneling */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 0, .avp_name = "Tunneling"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 0, .avp_name = "Tunnel-Type"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Tunnel-Medium-Type"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Tunnel-Client-Endpoint"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Tunnel-Server-Endpoint"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Tunnel-Preference"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Tunnel-Client-Auth-Id"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Tunnel-Server-Auth-Id"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Tunnel-Assignment-Id"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Tunnel-Password"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Tunnel-Private-Group-Id"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* CHAP-Auth */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 0, .avp_name = "CHAP-Auth"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 0, .avp_name = "CHAP-Algorithm"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "CHAP-Ident"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "CHAP-Response"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+
+   }	
+
+   /* Commands section */
+   {
+
+   }
+
+   LOG_D( "Extension 'Dictionary definitions for rfc7155_avps (None)' initialized");
+   return 0;
+}
+
+int dict_entry(char * conffile)
+{
+	dict_rfc7155_avps_load_defs(conffile);
+	return dict_rfc7155_avps_load_rules(conffile);
+}
+
+const char* dict_rfc7155_avps_proto_ver(char * conffile) {
+	return rfc7155_avps_proto_ver;
+}
+
+const double dict_rfc7155_avps_gen_ts(char * conffile) {
+	return rfc7155_avps_gen_date;
+}
+
+EXTENSION_ENTRY2("dict_rfc7155_avps", dict_rfc7155_avps_load_defs, dict_rfc7155_avps_load_rules, "dict_rfc4004_avps");
+
+
+
diff --git a/extensions/dict_rfc7155_avps/rfc7155_avps.did b/extensions/dict_rfc7155_avps/rfc7155_avps.did
new file mode 100644
index 0000000..b774d5e
--- /dev/null
+++ b/extensions/dict_rfc7155_avps/rfc7155_avps.did
@@ -0,0 +1,2 @@
+dict_rfc4004_avps
+dict_rfc7155_avps
diff --git a/extensions/dict_rfc7683_avps/CMakeLists.txt b/extensions/dict_rfc7683_avps/CMakeLists.txt
new file mode 100644
index 0000000..5e5966b
--- /dev/null
+++ b/extensions/dict_rfc7683_avps/CMakeLists.txt
@@ -0,0 +1,16 @@
+# The dict_rfc7683_avps extension
+PROJECT("dict_rfc7683_avps library generated by FdGen " C)
+
+# Compile as a module
+FD_ADD_EXTENSION(dict_rfc7683_avps dict_rfc7683_avps.c)
+
+
+####
+## INSTALL section ##
+
+INSTALL(TARGETS dict_rfc7683_avps
+	LIBRARY DESTINATION ${INSTALL_EXTENSIONS_SUFFIX}
+COMPONENT freeDiameter-dictionary-RFC7683_AVPS)
+
+
+
diff --git a/extensions/dict_rfc7683_avps/dict_rfc7683_avps.c b/extensions/dict_rfc7683_avps/dict_rfc7683_avps.c
new file mode 100644
index 0000000..431b677
--- /dev/null
+++ b/extensions/dict_rfc7683_avps/dict_rfc7683_avps.c
@@ -0,0 +1,291 @@
+/*
+* Copyright (c) 2017 Sprint
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*    http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+/****************
+ Generated By: fdtool enhancements to diafuzzer
+ License: same as freeDiameter
+****************/
+
+
+/* 
+ * Dictionary definitions of objects specified in rfc7683_avps.
+ */
+#include <freeDiameter/extension.h>
+
+#define PROTO_VER "unspecified"
+#define GEN_DATE  1506697143.69
+
+const char *rfc7683_avps_proto_ver = PROTO_VER;
+const double rfc7683_avps_gen_date = GEN_DATE;
+
+/* The content of this file follows the same structure as dict_base_proto.c */
+
+#define CHECK_dict_new( _type, _data, _parent, _ref )                                     \
+{                                                                                         \
+    int _ret = fd_dict_new( fd_g_config->cnf_dict, (_type), (_data), (_parent), (_ref) ); \
+    if ( _ret != 0 && _ret != EEXIST )                                                    \
+       return _ret;                                                                       \
+}
+
+#define CHECK_dict_search( _type, _criteria, _what, _result )		\
+    CHECK_FCT(  fd_dict_search( fd_g_config->cnf_dict, (_type), (_criteria), (_what), (_result), ENOENT) );
+
+struct local_rules_definition {
+    struct dict_avp_request avp_vendor_plus_name;
+    enum rule_position	position;
+    int 			min;
+    int			max;
+};
+
+#define RULE_ORDER( _position ) ((((_position) == RULE_FIXED_HEAD) || ((_position) == RULE_FIXED_TAIL)) ? 1 : 0 )
+
+/* Attention! This version of the macro uses AVP_BY_NAME_AND_VENDOR, in contrast to most other copies! */
+#define PARSE_loc_rules( _rulearray, _parent) {                                                         \
+        int __ar;                                                                                       \
+        for (__ar=0; __ar < sizeof(_rulearray) / sizeof((_rulearray)[0]); __ar++) {                     \
+                struct dict_rule_data __data = { NULL,                                                  \
+                        (_rulearray)[__ar].position,                                                    \
+                        0,                                                                              \
+                        (_rulearray)[__ar].min,                                                         \
+                        (_rulearray)[__ar].max};                                                        \
+                __data.rule_order = RULE_ORDER(__data.rule_position);                                   \
+                CHECK_FCT(  fd_dict_search(                                                             \
+                        fd_g_config->cnf_dict,                                                          \
+                        DICT_AVP,                                                                       \
+                        AVP_BY_NAME_AND_VENDOR,                                                         \
+                        &(_rulearray)[__ar].avp_vendor_plus_name,                                       \
+                        &__data.rule_avp, 0 ) );                                                        \
+                if ( !__data.rule_avp ) {                                                               \
+                        TRACE_DEBUG(INFO, "AVP Not found: '%s'", (_rulearray)[__ar].avp_vendor_plus_name.avp_name);             \
+                        return ENOENT;                                                                  \
+                }                                                                                       \
+                {                                                                                       \
+                         int _ret = fd_dict_new( fd_g_config->cnf_dict, DICT_RULE, &(__data), (_parent), NULL ); \
+                         if ( _ret != 0 && _ret != EEXIST )      {                                      \
+                                TRACE_DEBUG(INFO, "Error on rule with AVP '%s'",                        \
+                                            (_rulearray)[__ar].avp_vendor_plus_name.avp_name);          \
+                                return EINVAL;                                                          \
+                         }                                                                              \
+                }                                                                                       \
+        }                                                                                               \
+}
+
+#define CHECK_vendor_new( _data ) { \
+        struct dict_object * vendor_found; \
+        if (fd_dict_search(fd_g_config->cnf_dict,DICT_VENDOR,VENDOR_BY_ID,&_data.vendor_id,&vendor_found,ENOENT) == ENOENT) { \
+                CHECK_FCT(fd_dict_new(fd_g_config->cnf_dict, DICT_VENDOR, &_data, NULL, NULL)); \
+        } \
+}
+
+#define enumval_def_u32( _val_, _str_ )		\
+    { _str_, 		{ .u32 = _val_ }}
+
+#define enumval_def_os( _len_, _val_, _str_ )				\
+    { _str_, 		{ .os = { .data = (unsigned char *)_val_, .len = _len_ }}}
+
+
+static int dict_rfc7683_avps_load_defs(char * conffile)
+{
+   TRACE_ENTRY("%p", conffile);
+
+   /* AVP section */
+   {
+		struct dict_object * Address_type;
+		struct dict_object * UTF8String_type;
+		struct dict_object * DiameterIdentity_type;
+		struct dict_object * DiameterURI_type;
+		struct dict_object * Time_type;
+		struct dict_object * IPFilterRule_type;
+
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "Address", &Address_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "UTF8String", &UTF8String_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "DiameterIdentity", &DiameterIdentity_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "DiameterURI", &DiameterURI_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "Time", &Time_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "IPFilterRule", &IPFilterRule_type);
+		/* OC-Feature-Vector */
+		{
+			struct dict_avp_data data = {
+				622,	/* Code */
+				0,	/* Vendor */
+				"OC-Feature-Vector",	/* Name */
+				AVP_FLAG_VENDOR,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED64	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* OC-Sequence-Number */
+		{
+			struct dict_avp_data data = {
+				624,	/* Code */
+				0,	/* Vendor */
+				"OC-Sequence-Number",	/* Name */
+				AVP_FLAG_VENDOR,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED64	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* OC-Validity-Duration */
+		{
+			struct dict_avp_data data = {
+				625,	/* Code */
+				0,	/* Vendor */
+				"OC-Validity-Duration",	/* Name */
+				AVP_FLAG_VENDOR,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* OC-Report-Type */
+		{
+			struct dict_avp_data data = {
+				626,	/* Code */
+				0,	/* Vendor */
+				"OC-Report-Type",	/* Name */
+				AVP_FLAG_VENDOR,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "Enumerated(OC-Report-Type)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "HOST_REPORT", { .i32=0 }};
+			struct dict_enumval_data        t_2 = { "REALM_REPORT", { .i32=1 }};
+			struct dict_enumval_data        t_3 = { "Texas", { .i32=75034 }};
+			struct dict_enumval_data        t_4 = { "CA", { .i32=95134 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_3, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_4, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* OC-Reduction-Percentage */
+		{
+			struct dict_avp_data data = {
+				627,	/* Code */
+				0,	/* Vendor */
+				"OC-Reduction-Percentage",	/* Name */
+				AVP_FLAG_VENDOR,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* OC-Supported-Features */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				621,	/* Code */
+				0,	/* Vendor */
+				"OC-Supported-Features",	/* Name */
+				AVP_FLAG_VENDOR,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* OC-OLR */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				623,	/* Code */
+				0,	/* Vendor */
+				"OC-OLR",	/* Name */
+				AVP_FLAG_VENDOR,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+
+	
+   }
+
+   /* Commands section */
+   {
+
+   }
+
+   return 0;
+}
+
+static int dict_rfc7683_avps_load_rules(char * conffile)
+{
+   /* Grouped AVP section */
+   {
+	  /* OC-Supported-Features */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 0, .avp_name = "OC-Supported-Features"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 0, .avp_name = "OC-Feature-Vector"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* OC-OLR */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 0, .avp_name = "OC-OLR"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 0, .avp_name = "OC-Sequence-Number"}, RULE_FIXED_HEAD, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "OC-Report-Type"}, RULE_FIXED_HEAD, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "OC-Reduction-Percentage"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "OC-Validity-Duration"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+
+   }	
+
+   /* Commands section */
+   {
+
+   }
+
+   LOG_D( "Extension 'Dictionary definitions for rfc7683_avps (None)' initialized");
+   return 0;
+}
+
+int dict_entry(char * conffile)
+{
+	dict_rfc7683_avps_load_defs(conffile);
+	return dict_rfc7683_avps_load_rules(conffile);
+}
+
+const char* dict_rfc7683_avps_proto_ver(char * conffile) {
+	return rfc7683_avps_proto_ver;
+}
+
+const double dict_rfc7683_avps_gen_ts(char * conffile) {
+	return rfc7683_avps_gen_date;
+}
+
+EXTENSION_ENTRY2("dict_rfc7683_avps", dict_rfc7683_avps_load_defs, dict_rfc7683_avps_load_rules);
+
+
+
diff --git a/extensions/dict_rfc7683_avps/rfc7683_avps.did b/extensions/dict_rfc7683_avps/rfc7683_avps.did
new file mode 100644
index 0000000..926b149
--- /dev/null
+++ b/extensions/dict_rfc7683_avps/rfc7683_avps.did
@@ -0,0 +1 @@
+dict_rfc7683_avps
diff --git a/extensions/dict_rfc7944_avps/CMakeLists.txt b/extensions/dict_rfc7944_avps/CMakeLists.txt
new file mode 100644
index 0000000..8df8df8
--- /dev/null
+++ b/extensions/dict_rfc7944_avps/CMakeLists.txt
@@ -0,0 +1,16 @@
+# The dict_rfc7944_avps extension
+PROJECT("dict_rfc7944_avps library generated by FdGen " C)
+
+# Compile as a module
+FD_ADD_EXTENSION(dict_rfc7944_avps dict_rfc7944_avps.c)
+
+
+####
+## INSTALL section ##
+
+INSTALL(TARGETS dict_rfc7944_avps
+	LIBRARY DESTINATION ${INSTALL_EXTENSIONS_SUFFIX}
+COMPONENT freeDiameter-dictionary-RFC7944_AVPS)
+
+
+
diff --git a/extensions/dict_rfc7944_avps/dict_rfc7944_avps.c b/extensions/dict_rfc7944_avps/dict_rfc7944_avps.c
new file mode 100644
index 0000000..6c1bd17
--- /dev/null
+++ b/extensions/dict_rfc7944_avps/dict_rfc7944_avps.c
@@ -0,0 +1,212 @@
+/*
+* Copyright (c) 2017 Sprint
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*    http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+/****************
+ Generated By: fdtool enhancements to diafuzzer
+ License: same as freeDiameter
+****************/
+
+
+/* 
+ * Dictionary definitions of objects specified in rfc7944_avps.
+ */
+#include <freeDiameter/extension.h>
+
+#define PROTO_VER "unspecified"
+#define GEN_DATE  1506697143.69
+
+const char *rfc7944_avps_proto_ver = PROTO_VER;
+const double rfc7944_avps_gen_date = GEN_DATE;
+
+/* The content of this file follows the same structure as dict_base_proto.c */
+
+#define CHECK_dict_new( _type, _data, _parent, _ref )                                     \
+{                                                                                         \
+    int _ret = fd_dict_new( fd_g_config->cnf_dict, (_type), (_data), (_parent), (_ref) ); \
+    if ( _ret != 0 && _ret != EEXIST )                                                    \
+       return _ret;                                                                       \
+}
+
+#define CHECK_dict_search( _type, _criteria, _what, _result )		\
+    CHECK_FCT(  fd_dict_search( fd_g_config->cnf_dict, (_type), (_criteria), (_what), (_result), ENOENT) );
+
+struct local_rules_definition {
+    struct dict_avp_request avp_vendor_plus_name;
+    enum rule_position	position;
+    int 			min;
+    int			max;
+};
+
+#define RULE_ORDER( _position ) ((((_position) == RULE_FIXED_HEAD) || ((_position) == RULE_FIXED_TAIL)) ? 1 : 0 )
+
+/* Attention! This version of the macro uses AVP_BY_NAME_AND_VENDOR, in contrast to most other copies! */
+#define PARSE_loc_rules( _rulearray, _parent) {                                                         \
+        int __ar;                                                                                       \
+        for (__ar=0; __ar < sizeof(_rulearray) / sizeof((_rulearray)[0]); __ar++) {                     \
+                struct dict_rule_data __data = { NULL,                                                  \
+                        (_rulearray)[__ar].position,                                                    \
+                        0,                                                                              \
+                        (_rulearray)[__ar].min,                                                         \
+                        (_rulearray)[__ar].max};                                                        \
+                __data.rule_order = RULE_ORDER(__data.rule_position);                                   \
+                CHECK_FCT(  fd_dict_search(                                                             \
+                        fd_g_config->cnf_dict,                                                          \
+                        DICT_AVP,                                                                       \
+                        AVP_BY_NAME_AND_VENDOR,                                                         \
+                        &(_rulearray)[__ar].avp_vendor_plus_name,                                       \
+                        &__data.rule_avp, 0 ) );                                                        \
+                if ( !__data.rule_avp ) {                                                               \
+                        TRACE_DEBUG(INFO, "AVP Not found: '%s'", (_rulearray)[__ar].avp_vendor_plus_name.avp_name);             \
+                        return ENOENT;                                                                  \
+                }                                                                                       \
+                {                                                                                       \
+                         int _ret = fd_dict_new( fd_g_config->cnf_dict, DICT_RULE, &(__data), (_parent), NULL ); \
+                         if ( _ret != 0 && _ret != EEXIST )      {                                      \
+                                TRACE_DEBUG(INFO, "Error on rule with AVP '%s'",                        \
+                                            (_rulearray)[__ar].avp_vendor_plus_name.avp_name);          \
+                                return EINVAL;                                                          \
+                         }                                                                              \
+                }                                                                                       \
+        }                                                                                               \
+}
+
+#define CHECK_vendor_new( _data ) { \
+        struct dict_object * vendor_found; \
+        if (fd_dict_search(fd_g_config->cnf_dict,DICT_VENDOR,VENDOR_BY_ID,&_data.vendor_id,&vendor_found,ENOENT) == ENOENT) { \
+                CHECK_FCT(fd_dict_new(fd_g_config->cnf_dict, DICT_VENDOR, &_data, NULL, NULL)); \
+        } \
+}
+
+#define enumval_def_u32( _val_, _str_ )		\
+    { _str_, 		{ .u32 = _val_ }}
+
+#define enumval_def_os( _len_, _val_, _str_ )				\
+    { _str_, 		{ .os = { .data = (unsigned char *)_val_, .len = _len_ }}}
+
+
+static int dict_rfc7944_avps_load_defs(char * conffile)
+{
+   TRACE_ENTRY("%p", conffile);
+
+   /* AVP section */
+   {
+		struct dict_object * Address_type;
+		struct dict_object * UTF8String_type;
+		struct dict_object * DiameterIdentity_type;
+		struct dict_object * DiameterURI_type;
+		struct dict_object * Time_type;
+		struct dict_object * IPFilterRule_type;
+
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "Address", &Address_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "UTF8String", &UTF8String_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "DiameterIdentity", &DiameterIdentity_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "DiameterURI", &DiameterURI_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "Time", &Time_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "IPFilterRule", &IPFilterRule_type);
+		/* DRMP */
+		{
+			struct dict_avp_data data = {
+				301,	/* Code */
+				0,	/* Vendor */
+				"DRMP",	/* Name */
+				AVP_FLAG_VENDOR,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "Enumerated(DRMP)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "PRIORITY_15", { .i32=15 }};
+			struct dict_enumval_data        t_2 = { "PRIORITY_14", { .i32=14 }};
+			struct dict_enumval_data        t_3 = { "PRIORITY_13", { .i32=13 }};
+			struct dict_enumval_data        t_4 = { "PRIORITY_12", { .i32=12 }};
+			struct dict_enumval_data        t_5 = { "PRIORITY_11", { .i32=11 }};
+			struct dict_enumval_data        t_6 = { "PRIORITY_10", { .i32=10 }};
+			struct dict_enumval_data        t_7 = { "PRIORITY_9", { .i32=9 }};
+			struct dict_enumval_data        t_8 = { "PRIORITY_8", { .i32=8 }};
+			struct dict_enumval_data        t_9 = { "PRIORITY_7", { .i32=7 }};
+			struct dict_enumval_data        t_10 = { "PRIORITY_6", { .i32=6 }};
+			struct dict_enumval_data        t_11 = { "PRIORITY_5", { .i32=5 }};
+			struct dict_enumval_data        t_12 = { "PRIORITY_4", { .i32=4 }};
+			struct dict_enumval_data        t_13 = { "PRIORITY_3", { .i32=3 }};
+			struct dict_enumval_data        t_14 = { "PRIORITY_2", { .i32=2 }};
+			struct dict_enumval_data        t_15 = { "PRIORITY_1", { .i32=1 }};
+			struct dict_enumval_data        t_16 = { "PRIORITY_0", { .i32=0 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_3, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_4, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_5, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_6, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_7, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_8, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_9, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_10, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_11, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_12, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_13, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_14, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_15, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_16, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+
+	
+   }
+
+   /* Commands section */
+   {
+
+   }
+
+   return 0;
+}
+
+static int dict_rfc7944_avps_load_rules(char * conffile)
+{
+   /* Grouped AVP section */
+   {
+
+   }	
+
+   /* Commands section */
+   {
+
+   }
+
+   LOG_D( "Extension 'Dictionary definitions for rfc7944_avps (None)' initialized");
+   return 0;
+}
+
+int dict_entry(char * conffile)
+{
+	dict_rfc7944_avps_load_defs(conffile);
+	return dict_rfc7944_avps_load_rules(conffile);
+}
+
+const char* dict_rfc7944_avps_proto_ver(char * conffile) {
+	return rfc7944_avps_proto_ver;
+}
+
+const double dict_rfc7944_avps_gen_ts(char * conffile) {
+	return rfc7944_avps_gen_date;
+}
+
+EXTENSION_ENTRY2("dict_rfc7944_avps", dict_rfc7944_avps_load_defs, dict_rfc7944_avps_load_rules);
+
+
+
diff --git a/extensions/dict_rfc7944_avps/rfc7944_avps.did b/extensions/dict_rfc7944_avps/rfc7944_avps.did
new file mode 100644
index 0000000..bce475a
--- /dev/null
+++ b/extensions/dict_rfc7944_avps/rfc7944_avps.did
@@ -0,0 +1 @@
+dict_rfc7944_avps
diff --git a/extensions/dict_sip/CMakeLists.txt b/extensions/dict_sip/CMakeLists.txt
new file mode 100644
index 0000000..03409d7
--- /dev/null
+++ b/extensions/dict_sip/CMakeLists.txt
@@ -0,0 +1,13 @@
+# The dict_sip extension
+PROJECT("Diameter SIP (RFC4740) dictionary definitions" C)
+
+# Compile as a module
+FD_ADD_EXTENSION(dict_sip dict_sip.c)
+
+
+####
+## INSTALL section ##
+
+INSTALL(TARGETS dict_sip
+	LIBRARY DESTINATION ${INSTALL_EXTENSIONS_SUFFIX}
+	COMPONENT freeDiameter-dictionary-RFC4740)
diff --git a/extensions/dict_sip/dict_sip.c b/extensions/dict_sip/dict_sip.c
new file mode 100644
index 0000000..636c0cb
--- /dev/null
+++ b/extensions/dict_sip/dict_sip.c
@@ -0,0 +1,2952 @@
+/*********************************************************************************************************
+* Software License Agreement (BSD License)                                                               *
+* Author: Alexandre Westfahl <awestfahl@freediameter.net>						 *
+*													 *
+* Copyright (c) 2010, Alexandre Westfahl, Teraoka Laboratory (Keio University), and the WIDE Project. 	 *										 *
+* All rights reserved.											 *
+* 													 *
+* Redistribution and use of this software in source and binary forms, with or without modification, are  *
+* permitted provided that the following conditions are met:						 *
+* 													 *
+* * Redistributions of source code must retain the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer.										 *
+*    													 *
+* * Redistributions in binary form must reproduce the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer in the documentation and/or other						 *
+*   materials provided with the distribution.								 *
+* 													 *
+* * Neither the name of the Teraoka Laboratory nor the 							 *
+*   names of its contributors may be used to endorse or 						 *
+*   promote products derived from this software without 						 *
+*   specific prior written permission of Teraoka Laboratory 						 *
+*   													 *
+* 													 *
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED *
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
+* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR *
+* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 	 *
+* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 	 *
+* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR *
+* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF   *
+* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.								 *
+*********************************************************************************************************/
+
+#include <freeDiameter/extension.h>
+
+
+
+/* The content of this file follows the same structure as dict_base_proto.c */
+
+#define CHECK_dict_new( _type, _data, _parent, _ref )	\
+	CHECK_FCT(  fd_dict_new( fd_g_config->cnf_dict, (_type), (_data), (_parent), (_ref))  );
+
+#define CHECK_dict_search( _type, _criteria, _what, _result )	\
+	CHECK_FCT(  fd_dict_search( fd_g_config->cnf_dict, (_type), (_criteria), (_what), (_result), ENOENT) );
+
+struct local_rules_definition {
+	char 			*avp_name;
+	enum rule_position	position;
+	int 			min;
+	int			max;
+};
+
+#define RULE_ORDER( _position ) ((((_position) == RULE_FIXED_HEAD) || ((_position) == RULE_FIXED_TAIL)) ? 1 : 0 )
+
+#define PARSE_loc_rules( _rulearray, _parent) {								\
+	int __ar;											\
+	for (__ar=0; __ar < sizeof(_rulearray) / sizeof((_rulearray)[0]); __ar++) {			\
+		struct dict_rule_data __data = { NULL, 							\
+			(_rulearray)[__ar].position,							\
+			0, 										\
+			(_rulearray)[__ar].min,								\
+			(_rulearray)[__ar].max};							\
+		__data.rule_order = RULE_ORDER(__data.rule_position);					\
+		CHECK_FCT(  fd_dict_search( 								\
+			fd_g_config->cnf_dict,								\
+			DICT_AVP, 									\
+			AVP_BY_NAME, 									\
+			(_rulearray)[__ar].avp_name, 							\
+			&__data.rule_avp, 0 ) );							\
+		if ( !__data.rule_avp ) {								\
+			TRACE_DEBUG(INFO, "AVP Not found: '%s'", (_rulearray)[__ar].avp_name );		\
+			return ENOENT;									\
+		}											\
+		CHECK_FCT_DO( fd_dict_new( fd_g_config->cnf_dict, DICT_RULE, &__data, _parent, NULL),	\
+			{							        		\
+				TRACE_DEBUG(INFO, "Error on rule with AVP '%s'",      			\
+					 (_rulearray)[__ar].avp_name );		      			\
+				return EINVAL;					      			\
+			} );							      			\
+	}									      			\
+}
+
+#define enumval_def_u32( _val_, _str_ ) \
+		{ _str_, 		{ .u32 = _val_ }}
+
+#define enumval_def_os( _len_, _val_, _str_ ) \
+		{ _str_, 		{ .os = { .data = (unsigned char *)_val_, .len = _len_ }}}
+
+
+
+int ds_dict_init(char * conffile)
+{
+	struct dict_object * sip;
+	{
+		struct dict_application_data data  = { 	6, "Diameter Session Initiation Protocol (SIP) Application"	};
+		CHECK_dict_new( DICT_APPLICATION, &data , NULL, &sip);
+	}
+
+	/* AVP section */
+	{
+		struct dict_object * UTF8String_type;
+		struct dict_object * DiameterURI_type;
+
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "UTF8String", &UTF8String_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "DiameterURI", &DiameterURI_type);
+
+		/* Digest AVPs (from RADIUS) */
+		
+		/* Digest-Response */
+		{
+			/*
+
+			*/
+
+			struct dict_avp_data data = { 
+					103, 					/* Code */
+					0, 					/* Vendor */
+					"Digest-Response", 		/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,		 	/* Fixed flag values */
+					AVP_TYPE_OCTETSTRING 			/* base type of data */
+					};
+			CHECK_dict_new( DICT_AVP, &data , UTF8String_type, NULL);
+		}
+
+		/* Digest-Realm */
+		{
+			/*
+
+			*/
+
+			struct dict_avp_data data = { 
+					104, 					/* Code */
+					0, 					/* Vendor */
+					"Digest-Realm", 		/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,		 	/* Fixed flag values */
+					AVP_TYPE_OCTETSTRING 			/* base type of data */
+					};
+			CHECK_dict_new( DICT_AVP, &data , UTF8String_type, NULL);
+		}
+
+		/* Digest-Nonce */
+		{
+			/*
+
+			*/
+
+			struct dict_avp_data data = { 
+					105, 					/* Code */
+					0, 					/* Vendor */
+					"Digest-Nonce", 		/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,		 	/* Fixed flag values */
+					AVP_TYPE_OCTETSTRING 			/* base type of data */
+					};
+			CHECK_dict_new( DICT_AVP, &data , UTF8String_type, NULL);
+		}
+
+		/* Digest-Response-Auth */
+		{
+			/*
+
+			*/
+
+			struct dict_avp_data data = { 
+					106, 					/* Code */
+					0, 					/* Vendor */
+					"Digest-Response-Auth", 		/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,		 	/* Fixed flag values */
+					AVP_TYPE_OCTETSTRING 			/* base type of data */
+					};
+			CHECK_dict_new( DICT_AVP, &data , UTF8String_type, NULL);
+		}
+
+		/* Digest-Nextnonce */
+		{
+			/*
+
+			*/
+
+			struct dict_avp_data data = { 
+					107, 					/* Code */
+					0, 					/* Vendor */
+					"Digest-Nextnonce", 		/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,		 	/* Fixed flag values */
+					AVP_TYPE_OCTETSTRING 			/* base type of data */
+					};
+			CHECK_dict_new( DICT_AVP, &data , UTF8String_type, NULL);
+		}
+
+		/* Digest-Method */
+		{
+			/*
+
+			*/
+
+			struct dict_avp_data data = { 
+					108, 					/* Code */
+					0, 					/* Vendor */
+					"Digest-Method", 		/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,		 	/* Fixed flag values */
+					AVP_TYPE_OCTETSTRING 			/* base type of data */
+					};
+			CHECK_dict_new( DICT_AVP, &data , UTF8String_type, NULL);
+		}
+
+		/* Digest-URI */
+		{
+			/*
+
+			*/
+
+			struct dict_avp_data data = { 
+					109, 					/* Code */
+					0, 					/* Vendor */
+					"Digest-URI", 		/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,		 	/* Fixed flag values */
+					AVP_TYPE_OCTETSTRING 			/* base type of data */
+					};
+			CHECK_dict_new( DICT_AVP, &data , UTF8String_type, NULL);
+		}
+
+		/* Digest-QoP */
+		{
+			/*
+
+			*/
+
+			struct dict_avp_data data = { 
+					110, 					/* Code */
+					0, 					/* Vendor */
+					"Digest-QoP", 		/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,		 	/* Fixed flag values */
+					AVP_TYPE_OCTETSTRING 			/* base type of data */
+					};
+			CHECK_dict_new( DICT_AVP, &data , UTF8String_type, NULL);
+		}
+
+		/* Digest-Algorithm */
+		{
+			/*
+
+			*/
+
+			struct dict_avp_data data = { 
+					111, 					/* Code */
+					0, 					/* Vendor */
+					"Digest-Algorithm", 		/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,		 	/* Fixed flag values */
+					AVP_TYPE_OCTETSTRING 			/* base type of data */
+					};
+			CHECK_dict_new( DICT_AVP, &data , UTF8String_type, NULL);
+		}
+
+		/* Digest-Entity-Body-Hash */
+		{
+			/*
+
+			*/
+
+			struct dict_avp_data data = { 
+					112, 					/* Code */
+					0, 					/* Vendor */
+					"Digest-Entity-Body-Hash", 		/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,		 	/* Fixed flag values */
+					AVP_TYPE_OCTETSTRING 			/* base type of data */
+					};
+			CHECK_dict_new( DICT_AVP, &data , UTF8String_type, NULL);
+		}
+
+		/* Digest-CNonce */
+		{
+			/*
+
+			*/
+
+			struct dict_avp_data data = { 
+					113, 					/* Code */
+					0, 					/* Vendor */
+					"Digest-CNonce", 		/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,		 	/* Fixed flag values */
+					AVP_TYPE_OCTETSTRING 			/* base type of data */
+					};
+			CHECK_dict_new( DICT_AVP, &data , UTF8String_type, NULL);
+		}
+
+		/* Digest-Nonce-Count */
+		{
+			/*
+
+			*/
+
+			struct dict_avp_data data = { 
+					114, 					/* Code */
+					0, 					/* Vendor */
+					"Digest-Nonce-Count", 		/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,		 	/* Fixed flag values */
+					AVP_TYPE_OCTETSTRING 			/* base type of data */
+					};
+			CHECK_dict_new( DICT_AVP, &data , UTF8String_type, NULL);
+		}
+
+		/* Digest-Username */
+		{
+			/*
+
+			*/
+
+			struct dict_avp_data data = { 
+					115, 					/* Code */
+					0, 					/* Vendor */
+					"Digest-Username", 		/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,		 	/* Fixed flag values */
+					AVP_TYPE_OCTETSTRING 			/* base type of data */
+					};
+			CHECK_dict_new( DICT_AVP, &data , UTF8String_type, NULL);
+		}
+
+		/* Digest-Opaque */
+		{
+			/*
+
+			*/
+
+			struct dict_avp_data data = { 
+					116, 					/* Code */
+					0, 					/* Vendor */
+					"Digest-Opaque", 		/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,		 	/* Fixed flag values */
+					AVP_TYPE_OCTETSTRING 			/* base type of data */
+					};
+			CHECK_dict_new( DICT_AVP, &data , UTF8String_type, NULL);
+		}
+
+		/* Digest-Auth-Param */
+		{
+			/*
+
+			*/
+
+			struct dict_avp_data data = { 
+					117, 					/* Code */
+					0, 					/* Vendor */
+					"Digest-Auth-Param", 		/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,		 	/* Fixed flag values */
+					AVP_TYPE_OCTETSTRING 			/* base type of data */
+					};
+			CHECK_dict_new( DICT_AVP, &data , UTF8String_type, NULL);
+		}
+
+		/* Digest-AKA-Auts */
+		{
+			/*
+
+			*/
+
+			struct dict_avp_data data = { 
+					118, 					/* Code */
+					0, 					/* Vendor */
+					"Digest-AKA-Auts", 		/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,		 	/* Fixed flag values */
+					AVP_TYPE_OCTETSTRING 			/* base type of data */
+					};
+			CHECK_dict_new( DICT_AVP, &data , UTF8String_type, NULL);
+		}
+
+		/* Digest-Domain */
+		{
+			/*
+
+			*/
+
+			struct dict_avp_data data = { 
+					119, 					/* Code */
+					0, 					/* Vendor */
+					"Digest-Domain", 		/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,		 	/* Fixed flag values */
+					AVP_TYPE_OCTETSTRING 			/* base type of data */
+					};
+			CHECK_dict_new( DICT_AVP, &data , UTF8String_type, NULL);
+		}
+
+		/* Digest-Stale */
+		{
+			/*
+
+			*/
+
+			struct dict_avp_data data = { 
+					120, 					/* Code */
+					0, 					/* Vendor */
+					"Digest-Stale", 		/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,		 	/* Fixed flag values */
+					AVP_TYPE_OCTETSTRING 			/* base type of data */
+					};
+			CHECK_dict_new( DICT_AVP, &data , UTF8String_type, NULL);
+		}
+
+		/* Digest-HA1 */
+		{
+			/*
+
+			*/
+
+			struct dict_avp_data data = { 
+					121, 					/* Code */
+					0, 					/* Vendor */
+					"Digest-HA1", 		/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,		 	/* Fixed flag values */
+					AVP_TYPE_OCTETSTRING 			/* base type of data */
+					};
+			CHECK_dict_new( DICT_AVP, &data , UTF8String_type, NULL);
+		}
+		/* SIP-AOR */
+		{
+			/*
+
+			*/
+
+			struct dict_avp_data data = { 
+					122, 					/* Code */
+					0, 					/* Vendor */
+					"SIP-AOR", 		/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,		 	/* Fixed flag values */
+					AVP_TYPE_OCTETSTRING 			/* base type of data */
+					};
+			CHECK_dict_new( DICT_AVP, &data , UTF8String_type, NULL);
+		}
+
+
+		/* Diameter SIP AVPs*/
+		/* SIP-Accounting-Server-URI*/
+		{
+			/*
+				The SIP-Accounting-Server-URI AVP (AVP Code 369) is of type
+				DiameterURI.  This AVP contains the address of a Diameter server that
+				is able to receive SIP-session-related accounting information.
+			*/
+
+			struct dict_avp_data data = { 
+					369, 					/* Code */
+					0, 					/* Vendor */
+					"SIP-Accounting-Server-URI", 		/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,		 	/* Fixed flag values */
+					AVP_TYPE_OCTETSTRING 			/* base type of data */
+					};
+			CHECK_dict_new( DICT_AVP, &data , DiameterURI_type, NULL);
+		}
+		/* SIP-Credit-Control-Server-URI */
+		{
+			/*
+			The SIP-Credit-Control-Server-URI AVP (AVP Code 370) is of type
+			DiameterURI.  This AVP contains the address of a Diameter server that
+			is able to authorize real-time credit control usage.  The Diameter
+			Credit-Control Application [RFC4006] may be used for this purpose.
+
+
+			*/
+
+			struct dict_avp_data data = { 
+					370, 					/* Code */
+					0, 					/* Vendor */
+					"SIP-Credit-Control-Server-URI", 		/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,		 	/* Fixed flag values */
+					AVP_TYPE_OCTETSTRING 			/* base type of data */
+					};
+			CHECK_dict_new( DICT_AVP, &data , DiameterURI_type, NULL);
+		}
+
+		/* SIP-Accounting-Information */
+		{
+			/*
+				The SIP-Accounting-Information (AVP Code 368) is of type Grouped, and
+				contains the Diameter addresses of those nodes that are able to
+				collect accounting information.
+
+				The SIP-Accounting-Information AVP is defined as follows (per the
+				grouped-avp-def of RFC 3588 [RFC3588]):
+
+				SIP-Accounting-Information ::= < AVP Header: 368 >
+					* [ SIP-Accounting-Server-URI ]
+					* [ SIP-Credit-Control-Server-URI ]
+					* [ AVP]
+
+			*/
+			struct dict_object * avp;
+			struct dict_avp_data data = { 
+					368, 					/* Code */
+					0, 					/* Vendor */
+					"SIP-Accounting-Information", 		/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,			/* Fixed flag values */
+					AVP_TYPE_GROUPED 			/* base type of data */
+					};
+			struct local_rules_definition rules[] = 
+						{ 	 {  "SIP-Accounting-Server-URI", 			RULE_OPTIONAL, -1, -1 }
+							,{  "SIP-Credit-Control-Server-URI",			RULE_OPTIONAL, -1, -1 }
+						};
+			
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+			PARSE_loc_rules( rules, avp );
+		}
+
+		/* SIP-Server-URI */
+		{
+			/*
+				The SIP-Server-URI AVP (AVP Code 371) is of type UTF8String.  This
+				AVP contains a SIP or SIPS URI (as defined in RFC 3261 [RFC3261])
+				that identifies a SIP server.
+			*/
+
+			struct dict_avp_data data = { 
+					371, 					/* Code */
+					0, 					/* Vendor */
+					"SIP-Server-URI", 		/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,		 	/* Fixed flag values */
+					AVP_TYPE_OCTETSTRING 			/* base type of data */
+					};
+			CHECK_dict_new( DICT_AVP, &data , UTF8String_type, NULL);
+		}
+
+		/* SIP-Mandatory-Capability */
+		{
+			/*
+				The SIP-Mandatory-Capability AVP (AVP Code 373) is of type
+				Unsigned32.  The value represents a certain capability (or set of
+				capabilities) that have to be fulfilled by the SIP server allocated
+				to the user.
+
+				The semantics of the different values are not standardized, as it is
+				a matter of the administrative network to allocate its own semantics
+				within its own network.  Each value has to represent a single
+				capability within the administrative network.
+
+			*/
+
+			struct dict_avp_data data = { 
+					373, 					/* Code */
+					0, 					/* Vendor */
+					"SIP-Mandatory-Capability", 		/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,		 	/* Fixed flag values */
+					AVP_TYPE_UNSIGNED32 			/* base type of data */
+					};
+			CHECK_dict_new( DICT_AVP, &data , NULL, NULL);
+		}
+		/* SIP-Optional-Capability */
+		{
+			/*
+				The SIP-Optional-Capability AVP (AVP Code 374) is of type Unsigned32.
+				The value represents a certain capability (or set of capabilities)
+				that, optionally, may be fulfilled by the SIP server allocated to the
+				user.
+
+				The semantics of the different values are not standardized, as it is
+				a matter of the administrative network to allocate its own semantics
+				within its own network.  Each value has to represent a single
+				capability within the administrative network.
+
+			*/
+
+			struct dict_avp_data data = { 
+					374, 					/* Code */
+					0, 					/* Vendor */
+					"SIP-Optional-Capability", 		/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,		 	/* Fixed flag values */
+					AVP_TYPE_UNSIGNED32 			/* base type of data */
+					};
+			CHECK_dict_new( DICT_AVP, &data , NULL, NULL);
+		}
+
+
+		/* SIP-Server-Capabilities */
+		{
+			/*
+				The SIP-Server-Capabilities AVP (AVP Code 372) is of type Grouped.
+				The Diameter indicates in this AVP the requirements for a particular
+				SIP capability, so that the Diameter client (SIP server) is able to
+				select another appropriate SIP server to serve the user.
+
+				The SIP-Server-Capabilities AVP allows a Diameter client (SIP server)
+				to select another SIP server for triggering or executing services to
+				the user.  A user may have enabled some services that require the
+				implementation of certain capabilities in the SIP server that
+				triggers or executes those services.  For example, the SIP server
+				that triggers or executes services to this user may need to implement
+				SIP servlets [JSR-000116], Call Processing Language (CPL) [RFC3880],
+				or any other kind of capability.  Or perhaps that user belongs to a
+				premium users group that has a certain stringent quality-of-service
+				agreement that requires a fast SIP server.  The capabilities required
+				or recommended to a given user are conveyed in the
+				SIP-Server-Capabilities AVP.  When it receives them, the Diameter
+				client (SIP server) that does the SIP server selection needs to have
+				the means to find out available SIP servers that meet the required or
+				optional capabilities.  Such means are outside the scope of this
+				specification.
+
+				Note that the SIP-Server-Capabilities AVP assists the Diameter client
+				(SIP server) to produce a subset of all the available SIP servers to
+				be allocated to the user in the Home Realm; this is the subset that
+				conforms the requirements of capabilities on a per-user basis.
+				Typically this subset will be formed of more than a single SIP
+				server, so once the subset of those SIP servers is identified, it is
+				possible that several instances of these SIP servers exist, in which
+				case the Diameter client (SIP server) should choose one particular
+				SIP server to execute and trigger services to this user.  It is
+				expected that at this point the SIP server (Diameter client) will
+				follow the procedures of RFC 3263 [RFC3263] to allocate one SIP
+				server to the user.
+
+				The SIP-Server-Capabilities AVP is defined as follows (per the
+				grouped-avp-def of RFC 3588 [RFC3588]):
+
+				SIP-Server-Capabilities ::= < AVP Header: 372 >
+					* [ SIP-Mandatory-Capability ]
+					* [ SIP-Optional-Capability ]
+					* [ SIP-Server-URI ]
+					* [ AVP ]
+	
+			*/
+			struct dict_object * avp;
+			struct dict_avp_data data = { 
+					372, 					/* Code */
+					0, 					/* Vendor */
+					"SIP-Server-Capabilities", 		/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,		 	/* Fixed flag values */
+					AVP_TYPE_GROUPED 			/* base type of data */
+					};
+			struct local_rules_definition rules[] = 
+						{ 	 {  "SIP-Mandatory-Capability", 	RULE_OPTIONAL, -1, -1 }
+							,{  "SIP-Optional-Capability",		RULE_OPTIONAL, -1, -1 }
+							,{  "SIP-Server-URI",			RULE_OPTIONAL, -1, -1 }
+						};
+			
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+			PARSE_loc_rules( rules, avp );
+		}
+
+
+		/* SIP-Server-Assignment-Type */
+		{
+			/*
+				The SIP-Server-Assignment-Type AVP (AVP Code 375) is of type
+				Enumerated and indicates the type of server update being performed in
+				a Diameter Server-Assignment-Request (SAR) operation.  The following
+				values are defined:
+
+
+				o  NO_ASSIGNMENT (0)
+				The Diameter client uses this value to request the user profile of
+				a SIP AOR, without affecting the registration state of that
+				identity.
+
+				o  REGISTRATION (1)
+				First SIP registration of a SIP AOR.
+
+				o  RE_REGISTRATION (2)
+				Subsequent SIP registration of a SIP AOR.
+
+				o  UNREGISTERED_USER (3)
+				The SIP server has received a SIP request (e.g., SIP INVITE)
+				addressed for a SIP AOR that is not registered.
+
+				o  TIMEOUT_DEREGISTRATION (4)
+				The SIP registration timer of an identity has expired.
+
+				o  USER_DEREGISTRATION (5)
+				The SIP server has received a request to deregister a SIP AOR.
+
+				o  TIMEOUT_DEREGISTRATION_STORE_SERVER_NAME (6)
+				The SIP registration timer of an identity has expired.  The SIP
+				server keeps the user data stored and requests the Diameter server
+				to store the SIP server address.
+
+				o  USER_DEREGISTRATION_STORE_SERVER_NAME (7)
+				The SIP server has received a user-initiated deregistration
+				request.  The SIP server keeps the user data stored and requests
+				the Diameter server to store the SIP server address.
+
+				o  ADMINISTRATIVE_DEREGISTRATION (8)
+				The SIP server, due to administrative reasons, has deregistered a
+				SIP AOR.
+
+				o  AUTHENTICATION_FAILURE (9)
+				The authentication of a user has failed.
+
+				o  AUTHENTICATION_TIMEOUT (10)
+				The authentication timer has expired.
+
+				o  DEREGISTRATION_TOO_MUCH_DATA (11)
+				The SIP server has requested user profile information from the
+				Diameter server and has received a volume of data higher than it
+				can accept.
+
+			*/
+			struct dict_object 	*type;
+			struct dict_type_data 	 tdata = { AVP_TYPE_UNSIGNED32,	"Enumerated(SIP-Server-Assignment-Type)"	, NULL, NULL};
+			struct dict_enumval_data tvals[] = {
+				enumval_def_u32( 0, "NO_ASSIGNMENT"),
+				enumval_def_u32( 1, "REGISTRATION"),
+				enumval_def_u32( 2, "RE_REGISTRATION"),
+				enumval_def_u32( 3, "UNREGISTERED_USER"),
+				enumval_def_u32( 4, "TIMEOUT_DEREGISTRATION"),
+				enumval_def_u32( 5, "USER_DEREGISTRATION"),
+				enumval_def_u32( 6, "TIMEOUT_DEREGISTRATION_STORE_SERVER_NAME"),
+				enumval_def_u32( 7, "USER_DEREGISTRATION_STORE_SERVER_NAME"),
+				enumval_def_u32( 8, "ADMINISTRATIVE_DEREGISTRATION"),
+				enumval_def_u32( 9, "AUTHENTICATION_FAILURE"),
+				enumval_def_u32( 10, "AUTHENTICATION_TIMEOUT"),
+				enumval_def_u32( 11, "DEREGISTRATION_TOO_MUCH_DATA")
+			};
+			struct dict_avp_data data = { 
+					375, 					/* Code */
+					0, 					/* Vendor */
+					"SIP-Server-Assignment-Type", 		/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,		 	/* Fixed flag values */
+					AVP_TYPE_UNSIGNED32 			/* base type of data */
+			};
+			int i;
+			/* Create the Enumerated type, enumerated values, and the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata , NULL, &type);
+			for (i = 0; i < sizeof(tvals) / sizeof(tvals[0]); i++) {
+				CHECK_dict_new( DICT_ENUMVAL, &tvals[i], type, NULL);
+			}
+			CHECK_dict_new( DICT_AVP, &data , type, NULL);
+		}
+		
+
+		/* SIP-Authenticate */
+		{
+			/*
+				The SIP-Authenticate AVP (AVP Code 379) is of type Grouped and
+				contains a reconstruction of either the SIP WWW-Authenticate or
+				Proxy-Authentication header fields specified in RFC 2617 [RFC2617]
+				for the HTTP Digest authentication scheme.  Additionally, the AVP may
+				include a Digest-HA1 AVP that contains H(A1) (as defined in RFC 2617
+				[RFC2617]).  H(A1) allows the Diameter client to create an expected
+				response and compare it with the Digest response received from the
+				SIP UA.
+				The SIP-Authenticate AVP is defined as follows (per the
+				grouped-avp-def of RFC 3588 [RFC3588]):
+
+				SIP-Authenticate ::= < AVP Header: 379 >
+						   { Digest-Realm }
+						   { Digest-Nonce }
+						   [ Digest-Domain ]
+						   [ Digest-Opaque ]
+						   [ Digest-Stale ]
+						   [ Digest-Algorithm ]
+						   [ Digest-QoP ]
+						   [ Digest-HA1]
+						 * [ Digest-Auth-Param ]
+						 * [ AVP ]
+
+
+			*/
+			struct dict_object * avp;
+			struct dict_avp_data data = { 
+					379, 					/* Code */
+					0, 					/* Vendor */
+					"SIP-Authenticate", 		/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,		 	/* Fixed flag values */
+					AVP_TYPE_GROUPED 			/* base type of data */
+					};
+			struct local_rules_definition rules[] = 
+						{ 	 {  "Digest-Realm", 		RULE_REQUIRED, -1, 1 }
+							,{  "Digest-Nonce",		RULE_REQUIRED, -1, 1 }
+							,{  "Digest-Domain",		RULE_OPTIONAL, -1, 1 }
+							,{  "Digest-Opaque",		RULE_OPTIONAL, -1, 1 }
+							,{  "Digest-Stale",		RULE_OPTIONAL, -1, 1 }
+							,{  "Digest-Algorithm",		RULE_OPTIONAL, -1, 1 }
+							,{  "Digest-QoP",		RULE_OPTIONAL, -1, 1 }
+							,{  "Digest-HA1",		RULE_OPTIONAL, -1, 1 }
+							,{  "Digest-Auth-Param",	RULE_OPTIONAL, -1, -1 }
+
+						};
+			
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+			PARSE_loc_rules( rules, avp );
+		}
+		/* SIP-Authorization */
+		{
+			/*
+				The SIP-Authorization AVP (AVP Code 380) is of type Grouped and
+				contains a reconstruction of either the SIP Authorization or
+				Proxy-Authorization header fields specified in RFC 2617 [RFC2617] for
+				the HTTP Digest authentication scheme.
+
+				The SIP-Authorization AVP is defined as follows (per the
+				grouped-avp-def of RFC 3588 [RFC3588]):
+
+				SIP-Authorization ::= < AVP Header: 380 >
+						    { Digest-Username }
+						    { Digest-Realm }
+						    { Digest-Nonce }
+						    { Digest-URI }
+						    { Digest-Response }
+						    [ Digest-Algorithm ]
+						    [ Digest-CNonce ]
+						    [ Digest-Opaque ]
+						    [ Digest-QoP ]
+						    [ Digest-Nonce-Count ]
+						    [ Digest-Method]
+						    [ Digest-Entity-Body-Hash ]
+						  * [ Digest-Auth-Param ]
+						  * [ AVP ]
+
+			*/
+			struct dict_object * avp;
+			struct dict_avp_data data = { 
+					380, 					/* Code */
+					0, 					/* Vendor */
+					"SIP-Authorization", 		/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,		 	/* Fixed flag values */
+					AVP_TYPE_GROUPED 			/* base type of data */
+					};
+			struct local_rules_definition rules[] = 
+						{ 	 {  "Digest-Username", 		RULE_REQUIRED, -1, 1 }
+							,{  "Digest-Realm",		RULE_REQUIRED, -1, 1 }
+							,{  "Digest-Nonce",		RULE_REQUIRED, -1, 1 }
+							,{  "Digest-URI",		RULE_REQUIRED, -1, 1 }
+							,{  "Digest-Response",		RULE_REQUIRED, -1, 1 }
+							,{  "Digest-Algorithm",		RULE_OPTIONAL, -1, 1 }
+							,{  "Digest-CNonce",		RULE_OPTIONAL, -1, 1 }
+							,{  "Digest-Opaque",		RULE_OPTIONAL, -1, 1 }
+							,{  "Digest-QoP",		RULE_OPTIONAL, -1, 1 }
+							,{  "Digest-Nonce-Count",	RULE_OPTIONAL, -1, 1 }
+							,{  "Digest-Method",		RULE_OPTIONAL, -1, 1 }
+							,{  "Digest-Entity-Body-Hash",	RULE_OPTIONAL, -1, 1 }
+							,{  "Digest-Auth-Param",	RULE_OPTIONAL, -1, -1 }
+						};
+			
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+			PARSE_loc_rules( rules, avp );
+		}
+		/* SIP-Authentication-Info */
+		{
+			/*
+				The SIP-Authentication-Info AVP (AVP Code 381) is of type Grouped and
+				contains a reconstruction of the SIP Authentication-Info header
+				specified in RFC 2617 [RFC2617] for the HTTP Digest authentication
+				scheme.
+				The SIP-Authentication-Info AVP is defined as follows (per the
+				grouped-avp-def of RFC 3588 [RFC3588]):
+
+				SIP-Authentication-Info ::= < AVP Header: 381 >
+							  [ Digest-Nextnonce ]
+							  [ Digest-QoP ]
+							  [ Digest-Response-Auth ]
+							  [ Digest-CNonce ]
+							  [ Digest-Nonce-Count ]
+							* [ AVP ]
+
+				Note that, in some cases, the Digest-Response-Auth AVP cannot be
+				calculated at the Diameter server, but has to be calculated at the
+				Diameter client (SIP server).  For example, if the value of the
+				quality of protection (qop) parameter in Digest is set to "auth-int",
+				then the response-digest (rspauth parameter value in Digest) is
+				calculated with the hash of the body of the SIP response, which is
+				not available at the Diameter server.  In this case, the Diameter
+				client (SIP server) must calculate the response-digest once the body
+				of the SIP response is calculated.
+
+				Therefore, a value of "auth-int" in the Digest-QoP AVP of the
+				SIP-Authentication-Info AVP indicates that the Diameter client (SIP
+				server) MUST compute the Digest "rspauth" parameter value at the
+				Diameter client (SIP server).
+
+			*/
+			struct dict_object * avp;
+			struct dict_avp_data data = { 
+					381, 					/* Code */
+					0, 					/* Vendor */
+					"SIP-Authentication-Info", 		/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,		 	/* Fixed flag values */
+					AVP_TYPE_GROUPED 			/* base type of data */
+					};
+			struct local_rules_definition rules[] = 
+						{ 	 {  "Digest-Nextnonce", 	RULE_OPTIONAL, -1, 1 }
+							,{  "Digest-QoP",		RULE_OPTIONAL, -1, 1 }
+							,{  "Digest-Response-Auth",	RULE_OPTIONAL, -1, 1 }
+							,{  "Digest-CNonce",		RULE_OPTIONAL, -1, 1 }
+							,{  "Digest-Nonce-Count",	RULE_OPTIONAL, -1, 1 }
+						};
+			
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+			PARSE_loc_rules( rules, avp );
+		}
+		/* SIP-Authentication-Scheme */
+		{
+			/*
+				The SIP-Authentication-Scheme AVP (AVP Code 377) is of type
+				Enumerated and indicates the authentication scheme used in the
+				authentication of SIP services.  RFC 2617 identifies this value as an
+				"auth-scheme" (see Section 1.2 of RFC 2617 [RFC2617]).  The only
+				currently defined value is:
+
+				o  DIGEST (0) to indicate HTTP Digest authentication as specified in
+				RFC 2617 [RFC2617] Section 3.2.1.  Derivative work is also
+				considered Digest authentication scheme, as long as the
+				"auth-scheme" is identified as Digest in the SIP headers carrying
+				the HTTP authentication.  This includes, e.g., the HTTP Digest
+				authentication using AKA [RFC3310].
+
+				Each HTTP Digest directive (parameter) is transported in a
+				corresponding AVP, whose name follows the pattern Digest-*.  The
+				Digest-* AVPs are RADIUS attributes imported from the RADIUS
+				Extension for Digest Authentication [RFC4590] namespace, allowing a
+				smooth transition between RADIUS and Diameter applications supporting
+				SIP.  The Diameter SIP application goes a step further by grouping
+				the Digest-* AVPs into the SIP-Authenticate, SIP-Authorization, and
+				SIP-Authentication-Info grouped AVPs that correspond to the SIP WWW-
+				Authenticate/Proxy-Authentication, Authorization/Proxy-Authorization,
+				and Authentication-Info headers fields, respectively.
+
+				Note: Due to the fact that HTTP Digest authentication [RFC2617] is
+				the only mandatory authentication mechanism in SIP, this memo only
+				provides support for HTTP Digest authentication and derivative
+				work such as HTTP Digest authentication using AKA [RFC3310].
+				Extensions to this memo can register new values and new AVPs to
+				provide support for other authentication schemes or extensions to
+				HTTP Digest authentication.
+
+				Note: Although RFC 2617 [RFC2617] defines the Basic and Digest
+				schemes for authenticating HTTP requests, RFC 3261 [RFC3261] only
+				imports HTTP Digest as a mechanism to provide authentication in
+				SIP.
+
+				Due to syntactic requirements, HTTP Digest authentication has to
+				escape quote characters in contents of HTTP Digest directives.  When
+				translating directives into Digest-* AVPs, the Diameter client or
+				server removes the surrounding quotes where present, as required by
+				the syntax of the Digest-* attributes defined in the "RADIUS
+				Extension for Digest Authentication" [RFC4590].
+
+			*/
+
+			struct dict_object 	*type;
+			struct dict_type_data 	 tdata = { AVP_TYPE_UNSIGNED32,	"Enumerated(SIP-Authentication-Scheme)"	, NULL, NULL};
+			struct dict_enumval_data tvals[] = {
+				enumval_def_u32( 0, "DIGEST")
+			};
+			struct dict_avp_data data = { 
+					377, 					/* Code */
+					0, 					/* Vendor */
+					"SIP-Authentication-Scheme", 		/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,		 	/* Fixed flag values */
+					AVP_TYPE_UNSIGNED32 			/* base type of data */
+			};
+			int i;
+			/* Create the Enumerated type, enumerated values, and the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata , NULL, &type);
+			for (i = 0; i < sizeof(tvals) / sizeof(tvals[0]); i++) {
+				CHECK_dict_new( DICT_ENUMVAL, &tvals[i], type, NULL);
+			}
+			CHECK_dict_new( DICT_AVP, &data , type, NULL);
+		}
+		/* SIP-Item-Number */
+		{
+			/*
+				The SIP-Item-Number (AVP Code 378) is of type Unsigned32 and is
+				included in a SIP-Auth-Data-Item grouped AVP in circumstances where
+				there are multiple occurrences of SIP-Auth-Data-Item AVPs and the
+				order of processing is relevant.  The AVP indicates the order in
+				which the Grouped SIP-Auth-Data-Item should be processed.  Lower
+				values of the SIP-Item-Number AVP indicate that the whole
+				SIP-Auth-Data-Item SHOULD be processed before other
+				SIP-Auth-Data-Item AVPs that contain higher values in the
+				SIP-Item-Number AVP.
+
+			*/
+
+			struct dict_avp_data data = { 
+					378, 					/* Code */
+					0, 					/* Vendor */
+					"SIP-Item-Number", 		/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,		 	/* Fixed flag values */
+					AVP_TYPE_UNSIGNED32 			/* base type of data */
+					};
+			CHECK_dict_new( DICT_AVP, &data , NULL, NULL);
+		}
+		/* SIP-Auth-Data-Item */
+		{
+			/*
+				The SIP-Auth-Data-Item (AVP Code 376) is of type Grouped and contains
+				the authentication and/or authorization information pertaining to a
+				user.
+
+				When the Diameter server uses the grouped SIP-Auth-Data-Item AVP to
+				include a SIP-Authenticate AVP, the Diameter server MUST send a
+				maximum of one authentication data item (e.g., in case the SIP
+				request contained several credentials).  Section 11 contains a
+				detailed discussion and normative text of the case when a SIP request
+				contains several credentials.
+
+				The SIP-Auth-Data-Item AVP is defined as follows (per the
+				grouped-avp-def of RFC 3588 [RFC3588]):
+
+				SIP-Auth-Data-Item ::= < AVP Header: 376 >
+				{ SIP-Authentication-Scheme }
+					[ SIP-Item-Number ]
+					[ SIP-Authenticate ]
+					[ SIP-Authorization ]
+					[ SIP-Authentication-Info ]
+					* [ AVP ]
+
+
+			*/
+			struct dict_object * avp;
+			struct dict_avp_data data = { 
+					376, 					/* Code */
+					0, 					/* Vendor */
+					"SIP-Auth-Data-Item", 		/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,		 	/* Fixed flag values */
+					AVP_TYPE_GROUPED 			/* base type of data */
+					};
+			struct local_rules_definition rules[] = 
+						{ 	 {  "SIP-Authentication-Scheme",RULE_REQUIRED, -1, 1 }
+							,{  "SIP-Item-Number", 		RULE_OPTIONAL, -1, 1 }
+							,{  "SIP-Authenticate",		RULE_OPTIONAL, -1, 1 }
+							,{  "SIP-Authorization",	RULE_OPTIONAL, -1, 1 }
+							,{  "SIP-Authentication-Info",	RULE_OPTIONAL, -1, 1 }
+						};
+			
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+			PARSE_loc_rules( rules, avp );
+		}
+		/* SIP-Number-Auth-Items */
+		{
+			/*
+				The SIP-Number-Auth-Items AVP (AVP Code 382) is of type Unsigned32
+				and indicates the number of authentication and/or authorization
+				credentials that the Diameter server included in a Diameter message.
+
+				When the AVP is present in a request, it indicates the number of
+				SIP-Auth-Data-Items the Diameter client is requesting.  This can be
+				used, for instance, when the SIP server is requesting several
+				pre-calculated authentication credentials.  In the answer message,
+				the SIP-Number-Auth-Items AVP indicates the actual number of items
+				that the Diameter server included.
+
+			*/
+
+			struct dict_avp_data data = { 
+					382, 					/* Code */
+					0, 					/* Vendor */
+					"SIP-Number-Auth-Items", 		/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,		 	/* Fixed flag values */
+					AVP_TYPE_UNSIGNED32 			/* base type of data */
+					};
+			CHECK_dict_new( DICT_AVP, &data , NULL, NULL);
+		}
+
+		/* SIP-Reason-Code */
+		{
+			/*
+				The SIP-Reason-Code AVP (AVP Code 384) is of type Enumerated and
+				defines the reason for the network initiated deregistration.  The
+				following values are defined:
+
+				o  PERMANENT_TERMINATION (0)
+				o  NEW_SIP_SERVER_ASSIGNED (1)
+				o  SIP_SERVER_CHANGE (2)
+				o  REMOVE_SIP_SERVER (3)
+			*/
+
+			struct dict_object 	*type;
+			struct dict_type_data 	 tdata = { AVP_TYPE_UNSIGNED32,	"Enumerated(SIP-Reason-Code)"	, NULL, NULL};
+			struct dict_enumval_data tvals[] = {
+				enumval_def_u32( 0, "PERMANENT_TERMINATION"),
+				enumval_def_u32( 1, "NEW_SIP_SERVER_ASSIGNED"),
+				enumval_def_u32( 2, "SIP_SERVER_CHANGE"),
+				enumval_def_u32( 3, "REMOVE_SIP_SERVER")
+			};
+			struct dict_avp_data data = { 
+					384, 					/* Code */
+					0, 					/* Vendor */
+					"SIP-Reason-Code", 		/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,		 	/* Fixed flag values */
+					AVP_TYPE_UNSIGNED32 			/* base type of data */
+			};
+			int i;
+			/* Create the Enumerated type, enumerated values, and the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata , NULL, &type);
+			for (i = 0; i < sizeof(tvals) / sizeof(tvals[0]); i++) {
+				CHECK_dict_new( DICT_ENUMVAL, &tvals[i], type, NULL);
+			}
+			CHECK_dict_new( DICT_AVP, &data , type, NULL);
+		}
+
+		/* SIP-Reason-Info */
+		{
+			/*
+				The SIP-Reason-Info AVP (AVP Code 385) is of type UTF8String and
+				contains textual information that can be rendered to the user, about
+				the reason for a deregistration.
+				
+			*/
+
+			struct dict_avp_data data = { 
+					385, 					/* Code */
+					0, 					/* Vendor */
+					"SIP-Reason-Info", 		/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,		 	/* Fixed flag values */
+					AVP_TYPE_OCTETSTRING 			/* base type of data */
+					};
+			CHECK_dict_new( DICT_AVP, &data , UTF8String_type, NULL);
+		}
+
+		/* SIP-Deregistration-Reason */
+		{
+			/*
+				The SIP-Deregistration-Reason AVP (AVP Code 383) is of type Grouped
+				and indicates the reason for a deregistration operation.
+
+				The SIP-Deregistration-Reason AVP is defined as follows (per the
+				grouped-avp-def of RFC 3588 [RFC3588]):
+
+				SIP-Deregistration-Reason ::= < AVP Header: 383 >
+							    { SIP-Reason-Code }
+							    [ SIP-Reason-Info ]
+							  * [ AVP ]
+
+			*/
+			struct dict_object * avp;
+			struct dict_avp_data data = { 
+					383, 					/* Code */
+					0, 					/* Vendor */
+					"SIP-Deregistration-Reason", 		/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,		 	/* Fixed flag values */
+					AVP_TYPE_GROUPED 			/* base type of data */
+					};
+			struct local_rules_definition rules[] = 
+						{ 	 {  "SIP-Reason-Code", 	RULE_REQUIRED, -1, 1 }
+							,{  "SIP-Reason-Info",	RULE_OPTIONAL, -1, 1 }
+						};
+			
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+			PARSE_loc_rules( rules, avp );
+		}
+
+		/* SIP-Visited-Network-Id */
+		{
+			/*
+				The SIP-Visited-Network-Id AVP (AVP Code 386) is of type UTF8String.
+				This AVP contains an identifier that helps the home network identify
+				the visited network (e.g., the visited network domain name), in order
+				to authorize roaming to that visited network.
+				
+			*/
+
+			struct dict_avp_data data = { 
+					386, 					/* Code */
+					0, 					/* Vendor */
+					"SIP-Visited-Network-Id", 		/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,		 	/* Fixed flag values */
+					AVP_TYPE_OCTETSTRING 			/* base type of data */
+					};
+			CHECK_dict_new( DICT_AVP, &data , UTF8String_type, NULL);
+		}
+		/* SIP-User-Authorization-Type */
+		{
+			/*
+				The SIP-User-Authorization-Type AVP (AVP Code 387) is of type
+				Enumerated and indicates the type of user authorization being
+				performed in a User Authorization operation, i.e., the Diameter
+				User-Authorization-Request (UAR) command.  The following values are
+				defined:
+
+				o  REGISTRATION (0)
+				This value is used for initial registration or re-registration.
+				This is the default value.
+
+				o  DEREGISTRATION (1)
+				This value is used for deregistration.
+
+				o  REGISTRATION_AND_CAPABILITIES (2)
+				This value is used for initial registration or re-registration
+				when the SIP server explicitly requests the Diameter server to get
+				capability information.  This capability information helps the SIP
+				server to allocate another SIP server to serve the user.
+				
+			*/
+
+			struct dict_object 	*type;
+			struct dict_type_data 	 tdata = { AVP_TYPE_UNSIGNED32,	"Enumerated(SIP-User-Authorization-Type)"	, NULL, NULL};
+			struct dict_enumval_data tvals[] = {
+				enumval_def_u32( 0, "REGISTRATION"),
+				enumval_def_u32( 1, "DEREGISTRATION"),
+				enumval_def_u32( 2, "REGISTRATION_AND_CAPABILITIES")
+			};
+			struct dict_avp_data data = { 
+					387, 					/* Code */
+					0, 					/* Vendor */
+					"SIP-User-Authorization-Type", 		/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,		 	/* Fixed flag values */
+					AVP_TYPE_UNSIGNED32 			/* base type of data */
+			};
+			int i;
+			/* Create the Enumerated type, enumerated values, and the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata , NULL, &type);
+			for (i = 0; i < sizeof(tvals) / sizeof(tvals[0]); i++) {
+				CHECK_dict_new( DICT_ENUMVAL, &tvals[i], type, NULL);
+			}
+			CHECK_dict_new( DICT_AVP, &data , type, NULL);
+		}
+		/* SIP-Supported-User-Data-Type */
+		{
+			/*
+				The SIP-Supported-User-Data-Type AVP (AVP Code 388) is of type
+				UTF8String and contains a string that identifies the type of
+				supported user data (user profile, see SIP-User-Data AVP
+				(Section 9.12)) supported in the node.  The AVP can be repeated, if
+				the SIP server supports several user data types.  In case of
+				repetition, the Diameter client should order the different instances
+				of this AVP according to its preferences.
+
+				When the Diameter client inserts this AVP in a SAR message, it allows
+				the Diameter client to provide an indication to the Diameter server
+				of the types of user data supported by the SIP server.  The Diameter
+				server, upon inspection of these AVPs, will return a suitable
+				SIP-User-Data AVP (Section 9.12) of the type indicated in the
+				SIP-User-Data-Type AVP (Section 9.12.1).
+				
+			*/
+
+			struct dict_avp_data data = { 
+					388, 					/* Code */
+					0, 					/* Vendor */
+					"SIP-Supported-User-Data-Type", 		/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,		 	/* Fixed flag values */
+					AVP_TYPE_OCTETSTRING 			/* base type of data */
+					};
+			CHECK_dict_new( DICT_AVP, &data , UTF8String_type, NULL);
+		}
+		/* SIP-User-Data-Type */
+		{
+			/*
+				The SIP-User-Data-Type AVP (AVP Code 390) is of type UTF8String and
+				contains a string that identifies the type of user data included in
+				the SIP-User-Data-Type AVP (Section 9.12).
+
+				This document does not specify a convention to characterize the type
+				of user data contained in the SIP-User-Data-Type AVP (Section 9.12).  It
+				is believed that in most cases this feature will be used in
+				environments controlled by a network administrator who can configure
+				both the client and server to assign the same value type at the
+				client and server.  It is also RECOMMENDED that organizations
+				developing their own profile of SIP-User-Data-Type AVP (Section 9.12)
+				allocate a type based on their canonical DNS name.  For instance,
+				organization "example.com" can define several types of SIP-User-Data
+				and allocate the types "type1.dsa.example.com",
+				"type2.dsa.example.com", and so on.  This convention will avoid a
+				clash in the allocation of types of SIP-User-Data-Type AVP (Section 9.12).
+				
+			*/
+
+			struct dict_avp_data data = { 
+					390, 					/* Code */
+					0, 					/* Vendor */
+					"SIP-User-Data-Type", 		/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,		 	/* Fixed flag values */
+					AVP_TYPE_OCTETSTRING 			/* base type of data */
+					};
+			CHECK_dict_new( DICT_AVP, &data , UTF8String_type, NULL);
+		}
+		/* SIP-User-Data-Contents */
+		{
+			/*
+				The SIP-User-Data-Contents AVP (AVP Code 391) is of type OctetString.
+				The Diameter peers do not need to understand the value of this AVP.
+
+				The AVP contains the user profile data required for a SIP server to
+				give service to the user.
+
+				
+			*/
+
+			struct dict_avp_data data = { 
+					391, 					/* Code */
+					0, 					/* Vendor */
+					"SIP-User-Data-Contents", 		/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,		 	/* Fixed flag values */
+					AVP_TYPE_OCTETSTRING 			/* base type of data */
+					};
+			CHECK_dict_new( DICT_AVP, &data , NULL, NULL);
+		}
+
+		/* SIP-User-Data */
+		{
+			/*
+				The SIP-User-Data AVP (AVP Code 389) is of type Grouped.  This AVP
+				allows the Diameter server to transport user-specific data, such as a
+				user profile, to the SIP server (in the Diameter client).  The
+				Diameter server selects a type of user data that is understood by the
+				SIP server in the Diameter client, and has been indicated in a
+				SIP-Supported-User-Data-Type AVP.  In case the Diameter client
+				indicated support for several types of user data, the Diameter server
+				SHOULD choose the first type supported by the client.
+
+				The SIP-User-Data grouped AVP contains a SIP-User-Data-Type AVP that
+				indicates the type of user data included in the
+				SIP-User-Data-Contents-AVP.
+
+				The SIP-User-Data AVP is defined as follows (per the grouped-avp-def
+				of RFC 3588 [RFC3588]):
+
+
+				SIP-User-Data ::= < AVP Header: 389 >
+						{ SIP-User-Data-Type }
+						{ SIP-User-Data-Contents }
+					      * [ AVP ]
+				
+			*/
+			struct dict_object * avp;
+			struct dict_avp_data data = { 
+					389, 					/* Code */
+					0, 					/* Vendor */
+					"SIP-User-Data", 		/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,		 	/* Fixed flag values */
+					AVP_TYPE_GROUPED 			/* base type of data */
+					};
+			struct local_rules_definition rules[] = 
+						{ 	 {  "SIP-User-Data-Type", 	RULE_REQUIRED, -1, 1 }
+							,{  "SIP-User-Data-Contents",	RULE_REQUIRED, -1, 1 }
+						};
+			
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+			PARSE_loc_rules( rules, avp );
+		}
+		/* SIP-User-Data-Already-Available */
+		{
+			/*
+				The SIP-User-Data-Already-Available AVP (AVP Code 392) is of type
+				Enumerated and gives an indication to the Diameter server about
+				whether the Diameter client (SIP server) already received the portion
+				of the user profile needed in order to serve the user.  The following
+				values are defined:
+
+				o  USER_DATA_NOT_AVAILABLE (0)
+				The Diameter client (SIP server) does not have the data that it
+				needs to serve the user.
+
+				o  USER_DATA_ALREADY_AVAILABLE (1)
+				The Diameter client (SIP server) already has received the data
+				that it needs to serve the user.
+
+	
+			*/
+
+			struct dict_object 	*type;
+			struct dict_type_data 	 tdata = { AVP_TYPE_UNSIGNED32,	"Enumerated(SIP-User-Data-Already-Available)"	, NULL, NULL};
+			struct dict_enumval_data tvals[] = {
+				enumval_def_u32( 0, "USER_DATA_NOT_AVAILABLE"),
+				enumval_def_u32( 1, "USER_DATA_ALREADY_AVAILABLE")
+			};
+			struct dict_avp_data data = { 
+					392, 					/* Code */
+					0, 					/* Vendor */
+					"SIP-User-Data-Already-Available", 		/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,		 	/* Fixed flag values */
+					AVP_TYPE_UNSIGNED32 			/* base type of data */
+			};
+			int i;
+			/* Create the Enumerated type, enumerated values, and the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata , NULL, &type);
+			for (i = 0; i < sizeof(tvals) / sizeof(tvals[0]); i++) {
+				CHECK_dict_new( DICT_ENUMVAL, &tvals[i], type, NULL);
+			}
+			CHECK_dict_new( DICT_AVP, &data , type, NULL);
+		}
+		/* SIP-Method */
+		{
+			/*
+				The SIP-Method-AVP (AVP Code 393) is of type UTF8String and contains
+				the method of the SIP request that triggered the Diameter message.
+				The Diameter server MUST use this AVP solely for authorization of SIP
+				requests, and MUST NOT use it to compute the Digest authentication.
+				To compute the Digest authentication, the Diameter server MUST use
+				the Digest-Method AVP instead.
+
+				
+			*/
+
+			struct dict_avp_data data = { 
+					393, 					/* Code */
+					0, 					/* Vendor */
+					"SIP-Method", 		/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,		 	/* Fixed flag values */
+					AVP_TYPE_OCTETSTRING 			/* base type of data */
+					};
+			CHECK_dict_new( DICT_AVP, &data , UTF8String_type, NULL);
+		}
+		/* Complement of Result-Code AVP values */
+		{
+			struct dict_object * resultcode_data_type;
+			CHECK_dict_search(DICT_TYPE,TYPE_BY_NAME,"Enumerated(Result-Code)",&resultcode_data_type);
+		
+
+			{
+
+				/* Success */
+				{
+					/* 2003 */
+					{
+						/*
+							The user was not previously registered.  The Diameter server has
+							now authorized the registration.
+						*/
+						struct dict_enumval_data 	error_code = { "DIAMETER_FIRST_REGISTRATION", 	{ .u32 = 2003 }};
+						CHECK_dict_new( DICT_ENUMVAL, &error_code , resultcode_data_type, NULL);
+					}
+					/* 2004 */
+					{
+						/*
+							The user is already registered.  The Diameter server has now
+							authorized the re-registration.
+
+						*/
+						struct dict_enumval_data 	error_code = { "DIAMETER_SUBSEQUENT_REGISTRATION", 	{ .u32 = 2004 }};
+						CHECK_dict_new( DICT_ENUMVAL, &error_code , resultcode_data_type, NULL);
+					}
+					/* 2005 */
+					{
+						struct dict_enumval_data 	error_code = { "DIAMETER_UNREGISTERED_SERVICE", 	{ .u32 = 2005 }};
+						CHECK_dict_new( DICT_ENUMVAL, &error_code , resultcode_data_type, NULL);
+					}
+					/* 2006 */
+					{
+						struct dict_enumval_data 	error_code = { "DIAMETER_SUCCESS_SERVER_NAME_NOT_STORED", 	{ .u32 = 2006 }};
+						CHECK_dict_new( DICT_ENUMVAL, &error_code , resultcode_data_type, NULL);
+					}
+					/* 2007 */
+					{
+						struct dict_enumval_data 	error_code = { "DIAMETER_SERVER_SELECTION", 	{ .u32 = 2007 }};
+						CHECK_dict_new( DICT_ENUMVAL, &error_code , resultcode_data_type, NULL);
+					}
+					/* 2008 */
+					{
+						struct dict_enumval_data 	error_code = { "DIAMETER_SUCCESS_AUTH_SENT_SERVER_NOT_STORED", 	{ .u32 = 2008 }};
+						CHECK_dict_new( DICT_ENUMVAL, &error_code , resultcode_data_type, NULL);
+					}
+				}
+				/* Transient Failures */
+				{
+					/* 4013 */
+					{
+						struct dict_enumval_data 	error_code = { "DIAMETER_USER_NAME_REQUIRED", 	{ .u32 = 4013 }};
+						CHECK_dict_new( DICT_ENUMVAL, &error_code , resultcode_data_type, NULL);
+					}
+				}
+				/* Permanent Failures */
+				{
+					/* 5032 */
+					{
+						struct dict_enumval_data 	error_code = { "DIAMETER_ERROR_USER_UNKNOWN", 	{ .u32 = 5032 }};
+						CHECK_dict_new( DICT_ENUMVAL, &error_code , resultcode_data_type, NULL);
+					}
+					/* 5033 */
+					{
+						struct dict_enumval_data 	error_code = { "DIAMETER_ERROR_IDENTITIES_DONT_MATCH", 	{ .u32 = 5033 }};
+						CHECK_dict_new( DICT_ENUMVAL, &error_code , resultcode_data_type, NULL);
+					}
+					/* 5034 */
+					{
+						struct dict_enumval_data 	error_code = { "DIAMETER_ERROR_IDENTITY_NOT_REGISTERED", 	{ .u32 = 5034 }};
+						CHECK_dict_new( DICT_ENUMVAL, &error_code , resultcode_data_type, NULL);
+					}
+					/* 5035 */
+					{
+						struct dict_enumval_data 	error_code = { "DIAMETER_ERROR_ROAMING_NOT_ALLOWED", 	{ .u32 = 5035 }};
+						CHECK_dict_new( DICT_ENUMVAL, &error_code , resultcode_data_type, NULL);
+					}
+					/* 5036 */
+					{
+						struct dict_enumval_data 	error_code = { "DIAMETER_ERROR_IDENTITY_ALREADY_REGISTERED", 	{ .u32 = 5036 }};
+						CHECK_dict_new( DICT_ENUMVAL, &error_code , resultcode_data_type, NULL);
+					}
+					/* 5037 */
+					{
+						struct dict_enumval_data 	error_code = { "DIAMETER_ERROR_AUTH_SCHEME_NOT_SUPPORTED", 	{ .u32 = 5037 }};
+						CHECK_dict_new( DICT_ENUMVAL, &error_code , resultcode_data_type, NULL);
+					}
+					/* 5038 */
+					{
+						struct dict_enumval_data 	error_code = { "DIAMETER_ERROR_IN_ASSIGNMENT_TYPE", 	{ .u32 = 5038 }};
+						CHECK_dict_new( DICT_ENUMVAL, &error_code , resultcode_data_type, NULL);
+					}
+					/* 5039 */
+					{
+						struct dict_enumval_data 	error_code = { "DIAMETER_ERROR_TOO_MUCH_DATA", 	{ .u32 = 5039 }};
+						CHECK_dict_new( DICT_ENUMVAL, &error_code , resultcode_data_type, NULL);
+					}
+					/* 5040 */
+					{
+						struct dict_enumval_data 	error_code = { "DIAMETER_ERROR_NOT SUPPORTED_USER_DATA", 	{ .u32 = 5040 }};
+						CHECK_dict_new( DICT_ENUMVAL, &error_code , resultcode_data_type, NULL);
+					}
+				}
+			}
+		
+
+		}   
+	}
+	/* Command section */
+	{
+		/* User-Authorization-Request (UAR) Command */
+		{
+			/*
+			The User-Authorization-Request (UAR) is indicated by the Command-Code
+			set to 283 and the Command Flags' 'R' bit set.  The Diameter client
+			in a SIP server sends this command to the Diameter server to request
+			authorization for the SIP User Agent to route a SIP REGISTER request.
+			Because the SIP REGISTER request implicitly carries a permission to
+			bind an AOR to a contact address, the Diameter client uses the
+			Diameter UAR as a first authorization request towards the Diameter
+			server to authorize the registration.  For instance, the Diameter
+			server can verify that the AOR is a legitimate user of the realm.
+
+			The Diameter client in the SIP server requests authorization for one
+			of the possible values defined in the SIP-User-Authorization-Type AVP
+			(Section 9.10).
+
+			The user name used for authentication of the user is conveyed in a
+			User-Name AVP (defined in the Diameter base protocol, RFC 3588
+			[RFC3588]).  The location of the authentication user name in the SIP
+			REGISTER request varies depending on the authentication mechanism.
+			When the authentication mechanism is HTTP Digest as defined in RFC
+			2617 [RFC2617], the authentication user name is found in the
+			"username" directive of the SIP Authorization header field value.
+			This Diameter SIP application only provides support for HTTP Digest
+			authentication in SIP; other authentication mechanisms are not
+			currently supported.
+
+			The SIP or SIPS URI to be registered is conveyed in the SIP-AOR AVP
+			(Section 9.8).  Typically this SIP or SIPS URI is found in the To
+			header field value of the SIP REGISTER request that triggered the
+			Diameter UAR message.
+
+			The SIP-Visited-Network-Id AVP indicates the network that is
+			providing SIP services (e.g., SIP proxy functionality or any other
+			kind of services) to the SIP User Agent.
+
+			The Message Format of the UAR command is as follows:
+
+			<UAR> ::= < Diameter Header: 283, REQ, PXY >
+				 < Session-Id >
+				 { Auth-Application-Id }
+				 { Auth-Session-State }
+				 { Origin-Host }
+				 { Origin-Realm }
+				 { Destination-Realm }
+				 { SIP-AOR }
+				 [ Destination-Host ]
+				 [ User-Name ]
+				 [ SIP-Visited-Network-Id ]
+				 [ SIP-User-Authorization-Type ]
+			       * [ Proxy-Info ]
+			       * [ Route-Record ]
+			       * [ AVP ]
+
+			*/
+			struct dict_object * cmd;
+			struct dict_cmd_data data = { 
+					283, 					/* Code */
+					"User-Authorization-Request", 		/* Name */
+					CMD_FLAG_REQUEST | CMD_FLAG_PROXIABLE | CMD_FLAG_ERROR, 	/* Fixed flags */
+					CMD_FLAG_REQUEST | CMD_FLAG_PROXIABLE 			/* Fixed flag values */
+					};
+			struct local_rules_definition rules[] = 
+						{ 	 {  "Session-Id", 			RULE_FIXED_HEAD, -1, 1 }
+						 	,{  "Auth-Application-Id", 		RULE_REQUIRED,   -1, 1 }
+						 	,{  "Auth-Session-State", 		RULE_REQUIRED,   -1, 1 }
+						 	,{  "Origin-Host", 			RULE_REQUIRED,   -1, 1 }
+						 	,{  "Origin-Realm", 			RULE_REQUIRED,   -1, 1 }
+						 	,{  "Destination-Realm", 		RULE_REQUIRED,   -1, 1 }
+						 	,{  "SIP-AOR", 				RULE_REQUIRED,   -1, 1 }
+						 	,{  "Destination-Host", 		RULE_OPTIONAL,   -1, 1 }
+						 	,{  "User-Name", 			RULE_OPTIONAL,   -1, 1 }
+						 	,{  "SIP-Visited-Network-Id", 		RULE_OPTIONAL,   -1, 1 }
+						 	,{  "SIP-User-Authorization-Type", 	RULE_OPTIONAL,   -1, 1 }
+						 	,{  "Proxy-Info", 			RULE_OPTIONAL,   -1, -1 }
+						 	,{  "Route-Record", 			RULE_OPTIONAL,   -1, -1 }
+
+						};
+			
+			CHECK_dict_new( DICT_COMMAND, &data , sip, &cmd);
+			PARSE_loc_rules( rules, cmd );
+		}
+
+		/* User-Authorization-Answer (UAA) Command */
+		{
+			/*
+			The User-Authorization-Answer (UAA) is indicated by the Command-Code
+			set to 283 and the Command Flags' 'R' bit cleared.  The Diameter
+			server sends this command in response to a previously received
+			Diameter User-Authorization-Request (UAR) command.  The Diameter
+			server indicates the result of the requested registration
+			authorization.  Additionally, the Diameter server may indicate a
+			collection of SIP capabilities that assists the Diameter client to
+			select a SIP proxy to the AOR under registration.
+
+
+			In addition to the values already defined in RFC 3588 [RFC3588], the
+			Result-Code AVP may contain one of the values defined in
+			Section 10.1.
+
+			Whenever the Diameter server fails to process the Diameter UAR
+			message, it MUST stop processing and return the relevant error in the
+			Diameter UAA message.  When there is success in the process, the
+			Diameter server MUST set the code to DIAMETER_SUCCESS in the Diameter
+			UAA message.
+
+			If the Diameter server requires a User-Name AVP value to process the
+			Diameter UAR request, but the Diameter UAR message did not contain a
+			User-Name AVP value, the Diameter server MUST set the Result-Code AVP
+			value to DIAMETER_USER_NAME_REQUIRED (see Section 10.1.2) and return
+			it in a Diameter UAA message.  Upon reception of this Diameter UAA
+			message with the Result-Code AVP value set to
+			DIAMETER_USER_NAME_REQUIRED, the SIP server typically requests
+			authentication by sending a SIP 401 (Unauthorized) or SIP 407 (Proxy
+			Authentication Required) response back to the originator.
+
+			When the authorization procedure succeeds, the Diameter server
+			constructs a User-Authorization-Answer (UAA) message that MUST
+			include (1) the address of the SIP server already assigned to the
+			user name, (2) the capabilities needed by the SIP server (Diameter
+			client) to select another SIP server for the user, or (3) a
+			combination of the previous two options.
+
+			If the Diameter server is already aware of a SIP server allocated to
+			the user, the Diameter UAA message contains the address of that SIP
+			server.
+
+			The Diameter UAA message contains the capabilities required by a SIP
+			server to trigger and execute services.  It is required that these
+			capabilities are present in the Diameter UAA message due to the
+			possibility that the Diameter client (in the SIP server) allocates a
+			different SIP server to trigger and execute services for that
+			particular user.
+
+			If a User-Name AVP is present in the Diameter UAR message, then the
+			Diameter server MUST verify the existence of the user in the realm,
+			i.e., the User-Name AVP value is a valid user within that realm.  If
+			the Diameter server does not recognize the user name received in the
+			User-Name AVP, the Diameter server MUST build a Diameter User-
+			Authorization-Answer (UAA) message and MUST set the Result-Code AVP
+			to DIAMETER_ERROR_USER_UNKNOWN.
+
+
+			If a User-Name AVP is present in the Diameter UAR message, then the
+			Diameter server MUST authorize that User-Name AVP value is able to
+			register the SIP or SIPS URI included in the SIP-AOR AVP.  If this
+			authorization fails, the Diameter server must set the Result-Code AVP
+			to DIAMETER_ERROR_IDENTITIES_DONT_MATCH and send it in a Diameter
+			User-Authorization-Answer (UAA) message.
+
+			Note: Correlation between User-Name and SIP-AOR AVP values is
+			required in order to avoid registration of a SIP-AOR allocated to
+			another user.
+
+			If there is a SIP-Visited-Network-Id AVP in the Diameter UAR message,
+			and the SIP-User-Authorization-Type AVP value received in the
+			Diameter UAR message is set to REGISTRATION or REGISTRATION&
+			CAPABILITIES, then the Diameter server SHOULD verify whether the user
+			is allowed to roam into the network specified in the
+			SIP-Visited-Network-Id AVP in the Diameter UAR message.  If the user
+			is not allowed to roam into that network, the Diameter AAA server
+			MUST set the Result-Code AVP value in the Diameter UAA message to
+			DIAMETER_ERROR_ROAMING_NOT_ALLOWED.
+
+			If the SIP-User-Authorization-Type AVP value received in the Diameter
+			UAR message is set to REGISTRATION or REGISTRATION&CAPABILITIES, then
+			the Diameter server SHOULD verify whether the SIP-AOR AVP value is
+			authorized to register in the Home Realm.  Where the SIP AOR is not
+			authorized to register in the Home Realm, the Diameter server MUST
+			set the Result-Code AVP to DIAMETER_AUTHORIZATION_REJECTED and send
+			it in a Diameter UAA message.
+
+			When the SIP-User-Authorization-Type AVP is not present in the
+			Diameter UAR message, or when it is present and its value is set to
+			REGISTRATION, then:
+
+			o  If the Diameter server is not aware of any previous registration
+			of the user name (including registrations of other SIP AORs
+			allocated to the same user name), then the Diameter server does
+			not know of any SIP server allocated to the user.  In this case,
+			the Diameter server MUST set the Result-Code AVP value to
+			DIAMETER_FIRST_REGISTRATION in the Diameter UAA message, and the
+			Diameter server SHOULD include the required SIP server
+			capabilities in the SIP-Server-Capabilities AVP value in the
+			Diameter UAA message.  The SIP-Server-Capabilities AVP assists the
+			Diameter client (SIP server) to select an appropriate SIP server
+			for the user, according to the required capabilities.
+
+			o  In some cases, the Diameter server is aware of a previously
+			assigned SIP server for the same or different SIP AORs allocated
+			to the same user name.  In these cases, re-assignment of a new SIP
+			server may or may not be needed, depending on the capabilities of
+			the SIP server.  The Diameter server MUST always include the
+			allocated SIP server URI in the SIP-Server-URI AVP of the UAA
+			message.  If the Diameter server does not return the SIP
+			capabilities, the Diameter server MUST set the Result-Code AVP in
+			the Diameter UAA message to DIAMETER_SUBSEQUENT_REGISTRATION.
+			Otherwise (i.e., if the Diameter server includes a
+			SIP-Server-Capabilities AVP), then the Diameter server MUST set
+			the Result-Code AVP in the Diameter UAA message to
+			DIAMETER_SERVER_SELECTION.  Then the Diameter client determines,
+			based on the received information, whether it needs to select a
+			new SIP server.
+
+			When the SIP-User-Authorization-Type AVP value received in the
+			Diameter UAR message is set to REGISTRATION&CAPABILITIES, then
+			Diameter Server MUST return the list of capabilities in the
+			SIP-Server-Capabilities AVP value of the Diameter UAA message, it
+			MUST set the Result-Code to DIAMETER_SUCCESS, and it MUST NOT return
+			a SIP-Server-URI AVP.  The SIP-Server-Capabilities AVP enables the
+			SIP server (Diameter client) to select another appropriate SIP server
+			for invoking and executing services for the user, depending on the
+			required capabilities.  The Diameter server MAY leave the list of
+			capabilities empty to indicate that any SIP server can be selected.
+
+			When the SIP-User-Authorization-Type AVP value received in the
+			Diameter UAR message is set to DEREGISTRATION, then:
+
+			o  If the Diameter server is aware of a SIP server assigned to the
+			SIP AOR under deregistration, the Diameter server MUST set the
+			Result-Code AVP to DIAMETER_SUCCESS and MUST set the
+			SIP-Server-URI AVP value to the known SIP server, and return them
+			in the Diameter UAA message.
+
+			o  If the Diameter server is not aware of a SIP server assigned to
+			the SIP AOR under deregistration, then the Diameter server MUST
+			set the Result-Code AVP in the Diameter UAA message to
+			DIAMETER_ERROR_IDENTITY_NOT_REGISTERED.
+
+			The Message Format of the UAA command is as follows:
+
+			<UAA> ::= < Diameter Header: 283, PXY >
+				 < Session-Id >
+				 { Auth-Application-Id }
+				 { Auth-Session-State }
+				 { Result-Code }
+				 { Origin-Host }
+				 { Origin-Realm }
+				 [ SIP-Server-URI ]
+				 [ SIP-Server-Capabilities ]
+				 [ Authorization-Lifetime ]
+				 [ Auth-Grace-Period ]
+				 [ Redirect-Host ]
+				 [ Redirect-Host-Usage ]
+				 [ Redirect-Max-Cache-Time ]
+			       * [ Proxy-Info ]
+			       * [ Route-Record ]
+			       * [ AVP ]
+
+
+			*/
+			struct dict_object * cmd;
+			struct dict_cmd_data data = { 
+					283, 					/* Code */
+					"User-Authorization-Answer", 		/* Name */
+					CMD_FLAG_REQUEST | CMD_FLAG_PROXIABLE | CMD_FLAG_ERROR, 	/* Fixed flags */
+					CMD_FLAG_PROXIABLE 						/* Fixed flag values */
+					};
+			struct local_rules_definition rules[] = 
+						{ 	 {  "Session-Id", 		RULE_FIXED_HEAD, -1, 1 }
+						 	,{  "Auth-Application-Id", 	RULE_REQUIRED,   -1, 1 }
+						 	,{  "Auth-Session-State", 	RULE_REQUIRED,   -1, 1 }
+						 	,{  "Result-Code", 		RULE_REQUIRED,   -1, 1 }
+						 	,{  "Origin-Host", 		RULE_REQUIRED,   -1, 1 }
+						 	,{  "Origin-Realm", 		RULE_REQUIRED,   -1, 1 }
+						 	,{  "SIP-Server-URI", 		RULE_OPTIONAL,   -1, 1 }
+						 	,{  "SIP-Server-Capabilities", 	RULE_OPTIONAL,   -1, 1 }
+						 	,{  "Authorization-Lifetime", 	RULE_OPTIONAL,   -1, 1 }
+						 	,{  "Auth-Grace-Period", 	RULE_OPTIONAL,   -1, 1 }
+						 	,{  "Redirect-Host", 		RULE_OPTIONAL,   -1, 1 }
+						 	,{  "Redirect-Host-Usage", 	RULE_OPTIONAL,   -1, 1 }
+						 	,{  "Redirect-Max-Cache-Time", 	RULE_OPTIONAL,   -1, 1 }
+						 	,{  "Proxy-Info", 		RULE_OPTIONAL,   -1, -1 }
+						 	,{  "Route-Record", 		RULE_OPTIONAL,   -1, -1 }
+
+						};
+			
+			CHECK_dict_new( DICT_COMMAND, &data , sip, &cmd);
+			PARSE_loc_rules( rules, cmd );
+		}
+		
+		/* Multimedia-Auth-Request (MAR) Command */
+		{
+			/*
+			
+			The Multimedia-Auth-Request (MAR) command is indicated by the
+			Command-Code set to 286 and the Command Flags' 'R' bit set.  The
+			Diameter client in a SIP server sends this command to the Diameter
+			server to request that the Diameter server authenticate and authorize
+			a user attempt to use some SIP service (in this context, SIP service
+			can be something as simple as a SIP subscription or using the proxy
+			services for a SIP request).
+
+			The MAR command may also register the SIP server's own URI to the
+			Diameter server, so that future LIR/LIA messages can return this URI.
+			If the SIP server is acting as a SIP registrar (see examples in
+			Sections 6.2 and 6.3), its Diameter client MUST include a SIP-
+			Server-URI AVP in the MAR command.  In any other cases (see example
+			in Section 6.4), its Diameter client MUST NOT include a SIP-Server-
+			URI AVP in the MAR command.
+
+			The SIP-Method AVP MUST include the SIP method name of the SIP
+			request that triggered this Diameter MAR message.  The Diameter
+			server can use this AVP to authorize some SIP requests depending on
+			the method.
+
+			The Diameter MAR message MUST include a SIP-AOR AVP.  The SIP-AOR AVP
+			indicates the target of the SIP request.  The value of the AVP is
+			extracted from different places in SIP request, depending on the
+			semantics of the SIP request.  For SIP REGISTER messages the SIP-AOR
+			AVP value indicates the intended public user identity under
+			registration, and it is the SIP or SIPS URI populated in the To
+			header field value (addr-spec as per RFC 3261 [RFC3261]) of the SIP
+			REGISTER request.  For other types of SIP requests, such as INVITE,
+			SUBSCRIBE, MESSAGE, etc., the SIP-AOR AVP value indicates the
+			intended destination of the request.  This is typically populated in
+			the Request-URI of the SIP request.  Extracting the SIP-AOR AVP value
+			from the proper SIP header field is the Diameter client's
+			responsibility.  Extensions to SIP (new SIP methods or new semantics)
+			may require the SIP-AOR to be extracted from other parts of the
+			request.
+
+			If the SIP request includes some sort of authentication information,
+			the Diameter client MUST include the user name, extracted from the
+			authentication information of the SIP request, in the User-Name AVP
+			value.
+
+			The Message Format of the MAR command is as follows:
+
+			<MAR> ::= < Diameter Header: 286, REQ, PXY >
+				 < Session-Id >
+				 { Auth-Application-Id }
+				 { Auth-Session-State }
+				 { Origin-Host }
+				 { Origin-Realm }
+				 { Destination-Realm }
+				 { SIP-AOR }
+				 { SIP-Method }
+				 [ Destination-Host ]
+				 [ User-Name ]
+				 [ SIP-Server-URI ]
+				 [ SIP-Number-Auth-Items ]
+				 [ SIP-Auth-Data-Item ]
+			       * [ Proxy-Info ]
+			       * [ Route-Record ]
+			       * [ AVP ]
+
+
+
+			*/
+			struct dict_object * cmd;
+			struct dict_cmd_data data = { 
+					286, 					/* Code */
+					"Multimedia-Auth-Request", 		/* Name */
+					CMD_FLAG_REQUEST | CMD_FLAG_PROXIABLE | CMD_FLAG_ERROR, 	/* Fixed flags */
+					CMD_FLAG_REQUEST | CMD_FLAG_PROXIABLE 						/* Fixed flag values */
+					};
+			struct local_rules_definition rules[] = 
+						{ 	 {  "Session-Id", 		RULE_FIXED_HEAD, -1, 1 }
+						 	,{  "Auth-Application-Id", 	RULE_REQUIRED,   -1, 1 }
+						 	,{  "Auth-Session-State", 	RULE_REQUIRED,   -1, 1 }
+						 	,{  "Origin-Host", 		RULE_REQUIRED,   -1, 1 }
+						 	,{  "Origin-Realm", 		RULE_REQUIRED,   -1, 1 }
+						 	,{  "Destination-Realm",	RULE_REQUIRED,   -1, 1 }
+						 	,{  "SIP-AOR", 			RULE_REQUIRED,   -1, 1 }
+						 	,{  "SIP-Method", 		RULE_REQUIRED,   -1, 1 }
+						 	,{  "Destination-Host", 	RULE_OPTIONAL,   -1, 1 }
+						 	,{  "User-Name", 		RULE_OPTIONAL,   -1, 1 }
+						 	,{  "SIP-Server-URI", 		RULE_OPTIONAL,   -1, 1 }
+						 	,{  "SIP-Number-Auth-Items", 	RULE_OPTIONAL,   -1, 1 }
+						 	,{  "SIP-Auth-Data-Item", 	RULE_OPTIONAL,   -1, 1 }
+						 	,{  "Proxy-Info", 		RULE_OPTIONAL,   -1, -1 }
+						 	,{  "Route-Record", 		RULE_OPTIONAL,   -1, -1 }
+
+						};
+			
+			CHECK_dict_new( DICT_COMMAND, &data , sip, &cmd);
+			PARSE_loc_rules( rules, cmd );
+		}
+		/* Multimedia-Auth-Answer (MAA) Command */
+		{
+			/*
+			
+			The Multimedia-Auth-Answer (MAA) is indicated by the Command-Code set
+			to 286 and the Command Flags' 'R' bit cleared.  The Diameter server
+			sends this command in response to a previously received Diameter
+			Multimedia-Auth-Request (MAR) command.
+
+			In addition to the values already defined in RFC 3588 [RFC3588], the
+			Result-Code AVP may contain one of the values defined in
+			Section 10.1.
+
+			If the Diameter server requires a User-Name AVP value to process the
+			Diameter MAR request, but the Diameter MAR message did not contain a
+			User-Name AVP value, the Diameter server MUST set the Result-Code AVP
+			value to DIAMETER_USER_NAME_REQUIRED (see Section 10.1.2) and return
+			it in a Diameter MAA message.  The Diameter server MAY include a
+			SIP-Number-Auth-Items AVP and one or more SIP-Auth-Data-Item AVPs
+			with authentication information (e.g., a challenge).  Upon reception
+			of this Diameter MAA message with the Result-Code AVP value set to
+			DIAMETER_USER_NAME_REQUIRED, the SIP server typically requests
+			authentication by generating a SIP 401 (Unauthorized) or SIP 407
+			(Proxy Authentication Required) response back to the originator.
+
+			If the User-Name AVP is present in the Diameter MAR message, the
+			Diameter server MUST verify the existence of the user in the realm,
+			i.e., the User-Name AVP value is a valid user within that realm.  If
+			the Diameter server does not recognize the user name received in the
+			User-Name AVP, the Diameter server MUST build a Diameter
+			Multimedia-Auth-Answer (MAA) message and MUST set the Result-Code AVP
+			to DIAMETER_ERROR_USER_UNKNOWN.
+
+			If the SIP-Methods AVP value of the Diameter MAR message is set to
+			REGISTER and a User-Name AVP is present, then the Diameter server
+			MUST authorize that User-Name AVP value is able to use the URI
+			included in the SIP-AOR AVP.  If this authorization fails, the
+			Diameter server must set the Result-Code AVP to
+			DIAMETER_ERROR_IDENTITIES_DONT_MATCH and send it in a Diameter
+			Multimedia-Auth-Answer (MAA) message.
+
+			Note: Correlation between User-Name and SIP-AOR AVP values is only
+			required for SIP REGISTER request, to prevent a user from
+			registering a SIP-AOR allocated to another user.  In other types
+			of SIP requests (e.g., INVITE), the SIP-AOR indicates the intended
+			destination of the request, rather than the originator of it.
+
+			The Diameter server MUST verify whether the authentication scheme
+			(SIP-Authentication-Scheme AVP value) indicated in the grouped
+			SIP-Auth-Data-Item AVP is supported or not.  If that authentication
+			scheme is not supported, then the Diameter server MUST set the
+			Result-Code AVP to DIAMETER_ERROR_AUTH_SCHEME_NOT_SUPPORTED and send
+			it in a Diameter Multimedia-Auth-Answer (MAA) message.
+
+			If the SIP-Number-Auth-Items AVP is present in the Diameter MAR
+			message, it indicates the number of authentication data items that
+			the Diameter client is requesting.  It is RECOMMENDED that the
+			Diameter server, when building the Diameter MAA message, includes a
+			number of SIP-Auth-Data-Item AVPs that are a subset of the
+			authentication data items requested by the Diameter client in the
+			SIP-Number-Auth-Items AVP value of the Diameter MAR message.
+
+			If the SIP-Server-URI AVP is present in the Diameter MAR message,
+			then the Diameter server MUST compare the stored SIP server (assigned
+			to the user) with the SIP-Server-URI AVP value (received in the
+			Diameter MAR message).  If they don't match, the Diameter server MUST
+			temporarily save the newly received SIP server assigned to the user,
+			and MUST set an "authentication pending" flag for the user.  If they
+			match, the Diameter server shall clear the "authentication pending"
+			flag for the user.
+
+			In any other situation, if there is a success in processing the
+			Diameter MAR command and the Diameter server stored the
+			SIP-Server-URI, the Diameter server MUST set the Result-Code AVP
+			value to DIAMETER_SUCCESS and return it in a Diameter MAA message.
+
+			If there is a success in processing the Diameter MAR command, but the
+			Diameter server does not store the SIP-Server-URI because the AVP was
+			not present in the Diameter MAR command, then the Diameter server
+			MUST set the Result-Code AVP value to either:
+
+			1.  DIAMETER_SUCCESS_AUTH_SENT_SERVER_NOT_STORED, if the Diameter
+			server is sending authentication credentials to create a
+			challenge.
+
+			2.  DIAMETER_SUCCESS_SERVER_NAME_NOT_STORED, if the Diameter server
+			successfully authenticated the user and authorized the SIP server
+			to proceed with the SIP request.
+
+			Otherwise, the Diameter server MUST set the Result-Code AVP value to
+			DIAMETER_UNABLE_TO_COMPLY, and it MUST NOT include any
+			SIP-Auth-Data-Item AVP.
+
+			The Message Format of the MAA command is as follows:
+
+			<MAA> ::= < Diameter Header: 286, PXY >
+				 < Session-Id >
+				 { Auth-Application-Id }
+				 { Result-Code }
+				 { Auth-Session-State }
+				 { Origin-Host }
+				 { Origin-Realm }
+				 [ User-Name ]
+				 [ SIP-AOR ]
+				 [ SIP-Number-Auth-Items ]
+			       * [ SIP-Auth-Data-Item ]
+				 [ Authorization-Lifetime ]
+				 [ Auth-Grace-Period ]
+				 [ Redirect-Host ]
+				 [ Redirect-Host-Usage ]
+				 [ Redirect-Max-Cache-Time ]
+			       * [ Proxy-Info ]
+			       * [ Route-Record ]
+			       * [ AVP ]
+
+			*/
+			struct dict_object * cmd;
+			struct dict_cmd_data data = { 
+					286, 					/* Code */
+					"Multimedia-Auth-Answer", 		/* Name */
+					CMD_FLAG_REQUEST | CMD_FLAG_PROXIABLE | CMD_FLAG_ERROR, 	/* Fixed flags */
+					CMD_FLAG_PROXIABLE 						/* Fixed flag values */
+					};
+			struct local_rules_definition rules[] = 
+						{ 	 {  "Session-Id", 		RULE_FIXED_HEAD, -1, 1 }
+						 	,{  "Auth-Application-Id", 	RULE_REQUIRED,   -1, 1 }
+						 	,{  "Result-Code", 		RULE_REQUIRED,   -1, 1 }
+						 	,{  "Auth-Session-State", 	RULE_REQUIRED,   -1, 1 }
+						 	,{  "Origin-Host", 		RULE_REQUIRED,   -1, 1 }
+						 	,{  "Origin-Realm", 		RULE_REQUIRED,   -1, 1 }
+						 	,{  "User-Name", 		RULE_OPTIONAL,   -1, 1 }
+						 	,{  "SIP-AOR", 			RULE_OPTIONAL,   -1, 1 }
+						 	,{  "SIP-Number-Auth-Items", 	RULE_OPTIONAL,   -1, 1 }
+						 	,{  "SIP-Auth-Data-Item", 	RULE_OPTIONAL,   -1, -1 }
+						 	,{  "Authorization-Lifetime", 	RULE_OPTIONAL,   -1, 1 }
+						 	,{  "Auth-Grace-Period", 	RULE_OPTIONAL,   -1, 1 }
+						 	,{  "Redirect-Host", 		RULE_OPTIONAL,   -1, 1 }
+						 	,{  "Redirect-Host-Usage", 	RULE_OPTIONAL,   -1, 1 }
+						 	,{  "Redirect-Max-Cache-Time", 	RULE_OPTIONAL,   -1, 1 }
+						 	,{  "Proxy-Info", 		RULE_OPTIONAL,   -1, -1 }
+						 	,{  "Route-Record", 		RULE_OPTIONAL,   -1, -1 }
+
+						};
+			
+			CHECK_dict_new( DICT_COMMAND, &data , sip, &cmd);
+			PARSE_loc_rules( rules, cmd );
+		}
+		/* Server-Assignment-Request (SAR) Command */
+		{
+			/*
+			
+			The Server-Assignment-Request (SAR) command is indicated by the
+			Command-Code set to 284 and the Command Flags' 'R' bit set.  The
+			Diameter client in a SIP server sends this command to the Diameter
+			server to indicate the completion of the authentication process and
+			to request that the Diameter server store the URI of the SIP server
+			that is currently serving the user.  The main functions of the
+			Diameter SAR command are to inform the Diameter server of the URI of
+			the SIP server allocated to the user, and to store or clear it from
+			the Diameter server.  Additionally, the Diameter client can request
+			to download the user profile or part of it.
+
+			During the registration procedure, a SIP server becomes assigned to
+			the user.  The Diameter client in the assigned SIP server MUST
+			include its own URI in the SIP-Server-URI AVP of the
+			Server-Assignment-Request (SAR) Diameter message and send it to the
+			Diameter server.  The Diameter server then becomes aware of the
+			allocation of the SIP server to the user name and the server's URI.
+
+			The Diameter client in the SIP server MAY send a Diameter SAR message
+			because of other reasons.  These reasons are identified in the
+			SIP-Server-Assignment-Type AVP (Section 9.4) value.  For instance, a
+			Diameter client in a SIP server may contact the Diameter server to
+			request deregistration of a user, to inform the Diameter server of an
+			authentication failure, or just to download the user profile.  For a
+			complete description of all the SIP-Server-Assignment-Type AVP
+			values, see Section 9.4.
+
+			Typically the reception of a SIP REGISTER request in a SIP server
+			will trigger the Diameter client in the SIP server to send the
+			Diameter SAR message.  However, if a SIP server is receiving other
+			SIP request, such as INVITE, and the SIP server does not have the
+			user profile, the Diameter client in the SIP server may send the
+			Diameter SAR message to the Diameter server in order to download the
+			user profile and make the Diameter server aware of the SIP server
+			assigned to the user.
+			The user profile is an important piece of information that dictates
+			the behavior of the SIP server when triggering or providing services
+			for the user.  Typically the user profile is divided into:
+
+			o  Services to be rendered to the user when the user is registered
+			and initiates a SIP request.
+
+			o  Services to be rendered to the user when the user is registered
+			and a SIP request destined to that user arrives to the SIP proxy.
+
+			o  Services to be rendered to the user when the user is not
+			registered and a SIP request destined to that user arrives to the
+			SIP proxy.
+
+			The SIP-Server-Assignment-Type AVP indicates the reason why the
+			Diameter client (SIP server) contacted the Diameter server.  If the
+			Diameter client sets the SIP-Server-Assignment-Type AVP value to
+			REGISTRATION, RE_REGISTRATION, UNREGISTERED_USER, NO_ASSIGNMENT,
+			AUTHENTICATION_FAILURE or AUTHENTICATION_TIMEOUT, the Diameter client
+			MUST include exactly one SIP-AOR AVP in the Diameter SAR message.
+
+			The SAR message MAY contain zero or more SIP-Supported-User-Data-Type
+			AVPs.  Each of them contains a type of user data understood by the
+			SIP server.  This allows the Diameter client to provide an indication
+			to the Diameter server of the different format of user data
+			understood by the SIP server.  The Diameter server uses this
+			information to select one or more SIP-User-Data AVPs that will be
+			included in the SAA message.
+
+			The Message Format of the SAR command is as follows:
+
+			<SAR> ::= < Diameter Header: 284, REQ, PXY >
+				 < Session-Id >
+				 { Auth-Application-Id }
+				 { Auth-Session-State }
+				 { Origin-Host }
+				 { Origin-Realm }
+				 { Destination-Realm }
+				 { SIP-Server-Assignment-Type }
+				 { SIP-User-Data-Already-Available }
+				 [ Destination-Host ]
+				 [ User-Name ]
+				 [ SIP-Server-URI ]
+			       * [ SIP-Supported-User-Data-Type ]
+			       * [ SIP-AOR ]
+			       * [ Proxy-Info ]
+			       * [ Route-Record ]
+			       * [ AVP ]
+			*/
+			struct dict_object * cmd;
+			struct dict_cmd_data data = { 
+					284, 					/* Code */
+					"Server-Assignment-Request", 		/* Name */
+					CMD_FLAG_REQUEST | CMD_FLAG_PROXIABLE | CMD_FLAG_ERROR, 	/* Fixed flags */
+					CMD_FLAG_REQUEST | CMD_FLAG_PROXIABLE 						/* Fixed flag values */
+					};
+			struct local_rules_definition rules[] = 
+						{ 	 {  "Session-Id", 			RULE_FIXED_HEAD, -1, 1 }
+						 	,{  "Auth-Application-Id", 		RULE_REQUIRED,   -1, 1 }
+						 	,{  "Auth-Session-State", 		RULE_REQUIRED,   -1, 1 }
+						 	,{  "Origin-Host", 			RULE_REQUIRED,   -1, 1 }
+						 	,{  "Origin-Realm", 			RULE_REQUIRED,   -1, 1 }
+						 	,{  "Destination-Realm",		RULE_REQUIRED,   -1, 1 }
+						 	,{  "SIP-Server-Assignment-Type", 	RULE_REQUIRED,   -1, 1 }
+						 	,{  "SIP-User-Data-Already-Available", 	RULE_REQUIRED,   -1, 1 }
+						 	,{  "Destination-Host", 		RULE_OPTIONAL,   -1, 1 }
+						 	,{  "User-Name", 			RULE_OPTIONAL,   -1, 1 }
+						 	,{  "SIP-Server-URI", 			RULE_OPTIONAL,   -1, 1 }
+						 	,{  "SIP-Supported-User-Data-Type", 	RULE_OPTIONAL,   -1, -1 }
+						 	,{  "SIP-AOR", 				RULE_OPTIONAL,   -1, -1 }
+						 	,{  "Proxy-Info", 			RULE_OPTIONAL,   -1, -1 }
+						 	,{  "Route-Record", 			RULE_OPTIONAL,   -1, -1 }
+
+						};
+			
+			CHECK_dict_new( DICT_COMMAND, &data , sip, &cmd);
+			PARSE_loc_rules( rules, cmd );
+		}
+		/* Server-Assignment-Answer (SAA) Command */
+		{
+			/*
+			
+			   The Server-Assignment-Answer (SAA) is indicated by the Command-Code
+			   set to 284 and the Command Flags' 'R' bit cleared.  The Diameter
+			   server sends this command in response to a previously received
+			   Diameter Server-Assignment-Request (SAR) command.  The response may
+			   include the user profile or part of it, if requested.
+
+			   In addition to the values already defined in RFC 3588 [RFC3588], the
+			   Result-Code AVP may contain one of the values defined in
+			   Section 10.1.
+
+			   The Result-Code AVP value in the Diameter SAA message may indicate a
+			   success or an error in the execution of the Diameter SAR command.  If
+			   Result-Code AVP value in the Diameter SAA message does not contain an
+			   error code, the SAA message MAY include one or more SIP-User-Data
+			   AVPs that typically contain the profile of the user, indicating
+			   services that the SIP server can provide to that user.
+
+			   The Diameter server MAY include one or more
+			   SIP-Supported-User-Data-Type AVPs, each one identifying a type of
+			   user data format supported in the Diameter server.  If there is not a
+			   common supported user data type between the Diameter client and the
+			   Diameter server, the Diameter server SHOULD declare its list of
+			   supported user data types by including one or more
+			   SIP-Supported-User-Data-Type AVPs in a Diameter SAA message.  This
+			   indication is merely for debugging reasons, since there is not a
+			   fallback mechanism that allows the Diameter client to retrieve the
+			   profile in a supported format.
+
+			   If the Diameter server requires a User-Name AVP value to process the
+			   Diameter SAR request, but the Diameter SAR message did not contain a
+			   User-Name AVP value, the Diameter server MUST set the Result-Code AVP
+			   value to DIAMETER_USER_NAME_REQUIRED (see Section 10.1.2) and return
+			   it in a Diameter SAA message.  Upon reception of this Diameter SAA
+			   message with the Result-Code AVP value set to
+			   DIAMETER_USER_NAME_REQUIRED, the SIP server typically requests
+			   authentication by generating a SIP 401 (Unauthorized) or SIP 407
+			   (Proxy Authentication Required) response back to the originator.
+
+			   If the User-Name AVP is included in the Diameter SAR message, upon
+			   reception of the Diameter SAR message, the Diameter server MUST
+			   verify the existence of the user in the realm, i.e., the User-Name
+			   AVP value is a valid user within that realm.  If the Diameter server
+			   does not recognize the user name received in the User-Name AVP, the
+			   Diameter server MUST build a Diameter Server-Assignment-Answer (SAA)
+			   message and MUST set the Result-Code AVP to
+			   DIAMETER_ERROR_USER_UNKNOWN.
+			   Then the Diameter server MUST authorize that User-Name AVP value is a
+			   valid authentication name for the SIP or SIPS URI included in the
+			   SIP-AOR AVP of the Diameter SAR message.  If this authorization
+			   fails, the Diameter server must set the Result-Code AVP to
+			   DIAMETER_ERROR_IDENTITIES_DONT_MATCH and send it in a Diameter
+			   Server-Assignment-Answer (SAA) message.
+
+			   After successful execution of the Diameter SAR command, the Diameter
+			   server MUST clear the "authentication pending" flag and SHOULD move
+			   the temporarily stored SIP server URI to permanent storage.
+
+			   The actions of the Diameter server upon reception of the Diameter SAR
+			   message depend on the value of the SIP-Server-Assignment-Type:
+
+			   o  If the SIP-Server-Assignment-Type AVP value in the Diameter SAR
+			      message is set to REGISTRATION or RE_REGISTRATION, the Diameter
+			      server SHOULD verify that there is only one SIP-AOR AVP.
+			      Otherwise, the Diameter server MUST answer with a Diameter SAA
+			      message with the Result-Code AVP value set to
+			      DIAMETER_AVP_OCCURS_TOO_MANY_TIMES and MUST NOT include any
+			      SIP-User-Data AVP.  If there is only one SIP-AOR AVP and if the
+			      SIP-User-Data-Already-Available AVP value is set to
+			      USER_DATA_NOT_AVAILABLE, then the Diameter server SHOULD include
+			      one or more user profile data with the SIP or SIPS URI (SIP-AOR
+			      AVP) and all other SIP identities associated with that AVP in the
+			      SIP-User-Data AVP value of the Diameter SAA message.  On selecting
+			      the type of user data, the Diameter server SHOULD take into
+			      account the supported formats at the SIP server
+			      (SIP-Supported-User-Data-Type AVP in the SAR message) and the
+			      local policy.  Additionally, the Diameter server MUST set the
+			      Result-Code AVP value to DIAMETER_SUCCESS in the Diameter SAA
+			      message.  The Diameter server considers the SIP AOR authenticated
+			      and registered.
+
+			   o  If the SIP-Server-Assignment-Type AVP value in the Diameter SAR
+			      message is set to UNREGISTERED_USER, then the Diameter server MUST
+			      store the SIP server address included in the SIP-Server-URI AVP
+			      value.  The Diameter server will return the SIP server address in
+			      Diameter Location-Info-Answer (LIA) messages.  If the
+			      SIP-User-Data-Already-Available AVP value is set to
+			      USER_DATA_NOT_AVAILABLE, then the Diameter server SHOULD include
+			      one or more user profile data associated with the SIP or SIPS URI
+			      (SIP-AOR AVP) and associated identities in the SIP-User-Data AVP
+			      value of the Diameter SAA message.  On selecting the type of user
+			      data, the Diameter server SHOULD take into account the supported
+			      formats at the SIP server (SIP-Supported-User-Data-Type AVP in the
+			      SAR message) and the local policy.  The Diameter server MUST set
+			      the Result-Code AVP value to DIAMETER_SUCCESS.  The Diameter
+			      server considers the SIP AOR UNREGISTERED, but with a SIP server
+			      allocated to trigger and provide services for unregistered users.
+			      Note that in case of UNREGISTERED_USER (SIP-Server-Assignment-Type
+			      AVP), the Diameter server MUST verify that there is only one
+			      SIP-AOR AVP.  Otherwise, the Diameter server MUST answer the
+			      Diameter SAR message with a Diameter SAA message, and it MUST set
+			      the Result-Code AVP value to DIAMETER_AVP_OCCURS_TOO_MANY_TIMES
+			      and MUST NOT include any SIP-User-Data AVP.
+			      If the User-Name AVP was not present in the Diameter SAR message
+			      and the SIP-AOR is not known for the Diameter server, the Diameter
+			      server MUST NOT include a User-Name AVP in the Diameter SAA
+			      message and MUST set the Result-Code AVP value to
+			      DIAMETER_ERROR_USER_UNKNOWN.
+
+			   o  If the SIP-Server-Assignment-Type AVP value in the Diameter SAR
+			      message is set to TIMEOUT_DEREGISTRATION, USER_DEREGISTRATION,
+			      DEREGISTRATION_TOO_MUCH_DATA, or ADMINISTRATIVE_DEREGISTRATION,
+			      the Diameter server MUST clear the SIP server address associated
+			      with all SIP AORs indicated in each of the SIP-AOR AVP values
+			      included in the Diameter SAR message.  The Diameter server
+			      considers all of these SIP AORs as not registered.  The Diameter
+			      server MUST set the Result-Code AVP value to DIAMETER_SUCCESS in
+			      the Diameter SAA message.
+
+			   o  If the SIP-Server-Assignment-Type AVP value in the Diameter SAR
+			      message is set to TIMEOUT_DEREGISTRATION_STORE_SERVER_NAME or
+			      USER_DEREGISTRATION_STORE_SERVER_NAME, the Diameter server MAY
+			      keep the SIP server address associated with the SIP AORs included
+			      in the SIP-AOR AVP values of the Diameter SAR message, even though
+			      the SIP AORs become unregistered.  This feature allows a SIP
+			      server to request that the Diameter server remain an assigned SIP
+			      server for those SIP AORs (SIP-AOR AVP values) allocated to the
+			      same user name, and avoid SIP server assignment.  The Diameter
+			      server MUST consider all these SIP AORs as not registered.  If the
+			      Diameter server honors the request of the Diameter client (SIP
+			      server) to remain as an allocated SIP server, then the Diameter
+			      server MUST keep the SIP server assigned to those SIP AORs
+			      allocated to the username and MUST set the Result-Code AVP value
+			      to DIAMETER_SUCCESS in the Diameter SAA message.  Otherwise, when
+			      the Diameter server does not honor the request of the Diameter
+			      client (SIP server) to remain as an allocated SIP server, the
+			      Diameter server MUST clear the SIP server name assigned to those
+			      SIP AORs and it MUST set the Result-Code AVP value to
+			      DIAMETER_SUCCESS_SERVER_NAME_NOT_STORED in the Diameter SAA
+			      message.
+			   o  If the SIP-Server-Assignment-Type AVP value in the Diameter SAR
+			      message is set to NO_ASSIGNMENT, the Diameter server SHOULD first
+			      verify that the SIP-Server-URI AVP value in the Diameter SAR
+			      message is the same URI as the one assigned to the SIP-AOR AVP
+			      value.  If they differ, then the Diameter server MUST set the
+			      Result-Code AVP value to DIAMETER_UNABLE_TO_COMPLY in the Diameter
+			      SAA message.  Otherwise, if the SIP-User-Data-Already-Available
+			      AVP value is set to USER_DATA_NOT_AVAILABLE, then the Diameter
+			      server SHOULD include the user profile data with the SIP or SIPS
+			      URI (SIP-AOR AVP) and all other SIP identities associated with
+			      that AVP in the SIP-User-Data AVP value of the Diameter SAA
+			      message.  On selecting the type of user data, the Diameter server
+			      SHOULD take into account the supported formats at the SIP server
+			      (SIP-Supported-User-Data-Type AVP in the SAR message) and the
+			      local policy.
+
+			   o  If the SIP-Server-Assignment-Type AVP value in the Diameter SAR
+			      message is set to AUTHENTICATION_FAILURE or
+			      AUTHENTICATION_TIMEOUT, the Diameter server MUST verify that there
+			      is exactly one SIP-AOR AVP in the Diameter SAR message.  If the
+			      number of occurrences of the SIP-AOR AVP is not exactly one, the
+			      Diameter server MUST set the Result-Code AVP value to
+			      DIAMETER_AVP_OCCURS_TOO_MANY_TIMES in the Diameter SAA message,
+			      and SHOULD not take further actions.  If there is exactly one
+			      SIP-AOR AVP in the Diameter SAR message, the Diameter server MUST
+			      clear the address of the SIP server assigned to the SIP AOR
+			      allocated to the user name, and the Diameter server MUST set the
+			      Result-Code AVP value to DIAMETER_SUCCESS in the Diameter SAA
+			      message.  The Diameter server MUST consider the SIP AOR as not
+			      registered.
+
+			   The Message Format of the SAA command is as follows:
+
+			       <SAA> ::= < Diameter Header: 284, PXY >
+					 < Session-Id >
+					 { Auth-Application-Id }
+					 { Result-Code }
+					 { Auth-Session-State }
+					 { Origin-Host }
+					 { Origin-Realm }
+				       * [ SIP-User-Data ]
+					 [ SIP-Accounting-Information ]
+				       * [ SIP-Supported-User-Data-Type ]
+					 [ User-Name ]
+					 [ Auth-Grace-Period ]
+					 [ Authorization-Lifetime ]
+					 [ Redirect-Host ]
+					 [ Redirect-Host-Usage ]
+					 [ Redirect-Max-Cache-Time ]
+				       * [ Proxy-Info ]
+				       * [ Route-Record ]
+				       * [ AVP ]
+
+
+
+
+			*/
+			struct dict_object * cmd;
+			struct dict_cmd_data data = { 
+					284, 					/* Code */
+					"Server-Assignment-Answer", 		/* Name */
+					CMD_FLAG_REQUEST | CMD_FLAG_PROXIABLE | CMD_FLAG_ERROR, 	/* Fixed flags */
+					CMD_FLAG_PROXIABLE 						/* Fixed flag values */
+					};
+			struct local_rules_definition rules[] = 
+						{ 	 {  "Session-Id", 			RULE_FIXED_HEAD, -1, 1 }
+						 	,{  "Auth-Application-Id", 		RULE_REQUIRED,   -1, 1 }
+						 	,{  "Result-Code", 			RULE_REQUIRED,   -1, 1 }
+						 	,{  "Auth-Session-State", 		RULE_REQUIRED,   -1, 1 }
+						 	,{  "Origin-Host", 			RULE_REQUIRED,   -1, 1 }
+						 	,{  "Origin-Realm", 			RULE_REQUIRED,   -1, 1 }
+						 	,{  "SIP-User-Data",			RULE_OPTIONAL,   -1, -1 }
+						 	,{  "SIP-Accounting-Information", 	RULE_OPTIONAL,   -1, 1 }
+						 	,{  "SIP-Supported-User-Data-Type", 	RULE_OPTIONAL,   -1, -1 }
+						 	,{  "User-Name", 			RULE_OPTIONAL,   -1, 1 }
+						 	,{  "Auth-Grace-Period", 		RULE_OPTIONAL,   -1, 1 }
+						 	,{  "Authorization-Lifetime", 		RULE_OPTIONAL,   -1, 1 }
+						 	,{  "Redirect-Host", 			RULE_OPTIONAL,   -1, 1 }
+						 	,{  "Redirect-Host-Usage", 		RULE_OPTIONAL,   -1, 1 }
+						 	,{  "Redirect-Max-Cache-Time", 		RULE_OPTIONAL,   -1, 1 }
+						 	,{  "Proxy-Info", 			RULE_OPTIONAL,   -1, -1 }
+						 	,{  "Route-Record", 			RULE_OPTIONAL,   -1, -1 }
+
+						};
+			
+			CHECK_dict_new( DICT_COMMAND, &data , sip, &cmd);
+			PARSE_loc_rules( rules, cmd );
+		}
+		/* Location-Info-Request (LIR) Command */
+		{
+			/*
+			
+			The Location-Info-Request (LIR) is indicated by the Command-Code set
+			to 285 and the Command Flags' 'R' bit set.  The Diameter client in a
+			SIP server sends this command to the Diameter server to request
+			routing information, e.g., the URI of the SIP server assigned to the
+			SIP-AOR AVP value allocated to the users.
+
+			The Message Format of the LIR command is as follows:
+
+			<LIR> ::= < Diameter Header: 285, REQ, PXY >
+				 < Session-Id >
+				 { Auth-Application-Id }
+				 { Auth-Session-State }
+				 { Origin-Host }
+				 { Origin-Realm }
+				 { Destination-Realm }
+				 { SIP-AOR }
+				 [ Destination-Host ]
+			       * [ Proxy-Info ]
+			       * [ Route-Record ]
+			       * [ AVP ]
+			*/
+			struct dict_object * cmd;
+			struct dict_cmd_data data = { 
+					285, 					/* Code */
+					"Location-Info-Request", 		/* Name */
+					CMD_FLAG_REQUEST | CMD_FLAG_PROXIABLE | CMD_FLAG_ERROR, 	/* Fixed flags */
+					CMD_FLAG_REQUEST | CMD_FLAG_PROXIABLE 						/* Fixed flag values */
+					};
+			struct local_rules_definition rules[] = 
+						{ 	 {  "Session-Id", 		RULE_FIXED_HEAD, -1, 1 }
+						 	,{  "Auth-Application-Id", 	RULE_REQUIRED,   -1, 1 }
+						 	,{  "Auth-Session-State", 	RULE_REQUIRED,   -1, 1 }
+						 	,{  "Origin-Host", 		RULE_REQUIRED,   -1, 1 }
+						 	,{  "Origin-Realm", 		RULE_REQUIRED,   -1, 1 }
+						 	,{  "Destination-Realm",	RULE_REQUIRED,   -1, 1 }
+						 	,{  "SIP-AOR", 			RULE_REQUIRED,   -1, 1 }
+						 	,{  "Destination-Host", 	RULE_OPTIONAL,   -1, 1 }
+						 	,{  "Proxy-Info", 		RULE_OPTIONAL,   -1, -1 }
+						 	,{  "Route-Record", 		RULE_OPTIONAL,   -1, -1 }
+
+						};
+			
+			CHECK_dict_new( DICT_COMMAND, &data , sip, &cmd);
+			PARSE_loc_rules( rules, cmd );
+		}
+		/* Location-Info-Answer (LIA) Command */
+		{
+			/*
+			   The Location-Info-Answer (LIA) is indicated by the Command-Code set
+			   to 285 and the Command Flags' 'R' bit cleared.  The Diameter server
+			   sends this command in response to a previously received Diameter
+			   Location-Info-Request (LIR) command.
+
+			   In addition to the values already defined in RFC 3588 [RFC3588], the
+			   Result-Code AVP may contain one of the values defined in
+			   Section 10.1.  When the Diameter server finds an error in processing
+			   the Diameter LIR message, the Diameter server MUST stop the process
+			   of the message and answer with a Diameter LIA message that includes
+			   the appropriate error code in the Result-Code AVP value.  When there
+			   is no error, the Diameter server MUST set the Result-Code AVP value
+			   to DIAMETER_SUCCESS in the Diameter LIA message.
+
+			   One of the errors that the Diameter server may find is that the
+			   SIP-AOR AVP value is not a valid user in the realm.  In such cases,
+			   the Diameter server MUST set the Result-Code AVP value to
+			   DIAMETER_ERROR_USER_UNKNOWN and return it in a Diameter LIA message.
+
+			   If the Diameter server cannot process the Diameter LIR command, e.g.,
+			   due to a database error, the Diameter server MUST set the Result-Code
+			   AVP value to DIAMETER_UNABLE_TO_COMPLY and return it in a Diameter
+			   LIA message.  The Diameter server MUST NOT include any SIP-Server-URI
+			   or SIP-Server-Capabilities AVP in the Diameter LIA message.
+
+			   The Diameter server may or may not be aware of a SIP server assigned
+			   to the SIP-AOR AVP value included in the Diameter LIR message.  If
+			   the Diameter server is aware of a SIP server allocated to that
+			   particular user, the Diameter server MUST include the URI of such SIP
+			   server in the SIP-Server-URI AVP and return it in a Diameter LIA
+			   message.  This is typically the situation when the user is either
+			   registered, or unregistered but a SIP server is still assigned to the
+			   user.
+
+			   When the Diameter server is not aware of a SIP server allocated to
+			   the user (typically the case when the user unregistered), the
+			   Result-Code AVP value in the Diameter LIA message depends on whether
+			   the Diameter server is aware that the user has services defined for
+			   unregistered users:
+
+			   o  Those users who have services defined for unregistered users may
+			      require the allocation of a SIP server to trigger and perhaps
+			      execute those services.  Therefore, when the Diameter server is
+			      not aware of an assigned SIP server, but the user has services
+			      defined for unregistered users, the Diameter server MUST set the
+			      Result-Code AVP value to DIAMETER_UNREGISTERED_SERVICE and return
+			      it in a Diameter LIA message.  The Diameter server MAY also
+			      include a SIP-Server-Capabilities AVP to facilitate the SIP server
+			      (Diameter client) with the selection of an appropriate SIP server
+			      with the required capabilities.  Absence of the SIP-Server-
+			      Capabilities AVP indicates to the SIP server (Diameter client)
+			      that any SIP server is suitable to be allocated for the user.
+
+			   o  Those users who do not have service defined for unregistered users
+			      do not require further processing.  The Diameter server MUST set
+			      the Result-Code AVP value to
+			      DIAMETER_ERROR_IDENTITY_NOT_REGISTERED and return it to the
+			      Diameter client in a Diameter LIA message.  The SIP server
+			      (Diameter client) may return the appropriate SIP response (e.g.,
+			      480 (Temporarily unavailable)) to the original SIP request.
+
+			   The Message Format of the LIA command is as follows:
+
+			       <LIA> ::= < Diameter Header: 285, PXY >
+					 < Session-Id >
+					 { Auth-Application-Id }
+					 { Result-Code }
+					 { Auth-Session-State }
+					 { Origin-Host }
+					 { Origin-Realm }
+					 [ SIP-Server-URI ]
+					 [ SIP-Server-Capabilities ]
+					 [ Auth-Grace-Period ]
+					 [ Authorization-Lifetime ]
+					 [ Redirect-Host ]
+					 [ Redirect-Host-Usage ]
+					 [ Redirect-Max-Cache-Time ]
+				       * [ Proxy-Info ]
+				       * [ Route-Record ]
+				       * [ AVP ]
+			*/
+			struct dict_object * cmd;
+			struct dict_cmd_data data = { 
+					285, 					/* Code */
+					"Location-Info-Answer", 		/* Name */
+					CMD_FLAG_REQUEST | CMD_FLAG_PROXIABLE | CMD_FLAG_ERROR, 	/* Fixed flags */
+					CMD_FLAG_PROXIABLE 						/* Fixed flag values */
+					};
+			struct local_rules_definition rules[] = 
+						{ 	 {  "Session-Id", 		RULE_FIXED_HEAD, -1, 1 }
+						 	,{  "Auth-Application-Id", 	RULE_REQUIRED,   -1, 1 }
+						 	,{  "Result-Code", 		RULE_REQUIRED,   -1, 1 }
+						 	,{  "Auth-Session-State", 	RULE_REQUIRED,   -1, 1 }
+						 	,{  "Origin-Host", 		RULE_REQUIRED,   -1, 1 }
+						 	,{  "Origin-Realm", 		RULE_REQUIRED,   -1, 1 }
+						 	,{  "SIP-Server-URI",		RULE_OPTIONAL,   -1, 1 }
+						 	,{  "SIP-Server-Capabilities", 	RULE_OPTIONAL,   -1, 1 }
+						 	,{  "Auth-Grace-Period", 	RULE_OPTIONAL,   -1, 1 }
+						 	,{  "Authorization-Lifetime", 	RULE_OPTIONAL,   -1, 1 }
+						 	,{  "Redirect-Host", 		RULE_OPTIONAL,   -1, 1 }
+						 	,{  "Redirect-Host-Usage", 	RULE_OPTIONAL,   -1, 1 }
+						 	,{  "Redirect-Max-Cache-Time", 	RULE_OPTIONAL,   -1, 1 }
+						 	,{  "Proxy-Info", 		RULE_OPTIONAL,   -1, -1 }
+						 	,{  "Route-Record", 		RULE_OPTIONAL,   -1, -1 }
+
+						};
+			
+			CHECK_dict_new( DICT_COMMAND, &data , sip, &cmd);
+			PARSE_loc_rules( rules, cmd );
+		}
+		/* Registration-Termination-Request (RTR) Command */
+		{
+			/*
+			   The Registration-Termination-Request (RTR) command is indicated by
+			   the Command-Code set to 287 and the Command Flags' 'R' bit set.  The
+			   Diameter server sends this command to the Diameter client in a SIP
+			   server to indicate to the SIP server that one or more SIP AORs have
+			   to be deregistered.  The command allows an operator to
+			   administratively cancel the registration of a user from a centralized
+			   Diameter server.
+
+			   The Diameter server has the capability to initiate the deregistration
+			   of a user and inform the SIP server by means of the Diameter RTR
+			   command.  The Diameter server can decide whether only one SIP AOR is
+			   going to be deregistered, a list of SIP AORs, or all the SIP AORs
+			   allocated to the user.
+
+			   The absence of a SIP-AOR AVP in the Diameter RTR message indicates
+			   that all the SIP AORs allocated to the user identified by the
+			   User-Name AVP are being deregistered.
+
+			   The Diameter server MUST include a SIP-Deregistration-Reason AVP
+			   value to indicate the reason for the deregistration.
+
+			   The Message Format of the RTR command is as follows:
+
+			       <RTR> ::= < Diameter Header: 287, REQ, PXY >
+					 < Session-Id >
+					 { Auth-Application-Id }
+					 { Auth-Session-State }
+					 { Origin-Host }
+					 { Origin-Realm }
+					 { Destination-Host }
+					 { SIP-Deregistration-Reason }
+					 [ Destination-Realm ]
+					 [ User-Name ]
+				       * [ SIP-AOR ]
+				       * [ Proxy-Info ]
+				       * [ Route-Record ]
+				       * [ AVP ]
+
+			
+
+
+
+			*/
+			struct dict_object * cmd;
+			struct dict_cmd_data data = { 
+					287, 					/* Code */
+					"Registration-Termination-Request", 		/* Name */
+					CMD_FLAG_REQUEST | CMD_FLAG_PROXIABLE | CMD_FLAG_ERROR, 	/* Fixed flags */
+					CMD_FLAG_REQUEST | CMD_FLAG_PROXIABLE 						/* Fixed flag values */
+					};
+			struct local_rules_definition rules[] = 
+						{ 	 {  "Session-Id", 		RULE_FIXED_HEAD, -1, 1 }
+						 	,{  "Auth-Application-Id", 	RULE_REQUIRED,   -1, 1 }
+						 	,{  "Auth-Session-State", 	RULE_REQUIRED,   -1, 1 }
+						 	,{  "Origin-Host", 		RULE_REQUIRED,   -1, 1 }
+						 	,{  "Origin-Realm", 		RULE_REQUIRED,   -1, 1 }
+						 	,{  "Destination-Host", 	RULE_REQUIRED,   -1, 1 }
+						 	,{  "SIP-Deregistration-Reason",RULE_REQUIRED,   -1, 1 }	
+						 	,{  "Destination-Realm",	RULE_OPTIONAL,   -1, 1 }
+						 	,{  "User-Name", 		RULE_OPTIONAL,   -1, 1 }
+						 	,{  "SIP-AOR", 			RULE_REQUIRED,   -1, -1 }
+						 	,{  "Proxy-Info", 		RULE_OPTIONAL,   -1, -1 }
+						 	,{  "Route-Record", 		RULE_OPTIONAL,   -1, -1 }
+
+						};
+			
+			CHECK_dict_new( DICT_COMMAND, &data , sip, &cmd);
+			PARSE_loc_rules( rules, cmd );
+		}
+		/* Registration-Termination-Answer (RTA) Command */
+		{
+			/*
+			   The Registration-Termination-Answer (RTA) is indicated by the
+			   Command-Code set to 287 and the Command Flags' 'R' bit cleared.  The
+			   Diameter client sends this command in response to a previously
+			   received Diameter Registration-Termination-Request (RTR) command.
+
+			   In addition to the values already defined in RFC 3588 [RFC3588], the
+			   Result-Code AVP may contain one of the values defined in
+			   Section 10.1.
+
+			   If the SIP server (Diameter client) requires a User-Name AVP value to
+			   process the Diameter RTR request, but the Diameter RTR message did
+			   not contain a User-Name AVP value, the Diameter client MUST set the
+			   Result-Code AVP value to DIAMETER_USER_NAME_REQUIRED (see Section
+			   10.1.2) and return it in a Diameter RTA message.
+
+			   The SIP server (Diameter client) applies the administrative
+			   deregistration to each of the URIs included in each of the SIP-AOR
+			   AVP values, or, if there is no SIP-AOR AVP present in the Diameter
+			   RTR request, to all the URIs allocated to the User-Name AVP value.
+
+			   The value of the SIP-Deregistration-Reason AVP in the Diameter RTR
+			   command has an effect on the actions performed at the SIP server
+			   (Diameter client):
+
+			   o  If the value is set to PERMANENT_TERMINATION, then the user has
+			      terminated his/her registration to the realm.  If informing the
+			      interested parties (e.g., subscribers to the "reg" event
+			      [RFC3680]) about the administrative deregistration is supported
+			      through SIP procedures, the SIP server (Diameter client) will do
+			      so.  The Diameter Client in the SIP Server SHOULD NOT request a
+			      new user registration.  The SIP server clears the registration
+			      state of the deregistered AORs.
+
+			   o  If the value is set to NEW_SIP_SERVER_ASSIGNED, the Diameter
+			      server informs the SIP server (Diameter client) that a new SIP
+			      server has been allocated to the user, due to some reason.  The
+			      SIP server, if supported through SIP procedures, will inform the
+			      interested parties (e.g., subscribers to the "reg" event
+			      [RFC3680]) about the administrative deregistration at this SIP
+			      server.  The Diameter client in the SIP server SHOULD NOT request
+			      a new user registration.  The SIP server clears the registration
+			      state of the deregistered SIP AORs.
+
+			   o  If the value is set to SIP_SERVER_CHANGE, the Diameter server
+			      informs the SIP server (Diameter client) that a new SIP server has
+			      to be allocated to the user, e.g., due to user's capabilities
+			      requiring a new SIP server, or not enough resources in the current
+			      SIP server.  If informing the interested parties about the
+			      administrative deregistration is supported through SIP procedures
+			      (e.g., subscriptions to the "reg" event [RFC3680]), the SIP server
+			      will do so.  The Diameter client in the SIP Server SHOULD NOT
+			      request a new user registration.  The SIP server clears the
+			      registration state of the deregistered SIP AORs.
+
+			   o  If the value is set to REMOVE_SIP_SERVER, the Diameter server
+			      informs the SIP server (Diameter client) that the SIP server will
+			      no longer be bound in the Diameter server with that user.  The SIP
+			      server can delete all data related to the user.
+
+			   The Message Format of the RTA command is as follows:
+
+			       <RTA> ::= < Diameter Header: 287, PXY >
+					 < Session-Id >
+					 { Auth-Application-Id }
+					 { Result-Code }
+					 { Auth-Session-State }
+					 { Origin-Host }
+					 { Origin-Realm }
+					 [ Authorization-Lifetime ]
+					 [ Auth-Grace-Period ]
+					 [ Redirect-Host ]
+					 [ Redirect-Host-Usage ]
+					 [ Redirect-Max-Cache-Time ]
+				       * [ Proxy-Info ]
+				       * [ Route-Record ]
+				       * [ AVP ]
+
+			*/
+			struct dict_object * cmd;
+			struct dict_cmd_data data = { 
+					287, 					/* Code */
+					"Registration-Termination-Answer", 		/* Name */
+					CMD_FLAG_REQUEST | CMD_FLAG_PROXIABLE | CMD_FLAG_ERROR, 	/* Fixed flags */
+					CMD_FLAG_PROXIABLE 						/* Fixed flag values */
+					};
+			struct local_rules_definition rules[] = 
+						{ 	 {  "Session-Id", 		RULE_FIXED_HEAD, -1, 1 }
+						 	,{  "Auth-Application-Id", 	RULE_REQUIRED,   -1, 1 }
+						 	,{  "Result-Code", 		RULE_REQUIRED,   -1, 1 }
+						 	,{  "Auth-Session-State", 	RULE_REQUIRED,   -1, 1 }
+						 	,{  "Origin-Host", 		RULE_REQUIRED,   -1, 1 }
+						 	,{  "Origin-Realm", 		RULE_REQUIRED,   -1, 1 }
+						 	,{  "Authorization-Lifetime",	RULE_OPTIONAL,   -1, 1 }
+						 	,{  "Auth-Grace-Period", 	RULE_OPTIONAL,   -1, 1 }
+						 	,{  "Redirect-Host", 		RULE_OPTIONAL,   -1, 1 }
+						 	,{  "Redirect-Host-Usage", 	RULE_OPTIONAL,   -1, 1 }
+						 	,{  "Redirect-Max-Cache-Time", 	RULE_OPTIONAL,   -1, 1 }
+						 	,{  "Proxy-Info", 		RULE_OPTIONAL,   -1, -1 }
+						 	,{  "Route-Record", 		RULE_OPTIONAL,   -1, -1 }
+
+						};
+			
+			CHECK_dict_new( DICT_COMMAND, &data , sip, &cmd);
+			PARSE_loc_rules( rules, cmd );
+		}
+		
+		/* Push-Profile-Request (PPR) Command */
+		{
+			/*
+			   The Push-Profile-Request (PPR) command is indicated by the
+			   Command-Code set to 288 and the Command Flags' 'R' bit set.  The
+			   Diameter server sends this command to the Diameter client in a SIP
+			   server to update either the user profile of an already registered
+			   user in that SIP server or the SIP accounting information.  This
+			   allows an operator to modify the data of a user profile or the
+			   accounting information and push it to the SIP server where the user
+			   is registered.
+
+			   Each user has a user profile associated with him/her and other
+			   accounting information.  The profile or the accounting information
+			   may change with time, e.g., due to addition of new services to the
+			   user.  When the user profile or the accounting information changes,
+			   the Diameter server sends a Diameter Push-Profile-Request (PPR)
+			   command to the Diameter client in a SIP server, in order to start
+			   applying those new services.
+
+			   A PPR command MAY contain a SIP-Accounting-Information AVP that
+			   updates the addresses of the accounting servers.  Changes in the
+			   addresses of the accounting servers take effect immediately.  The
+			   Diameter client SHOULD close any existing accounting session with the
+			   existing server and start providing accounting information to the
+			   newly acquired accounting server.
+
+			   A PPR command MAY contain zero or more SIP-User-Data AVP values
+			   containing the new user profile.  On selecting the type of user data,
+			   the Diameter server SHOULD take into account the supported formats at
+			   the SIP server (SIP-Supported-User-Data-Type AVP sent in a previous
+			   SAR message) and the local policy.
+
+			   The User-Name AVP indicates the user to whom the profile is
+			   applicable.
+
+			   The Message Format of the PPR command is as follows:
+
+			       <PPR> ::= < Diameter Header: 288, REQ, PXY >
+					 < Session-Id >
+					 { Auth-Application-Id }
+					 { Auth-Session-State }
+					 { Origin-Host }
+					 { Origin-Realm }
+					 { Destination-Realm }
+					 { User-Name }
+				       * [ SIP-User-Data ]
+					 [ SIP-Accounting-Information ]
+					 [ Destination-Host ]
+					 [ Authorization-Lifetime ]
+					 [ Auth-Grace-Period ]
+				       * [ Proxy-Info ]
+				       * [ Route-Record ]
+				       * [ AVP ]
+
+			*/
+			struct dict_object * cmd;
+			struct dict_cmd_data data = { 
+					288, 					/* Code */
+					"Push-Profile-Request", 		/* Name */
+					CMD_FLAG_REQUEST | CMD_FLAG_PROXIABLE | CMD_FLAG_ERROR, 	/* Fixed flags */
+					CMD_FLAG_REQUEST | CMD_FLAG_PROXIABLE 						/* Fixed flag values */
+					};
+			struct local_rules_definition rules[] = 
+						{ 	 {  "Session-Id", 			RULE_FIXED_HEAD, -1, 1 }
+						 	,{  "Auth-Application-Id", 		RULE_REQUIRED,   -1, 1 }
+						 	,{  "Auth-Session-State", 		RULE_REQUIRED,   -1, 1 }
+						 	,{  "Origin-Host", 			RULE_REQUIRED,   -1, 1 }
+						 	,{  "Origin-Realm", 			RULE_REQUIRED,   -1, 1 }
+						 	,{  "Destination-Realm",		RULE_REQUIRED,   -1, 1 }
+						 	,{  "User-Name", 			RULE_REQUIRED,   -1, 1 }
+						 	,{  "SIP-User-Data", 			RULE_OPTIONAL,   -1, -1 }
+						 	,{  "SIP-Accounting-Information", 	RULE_OPTIONAL,   -1, 1 }
+						 	,{  "Destination-Host", 		RULE_OPTIONAL,   -1, 1 }
+						 	,{  "Authorization-Lifetime", 		RULE_OPTIONAL,   -1, 1 }
+						 	,{  "Auth-Grace-Period", 		RULE_OPTIONAL,   -1, 1 }
+						 	,{  "Proxy-Info", 			RULE_OPTIONAL,   -1, -1 }
+						 	,{  "Route-Record", 			RULE_OPTIONAL,   -1, -1 }
+
+						};
+			
+			CHECK_dict_new( DICT_COMMAND, &data , sip, &cmd);
+			PARSE_loc_rules( rules, cmd );
+		}
+		/* Push-Profile-Answer (PPA) Command */
+		{
+			/*
+			
+			
+			The Push-Profile-Answer (PPA) is indicated by the Command-Code set to
+			288 and the Command Flags' 'R' bit cleared.  The Diameter client
+			sends this command in response to a previously received Diameter
+			Push-Profile-Request (PPR) command.
+
+			In addition to the values already defined in RFC 3588 [RFC3588], the
+			Result-Code AVP may contain one of the values defined in
+			Section 10.1.
+
+			If there is no error when processing the received Diameter PPR
+			message, the SIP server (Diameter client) MUST download the received
+			user profile from the SIP-User-Data AVP values in the Diameter PPR
+			message and store it associated with the user specified in the
+			User-Name AVP value.
+
+			If the SIP server does not recognize or does not support some of the
+			data transferred in the SIP-User-Data AVP values, the Diameter client
+			in the SIP server MUST return a Diameter PPA message that includes a
+			Result-Code AVP set to the value DIAMETER_ERROR_NOT_SUPPORTED_USER_DATA.
+
+			If the SIP server (Diameter client) receives a Diameter PPR message
+			with a User-Name AVP that is unknown, the Diameter client MUST set
+			the Result-Code AVP value to DIAMETER_ERROR_USER_UNKNOWN and MUST
+			return it to the Diameter server in a Diameter PPA message.
+
+			If the SIP server (Diameter client) receives in the
+			SIP-User-Data-Content AVP value (of the grouped SIP-User-Data AVP)
+			more data than it can accept, it MUST set the Result-Code AVP value
+			to DIAMETER_ERROR_TOO_MUCH_DATA and MUST return it to the Diameter
+			server in a Diameter PPA message.  The SIP server MUST NOT override
+			the existing user profile with the one received in the PPR message.
+
+			If the Diameter server receives the Result-Code AVP value set to
+			DIAMETER_ERROR_TOO_MUCH_DATA in a Diameter PPA message, it SHOULD
+			force a new re-registration of the user by sending to the Diameter
+			client a Diameter Registration-Termination-Request (RTR) with the
+			SIP-Deregistration-Reason AVP value set to SIP_SERVER_CHANGE.  This
+			will force a re-registration of the user and will trigger a selection
+			of a new SIP server.
+
+			If the Diameter client is not able to honor the command, for any
+			other reason, it MUST set the Result-Code AVP value to
+			DIAMETER_UNABLE_TO_COMPLY and it MUST return it in a Diameter PPA
+			message.
+
+			The Message Format of the PPA command is as follows:
+
+			<PPA> ::= < Diameter Header: 288, PXY >
+				 < Session-Id >
+				 { Auth-Application-Id }
+				 { Result-Code }
+				 { Auth-Session-State }
+				 { Origin-Host }
+				 { Origin-Realm }
+				 [ Redirect-Host ]
+				 [ Redirect-Host-Usage ]
+				 [ Redirect-Max-Cache-Time ]
+			       * [ Proxy-Info ]
+			       * [ Route-Record ]
+			       * [ AVP ]
+
+
+
+			*/
+			struct dict_object * cmd;
+			struct dict_cmd_data data = { 
+					288, 					/* Code */
+					"Push-Profile-Answer", 		/* Name */
+					CMD_FLAG_REQUEST | CMD_FLAG_PROXIABLE | CMD_FLAG_ERROR, 	/* Fixed flags */
+					CMD_FLAG_PROXIABLE 						/* Fixed flag values */
+					};
+			struct local_rules_definition rules[] = 
+						{ 	 {  "Session-Id", 		RULE_FIXED_HEAD, -1, 1 }
+						 	,{  "Auth-Application-Id", 	RULE_REQUIRED,   -1, 1 }
+						 	,{  "Result-Code", 		RULE_REQUIRED,   -1, 1 }
+						 	,{  "Auth-Session-State", 	RULE_REQUIRED,   -1, 1 }
+						 	,{  "Origin-Host", 		RULE_REQUIRED,   -1, 1 }
+						 	,{  "Origin-Realm", 		RULE_REQUIRED,   -1, 1 }
+						 	,{  "Redirect-Host",		RULE_OPTIONAL,   -1, 1 }
+						 	,{  "Redirect-Host-Usage", 	RULE_OPTIONAL,   -1, 1 }
+						 	,{  "Redirect-Max-Cache-Time", 	RULE_OPTIONAL,   -1, 1 }
+						 	,{  "Proxy-Info", 		RULE_OPTIONAL,   -1, -1 }
+						 	,{  "Route-Record", 		RULE_OPTIONAL,   -1, -1 }
+
+						};
+			
+			CHECK_dict_new( DICT_COMMAND, &data , sip, &cmd);
+			PARSE_loc_rules( rules, cmd );
+		}
+	}
+	
+	LOG_D( "Extension 'Dictionary definitions for SIP' initialized");
+	return 0;
+}
+EXTENSION_ENTRY("dict_sip", ds_dict_init);
diff --git a/extensions/dict_ts29061_avps/CMakeLists.txt b/extensions/dict_ts29061_avps/CMakeLists.txt
new file mode 100644
index 0000000..d3858df
--- /dev/null
+++ b/extensions/dict_ts29061_avps/CMakeLists.txt
@@ -0,0 +1,16 @@
+# The dict_ts29061_avps extension
+PROJECT("dict_ts29061_avps library generated by FdGen " C)
+
+# Compile as a module
+FD_ADD_EXTENSION(dict_ts29061_avps dict_ts29061_avps.c)
+
+
+####
+## INSTALL section ##
+
+INSTALL(TARGETS dict_ts29061_avps
+	LIBRARY DESTINATION ${INSTALL_EXTENSIONS_SUFFIX}
+COMPONENT freeDiameter-dictionary-TS29061_AVPS)
+
+
+
diff --git a/extensions/dict_ts29061_avps/dict_ts29061_avps.c b/extensions/dict_ts29061_avps/dict_ts29061_avps.c
new file mode 100644
index 0000000..1e2ba8e
--- /dev/null
+++ b/extensions/dict_ts29061_avps/dict_ts29061_avps.c
@@ -0,0 +1,1022 @@
+/*
+* Copyright (c) 2017 Sprint
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*    http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+/****************
+ Generated By: fdtool enhancements to diafuzzer
+ License: same as freeDiameter
+****************/
+
+
+/* 
+ * Dictionary definitions of objects specified in ts29061_avps (e30).
+ */
+#include <freeDiameter/extension.h>
+
+#define PROTO_VER "e30"
+#define GEN_DATE  1506697184.9
+
+const char *ts29061_avps_proto_ver = PROTO_VER;
+const double ts29061_avps_gen_date = GEN_DATE;
+
+/* The content of this file follows the same structure as dict_base_proto.c */
+
+#define CHECK_dict_new( _type, _data, _parent, _ref )                                     \
+{                                                                                         \
+    int _ret = fd_dict_new( fd_g_config->cnf_dict, (_type), (_data), (_parent), (_ref) ); \
+    if ( _ret != 0 && _ret != EEXIST )                                                    \
+       return _ret;                                                                       \
+}
+
+#define CHECK_dict_search( _type, _criteria, _what, _result )		\
+    CHECK_FCT(  fd_dict_search( fd_g_config->cnf_dict, (_type), (_criteria), (_what), (_result), ENOENT) );
+
+struct local_rules_definition {
+    struct dict_avp_request avp_vendor_plus_name;
+    enum rule_position	position;
+    int 			min;
+    int			max;
+};
+
+#define RULE_ORDER( _position ) ((((_position) == RULE_FIXED_HEAD) || ((_position) == RULE_FIXED_TAIL)) ? 1 : 0 )
+
+/* Attention! This version of the macro uses AVP_BY_NAME_AND_VENDOR, in contrast to most other copies! */
+#define PARSE_loc_rules( _rulearray, _parent) {                                                         \
+        int __ar;                                                                                       \
+        for (__ar=0; __ar < sizeof(_rulearray) / sizeof((_rulearray)[0]); __ar++) {                     \
+                struct dict_rule_data __data = { NULL,                                                  \
+                        (_rulearray)[__ar].position,                                                    \
+                        0,                                                                              \
+                        (_rulearray)[__ar].min,                                                         \
+                        (_rulearray)[__ar].max};                                                        \
+                __data.rule_order = RULE_ORDER(__data.rule_position);                                   \
+                CHECK_FCT(  fd_dict_search(                                                             \
+                        fd_g_config->cnf_dict,                                                          \
+                        DICT_AVP,                                                                       \
+                        AVP_BY_NAME_AND_VENDOR,                                                         \
+                        &(_rulearray)[__ar].avp_vendor_plus_name,                                       \
+                        &__data.rule_avp, 0 ) );                                                        \
+                if ( !__data.rule_avp ) {                                                               \
+                        TRACE_DEBUG(INFO, "AVP Not found: '%s'", (_rulearray)[__ar].avp_vendor_plus_name.avp_name);             \
+                        return ENOENT;                                                                  \
+                }                                                                                       \
+                {                                                                                       \
+                         int _ret = fd_dict_new( fd_g_config->cnf_dict, DICT_RULE, &(__data), (_parent), NULL ); \
+                         if ( _ret != 0 && _ret != EEXIST )      {                                      \
+                                TRACE_DEBUG(INFO, "Error on rule with AVP '%s'",                        \
+                                            (_rulearray)[__ar].avp_vendor_plus_name.avp_name);          \
+                                return EINVAL;                                                          \
+                         }                                                                              \
+                }                                                                                       \
+        }                                                                                               \
+}
+
+#define CHECK_vendor_new( _data ) { \
+        struct dict_object * vendor_found; \
+        if (fd_dict_search(fd_g_config->cnf_dict,DICT_VENDOR,VENDOR_BY_ID,&_data.vendor_id,&vendor_found,ENOENT) == ENOENT) { \
+                CHECK_FCT(fd_dict_new(fd_g_config->cnf_dict, DICT_VENDOR, &_data, NULL, NULL)); \
+        } \
+}
+
+#define enumval_def_u32( _val_, _str_ )		\
+    { _str_, 		{ .u32 = _val_ }}
+
+#define enumval_def_os( _len_, _val_, _str_ )				\
+    { _str_, 		{ .os = { .data = (unsigned char *)_val_, .len = _len_ }}}
+
+
+static int dict_ts29061_avps_load_defs(char * conffile)
+{
+   TRACE_ENTRY("%p", conffile);
+	/* Application Section */
+	{
+		/* Create the vendors */		{
+			struct dict_vendor_data vendor_data = { 10415, "3GPP" };
+			CHECK_dict_new(DICT_VENDOR, &vendor_data, NULL, NULL)
+		}
+	}
+
+
+   /* AVP section */
+   {
+		struct dict_object * Address_type;
+		struct dict_object * UTF8String_type;
+		struct dict_object * DiameterIdentity_type;
+		struct dict_object * DiameterURI_type;
+		struct dict_object * Time_type;
+		struct dict_object * IPFilterRule_type;
+
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "Address", &Address_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "UTF8String", &UTF8String_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "DiameterIdentity", &DiameterIdentity_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "DiameterURI", &DiameterURI_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "Time", &Time_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "IPFilterRule", &IPFilterRule_type);
+		/* 3GPP-IMSI */
+		{
+			struct dict_avp_data data = {
+				1,	/* Code */
+				10415,	/* Vendor */
+				"3GPP-IMSI",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, UTF8String_type, NULL);
+		};
+		/* 3GPP-Charging-Id */
+		{
+			struct dict_avp_data data = {
+				2,	/* Code */
+				10415,	/* Vendor */
+				"3GPP-Charging-Id",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* 3GPP-PDP-Type */
+		{
+			struct dict_avp_data data = {
+				3,	/* Code */
+				10415,	/* Vendor */
+				"3GPP-PDP-Type",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(3GPP-PDP-Type)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "Ipv4", { .i32=0 }};
+			struct dict_enumval_data        t_2 = { "PPP", { .i32=1 }};
+			struct dict_enumval_data        t_3 = { "Ipv6", { .i32=2 }};
+			struct dict_enumval_data        t_4 = { "Ipv4v6", { .i32=3 }};
+			struct dict_enumval_data        t_5 = { "Non-IP", { .i32=4 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_3, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_4, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_5, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* 3GPP-CG-Address */
+		{
+			struct dict_avp_data data = {
+				4,	/* Code */
+				10415,	/* Vendor */
+				"3GPP-CG-Address",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* 3GPP-GPRS-Negotiated-QoS-Profile */
+		{
+			struct dict_avp_data data = {
+				5,	/* Code */
+				10415,	/* Vendor */
+				"3GPP-GPRS-Negotiated-QoS-Profile",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, UTF8String_type, NULL);
+		};
+		/* 3GPP-SGSN-Address */
+		{
+			struct dict_avp_data data = {
+				6,	/* Code */
+				10415,	/* Vendor */
+				"3GPP-SGSN-Address",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* 3GPP-GGSN-Address */
+		{
+			struct dict_avp_data data = {
+				7,	/* Code */
+				10415,	/* Vendor */
+				"3GPP-GGSN-Address",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* 3GPP-IMSI-MCC-MNC */
+		{
+			struct dict_avp_data data = {
+				8,	/* Code */
+				10415,	/* Vendor */
+				"3GPP-IMSI-MCC-MNC",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, UTF8String_type, NULL);
+		};
+		/* 3GPP-GGSN-MCC-MNC */
+		{
+			struct dict_avp_data data = {
+				9,	/* Code */
+				10415,	/* Vendor */
+				"3GPP-GGSN-MCC-MNC",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, UTF8String_type, NULL);
+		};
+		/* 3GPP-NSAPI */
+		{
+			struct dict_avp_data data = {
+				10,	/* Code */
+				10415,	/* Vendor */
+				"3GPP-NSAPI",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* 3GPP-Selection-Mode */
+		{
+			struct dict_avp_data data = {
+				12,	/* Code */
+				10415,	/* Vendor */
+				"3GPP-Selection-Mode",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, UTF8String_type, NULL);
+		};
+		/* 3GPP-Charging-Characteristics */
+		{
+			struct dict_avp_data data = {
+				13,	/* Code */
+				10415,	/* Vendor */
+				"3GPP-Charging-Characteristics",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, UTF8String_type, NULL);
+		};
+		/* 3GPP-CG-Ipv6-Address */
+		{
+			struct dict_avp_data data = {
+				14,	/* Code */
+				10415,	/* Vendor */
+				"3GPP-CG-Ipv6-Address",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* 3GPP-SGSN-Ipv6-Address */
+		{
+			struct dict_avp_data data = {
+				15,	/* Code */
+				10415,	/* Vendor */
+				"3GPP-SGSN-Ipv6-Address",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* 3GPP-GGSN-Ipv6-Address */
+		{
+			struct dict_avp_data data = {
+				16,	/* Code */
+				10415,	/* Vendor */
+				"3GPP-GGSN-Ipv6-Address",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* 3GPP-Ipv6-DNS-Servers */
+		{
+			struct dict_avp_data data = {
+				17,	/* Code */
+				10415,	/* Vendor */
+				"3GPP-Ipv6-DNS-Servers",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* 3GPP-SGSN-MCC-MNC */
+		{
+			struct dict_avp_data data = {
+				18,	/* Code */
+				10415,	/* Vendor */
+				"3GPP-SGSN-MCC-MNC",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, UTF8String_type, NULL);
+		};
+		/* 3GPP-IMEISV */
+		{
+			struct dict_avp_data data = {
+				20,	/* Code */
+				10415,	/* Vendor */
+				"3GPP-IMEISV",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* 3GPP-RAT-Type */
+		{
+			struct dict_avp_data data = {
+				21,	/* Code */
+				10415,	/* Vendor */
+				"3GPP-RAT-Type",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* 3GPP-User-Location-Info */
+		{
+			struct dict_avp_data data = {
+				22,	/* Code */
+				10415,	/* Vendor */
+				"3GPP-User-Location-Info",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* 3GPP-MS-TimeZone */
+		{
+			struct dict_avp_data data = {
+				23,	/* Code */
+				10415,	/* Vendor */
+				"3GPP-MS-TimeZone",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* 3GPP-CAMEL-Charging-Info */
+		{
+			struct dict_avp_data data = {
+				24,	/* Code */
+				10415,	/* Vendor */
+				"3GPP-CAMEL-Charging-Info",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* 3GPP-Packet-Filter */
+		{
+			struct dict_avp_data data = {
+				25,	/* Code */
+				10415,	/* Vendor */
+				"3GPP-Packet-Filter",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* 3GPP-Negotiated-DSCP */
+		{
+			struct dict_avp_data data = {
+				26,	/* Code */
+				10415,	/* Vendor */
+				"3GPP-Negotiated-DSCP",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* 3GPP-Allocate-IP-Type */
+		{
+			struct dict_avp_data data = {
+				27,	/* Code */
+				10415,	/* Vendor */
+				"3GPP-Allocate-IP-Type",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* TWAN-Identifier */
+		{
+			struct dict_avp_data data = {
+				29,	/* Code */
+				10415,	/* Vendor */
+				"TWAN-Identifier",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* 3GPP-User-Location-Info-Time */
+		{
+			struct dict_avp_data data = {
+				30,	/* Code */
+				10415,	/* Vendor */
+				"3GPP-User-Location-Info-Time",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* TMGI */
+		{
+			struct dict_avp_data data = {
+				900,	/* Code */
+				10415,	/* Vendor */
+				"TMGI",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Required-MBMS-Bearer-Capabilities */
+		{
+			struct dict_avp_data data = {
+				901,	/* Code */
+				10415,	/* Vendor */
+				"Required-MBMS-Bearer-Capabilities",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, UTF8String_type, NULL);
+		};
+		/* MBMS-StartStop-Indication */
+		{
+			struct dict_avp_data data = {
+				902,	/* Code */
+				10415,	/* Vendor */
+				"MBMS-StartStop-Indication",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(MBMS-StartStop-Indication)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "START", { .i32=0 }};
+			struct dict_enumval_data        t_2 = { "STOP", { .i32=1 }};
+			struct dict_enumval_data        t_3 = { "UPDATE", { .i32=2 }};
+			struct dict_enumval_data        t_4 = { "HEARTBEAT", { .i32=3 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_3, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_4, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* MBMS-Service-Area */
+		{
+			struct dict_avp_data data = {
+				903,	/* Code */
+				10415,	/* Vendor */
+				"MBMS-Service-Area",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* MBMS-Session-Duration */
+		{
+			struct dict_avp_data data = {
+				904,	/* Code */
+				10415,	/* Vendor */
+				"MBMS-Session-Duration",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Alternative-APN */
+		{
+			struct dict_avp_data data = {
+				905,	/* Code */
+				10415,	/* Vendor */
+				"Alternative-APN",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, UTF8String_type, NULL);
+		};
+		/* MBMS-Service-Type */
+		{
+			struct dict_avp_data data = {
+				906,	/* Code */
+				10415,	/* Vendor */
+				"MBMS-Service-Type",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(MBMS-Service-Type)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "MULTICAST", { .i32=0 }};
+			struct dict_enumval_data        t_2 = { "BROADCAST", { .i32=1 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* MBMS-2G-3G-Indicator */
+		{
+			struct dict_avp_data data = {
+				907,	/* Code */
+				10415,	/* Vendor */
+				"MBMS-2G-3G-Indicator",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(MBMS-2G-3G-Indicator)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "G_AND_3G", { .i32=2 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* MBMS-Session-Identity */
+		{
+			struct dict_avp_data data = {
+				908,	/* Code */
+				10415,	/* Vendor */
+				"MBMS-Session-Identity",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* RAI */
+		{
+			struct dict_avp_data data = {
+				909,	/* Code */
+				10415,	/* Vendor */
+				"RAI",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, UTF8String_type, NULL);
+		};
+		/* Additional-MBMS-Trace-Info */
+		{
+			struct dict_avp_data data = {
+				910,	/* Code */
+				10415,	/* Vendor */
+				"Additional-MBMS-Trace-Info",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* MBMS-Time-To-Data-Transfer */
+		{
+			struct dict_avp_data data = {
+				911,	/* Code */
+				10415,	/* Vendor */
+				"MBMS-Time-To-Data-Transfer",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* MBMS-Session-Repetition-Number */
+		{
+			struct dict_avp_data data = {
+				912,	/* Code */
+				10415,	/* Vendor */
+				"MBMS-Session-Repetition-Number",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* MBMS-Required-QoS */
+		{
+			struct dict_avp_data data = {
+				913,	/* Code */
+				10415,	/* Vendor */
+				"MBMS-Required-QoS",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, UTF8String_type, NULL);
+		};
+		/* MBMS-Counting-Information */
+		{
+			struct dict_avp_data data = {
+				914,	/* Code */
+				10415,	/* Vendor */
+				"MBMS-Counting-Information",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(MBMS-Counting-Information)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "COUNTING_NOT_APPLICABLE", { .i32=0 }};
+			struct dict_enumval_data        t_2 = { "COUNTING_APPLICABLE", { .i32=1 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* MBMS-User-Data-Mode-Indication */
+		{
+			struct dict_avp_data data = {
+				915,	/* Code */
+				10415,	/* Vendor */
+				"MBMS-User-Data-Mode-Indication",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(MBMS-User-Data-Mode-Indication)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "Unicast", { .i32=0 }};
+			struct dict_enumval_data        t_2 = { "Multicast_and_Unicast", { .i32=1 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* MBMS-GGSN-Address */
+		{
+			struct dict_avp_data data = {
+				916,	/* Code */
+				10415,	/* Vendor */
+				"MBMS-GGSN-Address",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* MBMS-GGSN-Ipv6-Address */
+		{
+			struct dict_avp_data data = {
+				917,	/* Code */
+				10415,	/* Vendor */
+				"MBMS-GGSN-Ipv6-Address",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* MBMS-BMSC-SSM-IP-Address */
+		{
+			struct dict_avp_data data = {
+				918,	/* Code */
+				10415,	/* Vendor */
+				"MBMS-BMSC-SSM-IP-Address",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* MBMS-BMSC-SSM-Ipv6-Address */
+		{
+			struct dict_avp_data data = {
+				919,	/* Code */
+				10415,	/* Vendor */
+				"MBMS-BMSC-SSM-Ipv6-Address",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* MBMS-Flow-Identifier */
+		{
+			struct dict_avp_data data = {
+				920,	/* Code */
+				10415,	/* Vendor */
+				"MBMS-Flow-Identifier",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* CN-IP-Multicast-Distribution */
+		{
+			struct dict_avp_data data = {
+				921,	/* Code */
+				10415,	/* Vendor */
+				"CN-IP-Multicast-Distribution",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(CN-IP-Multicast-Distribution)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "NO_IP_MULTICAST", { .i32=0 }};
+			struct dict_enumval_data        t_2 = { "IP_MULTICAST", { .i32=1 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* MBMS-HC-Indicator */
+		{
+			struct dict_avp_data data = {
+				922,	/* Code */
+				10415,	/* Vendor */
+				"MBMS-HC-Indicator",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(MBMS-HC-Indicator)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "General", { .i32=0 }};
+			struct dict_enumval_data        t_2 = { "Re_Auth_Request_Command", { .i32=1 }};
+			struct dict_enumval_data        t_3 = { "Usage_of_RADIUS_at_the_Pk_Reference_Point", { .i32=18 }};
+			struct dict_enumval_data        t_4 = { "Usage_of_Diameter_on_Mz_interface", { .i32=19 }};
+			struct dict_enumval_data        t_5 = { "RE_Auth_Answer_Command", { .i32=2 }};
+			struct dict_enumval_data        t_6 = { "Usage_of_Diameter_on_SGmb_interface", { .i32=20 }};
+			struct dict_enumval_data        t_7 = { "Session_Termination_Request_Command", { .i32=3 }};
+			struct dict_enumval_data        t_8 = { "Session_Termination_Answer_Command", { .i32=4 }};
+			struct dict_enumval_data        t_9 = { "Abort_Session_Request_Command", { .i32=5 }};
+			struct dict_enumval_data        t_10 = { "Abort_Session_Answer_Command", { .i32=6 }};
+			struct dict_enumval_data        t_11 = { "Gmb_specific_Experimental_Result_Code_AVP_values", { .i32=8 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_3, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_4, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_5, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_6, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_7, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_8, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_9, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_10, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_11, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* MBMS-Access-Indicator */
+		{
+			struct dict_avp_data data = {
+				923,	/* Code */
+				10415,	/* Vendor */
+				"MBMS-Access-Indicator",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(MBMS-Access-Indicator)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "UTRAN", { .i32=0 }};
+			struct dict_enumval_data        t_2 = { "E_UTRAN", { .i32=1 }};
+			struct dict_enumval_data        t_3 = { "UTRAN_AND_E_UTRAN", { .i32=2 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_3, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* MBMS-GW-SSM-IP-Address */
+		{
+			struct dict_avp_data data = {
+				924,	/* Code */
+				10415,	/* Vendor */
+				"MBMS-GW-SSM-IP-Address",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* MBMS-GW-SSM-Ipv6-Address */
+		{
+			struct dict_avp_data data = {
+				925,	/* Code */
+				10415,	/* Vendor */
+				"MBMS-GW-SSM-Ipv6-Address",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* MBMS-BMSC-SSM-UDP-Port */
+		{
+			struct dict_avp_data data = {
+				926,	/* Code */
+				10415,	/* Vendor */
+				"MBMS-BMSC-SSM-UDP-Port",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* MBMS-GW-UDP-Port */
+		{
+			struct dict_avp_data data = {
+				927,	/* Code */
+				10415,	/* Vendor */
+				"MBMS-GW-UDP-Port",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* MBMS-GW-UDP-Port-Indicator */
+		{
+			struct dict_avp_data data = {
+				928,	/* Code */
+				10415,	/* Vendor */
+				"MBMS-GW-UDP-Port-Indicator",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(MBMS-GW-UDP-Port-Indicator)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "UDP_PORT_REQUIRED", { .i32=1 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* MBMS-Data-Transfer-Start */
+		{
+			struct dict_avp_data data = {
+				929,	/* Code */
+				10415,	/* Vendor */
+				"MBMS-Data-Transfer-Start",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED64	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* MBMS-Data-Transfer-Stop */
+		{
+			struct dict_avp_data data = {
+				930,	/* Code */
+				10415,	/* Vendor */
+				"MBMS-Data-Transfer-Stop",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED64	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* MBMS-Flag */
+		{
+			struct dict_avp_data data = {
+				931,	/* Code */
+				10415,	/* Vendor */
+				"MBMS-Flag",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Restart-Counter */
+		{
+			struct dict_avp_data data = {
+				932,	/* Code */
+				10415,	/* Vendor */
+				"Restart-Counter",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Diagnostic-Info */
+		{
+			struct dict_avp_data data = {
+				933,	/* Code */
+				10415,	/* Vendor */
+				"Diagnostic-Info",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* MBMS-Cell-List */
+		{
+			struct dict_avp_data data = {
+				934,	/* Code */
+				10415,	/* Vendor */
+				"MBMS-Cell-List",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+
+	
+   }
+
+   /* Commands section */
+   {
+
+   }
+
+   return 0;
+}
+
+static int dict_ts29061_avps_load_rules(char * conffile)
+{
+   /* Grouped AVP section */
+   {
+
+   }	
+
+   /* Commands section */
+   {
+
+   }
+
+   LOG_D( "Extension 'Dictionary definitions for ts29061_avps (e30)' initialized");
+   return 0;
+}
+
+int dict_entry(char * conffile)
+{
+	dict_ts29061_avps_load_defs(conffile);
+	return dict_ts29061_avps_load_rules(conffile);
+}
+
+const char* dict_ts29061_avps_proto_ver(char * conffile) {
+	return ts29061_avps_proto_ver;
+}
+
+const double dict_ts29061_avps_gen_ts(char * conffile) {
+	return ts29061_avps_gen_date;
+}
+
+EXTENSION_ENTRY2("dict_ts29061_avps", dict_ts29061_avps_load_defs, dict_ts29061_avps_load_rules, "dict_ts29468_avps", "dict_ts29212_avps", "dict_ts29229_avps", "dict_ts29336_avps", "dict_rfc7155_avps");
+
+
+
diff --git a/extensions/dict_ts29061_avps/ts29061_avps.did b/extensions/dict_ts29061_avps/ts29061_avps.did
new file mode 100644
index 0000000..1616278
--- /dev/null
+++ b/extensions/dict_ts29061_avps/ts29061_avps.did
@@ -0,0 +1,37 @@
+dict_rfc6942_avps
+dict_ts29468_avps
+dict_ts29343_avps
+dict_ts29128_avps
+dict_ts29344_avps
+dict_ts29345_avps
+dict_ts29337_avps
+dict_3gpp2_avps
+dict_ts29154_avps
+dict_ts29214_avps
+dict_ts29215_avps
+dict_ts29217_avps
+dict_ts29338_avps
+dict_ts29173_avps
+dict_ts29336_avps
+dict_rfc4590_avps
+dict_ts29229_avps
+dict_ts29329_avps
+dict_ts29368_avps
+dict_ts32299_avps
+dict_rfc6734_avps
+dict_rfc5778_avps
+dict_draftload_avps
+dict_etsi283034_avps
+dict_rfc5580_avps
+dict_rfc4072_avps
+dict_ts29273_avps
+dict_rfc5447_avps
+dict_ts29272_avps
+dict_rfc7683_avps
+dict_rfc7944_avps
+dict_rfc5777_avps
+dict_rfc4006bis_avps
+dict_rfc4004_avps
+dict_rfc7155_avps
+dict_ts29212_avps
+dict_ts29061_avps
diff --git a/extensions/dict_ts29128_avps/CMakeLists.txt b/extensions/dict_ts29128_avps/CMakeLists.txt
new file mode 100644
index 0000000..d6f3a30
--- /dev/null
+++ b/extensions/dict_ts29128_avps/CMakeLists.txt
@@ -0,0 +1,16 @@
+# The dict_ts29128_avps extension
+PROJECT("dict_ts29128_avps library generated by FdGen " C)
+
+# Compile as a module
+FD_ADD_EXTENSION(dict_ts29128_avps dict_ts29128_avps.c)
+
+
+####
+## INSTALL section ##
+
+INSTALL(TARGETS dict_ts29128_avps
+	LIBRARY DESTINATION ${INSTALL_EXTENSIONS_SUFFIX}
+COMPONENT freeDiameter-dictionary-TS29128_AVPS)
+
+
+
diff --git a/extensions/dict_ts29128_avps/dict_ts29128_avps.c b/extensions/dict_ts29128_avps/dict_ts29128_avps.c
new file mode 100644
index 0000000..2dad78a
--- /dev/null
+++ b/extensions/dict_ts29128_avps/dict_ts29128_avps.c
@@ -0,0 +1,502 @@
+/*
+* Copyright (c) 2017 Sprint
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*    http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+/****************
+ Generated By: fdtool enhancements to diafuzzer
+ License: same as freeDiameter
+****************/
+
+
+/* 
+ * Dictionary definitions of objects specified in ts29128_avps (e20).
+ */
+#include <freeDiameter/extension.h>
+
+#define PROTO_VER "e20"
+#define GEN_DATE  1506697139.86
+
+const char *ts29128_avps_proto_ver = PROTO_VER;
+const double ts29128_avps_gen_date = GEN_DATE;
+
+/* The content of this file follows the same structure as dict_base_proto.c */
+
+#define CHECK_dict_new( _type, _data, _parent, _ref )                                     \
+{                                                                                         \
+    int _ret = fd_dict_new( fd_g_config->cnf_dict, (_type), (_data), (_parent), (_ref) ); \
+    if ( _ret != 0 && _ret != EEXIST )                                                    \
+       return _ret;                                                                       \
+}
+
+#define CHECK_dict_search( _type, _criteria, _what, _result )		\
+    CHECK_FCT(  fd_dict_search( fd_g_config->cnf_dict, (_type), (_criteria), (_what), (_result), ENOENT) );
+
+struct local_rules_definition {
+    struct dict_avp_request avp_vendor_plus_name;
+    enum rule_position	position;
+    int 			min;
+    int			max;
+};
+
+#define RULE_ORDER( _position ) ((((_position) == RULE_FIXED_HEAD) || ((_position) == RULE_FIXED_TAIL)) ? 1 : 0 )
+
+/* Attention! This version of the macro uses AVP_BY_NAME_AND_VENDOR, in contrast to most other copies! */
+#define PARSE_loc_rules( _rulearray, _parent) {                                                         \
+        int __ar;                                                                                       \
+        for (__ar=0; __ar < sizeof(_rulearray) / sizeof((_rulearray)[0]); __ar++) {                     \
+                struct dict_rule_data __data = { NULL,                                                  \
+                        (_rulearray)[__ar].position,                                                    \
+                        0,                                                                              \
+                        (_rulearray)[__ar].min,                                                         \
+                        (_rulearray)[__ar].max};                                                        \
+                __data.rule_order = RULE_ORDER(__data.rule_position);                                   \
+                CHECK_FCT(  fd_dict_search(                                                             \
+                        fd_g_config->cnf_dict,                                                          \
+                        DICT_AVP,                                                                       \
+                        AVP_BY_NAME_AND_VENDOR,                                                         \
+                        &(_rulearray)[__ar].avp_vendor_plus_name,                                       \
+                        &__data.rule_avp, 0 ) );                                                        \
+                if ( !__data.rule_avp ) {                                                               \
+                        TRACE_DEBUG(INFO, "AVP Not found: '%s'", (_rulearray)[__ar].avp_vendor_plus_name.avp_name);             \
+                        return ENOENT;                                                                  \
+                }                                                                                       \
+                {                                                                                       \
+                         int _ret = fd_dict_new( fd_g_config->cnf_dict, DICT_RULE, &(__data), (_parent), NULL ); \
+                         if ( _ret != 0 && _ret != EEXIST )      {                                      \
+                                TRACE_DEBUG(INFO, "Error on rule with AVP '%s'",                        \
+                                            (_rulearray)[__ar].avp_vendor_plus_name.avp_name);          \
+                                return EINVAL;                                                          \
+                         }                                                                              \
+                }                                                                                       \
+        }                                                                                               \
+}
+
+#define CHECK_vendor_new( _data ) { \
+        struct dict_object * vendor_found; \
+        if (fd_dict_search(fd_g_config->cnf_dict,DICT_VENDOR,VENDOR_BY_ID,&_data.vendor_id,&vendor_found,ENOENT) == ENOENT) { \
+                CHECK_FCT(fd_dict_new(fd_g_config->cnf_dict, DICT_VENDOR, &_data, NULL, NULL)); \
+        } \
+}
+
+#define enumval_def_u32( _val_, _str_ )		\
+    { _str_, 		{ .u32 = _val_ }}
+
+#define enumval_def_os( _len_, _val_, _str_ )				\
+    { _str_, 		{ .os = { .data = (unsigned char *)_val_, .len = _len_ }}}
+
+
+static int dict_ts29128_avps_load_defs(char * conffile)
+{
+   TRACE_ENTRY("%p", conffile);
+	/* Application Section */
+	{
+		/* Create the vendors */		{
+			struct dict_vendor_data vendor_data = { 10415, "3GPP" };
+			CHECK_dict_new(DICT_VENDOR, &vendor_data, NULL, NULL)
+		}
+	}
+
+
+   /* AVP section */
+   {
+		struct dict_object * Address_type;
+		struct dict_object * UTF8String_type;
+		struct dict_object * DiameterIdentity_type;
+		struct dict_object * DiameterURI_type;
+		struct dict_object * Time_type;
+		struct dict_object * IPFilterRule_type;
+
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "Address", &Address_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "UTF8String", &UTF8String_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "DiameterIdentity", &DiameterIdentity_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "DiameterURI", &DiameterURI_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "Time", &Time_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "IPFilterRule", &IPFilterRule_type);
+		/* Cause-Type */
+		{
+			struct dict_avp_data data = {
+				4301,	/* Code */
+				10415,	/* Vendor */
+				"Cause-Type",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* S1AP-Cause */
+		{
+			struct dict_avp_data data = {
+				4302,	/* Code */
+				10415,	/* Vendor */
+				"S1AP-Cause",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* RANAP-Cause */
+		{
+			struct dict_avp_data data = {
+				4303,	/* Code */
+				10415,	/* Vendor */
+				"RANAP-Cause",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* BSSGP-Cause */
+		{
+			struct dict_avp_data data = {
+				4309,	/* Code */
+				10415,	/* Vendor */
+				"BSSGP-Cause",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* GMM-Cause */
+		{
+			struct dict_avp_data data = {
+				4304,	/* Code */
+				10415,	/* Vendor */
+				"GMM-Cause",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* SM-Cause */
+		{
+			struct dict_avp_data data = {
+				4305,	/* Code */
+				10415,	/* Vendor */
+				"SM-Cause",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* UE-Count */
+		{
+			struct dict_avp_data data = {
+				4308,	/* Code */
+				10415,	/* Vendor */
+				"UE-Count",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Connection-Action */
+		{
+			struct dict_avp_data data = {
+				4314,	/* Code */
+				10415,	/* Vendor */
+				"Connection-Action",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Non-IP-Data */
+		{
+			struct dict_avp_data data = {
+				4315,	/* Code */
+				10415,	/* Vendor */
+				"Non-IP-Data",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Uplink-Rate-Limit */
+		{
+			struct dict_avp_data data = {
+				4311,	/* Code */
+				10415,	/* Vendor */
+				"Uplink-Rate-Limit",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Downlink-Rate-Limit */
+		{
+			struct dict_avp_data data = {
+				4312,	/* Code */
+				10415,	/* Vendor */
+				"Downlink-Rate-Limit",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Extended-PCO */
+		{
+			struct dict_avp_data data = {
+				4313,	/* Code */
+				10415,	/* Vendor */
+				"Extended-PCO",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* SCEF-Wait-Time */
+		{
+			struct dict_avp_data data = {
+				4316,	/* Code */
+				10415,	/* Vendor */
+				"SCEF-Wait-Time",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, Time_type, NULL);
+		};
+		/* CMR-Flags */
+		{
+			struct dict_avp_data data = {
+				4317,	/* Code */
+				10415,	/* Vendor */
+				"CMR-Flags",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Counter-Value */
+		{
+			struct dict_avp_data data = {
+				4319,	/* Code */
+				10415,	/* Vendor */
+				"Counter-Value",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* RRC-Counter-Timestamp */
+		{
+			struct dict_avp_data data = {
+				4320,	/* Code */
+				10415,	/* Vendor */
+				"RRC-Counter-Timestamp",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, Time_type, NULL);
+		};
+		/* Communication-Failure-Information */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				4300,	/* Code */
+				10415,	/* Vendor */
+				"Communication-Failure-Information",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* RRC-Cause-Counter */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				4318,	/* Code */
+				10415,	/* Vendor */
+				"RRC-Cause-Counter",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* Serving-PLMN-Rate-Control */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				4310,	/* Code */
+				10415,	/* Vendor */
+				"Serving-PLMN-Rate-Control",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* Number-Of-UE-Per-Location-Report */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				4307,	/* Code */
+				10415,	/* Vendor */
+				"Number-Of-UE-Per-Location-Report",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* Number-Of-UE-Per-Location-Configuration */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				4306,	/* Code */
+				10415,	/* Vendor */
+				"Number-Of-UE-Per-Location-Configuration",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+
+	
+   }
+
+   /* Commands section */
+   {
+
+   }
+
+   return 0;
+}
+
+static int dict_ts29128_avps_load_rules(char * conffile)
+{
+   /* Grouped AVP section */
+   {
+	  /* Communication-Failure-Information */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "Communication-Failure-Information"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 10415, .avp_name = "Cause-Type"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "S1AP-Cause"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "RANAP-Cause"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "BSSGP-Cause"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "GMM-Cause"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "SM-Cause"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* RRC-Cause-Counter */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "RRC-Cause-Counter"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 10415, .avp_name = "Counter-Value"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "RRC-Counter-Timestamp"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* Serving-PLMN-Rate-Control */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "Serving-PLMN-Rate-Control"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 10415, .avp_name = "Uplink-Rate-Limit"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Downlink-Rate-Limit"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* Number-Of-UE-Per-Location-Report */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "Number-Of-UE-Per-Location-Report"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 10415, .avp_name = "EPS-Location-Information"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "UE-Count"}, RULE_REQUIRED, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* Number-Of-UE-Per-Location-Configuration */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "Number-Of-UE-Per-Location-Configuration"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 10415, .avp_name = "EPS-Location-Information"}, RULE_REQUIRED, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+
+   }	
+
+   /* Commands section */
+   {
+
+   }
+
+   LOG_D( "Extension 'Dictionary definitions for ts29128_avps (e20)' initialized");
+   return 0;
+}
+
+int dict_entry(char * conffile)
+{
+	dict_ts29128_avps_load_defs(conffile);
+	return dict_ts29128_avps_load_rules(conffile);
+}
+
+const char* dict_ts29128_avps_proto_ver(char * conffile) {
+	return ts29128_avps_proto_ver;
+}
+
+const double dict_ts29128_avps_gen_ts(char * conffile) {
+	return ts29128_avps_gen_date;
+}
+
+EXTENSION_ENTRY2("dict_ts29128_avps", dict_ts29128_avps_load_defs, dict_ts29128_avps_load_rules, "dict_ts32299_avps", "dict_ts29272_avps", "dict_ts29336_avps", "dict_ts29212_avps", "dict_ts29338_avps", "dict_ts29229_avps", "dict_ts29061_avps", "dict_draftload_avps", "dict_rfc7683_avps", "dict_rfc5778_avps", "dict_rfc7944_avps");
+
+
+
diff --git a/extensions/dict_ts29128_avps/ts29128_avps.did b/extensions/dict_ts29128_avps/ts29128_avps.did
new file mode 100644
index 0000000..ef80f79
--- /dev/null
+++ b/extensions/dict_ts29128_avps/ts29128_avps.did
@@ -0,0 +1,37 @@
+dict_rfc6942_avps
+dict_ts29468_avps
+dict_ts29154_avps
+dict_ts29214_avps
+dict_ts29215_avps
+dict_ts29217_avps
+dict_3gpp2_avps
+dict_ts29338_avps
+dict_ts29343_avps
+dict_ts29344_avps
+dict_ts29345_avps
+dict_ts32299_avps
+dict_rfc6734_avps
+dict_rfc5778_avps
+dict_rfc5580_avps
+dict_rfc4072_avps
+dict_ts29273_avps
+dict_rfc5777_avps
+dict_rfc4006bis_avps
+dict_ts29212_avps
+dict_ts29061_avps
+dict_rfc5447_avps
+dict_ts29272_avps
+dict_ts29173_avps
+dict_ts29337_avps
+dict_etsi283034_avps
+dict_rfc4590_avps
+dict_rfc4004_avps
+dict_rfc7155_avps
+dict_ts29229_avps
+dict_rfc7683_avps
+dict_draftload_avps
+dict_rfc7944_avps
+dict_ts29329_avps
+dict_ts29368_avps
+dict_ts29336_avps
+dict_ts29128_avps
diff --git a/extensions/dict_ts29154_avps/CMakeLists.txt b/extensions/dict_ts29154_avps/CMakeLists.txt
new file mode 100644
index 0000000..5d5b8fc
--- /dev/null
+++ b/extensions/dict_ts29154_avps/CMakeLists.txt
@@ -0,0 +1,16 @@
+# The dict_ts29154_avps extension
+PROJECT("dict_ts29154_avps library generated by FdGen " C)
+
+# Compile as a module
+FD_ADD_EXTENSION(dict_ts29154_avps dict_ts29154_avps.c)
+
+
+####
+## INSTALL section ##
+
+INSTALL(TARGETS dict_ts29154_avps
+	LIBRARY DESTINATION ${INSTALL_EXTENSIONS_SUFFIX}
+COMPONENT freeDiameter-dictionary-TS29154_AVPS)
+
+
+
diff --git a/extensions/dict_ts29154_avps/dict_ts29154_avps.c b/extensions/dict_ts29154_avps/dict_ts29154_avps.c
new file mode 100644
index 0000000..02dae3d
--- /dev/null
+++ b/extensions/dict_ts29154_avps/dict_ts29154_avps.c
@@ -0,0 +1,313 @@
+/*
+* Copyright (c) 2017 Sprint
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*    http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+/****************
+ Generated By: fdtool enhancements to diafuzzer
+ License: same as freeDiameter
+****************/
+
+
+/* 
+ * Dictionary definitions of objects specified in ts29154_avps (e10).
+ */
+#include <freeDiameter/extension.h>
+
+#define PROTO_VER "e10"
+#define GEN_DATE  1506697149.99
+
+const char *ts29154_avps_proto_ver = PROTO_VER;
+const double ts29154_avps_gen_date = GEN_DATE;
+
+/* The content of this file follows the same structure as dict_base_proto.c */
+
+#define CHECK_dict_new( _type, _data, _parent, _ref )                                     \
+{                                                                                         \
+    int _ret = fd_dict_new( fd_g_config->cnf_dict, (_type), (_data), (_parent), (_ref) ); \
+    if ( _ret != 0 && _ret != EEXIST )                                                    \
+       return _ret;                                                                       \
+}
+
+#define CHECK_dict_search( _type, _criteria, _what, _result )		\
+    CHECK_FCT(  fd_dict_search( fd_g_config->cnf_dict, (_type), (_criteria), (_what), (_result), ENOENT) );
+
+struct local_rules_definition {
+    struct dict_avp_request avp_vendor_plus_name;
+    enum rule_position	position;
+    int 			min;
+    int			max;
+};
+
+#define RULE_ORDER( _position ) ((((_position) == RULE_FIXED_HEAD) || ((_position) == RULE_FIXED_TAIL)) ? 1 : 0 )
+
+/* Attention! This version of the macro uses AVP_BY_NAME_AND_VENDOR, in contrast to most other copies! */
+#define PARSE_loc_rules( _rulearray, _parent) {                                                         \
+        int __ar;                                                                                       \
+        for (__ar=0; __ar < sizeof(_rulearray) / sizeof((_rulearray)[0]); __ar++) {                     \
+                struct dict_rule_data __data = { NULL,                                                  \
+                        (_rulearray)[__ar].position,                                                    \
+                        0,                                                                              \
+                        (_rulearray)[__ar].min,                                                         \
+                        (_rulearray)[__ar].max};                                                        \
+                __data.rule_order = RULE_ORDER(__data.rule_position);                                   \
+                CHECK_FCT(  fd_dict_search(                                                             \
+                        fd_g_config->cnf_dict,                                                          \
+                        DICT_AVP,                                                                       \
+                        AVP_BY_NAME_AND_VENDOR,                                                         \
+                        &(_rulearray)[__ar].avp_vendor_plus_name,                                       \
+                        &__data.rule_avp, 0 ) );                                                        \
+                if ( !__data.rule_avp ) {                                                               \
+                        TRACE_DEBUG(INFO, "AVP Not found: '%s'", (_rulearray)[__ar].avp_vendor_plus_name.avp_name);             \
+                        return ENOENT;                                                                  \
+                }                                                                                       \
+                {                                                                                       \
+                         int _ret = fd_dict_new( fd_g_config->cnf_dict, DICT_RULE, &(__data), (_parent), NULL ); \
+                         if ( _ret != 0 && _ret != EEXIST )      {                                      \
+                                TRACE_DEBUG(INFO, "Error on rule with AVP '%s'",                        \
+                                            (_rulearray)[__ar].avp_vendor_plus_name.avp_name);          \
+                                return EINVAL;                                                          \
+                         }                                                                              \
+                }                                                                                       \
+        }                                                                                               \
+}
+
+#define CHECK_vendor_new( _data ) { \
+        struct dict_object * vendor_found; \
+        if (fd_dict_search(fd_g_config->cnf_dict,DICT_VENDOR,VENDOR_BY_ID,&_data.vendor_id,&vendor_found,ENOENT) == ENOENT) { \
+                CHECK_FCT(fd_dict_new(fd_g_config->cnf_dict, DICT_VENDOR, &_data, NULL, NULL)); \
+        } \
+}
+
+#define enumval_def_u32( _val_, _str_ )		\
+    { _str_, 		{ .u32 = _val_ }}
+
+#define enumval_def_os( _len_, _val_, _str_ )				\
+    { _str_, 		{ .os = { .data = (unsigned char *)_val_, .len = _len_ }}}
+
+
+static int dict_ts29154_avps_load_defs(char * conffile)
+{
+   TRACE_ENTRY("%p", conffile);
+	/* Application Section */
+	{
+		/* Create the vendors */		{
+			struct dict_vendor_data vendor_data = { 10415, "3GPP" };
+			CHECK_dict_new(DICT_VENDOR, &vendor_data, NULL, NULL)
+		}
+	}
+
+
+   /* AVP section */
+   {
+		struct dict_object * Address_type;
+		struct dict_object * UTF8String_type;
+		struct dict_object * DiameterIdentity_type;
+		struct dict_object * DiameterURI_type;
+		struct dict_object * Time_type;
+		struct dict_object * IPFilterRule_type;
+
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "Address", &Address_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "UTF8String", &UTF8String_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "DiameterIdentity", &DiameterIdentity_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "DiameterURI", &DiameterURI_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "Time", &Time_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "IPFilterRule", &IPFilterRule_type);
+		/* Network-Area-Info-List */
+		{
+			struct dict_avp_data data = {
+				4201,	/* Code */
+				10415,	/* Vendor */
+				"Network-Area-Info-List",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Number-Of-UEs */
+		{
+			struct dict_avp_data data = {
+				4209,	/* Code */
+				10415,	/* Vendor */
+				"Number-Of-UEs",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Reference-Id */
+		{
+			struct dict_avp_data data = {
+				4202,	/* Code */
+				10415,	/* Vendor */
+				"Reference-Id",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Transfer-Request-Type */
+		{
+			struct dict_avp_data data = {
+				4203,	/* Code */
+				10415,	/* Vendor */
+				"Transfer-Request-Type",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Transfer-End-Time */
+		{
+			struct dict_avp_data data = {
+				4205,	/* Code */
+				10415,	/* Vendor */
+				"Transfer-End-Time",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, Time_type, NULL);
+		};
+		/* Transfer-Policy-Id */
+		{
+			struct dict_avp_data data = {
+				4208,	/* Code */
+				10415,	/* Vendor */
+				"Transfer-Policy-Id",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Transfer-Start-Time */
+		{
+			struct dict_avp_data data = {
+				4206,	/* Code */
+				10415,	/* Vendor */
+				"Transfer-Start-Time",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, Time_type, NULL);
+		};
+		/* Time-Window */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				4204,	/* Code */
+				10415,	/* Vendor */
+				"Time-Window",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* Transfer-Policy */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				4207,	/* Code */
+				10415,	/* Vendor */
+				"Transfer-Policy",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+
+	
+   }
+
+   /* Commands section */
+   {
+
+   }
+
+   return 0;
+}
+
+static int dict_ts29154_avps_load_rules(char * conffile)
+{
+   /* Grouped AVP section */
+   {
+	  /* Time-Window */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "Time-Window"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 10415, .avp_name = "Transfer-Start-Time"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Transfer-End-Time"}, RULE_REQUIRED, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* Transfer-Policy */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "Transfer-Policy"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 10415, .avp_name = "Transfer-Policy-Id"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Time-Window"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Rating-Group"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Max-Requested-Bandwidth-DL"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Max-Requested-Bandwidth-UL"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+
+   }	
+
+   /* Commands section */
+   {
+
+   }
+
+   LOG_D( "Extension 'Dictionary definitions for ts29154_avps (e10)' initialized");
+   return 0;
+}
+
+int dict_entry(char * conffile)
+{
+	dict_ts29154_avps_load_defs(conffile);
+	return dict_ts29154_avps_load_rules(conffile);
+}
+
+const char* dict_ts29154_avps_proto_ver(char * conffile) {
+	return ts29154_avps_proto_ver;
+}
+
+const double dict_ts29154_avps_gen_ts(char * conffile) {
+	return ts29154_avps_gen_date;
+}
+
+EXTENSION_ENTRY2("dict_ts29154_avps", dict_ts29154_avps_load_defs, dict_ts29154_avps_load_rules, "dict_ts29215_avps", "dict_ts29214_avps", "dict_ts29229_avps", "dict_rfc7683_avps", "dict_rfc4006bis_avps", "dict_draftload_avps", "dict_rfc7944_avps");
+
+
+
diff --git a/extensions/dict_ts29154_avps/ts29154_avps.did b/extensions/dict_ts29154_avps/ts29154_avps.did
new file mode 100644
index 0000000..1a8b394
--- /dev/null
+++ b/extensions/dict_ts29154_avps/ts29154_avps.did
@@ -0,0 +1,37 @@
+dict_rfc6942_avps
+dict_ts29214_avps
+dict_ts29468_avps
+dict_ts29217_avps
+dict_3gpp2_avps
+dict_ts29343_avps
+dict_ts29338_avps
+dict_ts29128_avps
+dict_ts29344_avps
+dict_ts29345_avps
+dict_ts32299_avps
+dict_rfc6734_avps
+dict_rfc5778_avps
+dict_rfc5580_avps
+dict_rfc4072_avps
+dict_ts29273_avps
+dict_ts29173_avps
+dict_ts29337_avps
+dict_etsi283034_avps
+dict_rfc4590_avps
+dict_ts29229_avps
+dict_ts29329_avps
+dict_ts29368_avps
+dict_ts29336_avps
+dict_ts29061_avps
+dict_rfc5447_avps
+dict_ts29272_avps
+dict_rfc7683_avps
+dict_ts29212_avps
+dict_ts29215_avps
+dict_draftload_avps
+dict_rfc7944_avps
+dict_rfc4004_avps
+dict_rfc7155_avps
+dict_rfc5777_avps
+dict_rfc4006bis_avps
+dict_ts29154_avps
diff --git a/extensions/dict_ts29173_avps/CMakeLists.txt b/extensions/dict_ts29173_avps/CMakeLists.txt
new file mode 100644
index 0000000..7ea8b5c
--- /dev/null
+++ b/extensions/dict_ts29173_avps/CMakeLists.txt
@@ -0,0 +1,16 @@
+# The dict_ts29173_avps extension
+PROJECT("dict_ts29173_avps library generated by FdGen " C)
+
+# Compile as a module
+FD_ADD_EXTENSION(dict_ts29173_avps dict_ts29173_avps.c)
+
+
+####
+## INSTALL section ##
+
+INSTALL(TARGETS dict_ts29173_avps
+	LIBRARY DESTINATION ${INSTALL_EXTENSIONS_SUFFIX}
+COMPONENT freeDiameter-dictionary-TS29173_AVPS)
+
+
+
diff --git a/extensions/dict_ts29173_avps/dict_ts29173_avps.c b/extensions/dict_ts29173_avps/dict_ts29173_avps.c
new file mode 100644
index 0000000..d82e53d
--- /dev/null
+++ b/extensions/dict_ts29173_avps/dict_ts29173_avps.c
@@ -0,0 +1,360 @@
+/*
+* Copyright (c) 2017 Sprint
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*    http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+/****************
+ Generated By: fdtool enhancements to diafuzzer
+ License: same as freeDiameter
+****************/
+
+
+/* 
+ * Dictionary definitions of objects specified in ts29173_avps (e00).
+ */
+#include <freeDiameter/extension.h>
+
+#define PROTO_VER "e00"
+#define GEN_DATE  1506697172.2
+
+const char *ts29173_avps_proto_ver = PROTO_VER;
+const double ts29173_avps_gen_date = GEN_DATE;
+
+/* The content of this file follows the same structure as dict_base_proto.c */
+
+#define CHECK_dict_new( _type, _data, _parent, _ref )                                     \
+{                                                                                         \
+    int _ret = fd_dict_new( fd_g_config->cnf_dict, (_type), (_data), (_parent), (_ref) ); \
+    if ( _ret != 0 && _ret != EEXIST )                                                    \
+       return _ret;                                                                       \
+}
+
+#define CHECK_dict_search( _type, _criteria, _what, _result )		\
+    CHECK_FCT(  fd_dict_search( fd_g_config->cnf_dict, (_type), (_criteria), (_what), (_result), ENOENT) );
+
+struct local_rules_definition {
+    struct dict_avp_request avp_vendor_plus_name;
+    enum rule_position	position;
+    int 			min;
+    int			max;
+};
+
+#define RULE_ORDER( _position ) ((((_position) == RULE_FIXED_HEAD) || ((_position) == RULE_FIXED_TAIL)) ? 1 : 0 )
+
+/* Attention! This version of the macro uses AVP_BY_NAME_AND_VENDOR, in contrast to most other copies! */
+#define PARSE_loc_rules( _rulearray, _parent) {                                                         \
+        int __ar;                                                                                       \
+        for (__ar=0; __ar < sizeof(_rulearray) / sizeof((_rulearray)[0]); __ar++) {                     \
+                struct dict_rule_data __data = { NULL,                                                  \
+                        (_rulearray)[__ar].position,                                                    \
+                        0,                                                                              \
+                        (_rulearray)[__ar].min,                                                         \
+                        (_rulearray)[__ar].max};                                                        \
+                __data.rule_order = RULE_ORDER(__data.rule_position);                                   \
+                CHECK_FCT(  fd_dict_search(                                                             \
+                        fd_g_config->cnf_dict,                                                          \
+                        DICT_AVP,                                                                       \
+                        AVP_BY_NAME_AND_VENDOR,                                                         \
+                        &(_rulearray)[__ar].avp_vendor_plus_name,                                       \
+                        &__data.rule_avp, 0 ) );                                                        \
+                if ( !__data.rule_avp ) {                                                               \
+                        TRACE_DEBUG(INFO, "AVP Not found: '%s'", (_rulearray)[__ar].avp_vendor_plus_name.avp_name);             \
+                        return ENOENT;                                                                  \
+                }                                                                                       \
+                {                                                                                       \
+                         int _ret = fd_dict_new( fd_g_config->cnf_dict, DICT_RULE, &(__data), (_parent), NULL ); \
+                         if ( _ret != 0 && _ret != EEXIST )      {                                      \
+                                TRACE_DEBUG(INFO, "Error on rule with AVP '%s'",                        \
+                                            (_rulearray)[__ar].avp_vendor_plus_name.avp_name);          \
+                                return EINVAL;                                                          \
+                         }                                                                              \
+                }                                                                                       \
+        }                                                                                               \
+}
+
+#define CHECK_vendor_new( _data ) { \
+        struct dict_object * vendor_found; \
+        if (fd_dict_search(fd_g_config->cnf_dict,DICT_VENDOR,VENDOR_BY_ID,&_data.vendor_id,&vendor_found,ENOENT) == ENOENT) { \
+                CHECK_FCT(fd_dict_new(fd_g_config->cnf_dict, DICT_VENDOR, &_data, NULL, NULL)); \
+        } \
+}
+
+#define enumval_def_u32( _val_, _str_ )		\
+    { _str_, 		{ .u32 = _val_ }}
+
+#define enumval_def_os( _len_, _val_, _str_ )				\
+    { _str_, 		{ .os = { .data = (unsigned char *)_val_, .len = _len_ }}}
+
+
+static int dict_ts29173_avps_load_defs(char * conffile)
+{
+   TRACE_ENTRY("%p", conffile);
+	/* Application Section */
+	{
+		/* Create the vendors */		{
+			struct dict_vendor_data vendor_data = { 10415, "3GPP" };
+			CHECK_dict_new(DICT_VENDOR, &vendor_data, NULL, NULL)
+		}
+	}
+
+
+   /* AVP section */
+   {
+		struct dict_object * Address_type;
+		struct dict_object * UTF8String_type;
+		struct dict_object * DiameterIdentity_type;
+		struct dict_object * DiameterURI_type;
+		struct dict_object * Time_type;
+		struct dict_object * IPFilterRule_type;
+
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "Address", &Address_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "UTF8String", &UTF8String_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "DiameterIdentity", &DiameterIdentity_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "DiameterURI", &DiameterURI_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "Time", &Time_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "IPFilterRule", &IPFilterRule_type);
+		/* LMSI */
+		{
+			struct dict_avp_data data = {
+				2400,	/* Code */
+				10415,	/* Vendor */
+				"LMSI",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* MME-Name */
+		{
+			struct dict_avp_data data = {
+				2402,	/* Code */
+				10415,	/* Vendor */
+				"MME-Name",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, DiameterIdentity_type, NULL);
+		};
+		/* MSC-Number */
+		{
+			struct dict_avp_data data = {
+				2403,	/* Code */
+				10415,	/* Vendor */
+				"MSC-Number",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* LCS-Capabilities-Sets */
+		{
+			struct dict_avp_data data = {
+				2404,	/* Code */
+				10415,	/* Vendor */
+				"LCS-Capabilities-Sets",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* GMLC-Address */
+		{
+			struct dict_avp_data data = {
+				2405,	/* Code */
+				10415,	/* Vendor */
+				"GMLC-Address",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, Address_type, NULL);
+		};
+		/* PPR-Address */
+		{
+			struct dict_avp_data data = {
+				2407,	/* Code */
+				10415,	/* Vendor */
+				"PPR-Address",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, Address_type, NULL);
+		};
+		/* MME-Realm */
+		{
+			struct dict_avp_data data = {
+				2408,	/* Code */
+				10415,	/* Vendor */
+				"MME-Realm",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, DiameterIdentity_type, NULL);
+		};
+		/* SGSN-Name */
+		{
+			struct dict_avp_data data = {
+				2409,	/* Code */
+				10415,	/* Vendor */
+				"SGSN-Name",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, DiameterIdentity_type, NULL);
+		};
+		/* SGSN-Realm */
+		{
+			struct dict_avp_data data = {
+				2410,	/* Code */
+				10415,	/* Vendor */
+				"SGSN-Realm",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, DiameterIdentity_type, NULL);
+		};
+		/* RIA-Flags */
+		{
+			struct dict_avp_data data = {
+				2411,	/* Code */
+				10415,	/* Vendor */
+				"RIA-Flags",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Additional-Serving-Node */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				2406,	/* Code */
+				10415,	/* Vendor */
+				"Additional-Serving-Node",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* Serving-Node */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				2401,	/* Code */
+				10415,	/* Vendor */
+				"Serving-Node",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+
+	
+   }
+
+   /* Commands section */
+   {
+
+   }
+
+   return 0;
+}
+
+static int dict_ts29173_avps_load_rules(char * conffile)
+{
+   /* Grouped AVP section */
+   {
+	  /* Additional-Serving-Node */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "Additional-Serving-Node"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 10415, .avp_name = "SGSN-Number"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "MME-Name"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "SGSN-Name"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "SGSN-Realm"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "MME-Realm"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "MSC-Number"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "3GPP-AAA-Server-Name"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "LCS-Capabilities-Sets"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "GMLC-Address"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* Serving-Node */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "Serving-Node"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 10415, .avp_name = "SGSN-Number"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "SGSN-Name"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "SGSN-Realm"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "MME-Name"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "MME-Realm"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "MSC-Number"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "3GPP-AAA-Server-Name"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "LCS-Capabilities-Sets"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "GMLC-Address"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+
+   }	
+
+   /* Commands section */
+   {
+
+   }
+
+   LOG_D( "Extension 'Dictionary definitions for ts29173_avps (e00)' initialized");
+   return 0;
+}
+
+int dict_entry(char * conffile)
+{
+	dict_ts29173_avps_load_defs(conffile);
+	return dict_ts29173_avps_load_rules(conffile);
+}
+
+const char* dict_ts29173_avps_proto_ver(char * conffile) {
+	return ts29173_avps_proto_ver;
+}
+
+const double dict_ts29173_avps_gen_ts(char * conffile) {
+	return ts29173_avps_gen_date;
+}
+
+EXTENSION_ENTRY2("dict_ts29173_avps", dict_ts29173_avps_load_defs, dict_ts29173_avps_load_rules, "dict_ts29272_avps", "dict_ts29273_avps", "dict_ts29329_avps", "dict_ts29229_avps");
+
+
+
diff --git a/extensions/dict_ts29173_avps/ts29173_avps.did b/extensions/dict_ts29173_avps/ts29173_avps.did
new file mode 100644
index 0000000..3b61556
--- /dev/null
+++ b/extensions/dict_ts29173_avps/ts29173_avps.did
@@ -0,0 +1,37 @@
+dict_rfc6942_avps
+dict_ts29468_avps
+dict_ts29343_avps
+dict_ts29128_avps
+dict_ts29344_avps
+dict_ts29345_avps
+dict_ts29337_avps
+dict_3gpp2_avps
+dict_ts29154_avps
+dict_ts29214_avps
+dict_ts29215_avps
+dict_ts29217_avps
+dict_ts29338_avps
+dict_ts29336_avps
+dict_ts29368_avps
+dict_ts32299_avps
+dict_rfc6734_avps
+dict_rfc5778_avps
+dict_rfc5580_avps
+dict_rfc4072_avps
+dict_ts29273_avps
+dict_rfc5777_avps
+dict_rfc4006bis_avps
+dict_ts29212_avps
+dict_ts29061_avps
+dict_rfc5447_avps
+dict_ts29272_avps
+dict_etsi283034_avps
+dict_rfc4590_avps
+dict_rfc4004_avps
+dict_rfc7155_avps
+dict_ts29229_avps
+dict_rfc7683_avps
+dict_draftload_avps
+dict_rfc7944_avps
+dict_ts29329_avps
+dict_ts29173_avps
diff --git a/extensions/dict_ts29212_avps/CMakeLists.txt b/extensions/dict_ts29212_avps/CMakeLists.txt
new file mode 100644
index 0000000..0ede9a0
--- /dev/null
+++ b/extensions/dict_ts29212_avps/CMakeLists.txt
@@ -0,0 +1,16 @@
+# The dict_ts29212_avps extension
+PROJECT("dict_ts29212_avps library generated by FdGen " C)
+
+# Compile as a module
+FD_ADD_EXTENSION(dict_ts29212_avps dict_ts29212_avps.c)
+
+
+####
+## INSTALL section ##
+
+INSTALL(TARGETS dict_ts29212_avps
+	LIBRARY DESTINATION ${INSTALL_EXTENSIONS_SUFFIX}
+COMPONENT freeDiameter-dictionary-TS29212_AVPS)
+
+
+
diff --git a/extensions/dict_ts29212_avps/dict_ts29212_avps.c b/extensions/dict_ts29212_avps/dict_ts29212_avps.c
new file mode 100644
index 0000000..f0012be
--- /dev/null
+++ b/extensions/dict_ts29212_avps/dict_ts29212_avps.c
@@ -0,0 +1,3148 @@
+/*
+* Copyright (c) 2017 Sprint
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*    http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+/****************
+ Generated By: fdtool enhancements to diafuzzer
+ License: same as freeDiameter
+****************/
+
+
+/* 
+ * Dictionary definitions of objects specified in ts29212_avps (e30).
+ */
+#include <freeDiameter/extension.h>
+
+#define PROTO_VER "e30"
+#define GEN_DATE  1506697181.97
+
+const char *ts29212_avps_proto_ver = PROTO_VER;
+const double ts29212_avps_gen_date = GEN_DATE;
+
+/* The content of this file follows the same structure as dict_base_proto.c */
+
+#define CHECK_dict_new( _type, _data, _parent, _ref )                                     \
+{                                                                                         \
+    int _ret = fd_dict_new( fd_g_config->cnf_dict, (_type), (_data), (_parent), (_ref) ); \
+    if ( _ret != 0 && _ret != EEXIST )                                                    \
+       return _ret;                                                                       \
+}
+
+#define CHECK_dict_search( _type, _criteria, _what, _result )		\
+    CHECK_FCT(  fd_dict_search( fd_g_config->cnf_dict, (_type), (_criteria), (_what), (_result), ENOENT) );
+
+struct local_rules_definition {
+    struct dict_avp_request avp_vendor_plus_name;
+    enum rule_position	position;
+    int 			min;
+    int			max;
+};
+
+#define RULE_ORDER( _position ) ((((_position) == RULE_FIXED_HEAD) || ((_position) == RULE_FIXED_TAIL)) ? 1 : 0 )
+
+/* Attention! This version of the macro uses AVP_BY_NAME_AND_VENDOR, in contrast to most other copies! */
+#define PARSE_loc_rules( _rulearray, _parent) {                                                         \
+        int __ar;                                                                                       \
+        for (__ar=0; __ar < sizeof(_rulearray) / sizeof((_rulearray)[0]); __ar++) {                     \
+                struct dict_rule_data __data = { NULL,                                                  \
+                        (_rulearray)[__ar].position,                                                    \
+                        0,                                                                              \
+                        (_rulearray)[__ar].min,                                                         \
+                        (_rulearray)[__ar].max};                                                        \
+                __data.rule_order = RULE_ORDER(__data.rule_position);                                   \
+                CHECK_FCT(  fd_dict_search(                                                             \
+                        fd_g_config->cnf_dict,                                                          \
+                        DICT_AVP,                                                                       \
+                        AVP_BY_NAME_AND_VENDOR,                                                         \
+                        &(_rulearray)[__ar].avp_vendor_plus_name,                                       \
+                        &__data.rule_avp, 0 ) );                                                        \
+                if ( !__data.rule_avp ) {                                                               \
+                        TRACE_DEBUG(INFO, "AVP Not found: '%s'", (_rulearray)[__ar].avp_vendor_plus_name.avp_name);             \
+                        return ENOENT;                                                                  \
+                }                                                                                       \
+                {                                                                                       \
+                         int _ret = fd_dict_new( fd_g_config->cnf_dict, DICT_RULE, &(__data), (_parent), NULL ); \
+                         if ( _ret != 0 && _ret != EEXIST )      {                                      \
+                                TRACE_DEBUG(INFO, "Error on rule with AVP '%s'",                        \
+                                            (_rulearray)[__ar].avp_vendor_plus_name.avp_name);          \
+                                return EINVAL;                                                          \
+                         }                                                                              \
+                }                                                                                       \
+        }                                                                                               \
+}
+
+#define CHECK_vendor_new( _data ) { \
+        struct dict_object * vendor_found; \
+        if (fd_dict_search(fd_g_config->cnf_dict,DICT_VENDOR,VENDOR_BY_ID,&_data.vendor_id,&vendor_found,ENOENT) == ENOENT) { \
+                CHECK_FCT(fd_dict_new(fd_g_config->cnf_dict, DICT_VENDOR, &_data, NULL, NULL)); \
+        } \
+}
+
+#define enumval_def_u32( _val_, _str_ )		\
+    { _str_, 		{ .u32 = _val_ }}
+
+#define enumval_def_os( _len_, _val_, _str_ )				\
+    { _str_, 		{ .os = { .data = (unsigned char *)_val_, .len = _len_ }}}
+
+
+static int dict_ts29212_avps_load_defs(char * conffile)
+{
+   TRACE_ENTRY("%p", conffile);
+	/* Application Section */
+	{
+		/* Create the vendors */		{
+			struct dict_vendor_data vendor_data = { 10415, "3GPP" };
+			CHECK_dict_new(DICT_VENDOR, &vendor_data, NULL, NULL)
+		}
+	}
+
+
+   /* AVP section */
+   {
+		struct dict_object * Address_type;
+		struct dict_object * UTF8String_type;
+		struct dict_object * DiameterIdentity_type;
+		struct dict_object * DiameterURI_type;
+		struct dict_object * Time_type;
+		struct dict_object * IPFilterRule_type;
+
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "Address", &Address_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "UTF8String", &UTF8String_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "DiameterIdentity", &DiameterIdentity_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "DiameterURI", &DiameterURI_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "Time", &Time_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "IPFilterRule", &IPFilterRule_type);
+		/* 3GPP-PS-Data-Off-Status */
+		{
+			struct dict_avp_data data = {
+				2847,	/* Code */
+				10415,	/* Vendor */
+				"3GPP-PS-Data-Off-Status",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(3GPP-PS-Data-Off-Status)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "ACTIVE", { .i32=0 }};
+			struct dict_enumval_data        t_2 = { "INACTIVE", { .i32=1 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* Access-Availability-Change-Reason */
+		{
+			struct dict_avp_data data = {
+				2833,	/* Code */
+				10415,	/* Vendor */
+				"Access-Availability-Change-Reason",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* AN-GW-Address */
+		{
+			struct dict_avp_data data = {
+				1050,	/* Code */
+				10415,	/* Vendor */
+				"AN-GW-Address",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, Address_type, NULL);
+		};
+		/* AN-GW-Status */
+		{
+			struct dict_avp_data data = {
+				2811,	/* Code */
+				10415,	/* Vendor */
+				"AN-GW-Status",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(AN-GW-Status)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "AN_GW_FAILED", { .i32=0 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* APN-Aggregate-Max-Bitrate-DL */
+		{
+			struct dict_avp_data data = {
+				1040,	/* Code */
+				10415,	/* Vendor */
+				"APN-Aggregate-Max-Bitrate-DL",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* APN-Aggregate-Max-Bitrate-UL */
+		{
+			struct dict_avp_data data = {
+				1041,	/* Code */
+				10415,	/* Vendor */
+				"APN-Aggregate-Max-Bitrate-UL",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Bearer-Control-Mode */
+		{
+			struct dict_avp_data data = {
+				1023,	/* Code */
+				10415,	/* Vendor */
+				"Bearer-Control-Mode",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Bearer-Control-Mode)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "UE_ONLY", { .i32=0 }};
+			struct dict_enumval_data        t_2 = { "RESERVED", { .i32=1 }};
+			struct dict_enumval_data        t_3 = { "UE_NW", { .i32=2 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_3, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* Bearer-Identifier */
+		{
+			struct dict_avp_data data = {
+				1020,	/* Code */
+				10415,	/* Vendor */
+				"Bearer-Identifier",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Bearer-Operation */
+		{
+			struct dict_avp_data data = {
+				1021,	/* Code */
+				10415,	/* Vendor */
+				"Bearer-Operation",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Bearer-Operation)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "TERMINATION", { .i32=0 }};
+			struct dict_enumval_data        t_2 = { "ESTABLISHMENT", { .i32=1 }};
+			struct dict_enumval_data        t_3 = { "MODIFICATION", { .i32=2 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_3, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* Bearer-Usage */
+		{
+			struct dict_avp_data data = {
+				1000,	/* Code */
+				10415,	/* Vendor */
+				"Bearer-Usage",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Bearer-Usage)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "GENERAL", { .i32=0 }};
+			struct dict_enumval_data        t_2 = { "IMS_SIGNALLING", { .i32=1 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* Charging-Correlation-Indicator */
+		{
+			struct dict_avp_data data = {
+				1073,	/* Code */
+				10415,	/* Vendor */
+				"Charging-Correlation-Indicator",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Charging-Correlation-Indicator)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "CHARGING_IDENTIFIER_REQUIRED", { .i32=0 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* Charging-Rule-Base-Name */
+		{
+			struct dict_avp_data data = {
+				1004,	/* Code */
+				10415,	/* Vendor */
+				"Charging-Rule-Base-Name",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, UTF8String_type, NULL);
+		};
+		/* Charging-Rule-Name */
+		{
+			struct dict_avp_data data = {
+				1005,	/* Code */
+				10415,	/* Vendor */
+				"Charging-Rule-Name",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* CoA-IP-Address */
+		{
+			struct dict_avp_data data = {
+				1035,	/* Code */
+				10415,	/* Vendor */
+				"CoA-IP-Address",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, Address_type, NULL);
+		};
+		/* Credit-Management-Status */
+		{
+			struct dict_avp_data data = {
+				1082,	/* Code */
+				10415,	/* Vendor */
+				"Credit-Management-Status",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* CSG-Information-Reporting */
+		{
+			struct dict_avp_data data = {
+				1071,	/* Code */
+				10415,	/* Vendor */
+				"CSG-Information-Reporting",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(CSG-Information-Reporting)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "CHANGE_CSG_CELL", { .i32=0 }};
+			struct dict_enumval_data        t_2 = { "CHANGE_CSG_SUBSCRIBED_HYBRID_CELL", { .i32=1 }};
+			struct dict_enumval_data        t_3 = { "CHANGE_CSG_UNSUBSCRIBED_HYBRID_CELL", { .i32=2 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_3, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* Default-Access */
+		{
+			struct dict_avp_data data = {
+				2829,	/* Code */
+				10415,	/* Vendor */
+				"Default-Access",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Default-Access)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "GPP_GPRS", { .i32=0 }};
+			struct dict_enumval_data        t_2 = { "DOCSIS", { .i32=1 }};
+			struct dict_enumval_data        t_3 = { "xDSL", { .i32=2 }};
+			struct dict_enumval_data        t_4 = { "WiMAX", { .i32=3 }};
+			struct dict_enumval_data        t_5 = { "GPP2", { .i32=4 }};
+			struct dict_enumval_data        t_6 = { "GPP_EPS", { .i32=5 }};
+			struct dict_enumval_data        t_7 = { "Non_3GPP_EPS", { .i32=6 }};
+			struct dict_enumval_data        t_8 = { "FBA", { .i32=7 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_3, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_4, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_5, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_6, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_7, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_8, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* Default-Bearer-Indication */
+		{
+			struct dict_avp_data data = {
+				2844,	/* Code */
+				10415,	/* Vendor */
+				"Default-Bearer-Indication",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Default-Bearer-Indication)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "BIND_TO_DEF_BEARER", { .i32=0 }};
+			struct dict_enumval_data        t_2 = { "BIND_TO_APPLICABLE_BEARER", { .i32=1 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* Default-QoS-Name */
+		{
+			struct dict_avp_data data = {
+				2817,	/* Code */
+				10415,	/* Vendor */
+				"Default-QoS-Name",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, UTF8String_type, NULL);
+		};
+		/* Event-Trigger */
+		{
+			struct dict_avp_data data = {
+				1006,	/* Code */
+				10415,	/* Vendor */
+				"Event-Trigger",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Event-Trigger)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "SGSN_CHANGE", { .i32=0 }};
+			struct dict_enumval_data        t_2 = { "QOS_CHANGE", { .i32=1 }};
+			struct dict_enumval_data        t_3 = { "QOS_CHANGE_EXCEEDING_AUTHORIZATION", { .i32=11 }};
+			struct dict_enumval_data        t_4 = { "RAI_CHANGE", { .i32=12 }};
+			struct dict_enumval_data        t_5 = { "USER_LOCATION_CHANGE", { .i32=13 }};
+			struct dict_enumval_data        t_6 = { "NO_EVENT_TRIGGERS", { .i32=14 }};
+			struct dict_enumval_data        t_7 = { "OUT_OF_CREDIT", { .i32=15 }};
+			struct dict_enumval_data        t_8 = { "REALLOCATION_OF_CREDIT", { .i32=16 }};
+			struct dict_enumval_data        t_9 = { "REVALIDATION_TIMEOUT", { .i32=17 }};
+			struct dict_enumval_data        t_10 = { "UE_IP_ADDRESS_ALLOCATE", { .i32=18 }};
+			struct dict_enumval_data        t_11 = { "UE_IP_ADDRESS_RELEASE", { .i32=19 }};
+			struct dict_enumval_data        t_12 = { "RAT_CHANGE", { .i32=2 }};
+			struct dict_enumval_data        t_13 = { "DEFAULT_EPS_BEARER_QOS_CHANGE", { .i32=20 }};
+			struct dict_enumval_data        t_14 = { "AN_GW_CHANGE", { .i32=21 }};
+			struct dict_enumval_data        t_15 = { "SUCCESSFUL_RESOURCE_ALLOCATION", { .i32=22 }};
+			struct dict_enumval_data        t_16 = { "RESOURCE_MODIFICATION_REQUEST", { .i32=23 }};
+			struct dict_enumval_data        t_17 = { "PGW_TRACE_CONTROL", { .i32=24 }};
+			struct dict_enumval_data        t_18 = { "UE_TIME_ZONE_CHANGE", { .i32=25 }};
+			struct dict_enumval_data        t_19 = { "TAI_CHANGE", { .i32=26 }};
+			struct dict_enumval_data        t_20 = { "ECGI_CHANGE", { .i32=27 }};
+			struct dict_enumval_data        t_21 = { "CHARGING_CORRELATION_EXCHANGE", { .i32=28 }};
+			struct dict_enumval_data        t_22 = { "APN_AMBR_MODIFICATION_FAILURE", { .i32=29 }};
+			struct dict_enumval_data        t_23 = { "TFT_CHANGE", { .i32=3 }};
+			struct dict_enumval_data        t_24 = { "USER_CSG_INFORMATION_CHANGE", { .i32=30 }};
+			struct dict_enumval_data        t_25 = { "USAGE_REPORT", { .i32=33 }};
+			struct dict_enumval_data        t_26 = { "DEFAULT_EPS_BEARER_QOS_MODIFICATION_FAILURE", { .i32=34 }};
+			struct dict_enumval_data        t_27 = { "USER_CSG_HYBRID_SUBSCRIBED_INFORMATION_CHANGE", { .i32=35 }};
+			struct dict_enumval_data        t_28 = { "HYBRID_UNSUBSCRIBED_INFORMATION_CHANGE", { .i32=36 }};
+			struct dict_enumval_data        t_29 = { "ROUTING_RULE_CHANGE", { .i32=37 }};
+			struct dict_enumval_data        t_30 = { "APPLICATION_START", { .i32=39 }};
+			struct dict_enumval_data        t_31 = { "PLMN_CHANGE", { .i32=4 }};
+			struct dict_enumval_data        t_32 = { "APPLICATION_STOP", { .i32=40 }};
+			struct dict_enumval_data        t_33 = { "CS_TO_PS_HANDOVER", { .i32=42 }};
+			struct dict_enumval_data        t_34 = { "UE_LOCAL_IP_ADDRESS_CHANGE", { .i32=43 }};
+			struct dict_enumval_data        t_35 = { "NB_LOCAL_IP_ADDRESS_CHANGE", { .i32=44 }};
+			struct dict_enumval_data        t_36 = { "ACCESS_NETWORK_INFO_REPORT", { .i32=45 }};
+			struct dict_enumval_data        t_37 = { "CREDIT_MANAGEMENT_SESSION_FAILURE", { .i32=46 }};
+			struct dict_enumval_data        t_38 = { "DEFAULT_QOS_CHANGE", { .i32=47 }};
+			struct dict_enumval_data        t_39 = { "CHANGE_OF_UE_PRESENCE_IN_PRESENCE_REPORTING_AREA_REPORT", { .i32=48 }};
+			struct dict_enumval_data        t_40 = { "ADDITION_OF_ACCESS", { .i32=49 }};
+			struct dict_enumval_data        t_41 = { "LOSS_OF_BEARER", { .i32=5 }};
+			struct dict_enumval_data        t_42 = { "REMOVAL_OF_ACCESS", { .i32=50 }};
+			struct dict_enumval_data        t_43 = { "UNAVAILABLITY_OF_ACCESS", { .i32=51 }};
+			struct dict_enumval_data        t_44 = { "AVAILABLITY_OF_ACCESS", { .i32=52 }};
+			struct dict_enumval_data        t_45 = { "RESOURCE_RELEASE", { .i32=53 }};
+			struct dict_enumval_data        t_46 = { "ENODEB_CHANGE", { .i32=54 }};
+			struct dict_enumval_data        t_47 = { "GPP_PS_DATA_OFF_CHANGE", { .i32=55 }};
+			struct dict_enumval_data        t_48 = { "RECOVERY_OF_BEARER", { .i32=6 }};
+			struct dict_enumval_data        t_49 = { "IP_CAN_CHANGE", { .i32=7 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_3, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_4, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_5, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_6, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_7, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_8, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_9, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_10, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_11, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_12, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_13, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_14, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_15, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_16, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_17, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_18, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_19, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_20, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_21, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_22, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_23, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_24, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_25, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_26, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_27, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_28, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_29, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_30, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_31, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_32, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_33, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_34, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_35, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_36, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_37, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_38, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_39, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_40, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_41, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_42, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_43, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_44, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_45, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_46, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_47, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_48, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_49, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* Execution-Time */
+		{
+			struct dict_avp_data data = {
+				2839,	/* Code */
+				10415,	/* Vendor */
+				"Execution-Time",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, Time_type, NULL);
+		};
+		/* Flow-Direction */
+		{
+			struct dict_avp_data data = {
+				1080,	/* Code */
+				10415,	/* Vendor */
+				"Flow-Direction",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Flow-Direction)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "UNSPECIFIED", { .i32=0 }};
+			struct dict_enumval_data        t_2 = { "DOWNLINK", { .i32=1 }};
+			struct dict_enumval_data        t_3 = { "UPLINK", { .i32=2 }};
+			struct dict_enumval_data        t_4 = { "BIDIRECTIONAL", { .i32=3 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_3, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_4, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* Flow-Label */
+		{
+			struct dict_avp_data data = {
+				1057,	/* Code */
+				10415,	/* Vendor */
+				"Flow-Label",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Guaranteed-Bitrate-DL */
+		{
+			struct dict_avp_data data = {
+				1025,	/* Code */
+				10415,	/* Vendor */
+				"Guaranteed-Bitrate-DL",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Guaranteed-Bitrate-UL */
+		{
+			struct dict_avp_data data = {
+				1026,	/* Code */
+				10415,	/* Vendor */
+				"Guaranteed-Bitrate-UL",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* HeNB-Local-IP-Address */
+		{
+			struct dict_avp_data data = {
+				2804,	/* Code */
+				10415,	/* Vendor */
+				"HeNB-Local-IP-Address",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, Address_type, NULL);
+		};
+		/* IP-CAN-Session-Charging-Scope */
+		{
+			struct dict_avp_data data = {
+				2827,	/* Code */
+				10415,	/* Vendor */
+				"IP-CAN-Session-Charging-Scope",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(IP-CAN-Session-Charging-Scope)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "IP_CAN_SESSION_SCOPE", { .i32=0 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* IP-CAN-Type */
+		{
+			struct dict_avp_data data = {
+				1027,	/* Code */
+				10415,	/* Vendor */
+				"IP-CAN-Type",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(IP-CAN-Type)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "GPP_GPRS", { .i32=0 }};
+			struct dict_enumval_data        t_2 = { "DOCSIS", { .i32=1 }};
+			struct dict_enumval_data        t_3 = { "xDSL", { .i32=2 }};
+			struct dict_enumval_data        t_4 = { "WiMAX", { .i32=3 }};
+			struct dict_enumval_data        t_5 = { "GPP2", { .i32=4 }};
+			struct dict_enumval_data        t_6 = { "GPP_EPS", { .i32=5 }};
+			struct dict_enumval_data        t_7 = { "Non_3GPP_EPS", { .i32=6 }};
+			struct dict_enumval_data        t_8 = { "FBA", { .i32=7 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_3, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_4, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_5, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_6, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_7, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_8, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* Metering-Method */
+		{
+			struct dict_avp_data data = {
+				1007,	/* Code */
+				10415,	/* Vendor */
+				"Metering-Method",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Metering-Method)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "DURATION", { .i32=0 }};
+			struct dict_enumval_data        t_2 = { "VOLUME", { .i32=1 }};
+			struct dict_enumval_data        t_3 = { "DURATION_VOLUME", { .i32=2 }};
+			struct dict_enumval_data        t_4 = { "EVENT", { .i32=3 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_3, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_4, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* Monitoring-Flags */
+		{
+			struct dict_avp_data data = {
+				2828,	/* Code */
+				10415,	/* Vendor */
+				"Monitoring-Flags",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Monitoring-Key */
+		{
+			struct dict_avp_data data = {
+				1066,	/* Code */
+				10415,	/* Vendor */
+				"Monitoring-Key",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Mute-Notification */
+		{
+			struct dict_avp_data data = {
+				2809,	/* Code */
+				10415,	/* Vendor */
+				"Mute-Notification",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Mute-Notification)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "MUTE_REQUIRED", { .i32=0 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* Monitoring-Time */
+		{
+			struct dict_avp_data data = {
+				2810,	/* Code */
+				10415,	/* Vendor */
+				"Monitoring-Time",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, Time_type, NULL);
+		};
+		/* NBIFOM-Mode */
+		{
+			struct dict_avp_data data = {
+				2830,	/* Code */
+				10415,	/* Vendor */
+				"NBIFOM-Mode",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(NBIFOM-Mode)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "UE_INITIATED", { .i32=0 }};
+			struct dict_enumval_data        t_2 = { "NETWORK_INITIATED", { .i32=1 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* NBIFOM-Support */
+		{
+			struct dict_avp_data data = {
+				2831,	/* Code */
+				10415,	/* Vendor */
+				"NBIFOM-Support",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(NBIFOM-Support)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "NBIFOM_NOT_SUPPORTED", { .i32=0 }};
+			struct dict_enumval_data        t_2 = { "NBIFOM_SUPPORTED", { .i32=1 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* NetLoc-Access-Support */
+		{
+			struct dict_avp_data data = {
+				2824,	/* Code */
+				10415,	/* Vendor */
+				"NetLoc-Access-Support",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Network-Request-Support */
+		{
+			struct dict_avp_data data = {
+				1024,	/* Code */
+				10415,	/* Vendor */
+				"Network-Request-Support",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Network-Request-Support)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "NETWORK_REQUEST_NOT_SUPPORTED", { .i32=0 }};
+			struct dict_enumval_data        t_2 = { "NETWORK_REQUEST_SUPPORTED", { .i32=1 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* Offline */
+		{
+			struct dict_avp_data data = {
+				1008,	/* Code */
+				10415,	/* Vendor */
+				"Offline",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Offline)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "DISABLE_OFFLINE", { .i32=0 }};
+			struct dict_enumval_data        t_2 = { "ENABLE_OFFLINE", { .i32=1 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* Online */
+		{
+			struct dict_avp_data data = {
+				1009,	/* Code */
+				10415,	/* Vendor */
+				"Online",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Online)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "DISABLE_ONLINE", { .i32=0 }};
+			struct dict_enumval_data        t_2 = { "ENABLE_ONLINE", { .i32=1 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* Packet-Filter-Content */
+		{
+			struct dict_avp_data data = {
+				1059,	/* Code */
+				10415,	/* Vendor */
+				"Packet-Filter-Content",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, IPFilterRule_type, NULL);
+		};
+		/* Packet-Filter-Identifier */
+		{
+			struct dict_avp_data data = {
+				1060,	/* Code */
+				10415,	/* Vendor */
+				"Packet-Filter-Identifier",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Packet-Filter-Operation */
+		{
+			struct dict_avp_data data = {
+				1062,	/* Code */
+				10415,	/* Vendor */
+				"Packet-Filter-Operation",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Packet-Filter-Operation)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "DELETION", { .i32=0 }};
+			struct dict_enumval_data        t_2 = { "ADDITION", { .i32=1 }};
+			struct dict_enumval_data        t_3 = { "MODIFICATION", { .i32=2 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_3, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* Packet-Filter-Usage */
+		{
+			struct dict_avp_data data = {
+				1072,	/* Code */
+				10415,	/* Vendor */
+				"Packet-Filter-Usage",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Packet-Filter-Usage)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "SEND_TO_UE", { .i32=1 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* PCC-Rule-Status */
+		{
+			struct dict_avp_data data = {
+				1019,	/* Code */
+				10415,	/* Vendor */
+				"PCC-Rule-Status",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(PCC-Rule-Status)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "ACTIVE", { .i32=0 }};
+			struct dict_enumval_data        t_2 = { "INACTIVE", { .i32=1 }};
+			struct dict_enumval_data        t_3 = { "TEMPORARILY_INACTIVE", { .i32=2 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_3, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* PDN-Connection-ID */
+		{
+			struct dict_avp_data data = {
+				1065,	/* Code */
+				10415,	/* Vendor */
+				"PDN-Connection-ID",	/* Name */
+				AVP_FLAG_VENDOR,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Precedence */
+		{
+			struct dict_avp_data data = {
+				1010,	/* Code */
+				10415,	/* Vendor */
+				"Precedence",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Pre-emption-Capability */
+		{
+			struct dict_avp_data data = {
+				1047,	/* Code */
+				10415,	/* Vendor */
+				"Pre-emption-Capability",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Pre-emption-Capability)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "PRE_EMPTION_CAPABILITY_ENABLED", { .i32=0 }};
+			struct dict_enumval_data        t_2 = { "PRE_EMPTION_CAPABILITY_DISABLED", { .i32=1 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* Pre-emption-Vulnerability */
+		{
+			struct dict_avp_data data = {
+				1048,	/* Code */
+				10415,	/* Vendor */
+				"Pre-emption-Vulnerability",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Pre-emption-Vulnerability)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "PRE_EMPTION_VULNERABILITY_ENABLED", { .i32=0 }};
+			struct dict_enumval_data        t_2 = { "PRE_EMPTION_VULNERABILITY_DISABLED", { .i32=1 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* Presence-Reporting-Area-Elements-List */
+		{
+			struct dict_avp_data data = {
+				2820,	/* Code */
+				10415,	/* Vendor */
+				"Presence-Reporting-Area-Elements-List",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Presence-Reporting-Area-Identifier */
+		{
+			struct dict_avp_data data = {
+				2821,	/* Code */
+				10415,	/* Vendor */
+				"Presence-Reporting-Area-Identifier",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Presence-Reporting-Area-Status */
+		{
+			struct dict_avp_data data = {
+				2823,	/* Code */
+				10415,	/* Vendor */
+				"Presence-Reporting-Area-Status",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Priority-Level */
+		{
+			struct dict_avp_data data = {
+				1046,	/* Code */
+				10415,	/* Vendor */
+				"Priority-Level",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* PS-to-CS-Session-Continuity */
+		{
+			struct dict_avp_data data = {
+				1099,	/* Code */
+				10415,	/* Vendor */
+				"PS-to-CS-Session-Continuity",	/* Name */
+				AVP_FLAG_VENDOR,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(PS-to-CS-Session-Continuity)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "VIDEO_PS2CS_CONT_CANDIDATE", { .i32=0 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* QoS-Class-Identifier */
+		{
+			struct dict_avp_data data = {
+				1028,	/* Code */
+				10415,	/* Vendor */
+				"QoS-Class-Identifier",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(QoS-Class-Identifier)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "QCI_1", { .i32=1 }};
+			struct dict_enumval_data        t_2 = { "QCI_2", { .i32=2 }};
+			struct dict_enumval_data        t_3 = { "QCI_3", { .i32=3 }};
+			struct dict_enumval_data        t_4 = { "QCI_4", { .i32=4 }};
+			struct dict_enumval_data        t_5 = { "QCI_5", { .i32=5 }};
+			struct dict_enumval_data        t_6 = { "QCI_6", { .i32=6 }};
+			struct dict_enumval_data        t_7 = { "QCI_65", { .i32=65 }};
+			struct dict_enumval_data        t_8 = { "QCI_66", { .i32=66 }};
+			struct dict_enumval_data        t_9 = { "QCI_69", { .i32=69 }};
+			struct dict_enumval_data        t_10 = { "QCI_7", { .i32=7 }};
+			struct dict_enumval_data        t_11 = { "QCI_70", { .i32=70 }};
+			struct dict_enumval_data        t_12 = { "QCI_75", { .i32=75 }};
+			struct dict_enumval_data        t_13 = { "QCI_79", { .i32=79 }};
+			struct dict_enumval_data        t_14 = { "QCI_8", { .i32=8 }};
+			struct dict_enumval_data        t_15 = { "QCI_9", { .i32=9 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_3, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_4, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_5, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_6, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_7, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_8, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_9, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_10, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_11, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_12, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_13, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_14, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_15, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* QoS-Negotiation */
+		{
+			struct dict_avp_data data = {
+				1029,	/* Code */
+				10415,	/* Vendor */
+				"QoS-Negotiation",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(QoS-Negotiation)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "NO_QoS_NEGOTIATION", { .i32=0 }};
+			struct dict_enumval_data        t_2 = { "QoS_NEGOTIATION_SUPPORTED", { .i32=1 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* QoS-Upgrade */
+		{
+			struct dict_avp_data data = {
+				1030,	/* Code */
+				10415,	/* Vendor */
+				"QoS-Upgrade",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(QoS-Upgrade)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "QoS_UPGRADE_NOT_SUPPORTED", { .i32=0 }};
+			struct dict_enumval_data        t_2 = { "QoS_UPGRADE_SUPPORTED", { .i32=1 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* RAN-NAS-Release-Cause */
+		{
+			struct dict_avp_data data = {
+				2819,	/* Code */
+				10415,	/* Vendor */
+				"RAN-NAS-Release-Cause",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* RAN-Rule-Support */
+		{
+			struct dict_avp_data data = {
+				2832,	/* Code */
+				10415,	/* Vendor */
+				"RAN-Rule-Support",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* RAT-Type */
+		{
+			struct dict_avp_data data = {
+				1032,	/* Code */
+				10415,	/* Vendor */
+				"RAT-Type",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(RAT-Type)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "WLAN", { .i32=0 }};
+			struct dict_enumval_data        t_2 = { "VIRTUAL", { .i32=1 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* Redirect-Support */
+		{
+			struct dict_avp_data data = {
+				1086,	/* Code */
+				10415,	/* Vendor */
+				"Redirect-Support",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Redirect-Support)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "REDIRECTION_DISABLED", { .i32=0 }};
+			struct dict_enumval_data        t_2 = { "REDIRECTION_ENABLED", { .i32=1 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* Removal-Of-Access */
+		{
+			struct dict_avp_data data = {
+				2842,	/* Code */
+				10415,	/* Vendor */
+				"Removal-Of-Access",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Removal-Of-Access)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "REMOVAL_OF_ACCESS", { .i32=0 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* Reporting-Level */
+		{
+			struct dict_avp_data data = {
+				1011,	/* Code */
+				10415,	/* Vendor */
+				"Reporting-Level",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Reporting-Level)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "SERVICE_IDENTIFIER_LEVEL", { .i32=0 }};
+			struct dict_enumval_data        t_2 = { "RATING_GROUP_LEVEL", { .i32=1 }};
+			struct dict_enumval_data        t_3 = { "SPONSORED_CONNECTIVITY_LEVEL", { .i32=2 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_3, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* Resource-Allocation-Notification */
+		{
+			struct dict_avp_data data = {
+				1063,	/* Code */
+				10415,	/* Vendor */
+				"Resource-Allocation-Notification",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Resource-Allocation-Notification)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "ENABLE_NOTIFICATION", { .i32=0 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* Resource-Release-Notification */
+		{
+			struct dict_avp_data data = {
+				2841,	/* Code */
+				10415,	/* Vendor */
+				"Resource-Release-Notification",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Resource-Release-Notification)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "ENABLE_NOTIFICATION", { .i32=0 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* Revalidation-Time */
+		{
+			struct dict_avp_data data = {
+				1042,	/* Code */
+				10415,	/* Vendor */
+				"Revalidation-Time",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, Time_type, NULL);
+		};
+		/* Routing-IP-Address */
+		{
+			struct dict_avp_data data = {
+				1079,	/* Code */
+				10415,	/* Vendor */
+				"Routing-IP-Address",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, Address_type, NULL);
+		};
+		/* Routing-Rule-Identifier */
+		{
+			struct dict_avp_data data = {
+				1077,	/* Code */
+				10415,	/* Vendor */
+				"Routing-Rule-Identifier",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Routing-Rule-Failure-Code */
+		{
+			struct dict_avp_data data = {
+				2834,	/* Code */
+				10415,	/* Vendor */
+				"Routing-Rule-Failure-Code",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Rule-Activation-Time */
+		{
+			struct dict_avp_data data = {
+				1043,	/* Code */
+				10415,	/* Vendor */
+				"Rule-Activation-Time",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, Time_type, NULL);
+		};
+		/* Rule-Deactivation-Time */
+		{
+			struct dict_avp_data data = {
+				1044,	/* Code */
+				10415,	/* Vendor */
+				"Rule-Deactivation-Time",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, Time_type, NULL);
+		};
+		/* Rule-Failure-Code */
+		{
+			struct dict_avp_data data = {
+				1031,	/* Code */
+				10415,	/* Vendor */
+				"Rule-Failure-Code",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Rule-Failure-Code)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "UNKNOWN_RULE_NAME", { .i32=1 }};
+			struct dict_enumval_data        t_2 = { "RESOURCE_ALLOCATION_FAILURE", { .i32=10 }};
+			struct dict_enumval_data        t_3 = { "UNSUCCESSFUL_QOS_VALIDATION", { .i32=11 }};
+			struct dict_enumval_data        t_4 = { "INCORRECT_FLOW_INFORMATION", { .i32=12 }};
+			struct dict_enumval_data        t_5 = { "PS_TO_CS_HANDOVER", { .i32=13 }};
+			struct dict_enumval_data        t_6 = { "TDF_APPLICATION_IDENTIFIER_ERROR", { .i32=14 }};
+			struct dict_enumval_data        t_7 = { "NO_BEARER_BOUND", { .i32=15 }};
+			struct dict_enumval_data        t_8 = { "FILTER_RESTRICTIONS", { .i32=16 }};
+			struct dict_enumval_data        t_9 = { "AN_GW_FAILED", { .i32=17 }};
+			struct dict_enumval_data        t_10 = { "MISSING_REDIRECT_SERVER_ADDRESS", { .i32=18 }};
+			struct dict_enumval_data        t_11 = { "CM_END_USER_SERVICE_DENIED", { .i32=19 }};
+			struct dict_enumval_data        t_12 = { "RATING_GROUP_ERROR", { .i32=2 }};
+			struct dict_enumval_data        t_13 = { "CM_CREDIT_CONTROL_NOT_APPLICABLE", { .i32=20 }};
+			struct dict_enumval_data        t_14 = { "CM_AUTHORIZATION_REJECTED", { .i32=21 }};
+			struct dict_enumval_data        t_15 = { "CM_USER_UNKNOWN", { .i32=22 }};
+			struct dict_enumval_data        t_16 = { "CM_RATING_FAILED", { .i32=23 }};
+			struct dict_enumval_data        t_17 = { "ROUTING_RULE_REJECTION", { .i32=24 }};
+			struct dict_enumval_data        t_18 = { "NO_NBIFOM_SUPPORT", { .i32=25 }};
+			struct dict_enumval_data        t_19 = { "SERVICE_IDENTIFIER_ERROR", { .i32=3 }};
+			struct dict_enumval_data        t_20 = { "GW_PCEF_MALFUNCTION", { .i32=4 }};
+			struct dict_enumval_data        t_21 = { "RESOURCES_LIMITATION", { .i32=5 }};
+			struct dict_enumval_data        t_22 = { "MAX_NR_BEARERS_REACHED", { .i32=6 }};
+			struct dict_enumval_data        t_23 = { "UNKNOWN_BEARER_ID", { .i32=7 }};
+			struct dict_enumval_data        t_24 = { "MISSING_BEARER_ID", { .i32=8 }};
+			struct dict_enumval_data        t_25 = { "MISSING_FLOW_INFORMATION", { .i32=9 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_3, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_4, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_5, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_6, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_7, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_8, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_9, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_10, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_11, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_12, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_13, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_14, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_15, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_16, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_17, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_18, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_19, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_20, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_21, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_22, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_23, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_24, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_25, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* Security-Parameter-Index */
+		{
+			struct dict_avp_data data = {
+				1056,	/* Code */
+				10415,	/* Vendor */
+				"Security-Parameter-Index",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Session-Release-Cause */
+		{
+			struct dict_avp_data data = {
+				1045,	/* Code */
+				10415,	/* Vendor */
+				"Session-Release-Cause",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Session-Release-Cause)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "UNSPECIFIED_REASON", { .i32=0 }};
+			struct dict_enumval_data        t_2 = { "UE_SUBSCRIPTION_REASON", { .i32=1 }};
+			struct dict_enumval_data        t_3 = { "INSUFFICIENT_SERVER_RESOURCES", { .i32=2 }};
+			struct dict_enumval_data        t_4 = { "IP_CAN_SESSION_TERMINATION", { .i32=3 }};
+			struct dict_enumval_data        t_5 = { "UE_IP_ADDRESS_RELEASE", { .i32=4 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_3, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_4, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_5, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* TCP-Source-Port */
+		{
+			struct dict_avp_data data = {
+				2843,	/* Code */
+				10415,	/* Vendor */
+				"TCP-Source-Port",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* TDF-Application-Identifier */
+		{
+			struct dict_avp_data data = {
+				1088,	/* Code */
+				10415,	/* Vendor */
+				"TDF-Application-Identifier",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* TDF-Application-Instance-Identifier */
+		{
+			struct dict_avp_data data = {
+				2802,	/* Code */
+				10415,	/* Vendor */
+				"TDF-Application-Instance-Identifier",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* TDF-Destination-Host */
+		{
+			struct dict_avp_data data = {
+				1089,	/* Code */
+				10415,	/* Vendor */
+				"TDF-Destination-Host",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, DiameterIdentity_type, NULL);
+		};
+		/* TDF-Destination-Realm */
+		{
+			struct dict_avp_data data = {
+				1090,	/* Code */
+				10415,	/* Vendor */
+				"TDF-Destination-Realm",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, DiameterIdentity_type, NULL);
+		};
+		/* TDF-IP-Address */
+		{
+			struct dict_avp_data data = {
+				1091,	/* Code */
+				10415,	/* Vendor */
+				"TDF-IP-Address",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, Address_type, NULL);
+		};
+		/* TFT-Filter */
+		{
+			struct dict_avp_data data = {
+				1012,	/* Code */
+				10415,	/* Vendor */
+				"TFT-Filter",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, IPFilterRule_type, NULL);
+		};
+		/* Traffic-Steering-Policy-Identifier-DL */
+		{
+			struct dict_avp_data data = {
+				2836,	/* Code */
+				10415,	/* Vendor */
+				"Traffic-Steering-Policy-Identifier-DL",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Traffic-Steering-Policy-Identifier-UL */
+		{
+			struct dict_avp_data data = {
+				2837,	/* Code */
+				10415,	/* Vendor */
+				"Traffic-Steering-Policy-Identifier-UL",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* ToS-Traffic-Class */
+		{
+			struct dict_avp_data data = {
+				1014,	/* Code */
+				10415,	/* Vendor */
+				"ToS-Traffic-Class",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Tunnel-Header-Filter */
+		{
+			struct dict_avp_data data = {
+				1036,	/* Code */
+				10415,	/* Vendor */
+				"Tunnel-Header-Filter",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, IPFilterRule_type, NULL);
+		};
+		/* Tunnel-Header-Length */
+		{
+			struct dict_avp_data data = {
+				1037,	/* Code */
+				10415,	/* Vendor */
+				"Tunnel-Header-Length",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* UDP-Source-Port */
+		{
+			struct dict_avp_data data = {
+				2806,	/* Code */
+				10415,	/* Vendor */
+				"UDP-Source-Port",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* UE-Local-IP-Address */
+		{
+			struct dict_avp_data data = {
+				2805,	/* Code */
+				10415,	/* Vendor */
+				"UE-Local-IP-Address",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, Address_type, NULL);
+		};
+		/* Usage-Monitoring-Level */
+		{
+			struct dict_avp_data data = {
+				1068,	/* Code */
+				10415,	/* Vendor */
+				"Usage-Monitoring-Level",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Usage-Monitoring-Level)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "SESSION_LEVEL", { .i32=0 }};
+			struct dict_enumval_data        t_2 = { "PCC_RULE_LEVEL", { .i32=1 }};
+			struct dict_enumval_data        t_3 = { "ADC_RULE_LEVEL", { .i32=2 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_3, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* Usage-Monitoring-Report */
+		{
+			struct dict_avp_data data = {
+				1069,	/* Code */
+				10415,	/* Vendor */
+				"Usage-Monitoring-Report",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Usage-Monitoring-Report)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "USAGE_MONITORING_REPORT_REQUIRED", { .i32=0 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* Usage-Monitoring-Support */
+		{
+			struct dict_avp_data data = {
+				1070,	/* Code */
+				10415,	/* Vendor */
+				"Usage-Monitoring-Support",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Usage-Monitoring-Support)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "USAGE_MONITORING_DISABLED", { .i32=0 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* User-Location-Info-Time */
+		{
+			struct dict_avp_data data = {
+				2812,	/* Code */
+				10415,	/* Vendor */
+				"User-Location-Info-Time",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, Time_type, NULL);
+		};
+		/* PCSCF-Restoration-Indication */
+		{
+			struct dict_avp_data data = {
+				2826,	/* Code */
+				10415,	/* Vendor */
+				"PCSCF-Restoration-Indication",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* QoS-Rule-Name */
+		{
+			struct dict_avp_data data = {
+				1054,	/* Code */
+				10415,	/* Vendor */
+				"QoS-Rule-Name",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* QoS-Rule-Base-Name */
+		{
+			struct dict_avp_data data = {
+				1074,	/* Code */
+				10415,	/* Vendor */
+				"QoS-Rule-Base-Name",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, UTF8String_type, NULL);
+		};
+		/* Session-Linking-Indicator */
+		{
+			struct dict_avp_data data = {
+				1064,	/* Code */
+				10415,	/* Vendor */
+				"Session-Linking-Indicator",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Session-Linking-Indicator)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "UE_ONLY", { .i32=0 }};
+			struct dict_enumval_data        t_2 = { "RESERVED", { .i32=1 }};
+			struct dict_enumval_data        t_3 = { "UE_NW", { .i32=2 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_3, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* ADC-Rule-Base-Name */
+		{
+			struct dict_avp_data data = {
+				1095,	/* Code */
+				10415,	/* Vendor */
+				"ADC-Rule-Base-Name",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, UTF8String_type, NULL);
+		};
+		/* ADC-Rule-Name */
+		{
+			struct dict_avp_data data = {
+				1096,	/* Code */
+				10415,	/* Vendor */
+				"ADC-Rule-Name",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Request-Type */
+		{
+			struct dict_avp_data data = {
+				2838,	/* Code */
+				10415,	/* Vendor */
+				"Request-Type",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* CS-Service-QoS-Request-Identifier */
+		{
+			struct dict_avp_data data = {
+				2807,	/* Code */
+				10415,	/* Vendor */
+				"CS-Service-QoS-Request-Identifier",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* CS-Service-QoS-Request-Operation */
+		{
+			struct dict_avp_data data = {
+				2808,	/* Code */
+				10415,	/* Vendor */
+				"CS-Service-QoS-Request-Operation",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(CS-Service-QoS-Request-Operation)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "DELETION", { .i32=0 }};
+			struct dict_enumval_data        t_2 = { "MODIFICATION", { .i32=1 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* CS-Service-Resource-Failure-Cause */
+		{
+			struct dict_avp_data data = {
+				2814,	/* Code */
+				10415,	/* Vendor */
+				"CS-Service-Resource-Failure-Cause",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(CS-Service-Resource-Failure-Cause)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "RESOURCE_RELEASED", { .i32=0 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* CS-Service-Resource-Result-Operation */
+		{
+			struct dict_avp_data data = {
+				2815,	/* Code */
+				10415,	/* Vendor */
+				"CS-Service-Resource-Result-Operation",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(CS-Service-Resource-Result-Operation)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "DELETION", { .i32=0 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* Charging-Rule-Remove */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				1002,	/* Code */
+				10415,	/* Vendor */
+				"Charging-Rule-Remove",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* QoS-Rule-Report */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				1055,	/* Code */
+				10415,	/* Vendor */
+				"QoS-Rule-Report",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* Redirect-Information */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				1085,	/* Code */
+				10415,	/* Vendor */
+				"Redirect-Information",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* PRA-Remove */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				2846,	/* Code */
+				10415,	/* Vendor */
+				"PRA-Remove",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* Flow-Information */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				1058,	/* Code */
+				10415,	/* Vendor */
+				"Flow-Information",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* Tunnel-Information */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				1038,	/* Code */
+				10415,	/* Vendor */
+				"Tunnel-Information",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* TDF-Information */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				1087,	/* Code */
+				10415,	/* Vendor */
+				"TDF-Information",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* Routing-Rule-Remove */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				1075,	/* Code */
+				10415,	/* Vendor */
+				"Routing-Rule-Remove",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* CS-Service-Resource-Report */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				2813,	/* Code */
+				10415,	/* Vendor */
+				"CS-Service-Resource-Report",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* Presence-Reporting-Area-Information */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				2822,	/* Code */
+				10415,	/* Vendor */
+				"Presence-Reporting-Area-Information",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* Conditional-APN-Aggregate-Max-Bitrate */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				2818,	/* Code */
+				10415,	/* Vendor */
+				"Conditional-APN-Aggregate-Max-Bitrate",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* Access-Network-Charging-Identifier-Gx */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				1022,	/* Code */
+				10415,	/* Vendor */
+				"Access-Network-Charging-Identifier-Gx",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* Allocation-Retention-Priority */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				1034,	/* Code */
+				10415,	/* Vendor */
+				"Allocation-Retention-Priority",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* QoS-Rule-Remove */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				1052,	/* Code */
+				10415,	/* Vendor */
+				"QoS-Rule-Remove",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* Routing-Rule-Report */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				2835,	/* Code */
+				10415,	/* Vendor */
+				"Routing-Rule-Report",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* TFT-Packet-Filter-Information */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				1013,	/* Code */
+				10415,	/* Vendor */
+				"TFT-Packet-Filter-Information",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* Fixed-User-Location-Info */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				2825,	/* Code */
+				10415,	/* Vendor */
+				"Fixed-User-Location-Info",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* Default-QoS-Information */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				2816,	/* Code */
+				10415,	/* Vendor */
+				"Default-QoS-Information",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* Packet-Filter-Information */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				1061,	/* Code */
+				10415,	/* Vendor */
+				"Packet-Filter-Information",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* Routing-Filter */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				1078,	/* Code */
+				10415,	/* Vendor */
+				"Routing-Filter",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* ADC-Rule-Remove */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				1093,	/* Code */
+				10415,	/* Vendor */
+				"ADC-Rule-Remove",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* QoS-Information */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				1016,	/* Code */
+				10415,	/* Vendor */
+				"QoS-Information",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* PRA-Install */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				2845,	/* Code */
+				10415,	/* Vendor */
+				"PRA-Install",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* Routing-Rule-Definition */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				1076,	/* Code */
+				10415,	/* Vendor */
+				"Routing-Rule-Definition",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* Default-EPS-Bearer-QoS */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				1049,	/* Code */
+				10415,	/* Vendor */
+				"Default-EPS-Bearer-QoS",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* CoA-Information */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				1039,	/* Code */
+				10415,	/* Vendor */
+				"CoA-Information",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* Application-Detection-Information */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				1098,	/* Code */
+				10415,	/* Vendor */
+				"Application-Detection-Information",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* Conditional-Policy-Information */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				2840,	/* Code */
+				10415,	/* Vendor */
+				"Conditional-Policy-Information",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* Charging-Rule-Definition */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				1003,	/* Code */
+				10415,	/* Vendor */
+				"Charging-Rule-Definition",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* Routing-Rule-Install */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				1081,	/* Code */
+				10415,	/* Vendor */
+				"Routing-Rule-Install",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* ADC-Rule-Definition */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				1094,	/* Code */
+				10415,	/* Vendor */
+				"ADC-Rule-Definition",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* ADC-Rule-Report */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				1097,	/* Code */
+				10415,	/* Vendor */
+				"ADC-Rule-Report",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* QoS-Rule-Definition */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				1053,	/* Code */
+				10415,	/* Vendor */
+				"QoS-Rule-Definition",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* Charging-Rule-Report */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				1018,	/* Code */
+				10415,	/* Vendor */
+				"Charging-Rule-Report",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* Event-Report-Indication */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				1033,	/* Code */
+				10415,	/* Vendor */
+				"Event-Report-Indication",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* Charging-Rule-Install */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				1001,	/* Code */
+				10415,	/* Vendor */
+				"Charging-Rule-Install",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* QoS-Rule-Install */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				1051,	/* Code */
+				10415,	/* Vendor */
+				"QoS-Rule-Install",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* ADC-Rule-Install */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				1092,	/* Code */
+				10415,	/* Vendor */
+				"ADC-Rule-Install",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* Usage-Monitoring-Information */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				1067,	/* Code */
+				10415,	/* Vendor */
+				"Usage-Monitoring-Information",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+
+	
+   }
+
+   /* Commands section */
+   {
+
+   }
+
+   return 0;
+}
+
+static int dict_ts29212_avps_load_rules(char * conffile)
+{
+   /* Grouped AVP section */
+   {
+	  /* Charging-Rule-Remove */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "Charging-Rule-Remove"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 10415, .avp_name = "Charging-Rule-Name"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Charging-Rule-Base-Name"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Required-Access-Info"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Resource-Release-Notification"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* QoS-Rule-Report */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "QoS-Rule-Report"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 10415, .avp_name = "QoS-Rule-Name"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "QoS-Rule-Base-Name"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "PCC-Rule-Status"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Rule-Failure-Code"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Content-Version"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* Redirect-Information */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "Redirect-Information"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 10415, .avp_name = "Redirect-Support"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Redirect-Address-Type"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Redirect-Server-Address"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* PRA-Remove */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "PRA-Remove"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 10415, .avp_name = "Presence-Reporting-Area-Identifier"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* Flow-Information */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "Flow-Information"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 10415, .avp_name = "Flow-Description"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Packet-Filter-Identifier"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Packet-Filter-Usage"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "ToS-Traffic-Class"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Security-Parameter-Index"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Flow-Label"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Flow-Direction"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Routing-Rule-Identifier"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* Tunnel-Information */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "Tunnel-Information"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 10415, .avp_name = "Tunnel-Header-Length"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* TDF-Information */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "TDF-Information"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 10415, .avp_name = "TDF-Destination-Realm"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "TDF-Destination-Host"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "TDF-IP-Address"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* Routing-Rule-Remove */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "Routing-Rule-Remove"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 10415, .avp_name = "Routing-Rule-Identifier"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* CS-Service-Resource-Report */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "CS-Service-Resource-Report"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 10415, .avp_name = "CS-Service-QoS-Request-Identifier"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "CS-Service-Resource-Result-Operation"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "CS-Service-Resource-Failure-Cause"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* Presence-Reporting-Area-Information */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "Presence-Reporting-Area-Information"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 10415, .avp_name = "Presence-Reporting-Area-Identifier"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Presence-Reporting-Area-Status"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Presence-Reporting-Area-Elements-List"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* Conditional-APN-Aggregate-Max-Bitrate */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "Conditional-APN-Aggregate-Max-Bitrate"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 10415, .avp_name = "APN-Aggregate-Max-Bitrate-UL"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "APN-Aggregate-Max-Bitrate-DL"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "IP-CAN-Type"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "RAT-Type"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* Access-Network-Charging-Identifier-Gx */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "Access-Network-Charging-Identifier-Gx"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 10415, .avp_name = "Access-Network-Charging-Identifier-Value"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Charging-Rule-Base-Name"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Charging-Rule-Name"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "IP-CAN-Session-Charging-Scope"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* Allocation-Retention-Priority */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "Allocation-Retention-Priority"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 10415, .avp_name = "Priority-Level"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Pre-emption-Capability"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Pre-emption-Vulnerability"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* QoS-Rule-Remove */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "QoS-Rule-Remove"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 10415, .avp_name = "QoS-Rule-Name"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "QoS-Rule-Base-Name"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Required-Access-Info"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* Routing-Rule-Report */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "Routing-Rule-Report"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 10415, .avp_name = "Routing-Rule-Identifier"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "PCC-Rule-Status"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Routing-Rule-Failure-Code"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* TFT-Packet-Filter-Information */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "TFT-Packet-Filter-Information"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 10415, .avp_name = "Precedence"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "TFT-Filter"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "ToS-Traffic-Class"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Security-Parameter-Index"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Flow-Label"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Flow-Direction"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* Fixed-User-Location-Info */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "Fixed-User-Location-Info"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 10415, .avp_name = "SSID"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "BSSID"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 13019, .avp_name = "Logical-Access-Id"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 13019, .avp_name = "Physical-Access-Id"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* Default-QoS-Information */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "Default-QoS-Information"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 10415, .avp_name = "QoS-Class-Identifier"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Max-Requested-Bandwidth-UL"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Max-Requested-Bandwidth-DL"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Default-QoS-Name"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* Packet-Filter-Information */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "Packet-Filter-Information"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 10415, .avp_name = "Packet-Filter-Identifier"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Precedence"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Packet-Filter-Content"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "ToS-Traffic-Class"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Security-Parameter-Index"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Flow-Label"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Flow-Direction"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* Routing-Filter */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "Routing-Filter"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 10415, .avp_name = "Flow-Description"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Flow-Direction"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "ToS-Traffic-Class"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Security-Parameter-Index"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Flow-Label"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* ADC-Rule-Remove */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "ADC-Rule-Remove"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 10415, .avp_name = "ADC-Rule-Name"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "ADC-Rule-Base-Name"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* QoS-Information */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "QoS-Information"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 10415, .avp_name = "QoS-Class-Identifier"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Max-Requested-Bandwidth-UL"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Max-Requested-Bandwidth-DL"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Guaranteed-Bitrate-UL"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Guaranteed-Bitrate-DL"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Bearer-Identifier"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Allocation-Retention-Priority"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "APN-Aggregate-Max-Bitrate-UL"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "APN-Aggregate-Max-Bitrate-DL"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Conditional-APN-Aggregate-Max-Bitrate"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* PRA-Install */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "PRA-Install"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 10415, .avp_name = "Presence-Reporting-Area-Information"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* Routing-Rule-Definition */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "Routing-Rule-Definition"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 10415, .avp_name = "Routing-Rule-Identifier"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Routing-Filter"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Precedence"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Routing-IP-Address"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "IP-CAN-Type"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* Default-EPS-Bearer-QoS */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "Default-EPS-Bearer-QoS"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 10415, .avp_name = "QoS-Class-Identifier"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Allocation-Retention-Priority"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* CoA-Information */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "CoA-Information"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 10415, .avp_name = "Tunnel-Information"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "CoA-IP-Address"}, RULE_REQUIRED, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* Application-Detection-Information */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "Application-Detection-Information"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 10415, .avp_name = "TDF-Application-Identifier"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "TDF-Application-Instance-Identifier"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Flow-Information"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* Conditional-Policy-Information */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "Conditional-Policy-Information"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 10415, .avp_name = "Execution-Time"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Default-EPS-Bearer-QoS"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "APN-Aggregate-Max-Bitrate-UL"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "APN-Aggregate-Max-Bitrate-DL"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Conditional-APN-Aggregate-Max-Bitrate"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* Charging-Rule-Definition */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "Charging-Rule-Definition"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 10415, .avp_name = "Charging-Rule-Name"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Service-Identifier"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Rating-Group"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Flow-Information"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Default-Bearer-Indication"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "TDF-Application-Identifier"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Flow-Status"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "QoS-Information"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "PS-to-CS-Session-Continuity"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Reporting-Level"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Online"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Offline"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Metering-Method"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Precedence"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "AF-Charging-Identifier"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Flows"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Monitoring-Key"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Redirect-Information"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Mute-Notification"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "AF-Signalling-Protocol"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Sponsor-Identity"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Application-Service-Provider-Identity"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Required-Access-Info"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Sharing-Key-DL"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Sharing-Key-UL"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Traffic-Steering-Policy-Identifier-DL"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Traffic-Steering-Policy-Identifier-UL"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Content-Version"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* Routing-Rule-Install */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "Routing-Rule-Install"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 10415, .avp_name = "Routing-Rule-Definition"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* ADC-Rule-Definition */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "ADC-Rule-Definition"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 10415, .avp_name = "ADC-Rule-Name"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "TDF-Application-Identifier"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Flow-Information"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Service-Identifier"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Rating-Group"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Reporting-Level"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Online"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Offline"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Metering-Method"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Precedence"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Flow-Status"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "QoS-Information"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Monitoring-Key"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Sponsor-Identity"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Application-Service-Provider-Identity"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Redirect-Information"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Mute-Notification"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Traffic-Steering-Policy-Identifier-DL"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Traffic-Steering-Policy-Identifier-UL"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "ToS-Traffic-Class"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* ADC-Rule-Report */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "ADC-Rule-Report"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 10415, .avp_name = "ADC-Rule-Name"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "ADC-Rule-Base-Name"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "PCC-Rule-Status"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Rule-Failure-Code"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Final-Unit-Indication"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* QoS-Rule-Definition */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "QoS-Rule-Definition"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 10415, .avp_name = "QoS-Rule-Name"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Flow-Information"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "QoS-Information"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Precedence"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Required-Access-Info"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Sharing-Key-DL"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Sharing-Key-UL"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Content-Version"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* Charging-Rule-Report */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "Charging-Rule-Report"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 10415, .avp_name = "Charging-Rule-Name"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Charging-Rule-Base-Name"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Bearer-Identifier"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "PCC-Rule-Status"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Rule-Failure-Code"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Final-Unit-Indication"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "RAN-NAS-Release-Cause"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Content-Version"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* Event-Report-Indication */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "Event-Report-Indication"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 10415, .avp_name = "AN-Trusted"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Event-Trigger"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "User-CSG-Information"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "IP-CAN-Type"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "AN-GW-Address"}, RULE_OPTIONAL, 0, 2 },
+			{ { .avp_vendor = 10415, .avp_name = "3GPP-SGSN-Address"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "3GPP-SGSN-Ipv6-Address"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "3GPP-SGSN-MCC-MNC"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Framed-IP-Address"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "RAT-Type"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "RAI"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "3GPP-User-Location-Info"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Trace-Data"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Trace-Reference"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 5535, .avp_name = "3GPP2-BSID"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "3GPP-MS-TimeZone"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Routing-IP-Address"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "UE-Local-IP-Address"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "HeNB-Local-IP-Address"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "UDP-Source-Port"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Presence-Reporting-Area-Information"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* Charging-Rule-Install */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "Charging-Rule-Install"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 10415, .avp_name = "Charging-Rule-Definition"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Charging-Rule-Name"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Charging-Rule-Base-Name"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Bearer-Identifier"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Monitoring-Flags"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Rule-Activation-Time"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Rule-Deactivation-Time"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Resource-Allocation-Notification"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Charging-Correlation-Indicator"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "IP-CAN-Type"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* QoS-Rule-Install */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "QoS-Rule-Install"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 10415, .avp_name = "QoS-Rule-Definition"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "QoS-Rule-Name"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "QoS-Rule-Base-Name"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Tunnel-Information"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Access-Network-Charging-Identifier-Value"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Resource-Allocation-Notification"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Rule-Activation-Time"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Rule-Deactivation-Time"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "3GPP-GGSN-Address"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "3GPP-GGSN-Ipv6-Address"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "AN-GW-Address"}, RULE_OPTIONAL, 0, 2 },
+			{ { .avp_vendor = 10415, .avp_name = "UDP-Source-Port"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* ADC-Rule-Install */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "ADC-Rule-Install"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 10415, .avp_name = "ADC-Rule-Definition"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "ADC-Rule-Name"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "ADC-Rule-Base-Name"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Monitoring-Flags"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Rule-Activation-Time"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Rule-Deactivation-Time"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* Usage-Monitoring-Information */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "Usage-Monitoring-Information"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 10415, .avp_name = "Monitoring-Key"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Granted-Service-Unit"}, RULE_OPTIONAL, 0, 2 },
+			{ { .avp_vendor = 0, .avp_name = "Used-Service-Unit"}, RULE_OPTIONAL, 0, 2 },
+			{ { .avp_vendor = 10415, .avp_name = "Quota-Consumption-Time"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Usage-Monitoring-Level"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Usage-Monitoring-Report"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Usage-Monitoring-Support"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+
+   }	
+
+   /* Commands section */
+   {
+
+   }
+
+   LOG_D( "Extension 'Dictionary definitions for ts29212_avps (e30)' initialized");
+   return 0;
+}
+
+int dict_entry(char * conffile)
+{
+	dict_ts29212_avps_load_defs(conffile);
+	return dict_ts29212_avps_load_rules(conffile);
+}
+
+const char* dict_ts29212_avps_proto_ver(char * conffile) {
+	return ts29212_avps_proto_ver;
+}
+
+const double dict_ts29212_avps_gen_ts(char * conffile) {
+	return ts29212_avps_gen_date;
+}
+
+EXTENSION_ENTRY2("dict_ts29212_avps", dict_ts29212_avps_load_defs, dict_ts29212_avps_load_rules, "dict_ts32299_avps", "dict_ts29273_avps", "dict_ts29214_avps", "dict_ts29272_avps", "dict_ts29229_avps", "dict_rfc4006bis_avps", "dict_ts29061_avps", "dict_draftload_avps", "dict_rfc7683_avps", "dict_rfc7155_avps", "dict_etsi283034_avps", "dict_3gpp2_avps", "dict_rfc7944_avps");
+
+
+
diff --git a/extensions/dict_ts29212_avps/ts29212_avps.did b/extensions/dict_ts29212_avps/ts29212_avps.did
new file mode 100644
index 0000000..eb5c09b
--- /dev/null
+++ b/extensions/dict_ts29212_avps/ts29212_avps.did
@@ -0,0 +1,37 @@
+dict_rfc6942_avps
+dict_ts29468_avps
+dict_ts29154_avps
+dict_ts29214_avps
+dict_ts29215_avps
+dict_ts29217_avps
+dict_3gpp2_avps
+dict_ts29343_avps
+dict_ts29338_avps
+dict_ts29128_avps
+dict_ts29344_avps
+dict_ts29345_avps
+dict_ts32299_avps
+dict_rfc6734_avps
+dict_rfc5778_avps
+dict_rfc5580_avps
+dict_rfc4072_avps
+dict_ts29273_avps
+dict_ts29173_avps
+dict_ts29337_avps
+dict_etsi283034_avps
+dict_rfc4590_avps
+dict_ts29229_avps
+dict_draftload_avps
+dict_ts29329_avps
+dict_ts29368_avps
+dict_ts29336_avps
+dict_ts29061_avps
+dict_rfc5447_avps
+dict_ts29272_avps
+dict_rfc7683_avps
+dict_rfc7944_avps
+dict_rfc5777_avps
+dict_rfc4006bis_avps
+dict_rfc4004_avps
+dict_rfc7155_avps
+dict_ts29212_avps
diff --git a/extensions/dict_ts29214_avps/CMakeLists.txt b/extensions/dict_ts29214_avps/CMakeLists.txt
new file mode 100644
index 0000000..9cbcecc
--- /dev/null
+++ b/extensions/dict_ts29214_avps/CMakeLists.txt
@@ -0,0 +1,16 @@
+# The dict_ts29214_avps extension
+PROJECT("dict_ts29214_avps library generated by FdGen " C)
+
+# Compile as a module
+FD_ADD_EXTENSION(dict_ts29214_avps dict_ts29214_avps.c)
+
+
+####
+## INSTALL section ##
+
+INSTALL(TARGETS dict_ts29214_avps
+	LIBRARY DESTINATION ${INSTALL_EXTENSIONS_SUFFIX}
+COMPONENT freeDiameter-dictionary-TS29214_AVPS)
+
+
+
diff --git a/extensions/dict_ts29214_avps/dict_ts29214_avps.c b/extensions/dict_ts29214_avps/dict_ts29214_avps.c
new file mode 100644
index 0000000..734a5c8
--- /dev/null
+++ b/extensions/dict_ts29214_avps/dict_ts29214_avps.c
@@ -0,0 +1,1031 @@
+/*
+* Copyright (c) 2017 Sprint
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*    http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+/****************
+ Generated By: fdtool enhancements to diafuzzer
+ License: same as freeDiameter
+****************/
+
+
+/* 
+ * Dictionary definitions of objects specified in ts29214_avps (e30).
+ */
+#include <freeDiameter/extension.h>
+
+#define PROTO_VER "e30"
+#define GEN_DATE  1506697136.73
+
+const char *ts29214_avps_proto_ver = PROTO_VER;
+const double ts29214_avps_gen_date = GEN_DATE;
+
+/* The content of this file follows the same structure as dict_base_proto.c */
+
+#define CHECK_dict_new( _type, _data, _parent, _ref )                                     \
+{                                                                                         \
+    int _ret = fd_dict_new( fd_g_config->cnf_dict, (_type), (_data), (_parent), (_ref) ); \
+    if ( _ret != 0 && _ret != EEXIST )                                                    \
+       return _ret;                                                                       \
+}
+
+#define CHECK_dict_search( _type, _criteria, _what, _result )		\
+    CHECK_FCT(  fd_dict_search( fd_g_config->cnf_dict, (_type), (_criteria), (_what), (_result), ENOENT) );
+
+struct local_rules_definition {
+    struct dict_avp_request avp_vendor_plus_name;
+    enum rule_position	position;
+    int 			min;
+    int			max;
+};
+
+#define RULE_ORDER( _position ) ((((_position) == RULE_FIXED_HEAD) || ((_position) == RULE_FIXED_TAIL)) ? 1 : 0 )
+
+/* Attention! This version of the macro uses AVP_BY_NAME_AND_VENDOR, in contrast to most other copies! */
+#define PARSE_loc_rules( _rulearray, _parent) {                                                         \
+        int __ar;                                                                                       \
+        for (__ar=0; __ar < sizeof(_rulearray) / sizeof((_rulearray)[0]); __ar++) {                     \
+                struct dict_rule_data __data = { NULL,                                                  \
+                        (_rulearray)[__ar].position,                                                    \
+                        0,                                                                              \
+                        (_rulearray)[__ar].min,                                                         \
+                        (_rulearray)[__ar].max};                                                        \
+                __data.rule_order = RULE_ORDER(__data.rule_position);                                   \
+                CHECK_FCT(  fd_dict_search(                                                             \
+                        fd_g_config->cnf_dict,                                                          \
+                        DICT_AVP,                                                                       \
+                        AVP_BY_NAME_AND_VENDOR,                                                         \
+                        &(_rulearray)[__ar].avp_vendor_plus_name,                                       \
+                        &__data.rule_avp, 0 ) );                                                        \
+                if ( !__data.rule_avp ) {                                                               \
+                        TRACE_DEBUG(INFO, "AVP Not found: '%s'", (_rulearray)[__ar].avp_vendor_plus_name.avp_name);             \
+                        return ENOENT;                                                                  \
+                }                                                                                       \
+                {                                                                                       \
+                         int _ret = fd_dict_new( fd_g_config->cnf_dict, DICT_RULE, &(__data), (_parent), NULL ); \
+                         if ( _ret != 0 && _ret != EEXIST )      {                                      \
+                                TRACE_DEBUG(INFO, "Error on rule with AVP '%s'",                        \
+                                            (_rulearray)[__ar].avp_vendor_plus_name.avp_name);          \
+                                return EINVAL;                                                          \
+                         }                                                                              \
+                }                                                                                       \
+        }                                                                                               \
+}
+
+#define CHECK_vendor_new( _data ) { \
+        struct dict_object * vendor_found; \
+        if (fd_dict_search(fd_g_config->cnf_dict,DICT_VENDOR,VENDOR_BY_ID,&_data.vendor_id,&vendor_found,ENOENT) == ENOENT) { \
+                CHECK_FCT(fd_dict_new(fd_g_config->cnf_dict, DICT_VENDOR, &_data, NULL, NULL)); \
+        } \
+}
+
+#define enumval_def_u32( _val_, _str_ )		\
+    { _str_, 		{ .u32 = _val_ }}
+
+#define enumval_def_os( _len_, _val_, _str_ )				\
+    { _str_, 		{ .os = { .data = (unsigned char *)_val_, .len = _len_ }}}
+
+
+static int dict_ts29214_avps_load_defs(char * conffile)
+{
+   TRACE_ENTRY("%p", conffile);
+	/* Application Section */
+	{
+		/* Create the vendors */		{
+			struct dict_vendor_data vendor_data = { 10415, "3GPP" };
+			CHECK_dict_new(DICT_VENDOR, &vendor_data, NULL, NULL)
+		}
+	}
+
+
+   /* AVP section */
+   {
+		struct dict_object * Address_type;
+		struct dict_object * UTF8String_type;
+		struct dict_object * DiameterIdentity_type;
+		struct dict_object * DiameterURI_type;
+		struct dict_object * Time_type;
+		struct dict_object * IPFilterRule_type;
+
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "Address", &Address_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "UTF8String", &UTF8String_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "DiameterIdentity", &DiameterIdentity_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "DiameterURI", &DiameterURI_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "Time", &Time_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "IPFilterRule", &IPFilterRule_type);
+		/* Abort-Cause */
+		{
+			struct dict_avp_data data = {
+				500,	/* Code */
+				10415,	/* Vendor */
+				"Abort-Cause",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Abort-Cause)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "BEARER_RELEASED", { .i32=0 }};
+			struct dict_enumval_data        t_2 = { "INSUFFICIENT_SERVER_RESOURCES", { .i32=1 }};
+			struct dict_enumval_data        t_3 = { "INSUFFICIENT_BEARER_RESOURCES", { .i32=2 }};
+			struct dict_enumval_data        t_4 = { "PS_TO_CS_HANDOVER", { .i32=3 }};
+			struct dict_enumval_data        t_5 = { "DISALLOWED", { .i32=4 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_3, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_4, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_5, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* Access-Network-Charging-Address */
+		{
+			struct dict_avp_data data = {
+				501,	/* Code */
+				10415,	/* Vendor */
+				"Access-Network-Charging-Address",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, Address_type, NULL);
+		};
+		/* Access-Network-Charging-Identifier-Value */
+		{
+			struct dict_avp_data data = {
+				503,	/* Code */
+				10415,	/* Vendor */
+				"Access-Network-Charging-Identifier-Value",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* AF-Application-Identifier */
+		{
+			struct dict_avp_data data = {
+				504,	/* Code */
+				10415,	/* Vendor */
+				"AF-Application-Identifier",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* AF-Charging-Identifier */
+		{
+			struct dict_avp_data data = {
+				505,	/* Code */
+				10415,	/* Vendor */
+				"AF-Charging-Identifier",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* AF-Requested-Data */
+		{
+			struct dict_avp_data data = {
+				551,	/* Code */
+				10415,	/* Vendor */
+				"AF-Requested-Data",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* AF-Signalling-Protocol */
+		{
+			struct dict_avp_data data = {
+				529,	/* Code */
+				10415,	/* Vendor */
+				"AF-Signalling-Protocol",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(AF-Signalling-Protocol)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "NO_INFORMATION", { .i32=0 }};
+			struct dict_enumval_data        t_2 = { "SIP", { .i32=1 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* Application-Service-Provider-Identity */
+		{
+			struct dict_avp_data data = {
+				532,	/* Code */
+				10415,	/* Vendor */
+				"Application-Service-Provider-Identity",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, UTF8String_type, NULL);
+		};
+		/* Pre-emption-Control-Info */
+		{
+			struct dict_avp_data data = {
+				553,	/* Code */
+				10415,	/* Vendor */
+				"Pre-emption-Control-Info",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Codec-Data */
+		{
+			struct dict_avp_data data = {
+				524,	/* Code */
+				10415,	/* Vendor */
+				"Codec-Data",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Content-Version */
+		{
+			struct dict_avp_data data = {
+				552,	/* Code */
+				10415,	/* Vendor */
+				"Content-Version",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED64	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Flow-Description */
+		{
+			struct dict_avp_data data = {
+				507,	/* Code */
+				10415,	/* Vendor */
+				"Flow-Description",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, IPFilterRule_type, NULL);
+		};
+		/* Flow-Number */
+		{
+			struct dict_avp_data data = {
+				509,	/* Code */
+				10415,	/* Vendor */
+				"Flow-Number",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Flow-Status */
+		{
+			struct dict_avp_data data = {
+				511,	/* Code */
+				10415,	/* Vendor */
+				"Flow-Status",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Flow-Status)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "ENABLED_UPLINK", { .i32=0 }};
+			struct dict_enumval_data        t_2 = { "ENABLED_DOWNLINK", { .i32=1 }};
+			struct dict_enumval_data        t_3 = { "ENABLED", { .i32=2 }};
+			struct dict_enumval_data        t_4 = { "DISABLED", { .i32=3 }};
+			struct dict_enumval_data        t_5 = { "REMOVED", { .i32=4 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_3, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_4, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_5, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* Flow-Usage */
+		{
+			struct dict_avp_data data = {
+				512,	/* Code */
+				10415,	/* Vendor */
+				"Flow-Usage",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Flow-Usage)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "NO_INFORMATION", { .i32=0 }};
+			struct dict_enumval_data        t_2 = { "RTCP", { .i32=1 }};
+			struct dict_enumval_data        t_3 = { "AF_SIGNALLING", { .i32=2 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_3, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* GCS-Identifier */
+		{
+			struct dict_avp_data data = {
+				538,	/* Code */
+				10415,	/* Vendor */
+				"GCS-Identifier",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* IP-Domain-Id */
+		{
+			struct dict_avp_data data = {
+				537,	/* Code */
+				10415,	/* Vendor */
+				"IP-Domain-Id",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Max-Requested-Bandwidth-DL */
+		{
+			struct dict_avp_data data = {
+				515,	/* Code */
+				10415,	/* Vendor */
+				"Max-Requested-Bandwidth-DL",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Max-Requested-Bandwidth-UL */
+		{
+			struct dict_avp_data data = {
+				516,	/* Code */
+				10415,	/* Vendor */
+				"Max-Requested-Bandwidth-UL",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Max-Supported-Bandwidth-DL */
+		{
+			struct dict_avp_data data = {
+				543,	/* Code */
+				10415,	/* Vendor */
+				"Max-Supported-Bandwidth-DL",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Max-Supported-Bandwidth-UL */
+		{
+			struct dict_avp_data data = {
+				544,	/* Code */
+				10415,	/* Vendor */
+				"Max-Supported-Bandwidth-UL",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* MCPTT-Identifier */
+		{
+			struct dict_avp_data data = {
+				547,	/* Code */
+				10415,	/* Vendor */
+				"MCPTT-Identifier",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Media-Component-Number */
+		{
+			struct dict_avp_data data = {
+				518,	/* Code */
+				10415,	/* Vendor */
+				"Media-Component-Number",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Media-Component-Status */
+		{
+			struct dict_avp_data data = {
+				549,	/* Code */
+				10415,	/* Vendor */
+				"Media-Component-Status",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Media-Type */
+		{
+			struct dict_avp_data data = {
+				520,	/* Code */
+				10415,	/* Vendor */
+				"Media-Type",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Media-Type)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "AUDIO", { .i32=0 }};
+			struct dict_enumval_data        t_2 = { "VIDEO", { .i32=1 }};
+			struct dict_enumval_data        t_3 = { "DATA", { .i32=2 }};
+			struct dict_enumval_data        t_4 = { "APPLICATION", { .i32=3 }};
+			struct dict_enumval_data        t_5 = { "CONTROL", { .i32=4 }};
+			struct dict_enumval_data        t_6 = { "TEXT", { .i32=5 }};
+			struct dict_enumval_data        t_7 = { "MESSAGE", { .i32=6 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_3, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_4, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_5, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_6, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_7, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* MPS-Identifier */
+		{
+			struct dict_avp_data data = {
+				528,	/* Code */
+				10415,	/* Vendor */
+				"MPS-Identifier",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Min-Desired-Bandwidth-DL */
+		{
+			struct dict_avp_data data = {
+				545,	/* Code */
+				10415,	/* Vendor */
+				"Min-Desired-Bandwidth-DL",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Min-Desired-Bandwidth-UL */
+		{
+			struct dict_avp_data data = {
+				546,	/* Code */
+				10415,	/* Vendor */
+				"Min-Desired-Bandwidth-UL",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Min-Requested-Bandwidth-DL */
+		{
+			struct dict_avp_data data = {
+				534,	/* Code */
+				10415,	/* Vendor */
+				"Min-Requested-Bandwidth-DL",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Min-Requested-Bandwidth-UL */
+		{
+			struct dict_avp_data data = {
+				535,	/* Code */
+				10415,	/* Vendor */
+				"Min-Requested-Bandwidth-UL",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Priority-Sharing-Indicator */
+		{
+			struct dict_avp_data data = {
+				550,	/* Code */
+				10415,	/* Vendor */
+				"Priority-Sharing-Indicator",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Priority-Sharing-Indicator)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "PRIORITY_SHARING_ENABLED", { .i32=0 }};
+			struct dict_enumval_data        t_2 = { "PRIORITY_SHARING_DISABLED", { .i32=1 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* RR-Bandwidth */
+		{
+			struct dict_avp_data data = {
+				521,	/* Code */
+				10415,	/* Vendor */
+				"RR-Bandwidth",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* RS-Bandwidth */
+		{
+			struct dict_avp_data data = {
+				522,	/* Code */
+				10415,	/* Vendor */
+				"RS-Bandwidth",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Service-Authorization-Info */
+		{
+			struct dict_avp_data data = {
+				548,	/* Code */
+				10415,	/* Vendor */
+				"Service-Authorization-Info",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Service-URN */
+		{
+			struct dict_avp_data data = {
+				525,	/* Code */
+				10415,	/* Vendor */
+				"Service-URN",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Service-Info-Status */
+		{
+			struct dict_avp_data data = {
+				527,	/* Code */
+				10415,	/* Vendor */
+				"Service-Info-Status",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Service-Info-Status)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "FINAL_SERVICE_INFORMATION", { .i32=0 }};
+			struct dict_enumval_data        t_2 = { "PRELIMINARY_SERVICE_INFORMATION", { .i32=1 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* Sharing-Key-DL */
+		{
+			struct dict_avp_data data = {
+				539,	/* Code */
+				10415,	/* Vendor */
+				"Sharing-Key-DL",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Sharing-Key-UL */
+		{
+			struct dict_avp_data data = {
+				540,	/* Code */
+				10415,	/* Vendor */
+				"Sharing-Key-UL",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Specific-Action */
+		{
+			struct dict_avp_data data = {
+				513,	/* Code */
+				10415,	/* Vendor */
+				"Specific-Action",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Specific-Action)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "Void", { .i32=0 }};
+			struct dict_enumval_data        t_2 = { "CHARGING_CORRELATION_EXCHANGE", { .i32=1 }};
+			struct dict_enumval_data        t_3 = { "INDICATION_OF_LIMITED_PCC_DEPLOYMENT", { .i32=10 }};
+			struct dict_enumval_data        t_4 = { "USAGE_REPORT", { .i32=11 }};
+			struct dict_enumval_data        t_5 = { "ACCESS_NETWORK_INFO_REPORT", { .i32=12 }};
+			struct dict_enumval_data        t_6 = { "INDICATION_OF_RECOVERY_FROM_LIMITED_PCC_DEPLOYMENT", { .i32=13 }};
+			struct dict_enumval_data        t_7 = { "INDICATION_OF_ACCESS_NETWORK_INFO_REPORTING_FAILURE", { .i32=14 }};
+			struct dict_enumval_data        t_8 = { "INDICATION_OF_TRANSFER_POLICY_EXPIRED", { .i32=15 }};
+			struct dict_enumval_data        t_9 = { "PLMN_CHANGE", { .i32=16 }};
+			struct dict_enumval_data        t_10 = { "INDICATION_OF_LOSS_OF_BEARER", { .i32=2 }};
+			struct dict_enumval_data        t_11 = { "INDICATION_OF_RECOVERY_OF_BEARER", { .i32=3 }};
+			struct dict_enumval_data        t_12 = { "INDICATION_OF_RELEASE_OF_BEARER", { .i32=4 }};
+			struct dict_enumval_data        t_13 = { "Void2", { .i32=5 }};
+			struct dict_enumval_data        t_14 = { "IP_CAN_CHANGE", { .i32=6 }};
+			struct dict_enumval_data        t_15 = { "INDICATION_OF_OUT_OF_CREDIT", { .i32=7 }};
+			struct dict_enumval_data        t_16 = { "INDICATION_OF_SUCCESSFUL_RESOURCES_ALLOCATION", { .i32=8 }};
+			struct dict_enumval_data        t_17 = { "INDICATION_OF_FAILED_RESOURCES_ALLOCATION", { .i32=9 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_3, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_4, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_5, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_6, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_7, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_8, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_9, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_10, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_11, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_12, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_13, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_14, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_15, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_16, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_17, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* SIP-Forking-Indication */
+		{
+			struct dict_avp_data data = {
+				523,	/* Code */
+				10415,	/* Vendor */
+				"SIP-Forking-Indication",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(SIP-Forking-Indication)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "SINGLE_DIALOGUE", { .i32=0 }};
+			struct dict_enumval_data        t_2 = { "SEVERAL_DIALOGUES", { .i32=1 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* Sponsor-Identity */
+		{
+			struct dict_avp_data data = {
+				531,	/* Code */
+				10415,	/* Vendor */
+				"Sponsor-Identity",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, UTF8String_type, NULL);
+		};
+		/* Sponsoring-Action */
+		{
+			struct dict_avp_data data = {
+				542,	/* Code */
+				10415,	/* Vendor */
+				"Sponsoring-Action",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Sponsoring-Action)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "DISABLE_SPONSORING", { .i32=0 }};
+			struct dict_enumval_data        t_2 = { "ENABLE_SPONSORING", { .i32=1 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* Required-Access-Info */
+		{
+			struct dict_avp_data data = {
+				536,	/* Code */
+				10415,	/* Vendor */
+				"Required-Access-Info",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Required-Access-Info)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "USER_LOCATION", { .i32=0 }};
+			struct dict_enumval_data        t_2 = { "MS_TIME_ZONE", { .i32=1 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* Rx-Request-Type */
+		{
+			struct dict_avp_data data = {
+				533,	/* Code */
+				10415,	/* Vendor */
+				"Rx-Request-Type",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Rx-Request-Type)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "INITIAL_REQUEST", { .i32=0 }};
+			struct dict_enumval_data        t_2 = { "UPDATE_REQUEST", { .i32=1 }};
+			struct dict_enumval_data        t_3 = { "PCSCF_RESTORATION", { .i32=2 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_3, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* Retry-Interval */
+		{
+			struct dict_avp_data data = {
+				541,	/* Code */
+				10415,	/* Vendor */
+				"Retry-Interval",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Media-Sub-Component */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				519,	/* Code */
+				10415,	/* Vendor */
+				"Media-Sub-Component",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* Flows */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				510,	/* Code */
+				10415,	/* Vendor */
+				"Flows",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* Media-Component-Description */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				517,	/* Code */
+				10415,	/* Vendor */
+				"Media-Component-Description",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* Access-Network-Charging-Identifier */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				502,	/* Code */
+				10415,	/* Vendor */
+				"Access-Network-Charging-Identifier",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* Acceptable-Service-Info */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				526,	/* Code */
+				10415,	/* Vendor */
+				"Acceptable-Service-Info",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* Sponsored-Connectivity-Data */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				530,	/* Code */
+				10415,	/* Vendor */
+				"Sponsored-Connectivity-Data",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+
+	
+   }
+
+   /* Commands section */
+   {
+
+   }
+
+   return 0;
+}
+
+static int dict_ts29214_avps_load_rules(char * conffile)
+{
+   /* Grouped AVP section */
+   {
+	  /* Media-Sub-Component */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "Media-Sub-Component"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 10415, .avp_name = "Flow-Number"}, RULE_REQUIRED, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* Flows */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "Flows"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 10415, .avp_name = "Media-Component-Number"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Flow-Number"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Content-Version"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Final-Unit-Action"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Media-Component-Status"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* Media-Component-Description */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "Media-Component-Description"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 10415, .avp_name = "Media-Component-Number"}, RULE_REQUIRED, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* Access-Network-Charging-Identifier */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "Access-Network-Charging-Identifier"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 10415, .avp_name = "Access-Network-Charging-Identifier-Value"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Flows"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* Acceptable-Service-Info */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "Acceptable-Service-Info"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 10415, .avp_name = "Media-Component-Description"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Max-Requested-Bandwidth-DL"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Max-Requested-Bandwidth-UL"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* Sponsored-Connectivity-Data */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "Sponsored-Connectivity-Data"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 10415, .avp_name = "Sponsor-Identity"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Application-Service-Provider-Identity"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Granted-Service-Unit"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Used-Service-Unit"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Sponsoring-Action"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+
+   }	
+
+   /* Commands section */
+   {
+
+   }
+
+   LOG_D( "Extension 'Dictionary definitions for ts29214_avps (e30)' initialized");
+   return 0;
+}
+
+int dict_entry(char * conffile)
+{
+	dict_ts29214_avps_load_defs(conffile);
+	return dict_ts29214_avps_load_rules(conffile);
+}
+
+const char* dict_ts29214_avps_proto_ver(char * conffile) {
+	return ts29214_avps_proto_ver;
+}
+
+const double dict_ts29214_avps_gen_ts(char * conffile) {
+	return ts29214_avps_gen_date;
+}
+
+EXTENSION_ENTRY2("dict_ts29214_avps", dict_ts29214_avps_load_defs, dict_ts29214_avps_load_rules, "dict_ts29273_avps", "dict_ts29212_avps", "dict_ts29229_avps", "dict_ts29154_avps", "dict_ts29061_avps", "dict_rfc4006bis_avps", "dict_draftload_avps", "dict_rfc7683_avps", "dict_rfc7155_avps", "dict_etsi283034_avps", "dict_rfc7944_avps");
+
+
+
diff --git a/extensions/dict_ts29214_avps/ts29214_avps.did b/extensions/dict_ts29214_avps/ts29214_avps.did
new file mode 100644
index 0000000..b62bcfc
--- /dev/null
+++ b/extensions/dict_ts29214_avps/ts29214_avps.did
@@ -0,0 +1,37 @@
+dict_ts29154_avps
+dict_rfc6942_avps
+dict_ts29468_avps
+dict_ts29215_avps
+dict_ts29217_avps
+dict_3gpp2_avps
+dict_ts29343_avps
+dict_ts29338_avps
+dict_ts29128_avps
+dict_ts29344_avps
+dict_ts29345_avps
+dict_ts32299_avps
+dict_rfc6734_avps
+dict_rfc5778_avps
+dict_rfc5580_avps
+dict_rfc4072_avps
+dict_ts29273_avps
+dict_ts29173_avps
+dict_ts29337_avps
+dict_etsi283034_avps
+dict_rfc4590_avps
+dict_ts29229_avps
+dict_draftload_avps
+dict_ts29329_avps
+dict_ts29368_avps
+dict_ts29336_avps
+dict_ts29061_avps
+dict_rfc5447_avps
+dict_ts29272_avps
+dict_rfc7683_avps
+dict_ts29212_avps
+dict_rfc5777_avps
+dict_rfc4006bis_avps
+dict_rfc4004_avps
+dict_rfc7155_avps
+dict_rfc7944_avps
+dict_ts29214_avps
diff --git a/extensions/dict_ts29215_avps/CMakeLists.txt b/extensions/dict_ts29215_avps/CMakeLists.txt
new file mode 100644
index 0000000..b7cd4f3
--- /dev/null
+++ b/extensions/dict_ts29215_avps/CMakeLists.txt
@@ -0,0 +1,16 @@
+# The dict_ts29215_avps extension
+PROJECT("dict_ts29215_avps library generated by FdGen " C)
+
+# Compile as a module
+FD_ADD_EXTENSION(dict_ts29215_avps dict_ts29215_avps.c)
+
+
+####
+## INSTALL section ##
+
+INSTALL(TARGETS dict_ts29215_avps
+	LIBRARY DESTINATION ${INSTALL_EXTENSIONS_SUFFIX}
+COMPONENT freeDiameter-dictionary-TS29215_AVPS)
+
+
+
diff --git a/extensions/dict_ts29215_avps/dict_ts29215_avps.c b/extensions/dict_ts29215_avps/dict_ts29215_avps.c
new file mode 100644
index 0000000..ea3f1ec
--- /dev/null
+++ b/extensions/dict_ts29215_avps/dict_ts29215_avps.c
@@ -0,0 +1,416 @@
+/*
+* Copyright (c) 2017 Sprint
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*    http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+/****************
+ Generated By: fdtool enhancements to diafuzzer
+ License: same as freeDiameter
+****************/
+
+
+/* 
+ * Dictionary definitions of objects specified in ts29215_avps (e10).
+ */
+#include <freeDiameter/extension.h>
+
+#define PROTO_VER "e10"
+#define GEN_DATE  1506697191.31
+
+const char *ts29215_avps_proto_ver = PROTO_VER;
+const double ts29215_avps_gen_date = GEN_DATE;
+
+/* The content of this file follows the same structure as dict_base_proto.c */
+
+#define CHECK_dict_new( _type, _data, _parent, _ref )                                     \
+{                                                                                         \
+    int _ret = fd_dict_new( fd_g_config->cnf_dict, (_type), (_data), (_parent), (_ref) ); \
+    if ( _ret != 0 && _ret != EEXIST )                                                    \
+       return _ret;                                                                       \
+}
+
+#define CHECK_dict_search( _type, _criteria, _what, _result )		\
+    CHECK_FCT(  fd_dict_search( fd_g_config->cnf_dict, (_type), (_criteria), (_what), (_result), ENOENT) );
+
+struct local_rules_definition {
+    struct dict_avp_request avp_vendor_plus_name;
+    enum rule_position	position;
+    int 			min;
+    int			max;
+};
+
+#define RULE_ORDER( _position ) ((((_position) == RULE_FIXED_HEAD) || ((_position) == RULE_FIXED_TAIL)) ? 1 : 0 )
+
+/* Attention! This version of the macro uses AVP_BY_NAME_AND_VENDOR, in contrast to most other copies! */
+#define PARSE_loc_rules( _rulearray, _parent) {                                                         \
+        int __ar;                                                                                       \
+        for (__ar=0; __ar < sizeof(_rulearray) / sizeof((_rulearray)[0]); __ar++) {                     \
+                struct dict_rule_data __data = { NULL,                                                  \
+                        (_rulearray)[__ar].position,                                                    \
+                        0,                                                                              \
+                        (_rulearray)[__ar].min,                                                         \
+                        (_rulearray)[__ar].max};                                                        \
+                __data.rule_order = RULE_ORDER(__data.rule_position);                                   \
+                CHECK_FCT(  fd_dict_search(                                                             \
+                        fd_g_config->cnf_dict,                                                          \
+                        DICT_AVP,                                                                       \
+                        AVP_BY_NAME_AND_VENDOR,                                                         \
+                        &(_rulearray)[__ar].avp_vendor_plus_name,                                       \
+                        &__data.rule_avp, 0 ) );                                                        \
+                if ( !__data.rule_avp ) {                                                               \
+                        TRACE_DEBUG(INFO, "AVP Not found: '%s'", (_rulearray)[__ar].avp_vendor_plus_name.avp_name);             \
+                        return ENOENT;                                                                  \
+                }                                                                                       \
+                {                                                                                       \
+                         int _ret = fd_dict_new( fd_g_config->cnf_dict, DICT_RULE, &(__data), (_parent), NULL ); \
+                         if ( _ret != 0 && _ret != EEXIST )      {                                      \
+                                TRACE_DEBUG(INFO, "Error on rule with AVP '%s'",                        \
+                                            (_rulearray)[__ar].avp_vendor_plus_name.avp_name);          \
+                                return EINVAL;                                                          \
+                         }                                                                              \
+                }                                                                                       \
+        }                                                                                               \
+}
+
+#define CHECK_vendor_new( _data ) { \
+        struct dict_object * vendor_found; \
+        if (fd_dict_search(fd_g_config->cnf_dict,DICT_VENDOR,VENDOR_BY_ID,&_data.vendor_id,&vendor_found,ENOENT) == ENOENT) { \
+                CHECK_FCT(fd_dict_new(fd_g_config->cnf_dict, DICT_VENDOR, &_data, NULL, NULL)); \
+        } \
+}
+
+#define enumval_def_u32( _val_, _str_ )		\
+    { _str_, 		{ .u32 = _val_ }}
+
+#define enumval_def_os( _len_, _val_, _str_ )				\
+    { _str_, 		{ .os = { .data = (unsigned char *)_val_, .len = _len_ }}}
+
+
+static int dict_ts29215_avps_load_defs(char * conffile)
+{
+   TRACE_ENTRY("%p", conffile);
+	/* Application Section */
+	{
+		/* Create the vendors */		{
+			struct dict_vendor_data vendor_data = { 10415, "3GPP" };
+			CHECK_dict_new(DICT_VENDOR, &vendor_data, NULL, NULL)
+		}
+	}
+
+
+   /* AVP section */
+   {
+		struct dict_object * Address_type;
+		struct dict_object * UTF8String_type;
+		struct dict_object * DiameterIdentity_type;
+		struct dict_object * DiameterURI_type;
+		struct dict_object * Time_type;
+		struct dict_object * IPFilterRule_type;
+
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "Address", &Address_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "UTF8String", &UTF8String_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "DiameterIdentity", &DiameterIdentity_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "DiameterURI", &DiameterURI_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "Time", &Time_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "IPFilterRule", &IPFilterRule_type);
+		/* DRA-Deployment */
+		{
+			struct dict_avp_data data = {
+				2206,	/* Code */
+				10415,	/* Vendor */
+				"DRA-Deployment",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(DRA-Deployment)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "DRA_Deployed", { .i32=0 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* Multiple-BBERF-Action */
+		{
+			struct dict_avp_data data = {
+				2204,	/* Code */
+				10415,	/* Vendor */
+				"Multiple-BBERF-Action",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Multiple-BBERF-Action)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "ESTABLISHMENT", { .i32=0 }};
+			struct dict_enumval_data        t_2 = { "TERMINATION", { .i32=1 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* Subsession-Id */
+		{
+			struct dict_avp_data data = {
+				2202,	/* Code */
+				10415,	/* Vendor */
+				"Subsession-Id",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Subsession-Operation */
+		{
+			struct dict_avp_data data = {
+				2203,	/* Code */
+				10415,	/* Vendor */
+				"Subsession-Operation",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Subsession-Operation)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "TERMINATION", { .i32=0 }};
+			struct dict_enumval_data        t_2 = { "ESTABLISHMENT", { .i32=1 }};
+			struct dict_enumval_data        t_3 = { "MODIFICATION", { .i32=2 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_3, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* DRA-Binding */
+		{
+			struct dict_avp_data data = {
+				2208,	/* Code */
+				10415,	/* Vendor */
+				"DRA-Binding",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(DRA-Binding)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "DRA_BINDING_DELETION", { .i32=0 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* PCRF-Address */
+		{
+			struct dict_avp_data data = {
+				2207,	/* Code */
+				10415,	/* Vendor */
+				"PCRF-Address",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, DiameterIdentity_type, NULL);
+		};
+		/* UE-Local-IPv6-Prefix */
+		{
+			struct dict_avp_data data = {
+				2205,	/* Code */
+				10415,	/* Vendor */
+				"UE-Local-IPv6-Prefix",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Subsession-Enforcement-Info */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				2201,	/* Code */
+				10415,	/* Vendor */
+				"Subsession-Enforcement-Info",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* Subsession-Decision-Info */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				2200,	/* Code */
+				10415,	/* Vendor */
+				"Subsession-Decision-Info",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+
+	
+   }
+
+   /* Commands section */
+   {
+
+   }
+
+   return 0;
+}
+
+static int dict_ts29215_avps_load_rules(char * conffile)
+{
+   /* Grouped AVP section */
+   {
+	  /* Subsession-Enforcement-Info */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "Subsession-Enforcement-Info"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 10415, .avp_name = "Subsession-Id"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Subsession-Operation"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "AN-GW-Address"}, RULE_OPTIONAL, 0, 2 },
+			{ { .avp_vendor = 10415, .avp_name = "Bearer-Identifier"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Bearer-Operation"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Packet-Filter-Information"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Packet-Filter-Operation"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "QoS-Information"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Framed-IP-Address"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Framed-IPv6-Prefix"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "CoA-Information"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Called-Station-Id"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "PDN-Connection-ID"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Bearer-Usage"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "TFT-Packet-Filter-Information"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Online"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Offline"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Result-Code"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Experimental-Result-Code"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Charging-Rule-Report"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Credit-Management-Status"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "QoS-Rule-Report"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Application-Detection-Information"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "IP-CAN-Type"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "RAT-Type"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "3GPP-SGSN-MCC-MNC"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "3GPP-SGSN-Address"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "3GPP-SGSN-Ipv6-Address"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "RAI"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "3GPP-User-Location-Info"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 5535, .avp_name = "3GPP2-BSID"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "User-CSG-Information"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Default-EPS-Bearer-QoS"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Default-Access"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "NBIFOM-Support"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "NBIFOM-Mode"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Access-Availability-Change-Reason"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Network-Request-Support"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Routing-Rule-Install"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Routing-Rule-Remove"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "User-Location-Info-Time"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 13019, .avp_name = "Logical-Access-Id"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 13019, .avp_name = "Physical-Access-Id"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Usage-Monitoring-Information"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Multiple-BBERF-Action"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Event-Trigger"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Access-Network-Charging-Address"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Access-Network-Charging-Identifier-Gx"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Session-Linking-Indicator"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "HeNB-Local-IP-Address"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "UE-Local-IP-Address"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "UE-Local-IPv6-Prefix"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "UDP-Source-Port"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "AN-GW-Status"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* Subsession-Decision-Info */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "Subsession-Decision-Info"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 10415, .avp_name = "Subsession-Id"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "AN-GW-Address"}, RULE_OPTIONAL, 0, 2 },
+			{ { .avp_vendor = 0, .avp_name = "Result-Code"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Experimental-Result-Code"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Charging-Rule-Remove"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Charging-Rule-Install"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Event-Report-Indication"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "QoS-Rule-Install"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "QoS-Rule-Remove"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Default-EPS-Bearer-QoS"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Framed-IPv6-Prefix"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Usage-Monitoring-Information"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Session-Release-Cause"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Bearer-Control-Mode"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Event-Trigger"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Revalidation-Time"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Default-Access"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "NBIFOM-Support"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "NBIFOM-Mode"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "RAN-Rule-Support"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Routing-Rule-Report"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Removal-Of-Access"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "IP-CAN-Type"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Online"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Offline"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "QoS-Information"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+
+   }	
+
+   /* Commands section */
+   {
+
+   }
+
+   LOG_D( "Extension 'Dictionary definitions for ts29215_avps (e10)' initialized");
+   return 0;
+}
+
+int dict_entry(char * conffile)
+{
+	dict_ts29215_avps_load_defs(conffile);
+	return dict_ts29215_avps_load_rules(conffile);
+}
+
+const char* dict_ts29215_avps_proto_ver(char * conffile) {
+	return ts29215_avps_proto_ver;
+}
+
+const double dict_ts29215_avps_gen_ts(char * conffile) {
+	return ts29215_avps_gen_date;
+}
+
+EXTENSION_ENTRY2("dict_ts29215_avps", dict_ts29215_avps_load_defs, dict_ts29215_avps_load_rules, "dict_ts32299_avps", "dict_ts29212_avps", "dict_ts29214_avps", "dict_ts29229_avps", "dict_ts29061_avps", "dict_rfc4006bis_avps", "dict_draftload_avps", "dict_rfc7683_avps", "dict_rfc7155_avps", "dict_etsi283034_avps", "dict_3gpp2_avps", "dict_rfc7944_avps");
+
+
+
diff --git a/extensions/dict_ts29215_avps/ts29215_avps.did b/extensions/dict_ts29215_avps/ts29215_avps.did
new file mode 100644
index 0000000..0287b82
--- /dev/null
+++ b/extensions/dict_ts29215_avps/ts29215_avps.did
@@ -0,0 +1,37 @@
+dict_rfc6942_avps
+dict_ts29154_avps
+dict_ts29214_avps
+dict_ts29468_avps
+dict_ts29217_avps
+dict_3gpp2_avps
+dict_ts29343_avps
+dict_ts29338_avps
+dict_ts29128_avps
+dict_ts29344_avps
+dict_ts29345_avps
+dict_ts32299_avps
+dict_rfc6734_avps
+dict_rfc5778_avps
+dict_rfc5580_avps
+dict_rfc4072_avps
+dict_ts29273_avps
+dict_ts29173_avps
+dict_ts29337_avps
+dict_etsi283034_avps
+dict_rfc4590_avps
+dict_ts29229_avps
+dict_draftload_avps
+dict_ts29329_avps
+dict_ts29368_avps
+dict_ts29336_avps
+dict_ts29061_avps
+dict_rfc5447_avps
+dict_ts29272_avps
+dict_rfc7683_avps
+dict_rfc7944_avps
+dict_ts29212_avps
+dict_rfc5777_avps
+dict_rfc4006bis_avps
+dict_rfc4004_avps
+dict_rfc7155_avps
+dict_ts29215_avps
diff --git a/extensions/dict_ts29217_avps/CMakeLists.txt b/extensions/dict_ts29217_avps/CMakeLists.txt
new file mode 100644
index 0000000..b8a004b
--- /dev/null
+++ b/extensions/dict_ts29217_avps/CMakeLists.txt
@@ -0,0 +1,16 @@
+# The dict_ts29217_avps extension
+PROJECT("dict_ts29217_avps library generated by FdGen " C)
+
+# Compile as a module
+FD_ADD_EXTENSION(dict_ts29217_avps dict_ts29217_avps.c)
+
+
+####
+## INSTALL section ##
+
+INSTALL(TARGETS dict_ts29217_avps
+	LIBRARY DESTINATION ${INSTALL_EXTENSIONS_SUFFIX}
+COMPONENT freeDiameter-dictionary-TS29217_AVPS)
+
+
+
diff --git a/extensions/dict_ts29217_avps/dict_ts29217_avps.c b/extensions/dict_ts29217_avps/dict_ts29217_avps.c
new file mode 100644
index 0000000..acb9fa6
--- /dev/null
+++ b/extensions/dict_ts29217_avps/dict_ts29217_avps.c
@@ -0,0 +1,403 @@
+/*
+* Copyright (c) 2017 Sprint
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*    http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+/****************
+ Generated By: fdtool enhancements to diafuzzer
+ License: same as freeDiameter
+****************/
+
+
+/* 
+ * Dictionary definitions of objects specified in ts29217_avps (e10).
+ */
+#include <freeDiameter/extension.h>
+
+#define PROTO_VER "e10"
+#define GEN_DATE  1506697175.31
+
+const char *ts29217_avps_proto_ver = PROTO_VER;
+const double ts29217_avps_gen_date = GEN_DATE;
+
+/* The content of this file follows the same structure as dict_base_proto.c */
+
+#define CHECK_dict_new( _type, _data, _parent, _ref )                                     \
+{                                                                                         \
+    int _ret = fd_dict_new( fd_g_config->cnf_dict, (_type), (_data), (_parent), (_ref) ); \
+    if ( _ret != 0 && _ret != EEXIST )                                                    \
+       return _ret;                                                                       \
+}
+
+#define CHECK_dict_search( _type, _criteria, _what, _result )		\
+    CHECK_FCT(  fd_dict_search( fd_g_config->cnf_dict, (_type), (_criteria), (_what), (_result), ENOENT) );
+
+struct local_rules_definition {
+    struct dict_avp_request avp_vendor_plus_name;
+    enum rule_position	position;
+    int 			min;
+    int			max;
+};
+
+#define RULE_ORDER( _position ) ((((_position) == RULE_FIXED_HEAD) || ((_position) == RULE_FIXED_TAIL)) ? 1 : 0 )
+
+/* Attention! This version of the macro uses AVP_BY_NAME_AND_VENDOR, in contrast to most other copies! */
+#define PARSE_loc_rules( _rulearray, _parent) {                                                         \
+        int __ar;                                                                                       \
+        for (__ar=0; __ar < sizeof(_rulearray) / sizeof((_rulearray)[0]); __ar++) {                     \
+                struct dict_rule_data __data = { NULL,                                                  \
+                        (_rulearray)[__ar].position,                                                    \
+                        0,                                                                              \
+                        (_rulearray)[__ar].min,                                                         \
+                        (_rulearray)[__ar].max};                                                        \
+                __data.rule_order = RULE_ORDER(__data.rule_position);                                   \
+                CHECK_FCT(  fd_dict_search(                                                             \
+                        fd_g_config->cnf_dict,                                                          \
+                        DICT_AVP,                                                                       \
+                        AVP_BY_NAME_AND_VENDOR,                                                         \
+                        &(_rulearray)[__ar].avp_vendor_plus_name,                                       \
+                        &__data.rule_avp, 0 ) );                                                        \
+                if ( !__data.rule_avp ) {                                                               \
+                        TRACE_DEBUG(INFO, "AVP Not found: '%s'", (_rulearray)[__ar].avp_vendor_plus_name.avp_name);             \
+                        return ENOENT;                                                                  \
+                }                                                                                       \
+                {                                                                                       \
+                         int _ret = fd_dict_new( fd_g_config->cnf_dict, DICT_RULE, &(__data), (_parent), NULL ); \
+                         if ( _ret != 0 && _ret != EEXIST )      {                                      \
+                                TRACE_DEBUG(INFO, "Error on rule with AVP '%s'",                        \
+                                            (_rulearray)[__ar].avp_vendor_plus_name.avp_name);          \
+                                return EINVAL;                                                          \
+                         }                                                                              \
+                }                                                                                       \
+        }                                                                                               \
+}
+
+#define CHECK_vendor_new( _data ) { \
+        struct dict_object * vendor_found; \
+        if (fd_dict_search(fd_g_config->cnf_dict,DICT_VENDOR,VENDOR_BY_ID,&_data.vendor_id,&vendor_found,ENOENT) == ENOENT) { \
+                CHECK_FCT(fd_dict_new(fd_g_config->cnf_dict, DICT_VENDOR, &_data, NULL, NULL)); \
+        } \
+}
+
+#define enumval_def_u32( _val_, _str_ )		\
+    { _str_, 		{ .u32 = _val_ }}
+
+#define enumval_def_os( _len_, _val_, _str_ )				\
+    { _str_, 		{ .os = { .data = (unsigned char *)_val_, .len = _len_ }}}
+
+
+static int dict_ts29217_avps_load_defs(char * conffile)
+{
+   TRACE_ENTRY("%p", conffile);
+	/* Application Section */
+	{
+		/* Create the vendors */		{
+			struct dict_vendor_data vendor_data = { 10415, "3GPP" };
+			CHECK_dict_new(DICT_VENDOR, &vendor_data, NULL, NULL)
+		}
+	}
+
+
+   /* AVP section */
+   {
+		struct dict_object * Address_type;
+		struct dict_object * UTF8String_type;
+		struct dict_object * DiameterIdentity_type;
+		struct dict_object * DiameterURI_type;
+		struct dict_object * Time_type;
+		struct dict_object * IPFilterRule_type;
+
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "Address", &Address_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "UTF8String", &UTF8String_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "DiameterIdentity", &DiameterIdentity_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "DiameterURI", &DiameterURI_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "Time", &Time_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "IPFilterRule", &IPFilterRule_type);
+		/* Congestion-Level-Range */
+		{
+			struct dict_avp_data data = {
+				4003,	/* Code */
+				10415,	/* Vendor */
+				"Congestion-Level-Range",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Congestion-Level-Set-Id */
+		{
+			struct dict_avp_data data = {
+				4004,	/* Code */
+				10415,	/* Vendor */
+				"Congestion-Level-Set-Id",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Congestion-Level-Value */
+		{
+			struct dict_avp_data data = {
+				4005,	/* Code */
+				10415,	/* Vendor */
+				"Congestion-Level-Value",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Conditional-Restriction */
+		{
+			struct dict_avp_data data = {
+				4007,	/* Code */
+				10415,	/* Vendor */
+				"Conditional-Restriction",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* eNodeB-Id */
+		{
+			struct dict_avp_data data = {
+				4008,	/* Code */
+				10415,	/* Vendor */
+				"eNodeB-Id",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* IMSI-List */
+		{
+			struct dict_avp_data data = {
+				4009,	/* Code */
+				10415,	/* Vendor */
+				"IMSI-List",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* RCAF-Id */
+		{
+			struct dict_avp_data data = {
+				4010,	/* Code */
+				10415,	/* Vendor */
+				"RCAF-Id",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, DiameterIdentity_type, NULL);
+		};
+		/* Reporting-Restriction */
+		{
+			struct dict_avp_data data = {
+				4011,	/* Code */
+				10415,	/* Vendor */
+				"Reporting-Restriction",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* RUCI-Action */
+		{
+			struct dict_avp_data data = {
+				4012,	/* Code */
+				10415,	/* Vendor */
+				"RUCI-Action",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Extended-eNodeB-Id */
+		{
+			struct dict_avp_data data = {
+				4013,	/* Code */
+				10415,	/* Vendor */
+				"Extended-eNodeB-Id",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Congestion-Level-Definition */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				4002,	/* Code */
+				10415,	/* Vendor */
+				"Congestion-Level-Definition",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* Congestion-Location-Id */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				4006,	/* Code */
+				10415,	/* Vendor */
+				"Congestion-Location-Id",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* Aggregated-Congestion-Info */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				4000,	/* Code */
+				10415,	/* Vendor */
+				"Aggregated-Congestion-Info",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* Aggregated-RUCI-Report */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				4001,	/* Code */
+				10415,	/* Vendor */
+				"Aggregated-RUCI-Report",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+
+	
+   }
+
+   /* Commands section */
+   {
+
+   }
+
+   return 0;
+}
+
+static int dict_ts29217_avps_load_rules(char * conffile)
+{
+   /* Grouped AVP section */
+   {
+	  /* Congestion-Level-Definition */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "Congestion-Level-Definition"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 10415, .avp_name = "Congestion-Level-Set-Id"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Congestion-Level-Range"}, RULE_REQUIRED, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* Congestion-Location-Id */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "Congestion-Location-Id"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 10415, .avp_name = "3GPP-User-Location-Info"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "eNodeB-Id"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Extended-eNodeB-Id"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* Aggregated-Congestion-Info */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "Aggregated-Congestion-Info"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 10415, .avp_name = "Congestion-Location-Id"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "IMSI-List"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* Aggregated-RUCI-Report */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "Aggregated-RUCI-Report"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 10415, .avp_name = "Aggregated-Congestion-Info"}, RULE_REQUIRED, 1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Called-Station-Id"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Congestion-Level-Value"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Congestion-Level-Set-Id"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+
+   }	
+
+   /* Commands section */
+   {
+
+   }
+
+   LOG_D( "Extension 'Dictionary definitions for ts29217_avps (e10)' initialized");
+   return 0;
+}
+
+int dict_entry(char * conffile)
+{
+	dict_ts29217_avps_load_defs(conffile);
+	return dict_ts29217_avps_load_rules(conffile);
+}
+
+const char* dict_ts29217_avps_proto_ver(char * conffile) {
+	return ts29217_avps_proto_ver;
+}
+
+const double dict_ts29217_avps_gen_ts(char * conffile) {
+	return ts29217_avps_gen_date;
+}
+
+EXTENSION_ENTRY2("dict_ts29217_avps", dict_ts29217_avps_load_defs, dict_ts29217_avps_load_rules, "dict_ts29215_avps", "dict_ts29229_avps", "dict_ts29061_avps", "dict_rfc4006bis_avps", "dict_draftload_avps", "dict_rfc7683_avps", "dict_rfc7944_avps", "dict_rfc7155_avps");
+
+
+
diff --git a/extensions/dict_ts29217_avps/ts29217_avps.did b/extensions/dict_ts29217_avps/ts29217_avps.did
new file mode 100644
index 0000000..40e96aa
--- /dev/null
+++ b/extensions/dict_ts29217_avps/ts29217_avps.did
@@ -0,0 +1,37 @@
+dict_rfc6942_avps
+dict_ts29154_avps
+dict_ts29214_avps
+dict_ts29468_avps
+dict_3gpp2_avps
+dict_ts29343_avps
+dict_ts29338_avps
+dict_ts29128_avps
+dict_ts29344_avps
+dict_ts29345_avps
+dict_ts32299_avps
+dict_rfc6734_avps
+dict_rfc5778_avps
+dict_rfc5580_avps
+dict_rfc4072_avps
+dict_ts29273_avps
+dict_ts29173_avps
+dict_ts29337_avps
+dict_etsi283034_avps
+dict_rfc4590_avps
+dict_ts29229_avps
+dict_draftload_avps
+dict_ts29329_avps
+dict_ts29368_avps
+dict_ts29336_avps
+dict_ts29061_avps
+dict_rfc5447_avps
+dict_ts29272_avps
+dict_ts29212_avps
+dict_ts29215_avps
+dict_rfc7683_avps
+dict_rfc7944_avps
+dict_rfc5777_avps
+dict_rfc4006bis_avps
+dict_rfc4004_avps
+dict_rfc7155_avps
+dict_ts29217_avps
diff --git a/extensions/dict_ts29229_avps/CMakeLists.txt b/extensions/dict_ts29229_avps/CMakeLists.txt
new file mode 100644
index 0000000..e0fc692
--- /dev/null
+++ b/extensions/dict_ts29229_avps/CMakeLists.txt
@@ -0,0 +1,16 @@
+# The dict_ts29229_avps extension
+PROJECT("dict_ts29229_avps library generated by FdGen " C)
+
+# Compile as a module
+FD_ADD_EXTENSION(dict_ts29229_avps dict_ts29229_avps.c)
+
+
+####
+## INSTALL section ##
+
+INSTALL(TARGETS dict_ts29229_avps
+	LIBRARY DESTINATION ${INSTALL_EXTENSIONS_SUFFIX}
+COMPONENT freeDiameter-dictionary-TS29229_AVPS)
+
+
+
diff --git a/extensions/dict_ts29229_avps/dict_ts29229_avps.c b/extensions/dict_ts29229_avps/dict_ts29229_avps.c
new file mode 100644
index 0000000..d8beb19
--- /dev/null
+++ b/extensions/dict_ts29229_avps/dict_ts29229_avps.c
@@ -0,0 +1,1206 @@
+/*
+* Copyright (c) 2017 Sprint
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*    http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+/****************
+ Generated By: fdtool enhancements to diafuzzer
+ License: same as freeDiameter
+****************/
+
+
+/* 
+ * Dictionary definitions of objects specified in ts29229_avps (e10).
+ */
+#include <freeDiameter/extension.h>
+
+#define PROTO_VER "e10"
+#define GEN_DATE  1506697168.8
+
+const char *ts29229_avps_proto_ver = PROTO_VER;
+const double ts29229_avps_gen_date = GEN_DATE;
+
+/* The content of this file follows the same structure as dict_base_proto.c */
+
+#define CHECK_dict_new( _type, _data, _parent, _ref )                                     \
+{                                                                                         \
+    int _ret = fd_dict_new( fd_g_config->cnf_dict, (_type), (_data), (_parent), (_ref) ); \
+    if ( _ret != 0 && _ret != EEXIST )                                                    \
+       return _ret;                                                                       \
+}
+
+#define CHECK_dict_search( _type, _criteria, _what, _result )		\
+    CHECK_FCT(  fd_dict_search( fd_g_config->cnf_dict, (_type), (_criteria), (_what), (_result), ENOENT) );
+
+struct local_rules_definition {
+    struct dict_avp_request avp_vendor_plus_name;
+    enum rule_position	position;
+    int 			min;
+    int			max;
+};
+
+#define RULE_ORDER( _position ) ((((_position) == RULE_FIXED_HEAD) || ((_position) == RULE_FIXED_TAIL)) ? 1 : 0 )
+
+/* Attention! This version of the macro uses AVP_BY_NAME_AND_VENDOR, in contrast to most other copies! */
+#define PARSE_loc_rules( _rulearray, _parent) {                                                         \
+        int __ar;                                                                                       \
+        for (__ar=0; __ar < sizeof(_rulearray) / sizeof((_rulearray)[0]); __ar++) {                     \
+                struct dict_rule_data __data = { NULL,                                                  \
+                        (_rulearray)[__ar].position,                                                    \
+                        0,                                                                              \
+                        (_rulearray)[__ar].min,                                                         \
+                        (_rulearray)[__ar].max};                                                        \
+                __data.rule_order = RULE_ORDER(__data.rule_position);                                   \
+                CHECK_FCT(  fd_dict_search(                                                             \
+                        fd_g_config->cnf_dict,                                                          \
+                        DICT_AVP,                                                                       \
+                        AVP_BY_NAME_AND_VENDOR,                                                         \
+                        &(_rulearray)[__ar].avp_vendor_plus_name,                                       \
+                        &__data.rule_avp, 0 ) );                                                        \
+                if ( !__data.rule_avp ) {                                                               \
+                        TRACE_DEBUG(INFO, "AVP Not found: '%s'", (_rulearray)[__ar].avp_vendor_plus_name.avp_name);             \
+                        return ENOENT;                                                                  \
+                }                                                                                       \
+                {                                                                                       \
+                         int _ret = fd_dict_new( fd_g_config->cnf_dict, DICT_RULE, &(__data), (_parent), NULL ); \
+                         if ( _ret != 0 && _ret != EEXIST )      {                                      \
+                                TRACE_DEBUG(INFO, "Error on rule with AVP '%s'",                        \
+                                            (_rulearray)[__ar].avp_vendor_plus_name.avp_name);          \
+                                return EINVAL;                                                          \
+                         }                                                                              \
+                }                                                                                       \
+        }                                                                                               \
+}
+
+#define CHECK_vendor_new( _data ) { \
+        struct dict_object * vendor_found; \
+        if (fd_dict_search(fd_g_config->cnf_dict,DICT_VENDOR,VENDOR_BY_ID,&_data.vendor_id,&vendor_found,ENOENT) == ENOENT) { \
+                CHECK_FCT(fd_dict_new(fd_g_config->cnf_dict, DICT_VENDOR, &_data, NULL, NULL)); \
+        } \
+}
+
+#define enumval_def_u32( _val_, _str_ )		\
+    { _str_, 		{ .u32 = _val_ }}
+
+#define enumval_def_os( _len_, _val_, _str_ )				\
+    { _str_, 		{ .os = { .data = (unsigned char *)_val_, .len = _len_ }}}
+
+
+static int dict_ts29229_avps_load_defs(char * conffile)
+{
+   TRACE_ENTRY("%p", conffile);
+	/* Application Section */
+	{
+		/* Create the vendors */		{
+			struct dict_vendor_data vendor_data = { 10415, "3GPP" };
+			CHECK_dict_new(DICT_VENDOR, &vendor_data, NULL, NULL)
+		}
+	}
+
+
+   /* AVP section */
+   {
+		struct dict_object * Address_type;
+		struct dict_object * UTF8String_type;
+		struct dict_object * DiameterIdentity_type;
+		struct dict_object * DiameterURI_type;
+		struct dict_object * Time_type;
+		struct dict_object * IPFilterRule_type;
+
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "Address", &Address_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "UTF8String", &UTF8String_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "DiameterIdentity", &DiameterIdentity_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "DiameterURI", &DiameterURI_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "Time", &Time_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "IPFilterRule", &IPFilterRule_type);
+		/* Visited-Network-Identifier */
+		{
+			struct dict_avp_data data = {
+				600,	/* Code */
+				10415,	/* Vendor */
+				"Visited-Network-Identifier",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Public-Identity */
+		{
+			struct dict_avp_data data = {
+				601,	/* Code */
+				10415,	/* Vendor */
+				"Public-Identity",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, UTF8String_type, NULL);
+		};
+		/* Server-Name */
+		{
+			struct dict_avp_data data = {
+				602,	/* Code */
+				10415,	/* Vendor */
+				"Server-Name",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, UTF8String_type, NULL);
+		};
+		/* Mandatory-Capability */
+		{
+			struct dict_avp_data data = {
+				604,	/* Code */
+				10415,	/* Vendor */
+				"Mandatory-Capability",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Optional-Capability */
+		{
+			struct dict_avp_data data = {
+				605,	/* Code */
+				10415,	/* Vendor */
+				"Optional-Capability",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* User-Data */
+		{
+			struct dict_avp_data data = {
+				606,	/* Code */
+				10415,	/* Vendor */
+				"User-Data",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* SIP-Number-Auth-Items */
+		{
+			struct dict_avp_data data = {
+				607,	/* Code */
+				10415,	/* Vendor */
+				"SIP-Number-Auth-Items",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* SIP-Authentication-Scheme */
+		{
+			struct dict_avp_data data = {
+				608,	/* Code */
+				10415,	/* Vendor */
+				"SIP-Authentication-Scheme",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, UTF8String_type, NULL);
+		};
+		/* SIP-Authenticate */
+		{
+			struct dict_avp_data data = {
+				609,	/* Code */
+				10415,	/* Vendor */
+				"SIP-Authenticate",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* SIP-Authorization */
+		{
+			struct dict_avp_data data = {
+				610,	/* Code */
+				10415,	/* Vendor */
+				"SIP-Authorization",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* SIP-Authentication-Context */
+		{
+			struct dict_avp_data data = {
+				611,	/* Code */
+				10415,	/* Vendor */
+				"SIP-Authentication-Context",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* SIP-Item-Number */
+		{
+			struct dict_avp_data data = {
+				613,	/* Code */
+				10415,	/* Vendor */
+				"SIP-Item-Number",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Server-Assignment-Type */
+		{
+			struct dict_avp_data data = {
+				614,	/* Code */
+				10415,	/* Vendor */
+				"Server-Assignment-Type",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Server-Assignment-Type)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "NO_ASSIGNMENT", { .i32=0 }};
+			struct dict_enumval_data        t_2 = { "REGISTRATION", { .i32=1 }};
+			struct dict_enumval_data        t_3 = { "AUTHENTICATION_TIMEOUT", { .i32=10 }};
+			struct dict_enumval_data        t_4 = { "DEREGISTRATION_TOO_MUCH_DATA", { .i32=11 }};
+			struct dict_enumval_data        t_5 = { "AAA_USER_DATA_REQUEST", { .i32=12 }};
+			struct dict_enumval_data        t_6 = { "PGW_UPDATE", { .i32=13 }};
+			struct dict_enumval_data        t_7 = { "RESTORATION", { .i32=14 }};
+			struct dict_enumval_data        t_8 = { "RE_REGISTRATION", { .i32=2 }};
+			struct dict_enumval_data        t_9 = { "UNREGISTERED_USER", { .i32=3 }};
+			struct dict_enumval_data        t_10 = { "TIMEOUT_DEREGISTRATION", { .i32=4 }};
+			struct dict_enumval_data        t_11 = { "USER_DEREGISTRATION", { .i32=5 }};
+			struct dict_enumval_data        t_12 = { "TIMEOUT_DEREGISTRATION_STORE_SERVER_NAME", { .i32=6 }};
+			struct dict_enumval_data        t_13 = { "USER_DEREGISTRATION_STORE_SERVER_NAME", { .i32=7 }};
+			struct dict_enumval_data        t_14 = { "ADMINISTRATIVE_DEREGISTRATION", { .i32=8 }};
+			struct dict_enumval_data        t_15 = { "AUTHENTICATION_FAILURE", { .i32=9 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_3, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_4, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_5, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_6, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_7, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_8, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_9, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_10, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_11, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_12, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_13, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_14, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_15, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* Reason-Code */
+		{
+			struct dict_avp_data data = {
+				616,	/* Code */
+				10415,	/* Vendor */
+				"Reason-Code",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Reason-Code)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "PERMANENT_TERMINATION", { .i32=0 }};
+			struct dict_enumval_data        t_2 = { "NEW_SERVER_ASSIGNED", { .i32=1 }};
+			struct dict_enumval_data        t_3 = { "SERVER_CHANGE", { .i32=2 }};
+			struct dict_enumval_data        t_4 = { "REMOVE_S_CSCF", { .i32=3 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_3, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_4, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* Reason-Info */
+		{
+			struct dict_avp_data data = {
+				617,	/* Code */
+				10415,	/* Vendor */
+				"Reason-Info",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, UTF8String_type, NULL);
+		};
+		/* Primary-Event-Charging-Function-Name */
+		{
+			struct dict_avp_data data = {
+				619,	/* Code */
+				10415,	/* Vendor */
+				"Primary-Event-Charging-Function-Name",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, DiameterURI_type, NULL);
+		};
+		/* Secondary-Event-Charging-Function-Name */
+		{
+			struct dict_avp_data data = {
+				620,	/* Code */
+				10415,	/* Vendor */
+				"Secondary-Event-Charging-Function-Name",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, DiameterURI_type, NULL);
+		};
+		/* Primary-Charging-Collection-Function-Name */
+		{
+			struct dict_avp_data data = {
+				621,	/* Code */
+				10415,	/* Vendor */
+				"Primary-Charging-Collection-Function-Name",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, DiameterURI_type, NULL);
+		};
+		/* Secondary-Charging-Collection-Function-Name */
+		{
+			struct dict_avp_data data = {
+				622,	/* Code */
+				10415,	/* Vendor */
+				"Secondary-Charging-Collection-Function-Name",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, DiameterURI_type, NULL);
+		};
+		/* User-Authorization-Type */
+		{
+			struct dict_avp_data data = {
+				623,	/* Code */
+				10415,	/* Vendor */
+				"User-Authorization-Type",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(User-Authorization-Type)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "REGISTRATION", { .i32=0 }};
+			struct dict_enumval_data        t_2 = { "DE_REGISTRATION", { .i32=1 }};
+			struct dict_enumval_data        t_3 = { "REGISTRATION_AND_CAPABILITIES", { .i32=2 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_3, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* User-Data-Already-Available */
+		{
+			struct dict_avp_data data = {
+				624,	/* Code */
+				10415,	/* Vendor */
+				"User-Data-Already-Available",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(User-Data-Already-Available)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "USER_DATA_NOT_AVAILABLE", { .i32=0 }};
+			struct dict_enumval_data        t_2 = { "USER_DATA_ALREADY_AVAILABLE", { .i32=1 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* Confidentiality-Key */
+		{
+			struct dict_avp_data data = {
+				625,	/* Code */
+				10415,	/* Vendor */
+				"Confidentiality-Key",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Integrity-Key */
+		{
+			struct dict_avp_data data = {
+				626,	/* Code */
+				10415,	/* Vendor */
+				"Integrity-Key",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Feature-List-ID */
+		{
+			struct dict_avp_data data = {
+				629,	/* Code */
+				10415,	/* Vendor */
+				"Feature-List-ID",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Feature-List */
+		{
+			struct dict_avp_data data = {
+				630,	/* Code */
+				10415,	/* Vendor */
+				"Feature-List",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Originating-Request */
+		{
+			struct dict_avp_data data = {
+				633,	/* Code */
+				10415,	/* Vendor */
+				"Originating-Request",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Originating-Request)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "ORIGINATING", { .i32=0 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* Wildcarded-Public-Identity */
+		{
+			struct dict_avp_data data = {
+				634,	/* Code */
+				10415,	/* Vendor */
+				"Wildcarded-Public-Identity",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, UTF8String_type, NULL);
+		};
+		/* UAR-Flags */
+		{
+			struct dict_avp_data data = {
+				637,	/* Code */
+				10415,	/* Vendor */
+				"UAR-Flags",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Loose-Route-Indication */
+		{
+			struct dict_avp_data data = {
+				638,	/* Code */
+				10415,	/* Vendor */
+				"Loose-Route-Indication",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Loose-Route-Indication)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "LOOSE_ROUTE_NOT_REQUIRED", { .i32=0 }};
+			struct dict_enumval_data        t_2 = { "LOOSE_ROUTE_REQUIRED", { .i32=1 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* Path */
+		{
+			struct dict_avp_data data = {
+				640,	/* Code */
+				10415,	/* Vendor */
+				"Path",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Contact */
+		{
+			struct dict_avp_data data = {
+				641,	/* Code */
+				10415,	/* Vendor */
+				"Contact",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Call-ID-SIP-Header */
+		{
+			struct dict_avp_data data = {
+				643,	/* Code */
+				10415,	/* Vendor */
+				"Call-ID-SIP-Header",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* From-SIP-Header */
+		{
+			struct dict_avp_data data = {
+				644,	/* Code */
+				10415,	/* Vendor */
+				"From-SIP-Header",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* To-SIP-Header */
+		{
+			struct dict_avp_data data = {
+				645,	/* Code */
+				10415,	/* Vendor */
+				"To-SIP-Header",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Record-Route */
+		{
+			struct dict_avp_data data = {
+				646,	/* Code */
+				10415,	/* Vendor */
+				"Record-Route",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Multiple-Registration-Indication */
+		{
+			struct dict_avp_data data = {
+				648,	/* Code */
+				10415,	/* Vendor */
+				"Multiple-Registration-Indication",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Multiple-Registration-Indication)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "NOT_MULTIPLE_REGISTRATION", { .i32=0 }};
+			struct dict_enumval_data        t_2 = { "MULTIPLE_REGISTRATION", { .i32=1 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* Session-Priority */
+		{
+			struct dict_avp_data data = {
+				650,	/* Code */
+				10415,	/* Vendor */
+				"Session-Priority",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Session-Priority)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "PRIORITY_0", { .i32=0 }};
+			struct dict_enumval_data        t_2 = { "PRIORITY_1", { .i32=1 }};
+			struct dict_enumval_data        t_3 = { "PRIORITY_2", { .i32=2 }};
+			struct dict_enumval_data        t_4 = { "PRIORITY_3", { .i32=3 }};
+			struct dict_enumval_data        t_5 = { "PRIORITY_4", { .i32=4 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_3, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_4, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_5, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* Priviledged-Sender-Indication */
+		{
+			struct dict_avp_data data = {
+				652,	/* Code */
+				10415,	/* Vendor */
+				"Priviledged-Sender-Indication",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Priviledged-Sender-Indication)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "PRIVILEDGED_SENDER", { .i32=1 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* LIA-Flags */
+		{
+			struct dict_avp_data data = {
+				653,	/* Code */
+				10415,	/* Vendor */
+				"LIA-Flags",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Initial-CSeq-Sequence-Number */
+		{
+			struct dict_avp_data data = {
+				654,	/* Code */
+				10415,	/* Vendor */
+				"Initial-CSeq-Sequence-Number",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* SAR-Flags */
+		{
+			struct dict_avp_data data = {
+				655,	/* Code */
+				10415,	/* Vendor */
+				"SAR-Flags",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* WebRTC-Authentication-Function-Name */
+		{
+			struct dict_avp_data data = {
+				657,	/* Code */
+				10415,	/* Vendor */
+				"WebRTC-Authentication-Function-Name",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, UTF8String_type, NULL);
+		};
+		/* WebRTC-Web-Server-Function-Name */
+		{
+			struct dict_avp_data data = {
+				658,	/* Code */
+				10415,	/* Vendor */
+				"WebRTC-Web-Server-Function-Name",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, UTF8String_type, NULL);
+		};
+		/* Wildcarded-IMPU */
+		{
+			struct dict_avp_data data = {
+				636,	/* Code */
+				10415,	/* Vendor */
+				"Wildcarded-IMPU",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, UTF8String_type, NULL);
+		};
+		/* Subscription-Info */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				642,	/* Code */
+				10415,	/* Vendor */
+				"Subscription-Info",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* Server-Capabilities */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				603,	/* Code */
+				10415,	/* Vendor */
+				"Server-Capabilities",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* Associated-Registered-Identities */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				647,	/* Code */
+				10415,	/* Vendor */
+				"Associated-Registered-Identities",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* SIP-Digest-Authenticate */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				635,	/* Code */
+				10415,	/* Vendor */
+				"SIP-Digest-Authenticate",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* Supported-Features */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				628,	/* Code */
+				10415,	/* Vendor */
+				"Supported-Features",	/* Name */
+				AVP_FLAG_VENDOR,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* Allowed-WAF-WWSF-Identities */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				656,	/* Code */
+				10415,	/* Vendor */
+				"Allowed-WAF-WWSF-Identities",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* Identity-with-Emergency-Registration */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				651,	/* Code */
+				10415,	/* Vendor */
+				"Identity-with-Emergency-Registration",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* Associated-Identities */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				632,	/* Code */
+				10415,	/* Vendor */
+				"Associated-Identities",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* Deregistration-Reason */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				615,	/* Code */
+				10415,	/* Vendor */
+				"Deregistration-Reason",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* Charging-Information */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				618,	/* Code */
+				10415,	/* Vendor */
+				"Charging-Information",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* SIP-Auth-Data-Item */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				612,	/* Code */
+				10415,	/* Vendor */
+				"SIP-Auth-Data-Item",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* Restoration-Info */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				649,	/* Code */
+				10415,	/* Vendor */
+				"Restoration-Info",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* Supported-Applications */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				631,	/* Code */
+				10415,	/* Vendor */
+				"Supported-Applications",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* SCSCF-Restoration-Info */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				639,	/* Code */
+				10415,	/* Vendor */
+				"SCSCF-Restoration-Info",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+
+	
+   }
+
+   /* Commands section */
+   {
+
+   }
+
+   return 0;
+}
+
+static int dict_ts29229_avps_load_rules(char * conffile)
+{
+   /* Grouped AVP section */
+   {
+	  /* Subscription-Info */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "Subscription-Info"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 10415, .avp_name = "Call-ID-SIP-Header"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "From-SIP-Header"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "To-SIP-Header"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Record-Route"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Contact"}, RULE_REQUIRED, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* Server-Capabilities */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "Server-Capabilities"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 10415, .avp_name = "Mandatory-Capability"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Optional-Capability"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Server-Name"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* Associated-Registered-Identities */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "Associated-Registered-Identities"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 0, .avp_name = "User-Name"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* SIP-Digest-Authenticate */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "SIP-Digest-Authenticate"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 0, .avp_name = "Digest-Realm"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Digest-Algorithm"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Digest-QoP"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Digest-HA1"}, RULE_REQUIRED, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* Supported-Features */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "Supported-Features"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 0, .avp_name = "Vendor-Id"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Feature-List-ID"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Feature-List"}, RULE_REQUIRED, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* Allowed-WAF-WWSF-Identities */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "Allowed-WAF-WWSF-Identities"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 10415, .avp_name = "WebRTC-Authentication-Function-Name"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "WebRTC-Web-Server-Function-Name"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* Identity-with-Emergency-Registration */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "Identity-with-Emergency-Registration"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 0, .avp_name = "User-Name"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Public-Identity"}, RULE_REQUIRED, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* Associated-Identities */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "Associated-Identities"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 0, .avp_name = "User-Name"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* Deregistration-Reason */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "Deregistration-Reason"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 10415, .avp_name = "Reason-Code"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Reason-Info"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* Charging-Information */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "Charging-Information"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 10415, .avp_name = "Primary-Event-Charging-Function-Name"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Secondary-Event-Charging-Function-Name"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Primary-Charging-Collection-Function-Name"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Secondary-Charging-Collection-Function-Name"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* SIP-Auth-Data-Item */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "SIP-Auth-Data-Item"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 10415, .avp_name = "SIP-Item-Number"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "SIP-Authentication-Scheme"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "SIP-Authenticate"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "SIP-Authorization"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "SIP-Authentication-Context"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Confidentiality-Key"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Integrity-Key"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "SIP-Digest-Authenticate"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Framed-IP-Address"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Framed-IPv6-Prefix"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Framed-Interface-Id"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 13019, .avp_name = "Line-Identifier"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* Restoration-Info */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "Restoration-Info"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 10415, .avp_name = "Path"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Contact"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Initial-CSeq-Sequence-Number"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Call-ID-SIP-Header"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Subscription-Info"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* Supported-Applications */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "Supported-Applications"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 0, .avp_name = "Auth-Application-Id"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Acct-Application-Id"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Vendor-Specific-Application-Id"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* SCSCF-Restoration-Info */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "SCSCF-Restoration-Info"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 0, .avp_name = "User-Name"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Restoration-Info"}, RULE_REQUIRED, 1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "SIP-Authentication-Scheme"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+
+   }	
+
+   /* Commands section */
+   {
+
+   }
+
+   LOG_D( "Extension 'Dictionary definitions for ts29229_avps (e10)' initialized");
+   return 0;
+}
+
+int dict_entry(char * conffile)
+{
+	dict_ts29229_avps_load_defs(conffile);
+	return dict_ts29229_avps_load_rules(conffile);
+}
+
+const char* dict_ts29229_avps_proto_ver(char * conffile) {
+	return ts29229_avps_proto_ver;
+}
+
+const double dict_ts29229_avps_gen_ts(char * conffile) {
+	return ts29229_avps_gen_date;
+}
+
+EXTENSION_ENTRY2("dict_ts29229_avps", dict_ts29229_avps_load_defs, dict_ts29229_avps_load_rules, "dict_rfc7683_avps", "dict_rfc4590_avps", "dict_draftload_avps", "dict_rfc7155_avps", "dict_etsi283034_avps", "dict_rfc7944_avps");
+
+
+
diff --git a/extensions/dict_ts29229_avps/ts29229_avps.did b/extensions/dict_ts29229_avps/ts29229_avps.did
new file mode 100644
index 0000000..6a2c8ee
--- /dev/null
+++ b/extensions/dict_ts29229_avps/ts29229_avps.did
@@ -0,0 +1,8 @@
+dict_draftload_avps
+dict_etsi283034_avps
+dict_rfc4590_avps
+dict_rfc7683_avps
+dict_rfc7944_avps
+dict_rfc4004_avps
+dict_rfc7155_avps
+dict_ts29229_avps
diff --git a/extensions/dict_ts29272_avps/CMakeLists.txt b/extensions/dict_ts29272_avps/CMakeLists.txt
new file mode 100644
index 0000000..85b98a2
--- /dev/null
+++ b/extensions/dict_ts29272_avps/CMakeLists.txt
@@ -0,0 +1,16 @@
+# The dict_ts29272_avps extension
+PROJECT("dict_ts29272_avps library generated by FdGen " C)
+
+# Compile as a module
+FD_ADD_EXTENSION(dict_ts29272_avps dict_ts29272_avps.c)
+
+
+####
+## INSTALL section ##
+
+INSTALL(TARGETS dict_ts29272_avps
+	LIBRARY DESTINATION ${INSTALL_EXTENSIONS_SUFFIX}
+COMPONENT freeDiameter-dictionary-TS29272_AVPS)
+
+
+
diff --git a/extensions/dict_ts29272_avps/dict_ts29272_avps.c b/extensions/dict_ts29272_avps/dict_ts29272_avps.c
new file mode 100644
index 0000000..5d74805
--- /dev/null
+++ b/extensions/dict_ts29272_avps/dict_ts29272_avps.c
@@ -0,0 +1,3599 @@
+/*
+* Copyright (c) 2017 Sprint
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*    http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+/****************
+ Generated By: fdtool enhancements to diafuzzer
+ License: same as freeDiameter
+****************/
+
+
+/* 
+ * Dictionary definitions of objects specified in ts29272_avps (e30).
+ */
+#include <freeDiameter/extension.h>
+
+#define PROTO_VER "e30"
+#define GEN_DATE  1506697187.84
+
+const char *ts29272_avps_proto_ver = PROTO_VER;
+const double ts29272_avps_gen_date = GEN_DATE;
+
+/* The content of this file follows the same structure as dict_base_proto.c */
+
+#define CHECK_dict_new( _type, _data, _parent, _ref )                                     \
+{                                                                                         \
+    int _ret = fd_dict_new( fd_g_config->cnf_dict, (_type), (_data), (_parent), (_ref) ); \
+    if ( _ret != 0 && _ret != EEXIST )                                                    \
+       return _ret;                                                                       \
+}
+
+#define CHECK_dict_search( _type, _criteria, _what, _result )		\
+    CHECK_FCT(  fd_dict_search( fd_g_config->cnf_dict, (_type), (_criteria), (_what), (_result), ENOENT) );
+
+struct local_rules_definition {
+    struct dict_avp_request avp_vendor_plus_name;
+    enum rule_position	position;
+    int 			min;
+    int			max;
+};
+
+#define RULE_ORDER( _position ) ((((_position) == RULE_FIXED_HEAD) || ((_position) == RULE_FIXED_TAIL)) ? 1 : 0 )
+
+/* Attention! This version of the macro uses AVP_BY_NAME_AND_VENDOR, in contrast to most other copies! */
+#define PARSE_loc_rules( _rulearray, _parent) {                                                         \
+        int __ar;                                                                                       \
+        for (__ar=0; __ar < sizeof(_rulearray) / sizeof((_rulearray)[0]); __ar++) {                     \
+                struct dict_rule_data __data = { NULL,                                                  \
+                        (_rulearray)[__ar].position,                                                    \
+                        0,                                                                              \
+                        (_rulearray)[__ar].min,                                                         \
+                        (_rulearray)[__ar].max};                                                        \
+                __data.rule_order = RULE_ORDER(__data.rule_position);                                   \
+                CHECK_FCT(  fd_dict_search(                                                             \
+                        fd_g_config->cnf_dict,                                                          \
+                        DICT_AVP,                                                                       \
+                        AVP_BY_NAME_AND_VENDOR,                                                         \
+                        &(_rulearray)[__ar].avp_vendor_plus_name,                                       \
+                        &__data.rule_avp, 0 ) );                                                        \
+                if ( !__data.rule_avp ) {                                                               \
+                        TRACE_DEBUG(INFO, "AVP Not found: '%s'", (_rulearray)[__ar].avp_vendor_plus_name.avp_name);             \
+                        return ENOENT;                                                                  \
+                }                                                                                       \
+                {                                                                                       \
+                         int _ret = fd_dict_new( fd_g_config->cnf_dict, DICT_RULE, &(__data), (_parent), NULL ); \
+                         if ( _ret != 0 && _ret != EEXIST )      {                                      \
+                                TRACE_DEBUG(INFO, "Error on rule with AVP '%s'",                        \
+                                            (_rulearray)[__ar].avp_vendor_plus_name.avp_name);          \
+                                return EINVAL;                                                          \
+                         }                                                                              \
+                }                                                                                       \
+        }                                                                                               \
+}
+
+#define CHECK_vendor_new( _data ) { \
+        struct dict_object * vendor_found; \
+        if (fd_dict_search(fd_g_config->cnf_dict,DICT_VENDOR,VENDOR_BY_ID,&_data.vendor_id,&vendor_found,ENOENT) == ENOENT) { \
+                CHECK_FCT(fd_dict_new(fd_g_config->cnf_dict, DICT_VENDOR, &_data, NULL, NULL)); \
+        } \
+}
+
+#define enumval_def_u32( _val_, _str_ )		\
+    { _str_, 		{ .u32 = _val_ }}
+
+#define enumval_def_os( _len_, _val_, _str_ )				\
+    { _str_, 		{ .os = { .data = (unsigned char *)_val_, .len = _len_ }}}
+
+
+static int dict_ts29272_avps_load_defs(char * conffile)
+{
+   TRACE_ENTRY("%p", conffile);
+	/* Application Section */
+	{
+		/* Create the vendors */		{
+			struct dict_vendor_data vendor_data = { 10415, "3GPP" };
+			CHECK_dict_new(DICT_VENDOR, &vendor_data, NULL, NULL)
+		}
+	}
+
+
+   /* AVP section */
+   {
+		struct dict_object * Address_type;
+		struct dict_object * UTF8String_type;
+		struct dict_object * DiameterIdentity_type;
+		struct dict_object * DiameterURI_type;
+		struct dict_object * Time_type;
+		struct dict_object * IPFilterRule_type;
+
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "Address", &Address_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "UTF8String", &UTF8String_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "DiameterIdentity", &DiameterIdentity_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "DiameterURI", &DiameterURI_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "Time", &Time_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "IPFilterRule", &IPFilterRule_type);
+		/* IMEI */
+		{
+			struct dict_avp_data data = {
+				1402,	/* Code */
+				10415,	/* Vendor */
+				"IMEI",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, UTF8String_type, NULL);
+		};
+		/* Software-Version */
+		{
+			struct dict_avp_data data = {
+				1403,	/* Code */
+				10415,	/* Vendor */
+				"Software-Version",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, UTF8String_type, NULL);
+		};
+		/* QoS-Subscribed */
+		{
+			struct dict_avp_data data = {
+				1404,	/* Code */
+				10415,	/* Vendor */
+				"QoS-Subscribed",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* ULR-Flags */
+		{
+			struct dict_avp_data data = {
+				1405,	/* Code */
+				10415,	/* Vendor */
+				"ULR-Flags",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* ULA-Flags */
+		{
+			struct dict_avp_data data = {
+				1406,	/* Code */
+				10415,	/* Vendor */
+				"ULA-Flags",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Visited-PLMN-Id */
+		{
+			struct dict_avp_data data = {
+				1407,	/* Code */
+				10415,	/* Vendor */
+				"Visited-PLMN-Id",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Number-Of-Requested-Vectors */
+		{
+			struct dict_avp_data data = {
+				1410,	/* Code */
+				10415,	/* Vendor */
+				"Number-Of-Requested-Vectors",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Re-Synchronization-Info */
+		{
+			struct dict_avp_data data = {
+				1411,	/* Code */
+				10415,	/* Vendor */
+				"Re-Synchronization-Info",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Immediate-Response-Preferred */
+		{
+			struct dict_avp_data data = {
+				1412,	/* Code */
+				10415,	/* Vendor */
+				"Immediate-Response-Preferred",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Network-Access-Mode */
+		{
+			struct dict_avp_data data = {
+				1417,	/* Code */
+				10415,	/* Vendor */
+				"Network-Access-Mode",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Network-Access-Mode)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "PACKET_AND_CIRCUIT", { .i32=0 }};
+			struct dict_enumval_data        t_2 = { "Reserved", { .i32=1 }};
+			struct dict_enumval_data        t_3 = { "ONLY_PACKET", { .i32=2 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_3, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* HPLMN-ODB */
+		{
+			struct dict_avp_data data = {
+				1418,	/* Code */
+				10415,	/* Vendor */
+				"HPLMN-ODB",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Item-Number */
+		{
+			struct dict_avp_data data = {
+				1419,	/* Code */
+				10415,	/* Vendor */
+				"Item-Number",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Cancellation-Type */
+		{
+			struct dict_avp_data data = {
+				1420,	/* Code */
+				10415,	/* Vendor */
+				"Cancellation-Type",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Cancellation-Type)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "MME_UPDATE_PROCEDURE", { .i32=0 }};
+			struct dict_enumval_data        t_2 = { "SGSN_UPDATE_PROCEDURE", { .i32=1 }};
+			struct dict_enumval_data        t_3 = { "SUBSCRIPTION_WITHDRAWAL", { .i32=2 }};
+			struct dict_enumval_data        t_4 = { "UPDATE_PROCEDURE_IWF", { .i32=3 }};
+			struct dict_enumval_data        t_5 = { "INITIAL_ATTACH_PROCEDURE", { .i32=4 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_3, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_4, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_5, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* DSR-Flags */
+		{
+			struct dict_avp_data data = {
+				1421,	/* Code */
+				10415,	/* Vendor */
+				"DSR-Flags",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* DSA-Flags */
+		{
+			struct dict_avp_data data = {
+				1422,	/* Code */
+				10415,	/* Vendor */
+				"DSA-Flags",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Context-Identifier */
+		{
+			struct dict_avp_data data = {
+				1423,	/* Code */
+				10415,	/* Vendor */
+				"Context-Identifier",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Subscriber-Status */
+		{
+			struct dict_avp_data data = {
+				1424,	/* Code */
+				10415,	/* Vendor */
+				"Subscriber-Status",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Subscriber-Status)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "SERVICE_GRANTED", { .i32=0 }};
+			struct dict_enumval_data        t_2 = { "OPERATOR_DETERMINED_BARRING", { .i32=1 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* Operator-Determined-Barring */
+		{
+			struct dict_avp_data data = {
+				1425,	/* Code */
+				10415,	/* Vendor */
+				"Operator-Determined-Barring",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Access-Restriction-Data */
+		{
+			struct dict_avp_data data = {
+				1426,	/* Code */
+				10415,	/* Vendor */
+				"Access-Restriction-Data",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* APN-OI-Replacement */
+		{
+			struct dict_avp_data data = {
+				1427,	/* Code */
+				10415,	/* Vendor */
+				"APN-OI-Replacement",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, UTF8String_type, NULL);
+		};
+		/* All-APN-Configurations-Included-Indicator */
+		{
+			struct dict_avp_data data = {
+				1428,	/* Code */
+				10415,	/* Vendor */
+				"All-APN-Configurations-Included-Indicator",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(All-APN-Configurations-Included-Indicator)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "All_APN_CONFIGURATIONS_INCLUDED", { .i32=0 }};
+			struct dict_enumval_data        t_2 = { "MODIFIED_ADDED_APN_CONFIGURATIONS_INCLUDED", { .i32=1 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* VPLMN-Dynamic-Address-Allowed */
+		{
+			struct dict_avp_data data = {
+				1432,	/* Code */
+				10415,	/* Vendor */
+				"VPLMN-Dynamic-Address-Allowed",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(VPLMN-Dynamic-Address-Allowed)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "NOTALLOWED", { .i32=0 }};
+			struct dict_enumval_data        t_2 = { "ALLOWED", { .i32=1 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* STN-SR */
+		{
+			struct dict_avp_data data = {
+				1433,	/* Code */
+				10415,	/* Vendor */
+				"STN-SR",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Alert-Reason */
+		{
+			struct dict_avp_data data = {
+				1434,	/* Code */
+				10415,	/* Vendor */
+				"Alert-Reason",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Alert-Reason)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "UE_PRESENT", { .i32=0 }};
+			struct dict_enumval_data        t_2 = { "UE_MEMORY_AVAILABLE", { .i32=1 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* CSG-Id */
+		{
+			struct dict_avp_data data = {
+				1437,	/* Code */
+				10415,	/* Vendor */
+				"CSG-Id",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* PDN-GW-Allocation-Type */
+		{
+			struct dict_avp_data data = {
+				1438,	/* Code */
+				10415,	/* Vendor */
+				"PDN-GW-Allocation-Type",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(PDN-GW-Allocation-Type)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "STATIC", { .i32=0 }};
+			struct dict_enumval_data        t_2 = { "DYNAMIC", { .i32=1 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* Expiration-Date */
+		{
+			struct dict_avp_data data = {
+				1439,	/* Code */
+				10415,	/* Vendor */
+				"Expiration-Date",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, Time_type, NULL);
+		};
+		/* RAT-Frequency-Selection-Priority-ID */
+		{
+			struct dict_avp_data data = {
+				1440,	/* Code */
+				10415,	/* Vendor */
+				"RAT-Frequency-Selection-Priority-ID",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* IDA-Flags */
+		{
+			struct dict_avp_data data = {
+				1441,	/* Code */
+				10415,	/* Vendor */
+				"IDA-Flags",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* PUA-Flags */
+		{
+			struct dict_avp_data data = {
+				1442,	/* Code */
+				10415,	/* Vendor */
+				"PUA-Flags",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* NOR-Flags */
+		{
+			struct dict_avp_data data = {
+				1443,	/* Code */
+				10415,	/* Vendor */
+				"NOR-Flags",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* User-Id */
+		{
+			struct dict_avp_data data = {
+				1444,	/* Code */
+				10415,	/* Vendor */
+				"User-Id",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, UTF8String_type, NULL);
+		};
+		/* Equipment-Status */
+		{
+			struct dict_avp_data data = {
+				1445,	/* Code */
+				10415,	/* Vendor */
+				"Equipment-Status",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Equipment-Status)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "WHITELISTED", { .i32=0 }};
+			struct dict_enumval_data        t_2 = { "BLACKLISTED", { .i32=1 }};
+			struct dict_enumval_data        t_3 = { "GREYLISTED", { .i32=2 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_3, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* Regional-Subscription-Zone-Code */
+		{
+			struct dict_avp_data data = {
+				1446,	/* Code */
+				10415,	/* Vendor */
+				"Regional-Subscription-Zone-Code",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* RAND */
+		{
+			struct dict_avp_data data = {
+				1447,	/* Code */
+				10415,	/* Vendor */
+				"RAND",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* XRES */
+		{
+			struct dict_avp_data data = {
+				1448,	/* Code */
+				10415,	/* Vendor */
+				"XRES",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* AUTN */
+		{
+			struct dict_avp_data data = {
+				1449,	/* Code */
+				10415,	/* Vendor */
+				"AUTN",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* KASME */
+		{
+			struct dict_avp_data data = {
+				1450,	/* Code */
+				10415,	/* Vendor */
+				"KASME",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Trace-Collection-Entity */
+		{
+			struct dict_avp_data data = {
+				1452,	/* Code */
+				10415,	/* Vendor */
+				"Trace-Collection-Entity",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, Address_type, NULL);
+		};
+		/* Kc */
+		{
+			struct dict_avp_data data = {
+				1453,	/* Code */
+				10415,	/* Vendor */
+				"Kc",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* SRES */
+		{
+			struct dict_avp_data data = {
+				1454,	/* Code */
+				10415,	/* Vendor */
+				"SRES",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* PDN-Type */
+		{
+			struct dict_avp_data data = {
+				1456,	/* Code */
+				10415,	/* Vendor */
+				"PDN-Type",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(PDN-Type)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "IPv4", { .i32=0 }};
+			struct dict_enumval_data        t_2 = { "IPv6", { .i32=1 }};
+			struct dict_enumval_data        t_3 = { "IPv4v6", { .i32=2 }};
+			struct dict_enumval_data        t_4 = { "IPv4_OR_IPv6", { .i32=3 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_3, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_4, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* Roaming-Restricted-Due-To-Unsupported-Feature */
+		{
+			struct dict_avp_data data = {
+				1457,	/* Code */
+				10415,	/* Vendor */
+				"Roaming-Restricted-Due-To-Unsupported-Feature",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Roaming-Restricted-Due-To-Unsupported-Feature)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "Roaming_Restricted_Due_To_Unsupported_Feature", { .i32=0 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* Trace-Reference */
+		{
+			struct dict_avp_data data = {
+				1459,	/* Code */
+				10415,	/* Vendor */
+				"Trace-Reference",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Trace-Depth */
+		{
+			struct dict_avp_data data = {
+				1462,	/* Code */
+				10415,	/* Vendor */
+				"Trace-Depth",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Trace-Depth)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "GPRS_Subscription_Data", { .i32=72 }};
+			struct dict_enumval_data        t_2 = { "Complete_Data_List_Included_Indicator", { .i32=73 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* Trace-NE-Type-List */
+		{
+			struct dict_avp_data data = {
+				1463,	/* Code */
+				10415,	/* Vendor */
+				"Trace-NE-Type-List",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Trace-Interface-List */
+		{
+			struct dict_avp_data data = {
+				1464,	/* Code */
+				10415,	/* Vendor */
+				"Trace-Interface-List",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Trace-Event-List */
+		{
+			struct dict_avp_data data = {
+				1465,	/* Code */
+				10415,	/* Vendor */
+				"Trace-Event-List",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* OMC-Id */
+		{
+			struct dict_avp_data data = {
+				1466,	/* Code */
+				10415,	/* Vendor */
+				"OMC-Id",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Complete-Data-List-Included-Indicator */
+		{
+			struct dict_avp_data data = {
+				1468,	/* Code */
+				10415,	/* Vendor */
+				"Complete-Data-List-Included-Indicator",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Complete-Data-List-Included-Indicator)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "All_PDP_CONTEXTS_INCLUDED", { .i32=0 }};
+			struct dict_enumval_data        t_2 = { "CONTEXTS_INCLUDED", { .i32=1 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* PDP-Type */
+		{
+			struct dict_avp_data data = {
+				1470,	/* Code */
+				10415,	/* Vendor */
+				"PDP-Type",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* 3GPP2-MEID */
+		{
+			struct dict_avp_data data = {
+				1471,	/* Code */
+				10415,	/* Vendor */
+				"3GPP2-MEID",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* GMLC-Number */
+		{
+			struct dict_avp_data data = {
+				1474,	/* Code */
+				10415,	/* Vendor */
+				"GMLC-Number",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* SS-Code */
+		{
+			struct dict_avp_data data = {
+				1476,	/* Code */
+				10415,	/* Vendor */
+				"SS-Code",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* SS-Status */
+		{
+			struct dict_avp_data data = {
+				1477,	/* Code */
+				10415,	/* Vendor */
+				"SS-Status",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Notification-To-UE-User */
+		{
+			struct dict_avp_data data = {
+				1478,	/* Code */
+				10415,	/* Vendor */
+				"Notification-To-UE-User",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Notification-To-UE-User)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "NOTIFY_LOCATION_ALLOWED", { .i32=0 }};
+			struct dict_enumval_data        t_2 = { "NOTIFYANDVERIFY_LOCATION_ALLOWED_IF_NO_RESPONSE", { .i32=1 }};
+			struct dict_enumval_data        t_3 = { "NOTIFYANDVERIFY_LOCATION_NOT_ALLOWED_IF_NO_RESPONSE", { .i32=2 }};
+			struct dict_enumval_data        t_4 = { "LOCATION_NOT_ALLOWED", { .i32=3 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_3, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_4, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* Client-Identity */
+		{
+			struct dict_avp_data data = {
+				1480,	/* Code */
+				10415,	/* Vendor */
+				"Client-Identity",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* GMLC-Restriction */
+		{
+			struct dict_avp_data data = {
+				1481,	/* Code */
+				10415,	/* Vendor */
+				"GMLC-Restriction",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(GMLC-Restriction)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "GMLC_LIST", { .i32=0 }};
+			struct dict_enumval_data        t_2 = { "HOME_COUNTRY", { .i32=1 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* PLMN-Client */
+		{
+			struct dict_avp_data data = {
+				1482,	/* Code */
+				10415,	/* Vendor */
+				"PLMN-Client",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(PLMN-Client)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "BROADCAST_SERVICE", { .i32=0 }};
+			struct dict_enumval_data        t_2 = { "O_AND_M_HPLMN", { .i32=1 }};
+			struct dict_enumval_data        t_3 = { "O_AND_M_VPLMN", { .i32=2 }};
+			struct dict_enumval_data        t_4 = { "ANONYMOUS_LOCATION", { .i32=3 }};
+			struct dict_enumval_data        t_5 = { "TARGET_UE_SUBSCRIBED_SERVICE", { .i32=4 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_3, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_4, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_5, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* ServiceTypeIdentity */
+		{
+			struct dict_avp_data data = {
+				1484,	/* Code */
+				10415,	/* Vendor */
+				"ServiceTypeIdentity",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* TS-Code */
+		{
+			struct dict_avp_data data = {
+				1487,	/* Code */
+				10415,	/* Vendor */
+				"TS-Code",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* SGSN-Number */
+		{
+			struct dict_avp_data data = {
+				1489,	/* Code */
+				10415,	/* Vendor */
+				"SGSN-Number",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* IDR-Flags */
+		{
+			struct dict_avp_data data = {
+				1490,	/* Code */
+				10415,	/* Vendor */
+				"IDR-Flags",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* ICS-Indicator */
+		{
+			struct dict_avp_data data = {
+				1491,	/* Code */
+				10415,	/* Vendor */
+				"ICS-Indicator",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(ICS-Indicator)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "FALSE", { .i32=0 }};
+			struct dict_enumval_data        t_2 = { "TRUE", { .i32=1 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* IMS-Voice-Over-PS-Sessions-Supported */
+		{
+			struct dict_avp_data data = {
+				1492,	/* Code */
+				10415,	/* Vendor */
+				"IMS-Voice-Over-PS-Sessions-Supported",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(IMS-Voice-Over-PS-Sessions-Supported)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "NOT_SUPPORTED", { .i32=0 }};
+			struct dict_enumval_data        t_2 = { "SUPPORTED", { .i32=1 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* Homogeneous-Support-of-IMS-Voice-Over-PS-Sessions */
+		{
+			struct dict_avp_data data = {
+				1493,	/* Code */
+				10415,	/* Vendor */
+				"Homogeneous-Support-of-IMS-Voice-Over-PS-Sessions",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Homogeneous-Support-of-IMS-Voice-Over-PS-Sessions)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "NOT_SUPPORTED", { .i32=0 }};
+			struct dict_enumval_data        t_2 = { "SUPPORTED", { .i32=1 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* Last-UE-Activity-Time */
+		{
+			struct dict_avp_data data = {
+				1494,	/* Code */
+				10415,	/* Vendor */
+				"Last-UE-Activity-Time",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, Time_type, NULL);
+		};
+		/* User-State */
+		{
+			struct dict_avp_data data = {
+				1499,	/* Code */
+				10415,	/* Vendor */
+				"User-State",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(User-State)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "DETACHED", { .i32=0 }};
+			struct dict_enumval_data        t_2 = { "ATTACHED_NOT_REACHABLE_FOR_PAGING", { .i32=1 }};
+			struct dict_enumval_data        t_3 = { "ATTACHED_REACHABLE_FOR_PAGING", { .i32=2 }};
+			struct dict_enumval_data        t_4 = { "CONNECTED_NOT_REACHABLE_FOR_PAGING", { .i32=3 }};
+			struct dict_enumval_data        t_5 = { "CONNECTED_REACHABLE_FOR_PAGING", { .i32=4 }};
+			struct dict_enumval_data        t_6 = { "RESERVED", { .i32=5 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_3, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_4, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_5, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_6, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* E-UTRAN-Cell-Global-Identity */
+		{
+			struct dict_avp_data data = {
+				1602,	/* Code */
+				10415,	/* Vendor */
+				"E-UTRAN-Cell-Global-Identity",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Tracking-Area-Identity */
+		{
+			struct dict_avp_data data = {
+				1603,	/* Code */
+				10415,	/* Vendor */
+				"Tracking-Area-Identity",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Cell-Global-Identity */
+		{
+			struct dict_avp_data data = {
+				1604,	/* Code */
+				10415,	/* Vendor */
+				"Cell-Global-Identity",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Routing-Area-Identity */
+		{
+			struct dict_avp_data data = {
+				1605,	/* Code */
+				10415,	/* Vendor */
+				"Routing-Area-Identity",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Location-Area-Identity */
+		{
+			struct dict_avp_data data = {
+				1606,	/* Code */
+				10415,	/* Vendor */
+				"Location-Area-Identity",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Service-Area-Identity */
+		{
+			struct dict_avp_data data = {
+				1607,	/* Code */
+				10415,	/* Vendor */
+				"Service-Area-Identity",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Geographical-Information */
+		{
+			struct dict_avp_data data = {
+				1608,	/* Code */
+				10415,	/* Vendor */
+				"Geographical-Information",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Geodetic-Information */
+		{
+			struct dict_avp_data data = {
+				1609,	/* Code */
+				10415,	/* Vendor */
+				"Geodetic-Information",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Current-Location-Retrieved */
+		{
+			struct dict_avp_data data = {
+				1610,	/* Code */
+				10415,	/* Vendor */
+				"Current-Location-Retrieved",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Current-Location-Retrieved)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "ACTIVE_LOCATION_RETRIEVAL", { .i32=0 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* Age-Of-Location-Information */
+		{
+			struct dict_avp_data data = {
+				1611,	/* Code */
+				10415,	/* Vendor */
+				"Age-Of-Location-Information",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Error-Diagnostic */
+		{
+			struct dict_avp_data data = {
+				1614,	/* Code */
+				10415,	/* Vendor */
+				"Error-Diagnostic",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Error-Diagnostic)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "GPRS_DATA_SUBSCRIBED", { .i32=0 }};
+			struct dict_enumval_data        t_2 = { "NO_GPRS_DATA_SUBSCRIBED", { .i32=1 }};
+			struct dict_enumval_data        t_3 = { "ODB_ALL_APN", { .i32=2 }};
+			struct dict_enumval_data        t_4 = { "ODB_HPLMN_APN", { .i32=3 }};
+			struct dict_enumval_data        t_5 = { "ODB_VPLMN_APN", { .i32=4 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_3, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_4, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_5, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* Ext-PDP-Address */
+		{
+			struct dict_avp_data data = {
+				1621,	/* Code */
+				10415,	/* Vendor */
+				"Ext-PDP-Address",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, Address_type, NULL);
+		};
+		/* UE-SRVCC-Capability */
+		{
+			struct dict_avp_data data = {
+				1615,	/* Code */
+				10415,	/* Vendor */
+				"UE-SRVCC-Capability",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(UE-SRVCC-Capability)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "UE_SRVCC_NOT_SUPPORTED", { .i32=0 }};
+			struct dict_enumval_data        t_2 = { "UE_SRVCC_SUPPORTED", { .i32=1 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* MPS-Priority */
+		{
+			struct dict_avp_data data = {
+				1616,	/* Code */
+				10415,	/* Vendor */
+				"MPS-Priority",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* VPLMN-LIPA-Allowed */
+		{
+			struct dict_avp_data data = {
+				1617,	/* Code */
+				10415,	/* Vendor */
+				"VPLMN-LIPA-Allowed",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(VPLMN-LIPA-Allowed)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "LIPA_NOTALLOWED", { .i32=0 }};
+			struct dict_enumval_data        t_2 = { "LIPA_ALLOWED", { .i32=1 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* LIPA-Permission */
+		{
+			struct dict_avp_data data = {
+				1618,	/* Code */
+				10415,	/* Vendor */
+				"LIPA-Permission",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(LIPA-Permission)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "LIPA_PROHIBITED", { .i32=0 }};
+			struct dict_enumval_data        t_2 = { "LIPA_ONLY", { .i32=1 }};
+			struct dict_enumval_data        t_3 = { "LIPA_CONDITIONAL", { .i32=2 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_3, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* Subscribed-Periodic-RAU-TAU-Timer */
+		{
+			struct dict_avp_data data = {
+				1619,	/* Code */
+				10415,	/* Vendor */
+				"Subscribed-Periodic-RAU-TAU-Timer",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Ext-PDP-Type */
+		{
+			struct dict_avp_data data = {
+				1620,	/* Code */
+				10415,	/* Vendor */
+				"Ext-PDP-Type",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* SIPTO-Permission */
+		{
+			struct dict_avp_data data = {
+				1613,	/* Code */
+				10415,	/* Vendor */
+				"SIPTO-Permission",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(SIPTO-Permission)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "ALLOWED", { .i32=0 }};
+			struct dict_enumval_data        t_2 = { "NOTALLOWED", { .i32=1 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* Job-Type */
+		{
+			struct dict_avp_data data = {
+				1623,	/* Code */
+				10415,	/* Vendor */
+				"Job-Type",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Job-Type)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "Area_Scope", { .i32=138 }};
+			struct dict_enumval_data        t_2 = { "List_Of_Measurements", { .i32=139 }};
+			struct dict_enumval_data        t_3 = { "Reporting_Trigger", { .i32=140 }};
+			struct dict_enumval_data        t_4 = { "Report_Interval", { .i32=141 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_3, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_4, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* List-Of-Measurements */
+		{
+			struct dict_avp_data data = {
+				1625,	/* Code */
+				10415,	/* Vendor */
+				"List-Of-Measurements",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Reporting-Trigger */
+		{
+			struct dict_avp_data data = {
+				1626,	/* Code */
+				10415,	/* Vendor */
+				"Reporting-Trigger",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Report-Interval */
+		{
+			struct dict_avp_data data = {
+				1627,	/* Code */
+				10415,	/* Vendor */
+				"Report-Interval",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Report-Interval)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "Report_Amount", { .i32=142 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* Report-Amount */
+		{
+			struct dict_avp_data data = {
+				1628,	/* Code */
+				10415,	/* Vendor */
+				"Report-Amount",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Report-Amount)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "Event_Threshold_RSRP", { .i32=143 }};
+			struct dict_enumval_data        t_2 = { "Event_Threshold_RSRQ", { .i32=144 }};
+			struct dict_enumval_data        t_3 = { "Logging_Interval", { .i32=145 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_3, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* Event-Threshold-RSRP */
+		{
+			struct dict_avp_data data = {
+				1629,	/* Code */
+				10415,	/* Vendor */
+				"Event-Threshold-RSRP",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Event-Threshold-RSRQ */
+		{
+			struct dict_avp_data data = {
+				1630,	/* Code */
+				10415,	/* Vendor */
+				"Event-Threshold-RSRQ",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Logging-Interval */
+		{
+			struct dict_avp_data data = {
+				1631,	/* Code */
+				10415,	/* Vendor */
+				"Logging-Interval",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Logging-Interval)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "Logging_Duration", { .i32=146 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* Logging-Duration */
+		{
+			struct dict_avp_data data = {
+				1632,	/* Code */
+				10415,	/* Vendor */
+				"Logging-Duration",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Logging-Duration)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "Relay_Node_Indicator", { .i32=147 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* Relay-Node-Indicator */
+		{
+			struct dict_avp_data data = {
+				1633,	/* Code */
+				10415,	/* Vendor */
+				"Relay-Node-Indicator",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Relay-Node-Indicator)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "NOT_RELAY_NODE", { .i32=0 }};
+			struct dict_enumval_data        t_2 = { "RELAY_NODE", { .i32=1 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* MDT-User-Consent */
+		{
+			struct dict_avp_data data = {
+				1634,	/* Code */
+				10415,	/* Vendor */
+				"MDT-User-Consent",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(MDT-User-Consent)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "CONSENT_NOT_GIVEN", { .i32=0 }};
+			struct dict_enumval_data        t_2 = { "CONSENT_GIVEN", { .i32=1 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* PUR-Flags */
+		{
+			struct dict_avp_data data = {
+				1635,	/* Code */
+				10415,	/* Vendor */
+				"PUR-Flags",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Subscribed-VSRVCC */
+		{
+			struct dict_avp_data data = {
+				1636,	/* Code */
+				10415,	/* Vendor */
+				"Subscribed-VSRVCC",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Subscribed-VSRVCC)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "VSRVCC_SUBSCRIBED", { .i32=0 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* CLR-Flags */
+		{
+			struct dict_avp_data data = {
+				1638,	/* Code */
+				10415,	/* Vendor */
+				"CLR-Flags",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* UVR-Flags */
+		{
+			struct dict_avp_data data = {
+				1639,	/* Code */
+				10415,	/* Vendor */
+				"UVR-Flags",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* UVA-Flags */
+		{
+			struct dict_avp_data data = {
+				1640,	/* Code */
+				10415,	/* Vendor */
+				"UVA-Flags",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Time-Zone */
+		{
+			struct dict_avp_data data = {
+				1642,	/* Code */
+				10415,	/* Vendor */
+				"Time-Zone",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, UTF8String_type, NULL);
+		};
+		/* A-MSISDN */
+		{
+			struct dict_avp_data data = {
+				1643,	/* Code */
+				10415,	/* Vendor */
+				"A-MSISDN",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* MME-Number-for-MT-SMS */
+		{
+			struct dict_avp_data data = {
+				1645,	/* Code */
+				10415,	/* Vendor */
+				"MME-Number-for-MT-SMS",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* SMS-Register-Request */
+		{
+			struct dict_avp_data data = {
+				1648,	/* Code */
+				10415,	/* Vendor */
+				"SMS-Register-Request",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(SMS-Register-Request)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "SMS_REGISTRATION_REQUIRED", { .i32=0 }};
+			struct dict_enumval_data        t_2 = { "SMS_REGISTRATION_NOT_PREFERRED", { .i32=1 }};
+			struct dict_enumval_data        t_3 = { "NO_PREFERENCE", { .i32=2 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_3, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* Daylight-Saving-Time */
+		{
+			struct dict_avp_data data = {
+				1650,	/* Code */
+				10415,	/* Vendor */
+				"Daylight-Saving-Time",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Daylight-Saving-Time)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "NO_ADJUSTMENT", { .i32=0 }};
+			struct dict_enumval_data        t_2 = { "PLUS_ONE_HOUR_ADJUSTMENT", { .i32=1 }};
+			struct dict_enumval_data        t_3 = { "PLUS_TWO_HOURS_ADJUSTMENT", { .i32=2 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_3, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* Subscription-Data-Flags */
+		{
+			struct dict_avp_data data = {
+				1654,	/* Code */
+				10415,	/* Vendor */
+				"Subscription-Data-Flags",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Measurement-Period-LTE */
+		{
+			struct dict_avp_data data = {
+				1655,	/* Code */
+				10415,	/* Vendor */
+				"Measurement-Period-LTE",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Measurement-Period-LTE)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "Measurement_Period_UMTS", { .i32=167 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* Measurement-Period-UMTS */
+		{
+			struct dict_avp_data data = {
+				1656,	/* Code */
+				10415,	/* Vendor */
+				"Measurement-Period-UMTS",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Measurement-Period-UMTS)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "Collection_Period_RRM_LTE", { .i32=168 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* Collection-Period-RRM-LTE */
+		{
+			struct dict_avp_data data = {
+				1657,	/* Code */
+				10415,	/* Vendor */
+				"Collection-Period-RRM-LTE",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Collection-Period-RRM-LTE)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "Collection_Period_RRM_UMTS", { .i32=169 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* Collection-Period-RRM-UMTS */
+		{
+			struct dict_avp_data data = {
+				1658,	/* Code */
+				10415,	/* Vendor */
+				"Collection-Period-RRM-UMTS",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Collection-Period-RRM-UMTS)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "Positioning_Method", { .i32=170 }};
+			struct dict_enumval_data        t_2 = { "Measurement_Quantity", { .i32=171 }};
+			struct dict_enumval_data        t_3 = { "Event_Threshold_Event_1F", { .i32=172 }};
+			struct dict_enumval_data        t_4 = { "Event_Threshold_Event_1I", { .i32=173 }};
+			struct dict_enumval_data        t_5 = { "Restoration_Priority", { .i32=174 }};
+			struct dict_enumval_data        t_6 = { "SGs_MME_Identity", { .i32=175 }};
+			struct dict_enumval_data        t_7 = { "SIPTO_Local_Network_Permission", { .i32=176 }};
+			struct dict_enumval_data        t_8 = { "Coupled_Node_Diameter_ID", { .i32=177 }};
+			struct dict_enumval_data        t_9 = { "OC_Supported_Features", { .i32=178 }};
+			struct dict_enumval_data        t_10 = { "OC_OLR", { .i32=179 }};
+			struct dict_enumval_data        t_11 = { "ProSe_Subscription_Data", { .i32=180 }};
+			struct dict_enumval_data        t_12 = { "WLAN_offloadability", { .i32=181 }};
+			struct dict_enumval_data        t_13 = { "WLAN_offloadability_EUTRAN", { .i32=182 }};
+			struct dict_enumval_data        t_14 = { "WLAN_offloadability_UTRAN", { .i32=183 }};
+			struct dict_enumval_data        t_15 = { "Reset_ID", { .i32=184 }};
+			struct dict_enumval_data        t_16 = { "MDT_Allowed_PLMN_Id", { .i32=185 }};
+			struct dict_enumval_data        t_17 = { "Adjacent_PLMNs", { .i32=186 }};
+			struct dict_enumval_data        t_18 = { "Adjacent_Access_Restriction_Data", { .i32=187 }};
+			struct dict_enumval_data        t_19 = { "DL_Buffering_Suggested_Packet_Count", { .i32=188 }};
+			struct dict_enumval_data        t_20 = { "IMSI_Group_Id", { .i32=189 }};
+			struct dict_enumval_data        t_21 = { "Group_Service_Id", { .i32=190 }};
+			struct dict_enumval_data        t_22 = { "Group_PLMN_Id", { .i32=191 }};
+			struct dict_enumval_data        t_23 = { "Local_Group_Id", { .i32=192 }};
+			struct dict_enumval_data        t_24 = { "AESE_Communication_Pattern", { .i32=193 }};
+			struct dict_enumval_data        t_25 = { "Communication_Pattern_Set", { .i32=194 }};
+			struct dict_enumval_data        t_26 = { "Monitoring_Event_Configuration", { .i32=195 }};
+			struct dict_enumval_data        t_27 = { "Monitoring_Event_Report", { .i32=196 }};
+			struct dict_enumval_data        t_28 = { "UE_Reachability_Configuration", { .i32=197 }};
+			struct dict_enumval_data        t_29 = { "eNodeB_Id", { .i32=198 }};
+			struct dict_enumval_data        t_30 = { "Supported_Services", { .i32=199 }};
+			struct dict_enumval_data        t_31 = { "Supported_Monitoring_Events", { .i32=200 }};
+			struct dict_enumval_data        t_32 = { "AIR_Flags", { .i32=201 }};
+			struct dict_enumval_data        t_33 = { "UE_Usage_Type", { .i32=202 }};
+			struct dict_enumval_data        t_34 = { "DRMP", { .i32=203 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_3, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_4, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_5, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_6, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_7, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_8, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_9, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_10, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_11, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_12, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_13, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_14, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_15, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_16, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_17, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_18, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_19, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_20, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_21, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_22, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_23, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_24, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_25, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_26, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_27, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_28, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_29, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_30, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_31, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_32, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_33, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_34, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* Positioning-Method */
+		{
+			struct dict_avp_data data = {
+				1659,	/* Code */
+				10415,	/* Vendor */
+				"Positioning-Method",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Measurement-Quantity */
+		{
+			struct dict_avp_data data = {
+				1660,	/* Code */
+				10415,	/* Vendor */
+				"Measurement-Quantity",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Event-Threshold-Event-1F */
+		{
+			struct dict_avp_data data = {
+				1661,	/* Code */
+				10415,	/* Vendor */
+				"Event-Threshold-Event-1F",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Event-Threshold-Event-1I */
+		{
+			struct dict_avp_data data = {
+				1662,	/* Code */
+				10415,	/* Vendor */
+				"Event-Threshold-Event-1I",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Restoration-Priority */
+		{
+			struct dict_avp_data data = {
+				1663,	/* Code */
+				10415,	/* Vendor */
+				"Restoration-Priority",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* SGs-MME-Identity */
+		{
+			struct dict_avp_data data = {
+				1664,	/* Code */
+				10415,	/* Vendor */
+				"SGs-MME-Identity",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, UTF8String_type, NULL);
+		};
+		/* SIPTO-Local-Network-Permission */
+		{
+			struct dict_avp_data data = {
+				1665,	/* Code */
+				10415,	/* Vendor */
+				"SIPTO-Local-Network-Permission",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Coupled-Node-Diameter-ID */
+		{
+			struct dict_avp_data data = {
+				1666,	/* Code */
+				10415,	/* Vendor */
+				"Coupled-Node-Diameter-ID",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, DiameterIdentity_type, NULL);
+		};
+		/* WLAN-offloadability-EUTRAN */
+		{
+			struct dict_avp_data data = {
+				1668,	/* Code */
+				10415,	/* Vendor */
+				"WLAN-offloadability-EUTRAN",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* WLAN-offloadability-UTRAN */
+		{
+			struct dict_avp_data data = {
+				1669,	/* Code */
+				10415,	/* Vendor */
+				"WLAN-offloadability-UTRAN",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Reset-ID */
+		{
+			struct dict_avp_data data = {
+				1670,	/* Code */
+				10415,	/* Vendor */
+				"Reset-ID",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* MDT-Allowed-PLMN-Id */
+		{
+			struct dict_avp_data data = {
+				1671,	/* Code */
+				10415,	/* Vendor */
+				"MDT-Allowed-PLMN-Id",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* DL-Buffering-Suggested-Packet-Count */
+		{
+			struct dict_avp_data data = {
+				1674,	/* Code */
+				10415,	/* Vendor */
+				"DL-Buffering-Suggested-Packet-Count",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Group-Service-Id */
+		{
+			struct dict_avp_data data = {
+				1676,	/* Code */
+				10415,	/* Vendor */
+				"Group-Service-Id",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Group-PLMN-Id */
+		{
+			struct dict_avp_data data = {
+				1677,	/* Code */
+				10415,	/* Vendor */
+				"Group-PLMN-Id",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Local-Group-Id */
+		{
+			struct dict_avp_data data = {
+				1678,	/* Code */
+				10415,	/* Vendor */
+				"Local-Group-Id",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* AIR-Flags */
+		{
+			struct dict_avp_data data = {
+				1679,	/* Code */
+				10415,	/* Vendor */
+				"AIR-Flags",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* UE-Usage-Type */
+		{
+			struct dict_avp_data data = {
+				1680,	/* Code */
+				10415,	/* Vendor */
+				"UE-Usage-Type",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Non-IP-PDN-Type-Indicator */
+		{
+			struct dict_avp_data data = {
+				1681,	/* Code */
+				10415,	/* Vendor */
+				"Non-IP-PDN-Type-Indicator",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Non-IP-PDN-Type-Indicator)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "MAINTAIN_PDN_CONNECTION", { .i32=0 }};
+			struct dict_enumval_data        t_2 = { "DISCONNECT_PDN_CONNECTION_WITH_REACTIVATION_REQUEST", { .i32=1 }};
+			struct dict_enumval_data        t_3 = { "DISCONNECT_PDN_CONNECTION_WITHOUT_REACTIVATION_REQUEST", { .i32=2 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_3, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* Non-IP-Data-Delivery-Mechanism */
+		{
+			struct dict_avp_data data = {
+				1682,	/* Code */
+				10415,	/* Vendor */
+				"Non-IP-Data-Delivery-Mechanism",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Additional-Context-Identifier */
+		{
+			struct dict_avp_data data = {
+				1683,	/* Code */
+				10415,	/* Vendor */
+				"Additional-Context-Identifier",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* SCEF-Realm */
+		{
+			struct dict_avp_data data = {
+				1684,	/* Code */
+				10415,	/* Vendor */
+				"SCEF-Realm",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, DiameterIdentity_type, NULL);
+		};
+		/* Preferred-Data-Mode */
+		{
+			struct dict_avp_data data = {
+				1686,	/* Code */
+				10415,	/* Vendor */
+				"Preferred-Data-Mode",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* V2X-Permission */
+		{
+			struct dict_avp_data data = {
+				1689,	/* Code */
+				10415,	/* Vendor */
+				"V2X-Permission",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* PDN-Connection-Continuity */
+		{
+			struct dict_avp_data data = {
+				1690,	/* Code */
+				10415,	/* Vendor */
+				"PDN-Connection-Continuity",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* eDRX-Cycle-Length-Value */
+		{
+			struct dict_avp_data data = {
+				1692,	/* Code */
+				10415,	/* Vendor */
+				"eDRX-Cycle-Length-Value",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* UE-PC5-AMBR */
+		{
+			struct dict_avp_data data = {
+				1693,	/* Code */
+				10415,	/* Vendor */
+				"UE-PC5-AMBR",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* V2X-Subscription-Data */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				1688,	/* Code */
+				10415,	/* Vendor */
+				"V2X-Subscription-Data",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* E-UTRAN-Vector */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				1414,	/* Code */
+				10415,	/* Vendor */
+				"E-UTRAN-Vector",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* AMBR */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				1435,	/* Code */
+				10415,	/* Vendor */
+				"AMBR",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* Adjacent-Access-Restriction-Data */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				1673,	/* Code */
+				10415,	/* Vendor */
+				"Adjacent-Access-Restriction-Data",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* GERAN-Vector */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				1416,	/* Code */
+				10415,	/* Vendor */
+				"GERAN-Vector",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* eDRX-Cycle-Length */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				1691,	/* Code */
+				10415,	/* Vendor */
+				"eDRX-Cycle-Length",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* Area-Scope */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				1624,	/* Code */
+				10415,	/* Vendor */
+				"Area-Scope",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* Call-Barring-Info */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				1488,	/* Code */
+				10415,	/* Vendor */
+				"Call-Barring-Info",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* CSG-Subscription-Data */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				1436,	/* Code */
+				10415,	/* Vendor */
+				"CSG-Subscription-Data",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* VPLMN-CSG-Subscription-Data */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				1641,	/* Code */
+				10415,	/* Vendor */
+				"VPLMN-CSG-Subscription-Data",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* MO-LR */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				1485,	/* Code */
+				10415,	/* Vendor */
+				"MO-LR",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* WLAN-offloadability */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				1667,	/* Code */
+				10415,	/* Vendor */
+				"WLAN-offloadability",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* Equivalent-PLMN-List */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				1637,	/* Code */
+				10415,	/* Vendor */
+				"Equivalent-PLMN-List",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* UTRAN-Vector */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				1415,	/* Code */
+				10415,	/* Vendor */
+				"UTRAN-Vector",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* Local-Time-Zone */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				1649,	/* Code */
+				10415,	/* Vendor */
+				"Local-Time-Zone",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* IMSI-Group-Id */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				1675,	/* Code */
+				10415,	/* Vendor */
+				"IMSI-Group-Id",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* Terminal-Information */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				1401,	/* Code */
+				10415,	/* Vendor */
+				"Terminal-Information",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* Teleservice-List */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				1486,	/* Code */
+				10415,	/* Vendor */
+				"Teleservice-List",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* Service-Type */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				1483,	/* Code */
+				10415,	/* Vendor */
+				"Service-Type",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* Requested-UTRAN-GERAN-Authentication-Info */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				1409,	/* Code */
+				10415,	/* Vendor */
+				"Requested-UTRAN-GERAN-Authentication-Info",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* Subscription-Data-Deletion */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				1685,	/* Code */
+				10415,	/* Vendor */
+				"Subscription-Data-Deletion",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* MME-User-State */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				1497,	/* Code */
+				10415,	/* Vendor */
+				"MME-User-State",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* Requested-EUTRAN-Authentication-Info */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				1408,	/* Code */
+				10415,	/* Vendor */
+				"Requested-EUTRAN-Authentication-Info",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* Adjacent-PLMNs */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				1672,	/* Code */
+				10415,	/* Vendor */
+				"Adjacent-PLMNs",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* SGSN-User-State */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				1498,	/* Code */
+				10415,	/* Vendor */
+				"SGSN-User-State",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* External-Client */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				1479,	/* Code */
+				10415,	/* Vendor */
+				"External-Client",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* EPS-User-State */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				1495,	/* Code */
+				10415,	/* Vendor */
+				"EPS-User-State",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* SGSN-Location-Information */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				1601,	/* Code */
+				10415,	/* Vendor */
+				"SGSN-Location-Information",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* LCS-PrivacyException */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				1475,	/* Code */
+				10415,	/* Vendor */
+				"LCS-PrivacyException",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* EPS-Subscribed-QoS-Profile */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				1431,	/* Code */
+				10415,	/* Vendor */
+				"EPS-Subscribed-QoS-Profile",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* Authentication-Info */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				1413,	/* Code */
+				10415,	/* Vendor */
+				"Authentication-Info",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* Specific-APN-Info */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				1472,	/* Code */
+				10415,	/* Vendor */
+				"Specific-APN-Info",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* MDT-Configuration */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				1622,	/* Code */
+				10415,	/* Vendor */
+				"MDT-Configuration",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* MME-Location-Information */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				1600,	/* Code */
+				10415,	/* Vendor */
+				"MME-Location-Information",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* PDP-Context */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				1469,	/* Code */
+				10415,	/* Vendor */
+				"PDP-Context",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* Emergency-Info */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				1687,	/* Code */
+				10415,	/* Vendor */
+				"Emergency-Info",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* GPRS-Subscription-Data */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				1467,	/* Code */
+				10415,	/* Vendor */
+				"GPRS-Subscription-Data",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* APN-Configuration */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				1430,	/* Code */
+				10415,	/* Vendor */
+				"APN-Configuration",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* EPS-Location-Information */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				1496,	/* Code */
+				10415,	/* Vendor */
+				"EPS-Location-Information",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* Trace-Data */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				1458,	/* Code */
+				10415,	/* Vendor */
+				"Trace-Data",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* Active-APN */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				1612,	/* Code */
+				10415,	/* Vendor */
+				"Active-APN",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* LCS-Info */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				1473,	/* Code */
+				10415,	/* Vendor */
+				"LCS-Info",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* APN-Configuration-Profile */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				1429,	/* Code */
+				10415,	/* Vendor */
+				"APN-Configuration-Profile",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* Subscription-Data */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				1400,	/* Code */
+				10415,	/* Vendor */
+				"Subscription-Data",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+
+	
+   }
+
+   /* Commands section */
+   {
+
+   }
+
+   return 0;
+}
+
+static int dict_ts29272_avps_load_rules(char * conffile)
+{
+   /* Grouped AVP section */
+   {
+	  /* V2X-Subscription-Data */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "V2X-Subscription-Data"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 10415, .avp_name = "V2X-Permission"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "UE-PC5-AMBR"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* E-UTRAN-Vector */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "E-UTRAN-Vector"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 10415, .avp_name = "Item-Number"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "RAND"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "XRES"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "AUTN"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "KASME"}, RULE_REQUIRED, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* AMBR */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "AMBR"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 10415, .avp_name = "Max-Requested-Bandwidth-UL"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Max-Requested-Bandwidth-DL"}, RULE_REQUIRED, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* Adjacent-Access-Restriction-Data */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "Adjacent-Access-Restriction-Data"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 10415, .avp_name = "Visited-PLMN-Id"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Access-Restriction-Data"}, RULE_REQUIRED, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* GERAN-Vector */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "GERAN-Vector"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 10415, .avp_name = "Item-Number"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "RAND"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "SRES"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Kc"}, RULE_REQUIRED, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* eDRX-Cycle-Length */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "eDRX-Cycle-Length"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 10415, .avp_name = "RAT-Type"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "eDRX-Cycle-Length-Value"}, RULE_REQUIRED, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* Area-Scope */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "Area-Scope"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 10415, .avp_name = "Cell-Global-Identity"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "E-UTRAN-Cell-Global-Identity"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Routing-Area-Identity"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Location-Area-Identity"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Tracking-Area-Identity"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* Call-Barring-Info */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "Call-Barring-Info"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 10415, .avp_name = "SS-Code"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "SS-Status"}, RULE_REQUIRED, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* CSG-Subscription-Data */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "CSG-Subscription-Data"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 10415, .avp_name = "CSG-Id"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Expiration-Date"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Service-Selection"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Visited-PLMN-Id"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* VPLMN-CSG-Subscription-Data */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "VPLMN-CSG-Subscription-Data"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 10415, .avp_name = "CSG-Id"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Expiration-Date"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* MO-LR */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "MO-LR"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 10415, .avp_name = "SS-Code"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "SS-Status"}, RULE_REQUIRED, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* WLAN-offloadability */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "WLAN-offloadability"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 10415, .avp_name = "WLAN-offloadability-EUTRAN"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "WLAN-offloadability-UTRAN"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* Equivalent-PLMN-List */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "Equivalent-PLMN-List"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 10415, .avp_name = "Visited-PLMN-Id"}, RULE_REQUIRED, 1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* UTRAN-Vector */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "UTRAN-Vector"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 10415, .avp_name = "Item-Number"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "RAND"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "XRES"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "AUTN"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Confidentiality-Key"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Integrity-Key"}, RULE_REQUIRED, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* Local-Time-Zone */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "Local-Time-Zone"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 10415, .avp_name = "Time-Zone"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Daylight-Saving-Time"}, RULE_REQUIRED, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* IMSI-Group-Id */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "IMSI-Group-Id"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 10415, .avp_name = "Group-Service-Id"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Group-PLMN-Id"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Local-Group-Id"}, RULE_REQUIRED, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* Terminal-Information */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "Terminal-Information"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 10415, .avp_name = "IMEI"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "3GPP2-MEID"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Software-Version"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* Teleservice-List */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "Teleservice-List"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 10415, .avp_name = "TS-Code"}, RULE_REQUIRED, 1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* Service-Type */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "Service-Type"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 10415, .avp_name = "ServiceTypeIdentity"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "GMLC-Restriction"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Notification-To-UE-User"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* Requested-UTRAN-GERAN-Authentication-Info */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "Requested-UTRAN-GERAN-Authentication-Info"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 10415, .avp_name = "Number-Of-Requested-Vectors"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Immediate-Response-Preferred"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Re-Synchronization-Info"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* Subscription-Data-Deletion */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "Subscription-Data-Deletion"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 10415, .avp_name = "DSR-Flags"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "SCEF-ID"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Context-Identifier"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Trace-Reference"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "TS-Code"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "SS-Code"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* MME-User-State */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "MME-User-State"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 10415, .avp_name = "User-State"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* Requested-EUTRAN-Authentication-Info */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "Requested-EUTRAN-Authentication-Info"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 10415, .avp_name = "Number-Of-Requested-Vectors"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Immediate-Response-Preferred"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Re-Synchronization-Info"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* Adjacent-PLMNs */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "Adjacent-PLMNs"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 10415, .avp_name = "Visited-PLMN-Id"}, RULE_REQUIRED, 1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* SGSN-User-State */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "SGSN-User-State"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 10415, .avp_name = "User-State"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* External-Client */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "External-Client"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 10415, .avp_name = "Client-Identity"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "GMLC-Restriction"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Notification-To-UE-User"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* EPS-User-State */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "EPS-User-State"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 10415, .avp_name = "MME-User-State"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "SGSN-User-State"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* SGSN-Location-Information */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "SGSN-Location-Information"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 10415, .avp_name = "Cell-Global-Identity"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Location-Area-Identity"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Service-Area-Identity"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Routing-Area-Identity"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Geographical-Information"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Geodetic-Information"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Current-Location-Retrieved"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Age-Of-Location-Information"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "User-CSG-Information"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* LCS-PrivacyException */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "LCS-PrivacyException"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 10415, .avp_name = "SS-Code"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "SS-Status"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Notification-To-UE-User"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "External-Client"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "PLMN-Client"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Service-Type"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* EPS-Subscribed-QoS-Profile */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "EPS-Subscribed-QoS-Profile"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 10415, .avp_name = "QoS-Class-Identifier"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Allocation-Retention-Priority"}, RULE_REQUIRED, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* Authentication-Info */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "Authentication-Info"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 10415, .avp_name = "E-UTRAN-Vector"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "UTRAN-Vector"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "GERAN-Vector"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* Specific-APN-Info */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "Specific-APN-Info"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 0, .avp_name = "Service-Selection"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "MIP6-Agent-Info"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Visited-Network-Identifier"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* MDT-Configuration */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "MDT-Configuration"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 10415, .avp_name = "Job-Type"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Area-Scope"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "List-Of-Measurements"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Reporting-Trigger"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Report-Interval"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Report-Amount"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Event-Threshold-RSRP"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Event-Threshold-RSRQ"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Logging-Interval"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Logging-Duration"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Measurement-Period-LTE"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Measurement-Period-UMTS"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Collection-Period-RRM-LTE"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Collection-Period-RRM-UMTS"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Positioning-Method"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Measurement-Quantity"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Event-Threshold-Event-1F"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Event-Threshold-Event-1I"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "MDT-Allowed-PLMN-Id"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* MME-Location-Information */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "MME-Location-Information"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 10415, .avp_name = "E-UTRAN-Cell-Global-Identity"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Tracking-Area-Identity"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Geographical-Information"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Geodetic-Information"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Current-Location-Retrieved"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Age-Of-Location-Information"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "User-CSG-Information"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "eNodeB-Id"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Extended-eNodeB-Id"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* PDP-Context */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "PDP-Context"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 10415, .avp_name = "Context-Identifier"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "PDP-Type"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "PDP-Address"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "QoS-Subscribed"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "VPLMN-Dynamic-Address-Allowed"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Service-Selection"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "3GPP-Charging-Characteristics"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Ext-PDP-Type"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Ext-PDP-Address"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "AMBR"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "APN-OI-Replacement"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "SIPTO-Permission"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "LIPA-Permission"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Restoration-Priority"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "SIPTO-Local-Network-Permission"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Non-IP-Data-Delivery-Mechanism"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "SCEF-ID"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* Emergency-Info */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "Emergency-Info"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 10415, .avp_name = "MIP6-Agent-Info"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* GPRS-Subscription-Data */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "GPRS-Subscription-Data"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 10415, .avp_name = "Complete-Data-List-Included-Indicator"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "PDP-Context"}, RULE_REQUIRED, 1, 50 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* APN-Configuration */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "APN-Configuration"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 10415, .avp_name = "Context-Identifier"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Served-Party-IP-Address"}, RULE_OPTIONAL, -1, 2 },
+			{ { .avp_vendor = 10415, .avp_name = "PDN-Type"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Service-Selection"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "EPS-Subscribed-QoS-Profile"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "VPLMN-Dynamic-Address-Allowed"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "MIP6-Agent-Info"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Visited-Network-Identifier"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "PDN-GW-Allocation-Type"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "3GPP-Charging-Characteristics"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "AMBR"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Specific-APN-Info"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "APN-OI-Replacement"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "SIPTO-Permission"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "LIPA-Permission"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Restoration-Priority"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "SIPTO-Local-Network-Permission"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "WLAN-offloadability"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Non-IP-PDN-Type-Indicator"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Non-IP-Data-Delivery-Mechanism"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "SCEF-ID"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "SCEF-Realm"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Preferred-Data-Mode"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "PDN-Connection-Continuity"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* EPS-Location-Information */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "EPS-Location-Information"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 10415, .avp_name = "MME-Location-Information"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "SGSN-Location-Information"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* Trace-Data */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "Trace-Data"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 10415, .avp_name = "Trace-Reference"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Trace-Depth"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Trace-NE-Type-List"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Trace-Interface-List"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Trace-Event-List"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "OMC-Id"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Trace-Collection-Entity"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "MDT-Configuration"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* Active-APN */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "Active-APN"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 10415, .avp_name = "Context-Identifier"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Service-Selection"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "MIP6-Agent-Info"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Visited-Network-Identifier"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Specific-APN-Info"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* LCS-Info */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "LCS-Info"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 10415, .avp_name = "GMLC-Number"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "LCS-PrivacyException"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "MO-LR"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* APN-Configuration-Profile */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "APN-Configuration-Profile"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 10415, .avp_name = "Context-Identifier"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Additional-Context-Identifier"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "All-APN-Configurations-Included-Indicator"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "APN-Configuration"}, RULE_REQUIRED, 1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* Subscription-Data */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "Subscription-Data"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 10415, .avp_name = "Subscriber-Status"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "MSISDN"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "A-MSISDN"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "STN-SR"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "ICS-Indicator"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Network-Access-Mode"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Operator-Determined-Barring"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "HPLMN-ODB"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Regional-Subscription-Zone-Code"}, RULE_OPTIONAL, -1, 10 },
+			{ { .avp_vendor = 10415, .avp_name = "Access-Restriction-Data"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "APN-OI-Replacement"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "LCS-Info"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Teleservice-List"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Call-Barring-Info"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "3GPP-Charging-Characteristics"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "AMBR"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "APN-Configuration-Profile"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "RAT-Frequency-Selection-Priority-ID"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Trace-Data"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "GPRS-Subscription-Data"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "CSG-Subscription-Data"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Roaming-Restricted-Due-To-Unsupported-Feature"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Subscribed-Periodic-RAU-TAU-Timer"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "MPS-Priority"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "VPLMN-LIPA-Allowed"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Relay-Node-Indicator"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "MDT-User-Consent"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Subscribed-VSRVCC"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "ProSe-Subscription-Data"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Subscription-Data-Flags"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Adjacent-Access-Restriction-Data"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "DL-Buffering-Suggested-Packet-Count"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "IMSI-Group-Id"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "UE-Usage-Type"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "AESE-Communication-Pattern"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Monitoring-Event-Configuration"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Emergency-Info"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "V2X-Subscription-Data"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "eDRX-Cycle-Length"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+
+   }	
+
+   /* Commands section */
+   {
+
+   }
+
+   LOG_D( "Extension 'Dictionary definitions for ts29272_avps (e30)' initialized");
+   return 0;
+}
+
+int dict_entry(char * conffile)
+{
+	dict_ts29272_avps_load_defs(conffile);
+	return dict_ts29272_avps_load_rules(conffile);
+}
+
+const char* dict_ts29272_avps_proto_ver(char * conffile) {
+	return ts29272_avps_proto_ver;
+}
+
+const double dict_ts29272_avps_gen_ts(char * conffile) {
+	return ts29272_avps_gen_date;
+}
+
+EXTENSION_ENTRY2("dict_ts29272_avps", dict_ts29272_avps_load_defs, dict_ts29272_avps_load_rules, "dict_ts32299_avps", "dict_ts29336_avps", "dict_ts29273_avps", "dict_ts29212_avps", "dict_ts29214_avps", "dict_ts29344_avps", "dict_ts29338_avps", "dict_ts29217_avps", "dict_ts29329_avps", "dict_ts29229_avps", "dict_ts29173_avps", "dict_rfc5778_avps", "dict_ts29061_avps", "dict_rfc5447_avps", "dict_draftload_avps", "dict_rfc7683_avps", "dict_rfc4004_avps", "dict_rfc5777_avps", "dict_rfc7944_avps");
+
+
+
diff --git a/extensions/dict_ts29272_avps/ts29272_avps.did b/extensions/dict_ts29272_avps/ts29272_avps.did
new file mode 100644
index 0000000..f7022e2
--- /dev/null
+++ b/extensions/dict_ts29272_avps/ts29272_avps.did
@@ -0,0 +1,37 @@
+dict_rfc6942_avps
+dict_ts29468_avps
+dict_ts29343_avps
+dict_ts29128_avps
+dict_ts29344_avps
+dict_ts29345_avps
+dict_ts29337_avps
+dict_3gpp2_avps
+dict_ts29154_avps
+dict_ts29214_avps
+dict_ts29215_avps
+dict_ts29217_avps
+dict_ts29338_avps
+dict_ts29173_avps
+dict_ts29336_avps
+dict_rfc4590_avps
+dict_ts29229_avps
+dict_ts29329_avps
+dict_ts29368_avps
+dict_ts32299_avps
+dict_rfc6734_avps
+dict_rfc5778_avps
+dict_draftload_avps
+dict_etsi283034_avps
+dict_rfc5580_avps
+dict_rfc4072_avps
+dict_ts29273_avps
+dict_rfc7683_avps
+dict_rfc7944_avps
+dict_rfc5777_avps
+dict_rfc4006bis_avps
+dict_rfc7155_avps
+dict_ts29212_avps
+dict_ts29061_avps
+dict_rfc4004_avps
+dict_rfc5447_avps
+dict_ts29272_avps
diff --git a/extensions/dict_ts29273_avps/CMakeLists.txt b/extensions/dict_ts29273_avps/CMakeLists.txt
new file mode 100644
index 0000000..3e60d42
--- /dev/null
+++ b/extensions/dict_ts29273_avps/CMakeLists.txt
@@ -0,0 +1,16 @@
+# The dict_ts29273_avps extension
+PROJECT("dict_ts29273_avps library generated by FdGen " C)
+
+# Compile as a module
+FD_ADD_EXTENSION(dict_ts29273_avps dict_ts29273_avps.c)
+
+
+####
+## INSTALL section ##
+
+INSTALL(TARGETS dict_ts29273_avps
+	LIBRARY DESTINATION ${INSTALL_EXTENSIONS_SUFFIX}
+COMPONENT freeDiameter-dictionary-TS29273_AVPS)
+
+
+
diff --git a/extensions/dict_ts29273_avps/dict_ts29273_avps.c b/extensions/dict_ts29273_avps/dict_ts29273_avps.c
new file mode 100644
index 0000000..9906d3a
--- /dev/null
+++ b/extensions/dict_ts29273_avps/dict_ts29273_avps.c
@@ -0,0 +1,836 @@
+/*
+* Copyright (c) 2017 Sprint
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*    http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+/****************
+ Generated By: fdtool enhancements to diafuzzer
+ License: same as freeDiameter
+****************/
+
+
+/* 
+ * Dictionary definitions of objects specified in ts29273_avps (e20).
+ */
+#include <freeDiameter/extension.h>
+
+#define PROTO_VER "e20"
+#define GEN_DATE  1506697133.32
+
+const char *ts29273_avps_proto_ver = PROTO_VER;
+const double ts29273_avps_gen_date = GEN_DATE;
+
+/* The content of this file follows the same structure as dict_base_proto.c */
+
+#define CHECK_dict_new( _type, _data, _parent, _ref )                                     \
+{                                                                                         \
+    int _ret = fd_dict_new( fd_g_config->cnf_dict, (_type), (_data), (_parent), (_ref) ); \
+    if ( _ret != 0 && _ret != EEXIST )                                                    \
+       return _ret;                                                                       \
+}
+
+#define CHECK_dict_search( _type, _criteria, _what, _result )		\
+    CHECK_FCT(  fd_dict_search( fd_g_config->cnf_dict, (_type), (_criteria), (_what), (_result), ENOENT) );
+
+struct local_rules_definition {
+    struct dict_avp_request avp_vendor_plus_name;
+    enum rule_position	position;
+    int 			min;
+    int			max;
+};
+
+#define RULE_ORDER( _position ) ((((_position) == RULE_FIXED_HEAD) || ((_position) == RULE_FIXED_TAIL)) ? 1 : 0 )
+
+/* Attention! This version of the macro uses AVP_BY_NAME_AND_VENDOR, in contrast to most other copies! */
+#define PARSE_loc_rules( _rulearray, _parent) {                                                         \
+        int __ar;                                                                                       \
+        for (__ar=0; __ar < sizeof(_rulearray) / sizeof((_rulearray)[0]); __ar++) {                     \
+                struct dict_rule_data __data = { NULL,                                                  \
+                        (_rulearray)[__ar].position,                                                    \
+                        0,                                                                              \
+                        (_rulearray)[__ar].min,                                                         \
+                        (_rulearray)[__ar].max};                                                        \
+                __data.rule_order = RULE_ORDER(__data.rule_position);                                   \
+                CHECK_FCT(  fd_dict_search(                                                             \
+                        fd_g_config->cnf_dict,                                                          \
+                        DICT_AVP,                                                                       \
+                        AVP_BY_NAME_AND_VENDOR,                                                         \
+                        &(_rulearray)[__ar].avp_vendor_plus_name,                                       \
+                        &__data.rule_avp, 0 ) );                                                        \
+                if ( !__data.rule_avp ) {                                                               \
+                        TRACE_DEBUG(INFO, "AVP Not found: '%s'", (_rulearray)[__ar].avp_vendor_plus_name.avp_name);             \
+                        return ENOENT;                                                                  \
+                }                                                                                       \
+                {                                                                                       \
+                         int _ret = fd_dict_new( fd_g_config->cnf_dict, DICT_RULE, &(__data), (_parent), NULL ); \
+                         if ( _ret != 0 && _ret != EEXIST )      {                                      \
+                                TRACE_DEBUG(INFO, "Error on rule with AVP '%s'",                        \
+                                            (_rulearray)[__ar].avp_vendor_plus_name.avp_name);          \
+                                return EINVAL;                                                          \
+                         }                                                                              \
+                }                                                                                       \
+        }                                                                                               \
+}
+
+#define CHECK_vendor_new( _data ) { \
+        struct dict_object * vendor_found; \
+        if (fd_dict_search(fd_g_config->cnf_dict,DICT_VENDOR,VENDOR_BY_ID,&_data.vendor_id,&vendor_found,ENOENT) == ENOENT) { \
+                CHECK_FCT(fd_dict_new(fd_g_config->cnf_dict, DICT_VENDOR, &_data, NULL, NULL)); \
+        } \
+}
+
+#define enumval_def_u32( _val_, _str_ )		\
+    { _str_, 		{ .u32 = _val_ }}
+
+#define enumval_def_os( _len_, _val_, _str_ )				\
+    { _str_, 		{ .os = { .data = (unsigned char *)_val_, .len = _len_ }}}
+
+
+static int dict_ts29273_avps_load_defs(char * conffile)
+{
+   TRACE_ENTRY("%p", conffile);
+	/* Application Section */
+	{
+		/* Create the vendors */		{
+			struct dict_vendor_data vendor_data = { 10415, "3GPP" };
+			CHECK_dict_new(DICT_VENDOR, &vendor_data, NULL, NULL)
+		}
+	}
+
+
+   /* AVP section */
+   {
+		struct dict_object * Address_type;
+		struct dict_object * UTF8String_type;
+		struct dict_object * DiameterIdentity_type;
+		struct dict_object * DiameterURI_type;
+		struct dict_object * Time_type;
+		struct dict_object * IPFilterRule_type;
+
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "Address", &Address_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "UTF8String", &UTF8String_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "DiameterIdentity", &DiameterIdentity_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "DiameterURI", &DiameterURI_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "Time", &Time_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "IPFilterRule", &IPFilterRule_type);
+		/* ANID */
+		{
+			struct dict_avp_data data = {
+				1504,	/* Code */
+				10415,	/* Vendor */
+				"ANID",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, UTF8String_type, NULL);
+		};
+		/* AN-Trusted */
+		{
+			struct dict_avp_data data = {
+				1503,	/* Code */
+				10415,	/* Vendor */
+				"AN-Trusted",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(AN-Trusted)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "TRUSTED", { .i32=0 }};
+			struct dict_enumval_data        t_2 = { "UNTRUSTED", { .i32=1 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* MIP-FA-RK */
+		{
+			struct dict_avp_data data = {
+				1506,	/* Code */
+				10415,	/* Vendor */
+				"MIP-FA-RK",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* MIP-FA-RK-SPI */
+		{
+			struct dict_avp_data data = {
+				1507,	/* Code */
+				10415,	/* Vendor */
+				"MIP-FA-RK-SPI",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Full-Network-Name */
+		{
+			struct dict_avp_data data = {
+				1516,	/* Code */
+				10415,	/* Vendor */
+				"Full-Network-Name",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Short-Network-Name */
+		{
+			struct dict_avp_data data = {
+				1517,	/* Code */
+				10415,	/* Vendor */
+				"Short-Network-Name",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Mobile-Node-Identifier */
+		{
+			struct dict_avp_data data = {
+				506,	/* Code */
+				10415,	/* Vendor */
+				"Mobile-Node-Identifier",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, UTF8String_type, NULL);
+		};
+		/* AAA-Failure-Indication */
+		{
+			struct dict_avp_data data = {
+				1518,	/* Code */
+				10415,	/* Vendor */
+				"AAA-Failure-Indication",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Transport-Access-Type */
+		{
+			struct dict_avp_data data = {
+				1519,	/* Code */
+				10415,	/* Vendor */
+				"Transport-Access-Type",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Transport-Access-Type)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "BBF", { .i32=0 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* Visited-Network-Identifier */
+		{
+			struct dict_avp_data data = {
+				600,	/* Code */
+				10415,	/* Vendor */
+				"Visited-Network-Identifier",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* DER-Flags */
+		{
+			struct dict_avp_data data = {
+				1520,	/* Code */
+				10415,	/* Vendor */
+				"DER-Flags",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* DEA-Flags */
+		{
+			struct dict_avp_data data = {
+				1521,	/* Code */
+				10415,	/* Vendor */
+				"DEA-Flags",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* SSID */
+		{
+			struct dict_avp_data data = {
+				1524,	/* Code */
+				10415,	/* Vendor */
+				"SSID",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, UTF8String_type, NULL);
+		};
+		/* HESSID */
+		{
+			struct dict_avp_data data = {
+				1525,	/* Code */
+				10415,	/* Vendor */
+				"HESSID",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, UTF8String_type, NULL);
+		};
+		/* TWAN-Connection-Mode */
+		{
+			struct dict_avp_data data = {
+				1527,	/* Code */
+				10415,	/* Vendor */
+				"TWAN-Connection-Mode",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Connectivity-Flags */
+		{
+			struct dict_avp_data data = {
+				1529,	/* Code */
+				10415,	/* Vendor */
+				"Connectivity-Flags",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* TWAN-PCO */
+		{
+			struct dict_avp_data data = {
+				1530,	/* Code */
+				10415,	/* Vendor */
+				"TWAN-PCO",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* TWAG-CP-Address */
+		{
+			struct dict_avp_data data = {
+				1531,	/* Code */
+				10415,	/* Vendor */
+				"TWAG-CP-Address",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, Address_type, NULL);
+		};
+		/* TWAG-UP-Address */
+		{
+			struct dict_avp_data data = {
+				1532,	/* Code */
+				10415,	/* Vendor */
+				"TWAG-UP-Address",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, UTF8String_type, NULL);
+		};
+		/* TWAN-S2a-Failure-Cause */
+		{
+			struct dict_avp_data data = {
+				1533,	/* Code */
+				10415,	/* Vendor */
+				"TWAN-S2a-Failure-Cause",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* SM-Back-Off-Timer */
+		{
+			struct dict_avp_data data = {
+				1534,	/* Code */
+				10415,	/* Vendor */
+				"SM-Back-Off-Timer",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* WLCP-Key */
+		{
+			struct dict_avp_data data = {
+				1535,	/* Code */
+				10415,	/* Vendor */
+				"WLCP-Key",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Emergency-Services */
+		{
+			struct dict_avp_data data = {
+				1538,	/* Code */
+				10415,	/* Vendor */
+				"Emergency-Services",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* IMEI-Check-In-VPLMN-Result */
+		{
+			struct dict_avp_data data = {
+				1540,	/* Code */
+				10415,	/* Vendor */
+				"IMEI-Check-In-VPLMN-Result",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Non-3GPP-IP-Access */
+		{
+			struct dict_avp_data data = {
+				1501,	/* Code */
+				10415,	/* Vendor */
+				"Non-3GPP-IP-Access",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Non-3GPP-IP-Access)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "NON_3GPP_SUBSCRIPTION_ALLOWED", { .i32=0 }};
+			struct dict_enumval_data        t_2 = { "NON_3GPP_SUBSCRIPTION_BARRED", { .i32=1 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* Non-3GPP-IP-Access-APN */
+		{
+			struct dict_avp_data data = {
+				1502,	/* Code */
+				10415,	/* Vendor */
+				"Non-3GPP-IP-Access-APN",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Non-3GPP-IP-Access-APN)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "Non_3GPP_APNS_ENABLE", { .i32=0 }};
+			struct dict_enumval_data        t_2 = { "Non_3GPP_APNS_DISABLE", { .i32=1 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* PPR-Flags */
+		{
+			struct dict_avp_data data = {
+				1508,	/* Code */
+				10415,	/* Vendor */
+				"PPR-Flags",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* TWAN-Default-APN-Context-Id */
+		{
+			struct dict_avp_data data = {
+				1512,	/* Code */
+				10415,	/* Vendor */
+				"TWAN-Default-APN-Context-Id",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Access-Authorization-Flags */
+		{
+			struct dict_avp_data data = {
+				1511,	/* Code */
+				10415,	/* Vendor */
+				"Access-Authorization-Flags",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Service-Selection */
+		{
+			struct dict_avp_data data = {
+				493,	/* Code */
+				10415,	/* Vendor */
+				"Service-Selection",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, UTF8String_type, NULL);
+		};
+		/* 3GPP-AAA-Server-Name */
+		{
+			struct dict_avp_data data = {
+				318,	/* Code */
+				10415,	/* Vendor */
+				"3GPP-AAA-Server-Name",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, DiameterIdentity_type, NULL);
+		};
+		/* ERP-Authorization */
+		{
+			struct dict_avp_data data = {
+				1541,	/* Code */
+				10415,	/* Vendor */
+				"ERP-Authorization",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* MIP6-Feature-Vector */
+		{
+			struct dict_avp_data data = {
+				124,	/* Code */
+				10415,	/* Vendor */
+				"MIP6-Feature-Vector",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED64	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Origination-Time-Stamp */
+		{
+			struct dict_avp_data data = {
+				1536,	/* Code */
+				10415,	/* Vendor */
+				"Origination-Time-Stamp",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED64	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Maximum-Wait-Time */
+		{
+			struct dict_avp_data data = {
+				1537,	/* Code */
+				10415,	/* Vendor */
+				"Maximum-Wait-Time",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Access-Network-Info */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				1526,	/* Code */
+				10415,	/* Vendor */
+				"Access-Network-Info",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* MIP6-Agent-Info */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				486,	/* Code */
+				10415,	/* Vendor */
+				"MIP6-Agent-Info",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* WLAN-Identifier */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				1509,	/* Code */
+				10415,	/* Vendor */
+				"WLAN-Identifier",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* TWAN-Connectivity-Parameters */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				1528,	/* Code */
+				10415,	/* Vendor */
+				"TWAN-Connectivity-Parameters",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* TWAN-Access-Info */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				1510,	/* Code */
+				10415,	/* Vendor */
+				"TWAN-Access-Info",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* Trace-Info */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				1505,	/* Code */
+				10415,	/* Vendor */
+				"Trace-Info",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* Non-3GPP-User-Data */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				1500,	/* Code */
+				10415,	/* Vendor */
+				"Non-3GPP-User-Data",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+
+	
+   }
+
+   /* Commands section */
+   {
+
+   }
+
+   return 0;
+}
+
+static int dict_ts29273_avps_load_rules(char * conffile)
+{
+   /* Grouped AVP section */
+   {
+	  /* Access-Network-Info */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "Access-Network-Info"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 10415, .avp_name = "SSID"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "BSSID"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Location-Information"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Location-Data"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Operator-Name"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 13019, .avp_name = "Logical-Access-Id"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* MIP6-Agent-Info */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "MIP6-Agent-Info"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 0, .avp_name = "MIP-Home-Agent-Address"}, RULE_OPTIONAL, -1, 2 },
+			{ { .avp_vendor = 0, .avp_name = "MIP-Home-Agent-Host"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "MIP6-Home-Link-Prefix"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* WLAN-Identifier */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "WLAN-Identifier"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 10415, .avp_name = "SSID"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "HESSID"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* TWAN-Connectivity-Parameters */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "TWAN-Connectivity-Parameters"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 10415, .avp_name = "Connectivity-Flags"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Service-Selection"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "PDN-Type"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Served-Party-IP-Address"}, RULE_OPTIONAL, -1, 2 },
+			{ { .avp_vendor = 10415, .avp_name = "TWAN-PCO"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "TWAG-UP-Address"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "TWAN-S2a-Failure-Cause"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "SM-Back-Off-Timer"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* TWAN-Access-Info */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "TWAN-Access-Info"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 10415, .avp_name = "Access-Authorization-Flags"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "WLAN-Identifier"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* Trace-Info */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "Trace-Info"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 10415, .avp_name = "Trace-Data"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Trace-Reference"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* Non-3GPP-User-Data */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "Non-3GPP-User-Data"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 0, .avp_name = "Subscription-Id"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Non-3GPP-IP-Access"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Non-3GPP-IP-Access-APN"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "RAT-Type"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Session-Timeout"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "MIP6-Feature-Vector"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "AMBR"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "3GPP-Charging-Characteristics"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Context-Identifier"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "APN-OI-Replacement"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "APN-Configuration"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Trace-Info"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "TWAN-Default-APN-Context-Id"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "TWAN-Access-Info"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Emergency-Info"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "ERP-Authorization"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+
+   }	
+
+   /* Commands section */
+   {
+
+   }
+
+   LOG_D( "Extension 'Dictionary definitions for ts29273_avps (e20)' initialized");
+   return 0;
+}
+
+int dict_entry(char * conffile)
+{
+	dict_ts29273_avps_load_defs(conffile);
+	return dict_ts29273_avps_load_rules(conffile);
+}
+
+const char* dict_ts29273_avps_proto_ver(char * conffile) {
+	return ts29273_avps_proto_ver;
+}
+
+const double dict_ts29273_avps_gen_ts(char * conffile) {
+	return ts29273_avps_gen_date;
+}
+
+EXTENSION_ENTRY2("dict_ts29273_avps", dict_ts29273_avps_load_defs, dict_ts29273_avps_load_rules, "dict_ts32299_avps", "dict_ts29272_avps", "dict_ts29212_avps", "dict_ts29229_avps", "dict_rfc5778_avps", "dict_ts29061_avps", "dict_rfc4006bis_avps", "dict_rfc6942_avps", "dict_rfc7155_avps", "dict_rfc4072_avps", "dict_rfc5447_avps", "dict_rfc7683_avps", "dict_rfc6734_avps", "dict_rfc4004_avps", "dict_rfc5580_avps", "dict_rfc5777_avps", "dict_draftload_avps", "dict_etsi283034_avps", "dict_rfc7944_avps");
+
+
+
diff --git a/extensions/dict_ts29273_avps/ts29273_avps.did b/extensions/dict_ts29273_avps/ts29273_avps.did
new file mode 100644
index 0000000..923b7dc
--- /dev/null
+++ b/extensions/dict_ts29273_avps/ts29273_avps.did
@@ -0,0 +1,37 @@
+dict_rfc6942_avps
+dict_rfc6734_avps
+dict_rfc5580_avps
+dict_ts29468_avps
+dict_ts29154_avps
+dict_ts29214_avps
+dict_ts29215_avps
+dict_ts29217_avps
+dict_3gpp2_avps
+dict_ts29343_avps
+dict_ts29128_avps
+dict_ts29344_avps
+dict_ts29345_avps
+dict_ts32299_avps
+dict_rfc5778_avps
+dict_ts29338_avps
+dict_ts29173_avps
+dict_ts29337_avps
+dict_etsi283034_avps
+dict_rfc4590_avps
+dict_ts29229_avps
+dict_draftload_avps
+dict_ts29329_avps
+dict_ts29368_avps
+dict_ts29336_avps
+dict_ts29061_avps
+dict_ts29272_avps
+dict_rfc7683_avps
+dict_rfc7944_avps
+dict_rfc5777_avps
+dict_rfc4006bis_avps
+dict_ts29212_avps
+dict_rfc7155_avps
+dict_rfc4072_avps
+dict_rfc4004_avps
+dict_rfc5447_avps
+dict_ts29273_avps
diff --git a/extensions/dict_ts29329_avps/CMakeLists.txt b/extensions/dict_ts29329_avps/CMakeLists.txt
new file mode 100644
index 0000000..0af05e9
--- /dev/null
+++ b/extensions/dict_ts29329_avps/CMakeLists.txt
@@ -0,0 +1,16 @@
+# The dict_ts29329_avps extension
+PROJECT("dict_ts29329_avps library generated by FdGen " C)
+
+# Compile as a module
+FD_ADD_EXTENSION(dict_ts29329_avps dict_ts29329_avps.c)
+
+
+####
+## INSTALL section ##
+
+INSTALL(TARGETS dict_ts29329_avps
+	LIBRARY DESTINATION ${INSTALL_EXTENSIONS_SUFFIX}
+COMPONENT freeDiameter-dictionary-TS29329_AVPS)
+
+
+
diff --git a/extensions/dict_ts29329_avps/dict_ts29329_avps.c b/extensions/dict_ts29329_avps/dict_ts29329_avps.c
new file mode 100644
index 0000000..a3577ea
--- /dev/null
+++ b/extensions/dict_ts29329_avps/dict_ts29329_avps.c
@@ -0,0 +1,643 @@
+/*
+* Copyright (c) 2017 Sprint
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*    http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+/****************
+ Generated By: fdtool enhancements to diafuzzer
+ License: same as freeDiameter
+****************/
+
+
+/* 
+ * Dictionary definitions of objects specified in ts29329_avps (e20).
+ */
+#include <freeDiameter/extension.h>
+
+#define PROTO_VER "e20"
+#define GEN_DATE  1506697146.88
+
+const char *ts29329_avps_proto_ver = PROTO_VER;
+const double ts29329_avps_gen_date = GEN_DATE;
+
+/* The content of this file follows the same structure as dict_base_proto.c */
+
+#define CHECK_dict_new( _type, _data, _parent, _ref )                                     \
+{                                                                                         \
+    int _ret = fd_dict_new( fd_g_config->cnf_dict, (_type), (_data), (_parent), (_ref) ); \
+    if ( _ret != 0 && _ret != EEXIST )                                                    \
+       return _ret;                                                                       \
+}
+
+#define CHECK_dict_search( _type, _criteria, _what, _result )		\
+    CHECK_FCT(  fd_dict_search( fd_g_config->cnf_dict, (_type), (_criteria), (_what), (_result), ENOENT) );
+
+struct local_rules_definition {
+    struct dict_avp_request avp_vendor_plus_name;
+    enum rule_position	position;
+    int 			min;
+    int			max;
+};
+
+#define RULE_ORDER( _position ) ((((_position) == RULE_FIXED_HEAD) || ((_position) == RULE_FIXED_TAIL)) ? 1 : 0 )
+
+/* Attention! This version of the macro uses AVP_BY_NAME_AND_VENDOR, in contrast to most other copies! */
+#define PARSE_loc_rules( _rulearray, _parent) {                                                         \
+        int __ar;                                                                                       \
+        for (__ar=0; __ar < sizeof(_rulearray) / sizeof((_rulearray)[0]); __ar++) {                     \
+                struct dict_rule_data __data = { NULL,                                                  \
+                        (_rulearray)[__ar].position,                                                    \
+                        0,                                                                              \
+                        (_rulearray)[__ar].min,                                                         \
+                        (_rulearray)[__ar].max};                                                        \
+                __data.rule_order = RULE_ORDER(__data.rule_position);                                   \
+                CHECK_FCT(  fd_dict_search(                                                             \
+                        fd_g_config->cnf_dict,                                                          \
+                        DICT_AVP,                                                                       \
+                        AVP_BY_NAME_AND_VENDOR,                                                         \
+                        &(_rulearray)[__ar].avp_vendor_plus_name,                                       \
+                        &__data.rule_avp, 0 ) );                                                        \
+                if ( !__data.rule_avp ) {                                                               \
+                        TRACE_DEBUG(INFO, "AVP Not found: '%s'", (_rulearray)[__ar].avp_vendor_plus_name.avp_name);             \
+                        return ENOENT;                                                                  \
+                }                                                                                       \
+                {                                                                                       \
+                         int _ret = fd_dict_new( fd_g_config->cnf_dict, DICT_RULE, &(__data), (_parent), NULL ); \
+                         if ( _ret != 0 && _ret != EEXIST )      {                                      \
+                                TRACE_DEBUG(INFO, "Error on rule with AVP '%s'",                        \
+                                            (_rulearray)[__ar].avp_vendor_plus_name.avp_name);          \
+                                return EINVAL;                                                          \
+                         }                                                                              \
+                }                                                                                       \
+        }                                                                                               \
+}
+
+#define CHECK_vendor_new( _data ) { \
+        struct dict_object * vendor_found; \
+        if (fd_dict_search(fd_g_config->cnf_dict,DICT_VENDOR,VENDOR_BY_ID,&_data.vendor_id,&vendor_found,ENOENT) == ENOENT) { \
+                CHECK_FCT(fd_dict_new(fd_g_config->cnf_dict, DICT_VENDOR, &_data, NULL, NULL)); \
+        } \
+}
+
+#define enumval_def_u32( _val_, _str_ )		\
+    { _str_, 		{ .u32 = _val_ }}
+
+#define enumval_def_os( _len_, _val_, _str_ )				\
+    { _str_, 		{ .os = { .data = (unsigned char *)_val_, .len = _len_ }}}
+
+
+static int dict_ts29329_avps_load_defs(char * conffile)
+{
+   TRACE_ENTRY("%p", conffile);
+	/* Application Section */
+	{
+		/* Create the vendors */		{
+			struct dict_vendor_data vendor_data = { 10415, "3GPP" };
+			CHECK_dict_new(DICT_VENDOR, &vendor_data, NULL, NULL)
+		}
+	}
+
+
+   /* AVP section */
+   {
+		struct dict_object * Address_type;
+		struct dict_object * UTF8String_type;
+		struct dict_object * DiameterIdentity_type;
+		struct dict_object * DiameterURI_type;
+		struct dict_object * Time_type;
+		struct dict_object * IPFilterRule_type;
+
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "Address", &Address_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "UTF8String", &UTF8String_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "DiameterIdentity", &DiameterIdentity_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "DiameterURI", &DiameterURI_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "Time", &Time_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "IPFilterRule", &IPFilterRule_type);
+		/* MSISDN */
+		{
+			struct dict_avp_data data = {
+				701,	/* Code */
+				10415,	/* Vendor */
+				"MSISDN",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* User-Data */
+		{
+			struct dict_avp_data data = {
+				702,	/* Code */
+				10415,	/* Vendor */
+				"User-Data",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Data-Reference */
+		{
+			struct dict_avp_data data = {
+				703,	/* Code */
+				10415,	/* Vendor */
+				"Data-Reference",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Data-Reference)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "RepositoryData", { .i32=0 }};
+			struct dict_enumval_data        t_2 = { "IMSPublicIdentity", { .i32=10 }};
+			struct dict_enumval_data        t_3 = { "IMSUserState", { .i32=11 }};
+			struct dict_enumval_data        t_4 = { "S_CSCFName", { .i32=12 }};
+			struct dict_enumval_data        t_5 = { "InitialFilterCriteria", { .i32=13 }};
+			struct dict_enumval_data        t_6 = { "LocationInformation", { .i32=14 }};
+			struct dict_enumval_data        t_7 = { "UserState", { .i32=15 }};
+			struct dict_enumval_data        t_8 = { "ChargingInformation", { .i32=16 }};
+			struct dict_enumval_data        t_9 = { "MSISDN", { .i32=17 }};
+			struct dict_enumval_data        t_10 = { "PSIActivation", { .i32=18 }};
+			struct dict_enumval_data        t_11 = { "DSAI", { .i32=19 }};
+			struct dict_enumval_data        t_12 = { "ServiceLevelTraceInfo", { .i32=21 }};
+			struct dict_enumval_data        t_13 = { "IPAddressSecureBindingInformation", { .i32=22 }};
+			struct dict_enumval_data        t_14 = { "ServicePriorityLevel", { .i32=23 }};
+			struct dict_enumval_data        t_15 = { "SMSRegistrationInfo", { .i32=24 }};
+			struct dict_enumval_data        t_16 = { "UEReachabilityForIP", { .i32=25 }};
+			struct dict_enumval_data        t_17 = { "TADSinformation", { .i32=26 }};
+			struct dict_enumval_data        t_18 = { "STN_SR", { .i32=27 }};
+			struct dict_enumval_data        t_19 = { "UE_SRVCC_Capability", { .i32=28 }};
+			struct dict_enumval_data        t_20 = { "ExtendedPriority", { .i32=29 }};
+			struct dict_enumval_data        t_21 = { "CSRN", { .i32=30 }};
+			struct dict_enumval_data        t_22 = { "ReferenceLocationInformation", { .i32=31 }};
+			struct dict_enumval_data        t_23 = { "IMSI", { .i32=32 }};
+			struct dict_enumval_data        t_24 = { "IMSPrivateUserIdentity", { .i32=33 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_3, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_4, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_5, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_6, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_7, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_8, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_9, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_10, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_11, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_12, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_13, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_14, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_15, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_16, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_17, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_18, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_19, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_20, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_21, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_22, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_23, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_24, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* Service-Indication */
+		{
+			struct dict_avp_data data = {
+				704,	/* Code */
+				10415,	/* Vendor */
+				"Service-Indication",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Subs-Req-Type */
+		{
+			struct dict_avp_data data = {
+				705,	/* Code */
+				10415,	/* Vendor */
+				"Subs-Req-Type",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Subs-Req-Type)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "Subscribe", { .i32=0 }};
+			struct dict_enumval_data        t_2 = { "Unsubscribe", { .i32=1 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* Requested-Domain */
+		{
+			struct dict_avp_data data = {
+				706,	/* Code */
+				10415,	/* Vendor */
+				"Requested-Domain",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Requested-Domain)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "CS_Domain", { .i32=0 }};
+			struct dict_enumval_data        t_2 = { "PS_Domain", { .i32=1 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* Current-Location */
+		{
+			struct dict_avp_data data = {
+				707,	/* Code */
+				10415,	/* Vendor */
+				"Current-Location",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Current-Location)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "DoNotNeedInitiateActiveLocationRetrieval", { .i32=0 }};
+			struct dict_enumval_data        t_2 = { "InitiateActiveLocationRetrieval", { .i32=1 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* Identity-Set */
+		{
+			struct dict_avp_data data = {
+				708,	/* Code */
+				10415,	/* Vendor */
+				"Identity-Set",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Identity-Set)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "ALL_IDENTITIES", { .i32=0 }};
+			struct dict_enumval_data        t_2 = { "REGISTERED_IDENTITIES", { .i32=1 }};
+			struct dict_enumval_data        t_3 = { "IMPLICIT_IDENTITIES", { .i32=2 }};
+			struct dict_enumval_data        t_4 = { "ALIAS_IDENTITIES", { .i32=3 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_3, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_4, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* Expiry-Time */
+		{
+			struct dict_avp_data data = {
+				709,	/* Code */
+				10415,	/* Vendor */
+				"Expiry-Time",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, Time_type, NULL);
+		};
+		/* Send-Data-Indication */
+		{
+			struct dict_avp_data data = {
+				710,	/* Code */
+				10415,	/* Vendor */
+				"Send-Data-Indication",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Send-Data-Indication)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "USER_DATA_NOT_REQUESTED", { .i32=0 }};
+			struct dict_enumval_data        t_2 = { "USER_DATA_REQUESTED", { .i32=1 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* DSAI-Tag */
+		{
+			struct dict_avp_data data = {
+				711,	/* Code */
+				10415,	/* Vendor */
+				"DSAI-Tag",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Wildcarded-Public-Identity */
+		{
+			struct dict_avp_data data = {
+				634,	/* Code */
+				10415,	/* Vendor */
+				"Wildcarded-Public-Identity",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, UTF8String_type, NULL);
+		};
+		/* Wildcarded-IMPU */
+		{
+			struct dict_avp_data data = {
+				636,	/* Code */
+				10415,	/* Vendor */
+				"Wildcarded-IMPU",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, UTF8String_type, NULL);
+		};
+		/* One-Time-Notification */
+		{
+			struct dict_avp_data data = {
+				712,	/* Code */
+				10415,	/* Vendor */
+				"One-Time-Notification",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(One-Time-Notification)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "ONE_TIME_NOTIFICATION_REQUESTED", { .i32=0 }};
+			struct dict_enumval_data        t_2 = { "IP", { .i32=25 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* Requested-Nodes */
+		{
+			struct dict_avp_data data = {
+				713,	/* Code */
+				10415,	/* Vendor */
+				"Requested-Nodes",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Serving-Node-Indication */
+		{
+			struct dict_avp_data data = {
+				714,	/* Code */
+				10415,	/* Vendor */
+				"Serving-Node-Indication",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Serving-Node-Indication)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "ONLY_SERVING_NODES_REQUIRED", { .i32=0 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* Sequence-Number */
+		{
+			struct dict_avp_data data = {
+				716,	/* Code */
+				10415,	/* Vendor */
+				"Sequence-Number",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Pre-paging-Supported */
+		{
+			struct dict_avp_data data = {
+				717,	/* Code */
+				10415,	/* Vendor */
+				"Pre-paging-Supported",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Pre-paging-Supported)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "PREPAGING_NOT_SUPPORTED", { .i32=0 }};
+			struct dict_enumval_data        t_2 = { "PREPAGING_SUPPORTED", { .i32=1 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* Local-Time-Zone-Indication */
+		{
+			struct dict_avp_data data = {
+				718,	/* Code */
+				10415,	/* Vendor */
+				"Local-Time-Zone-Indication",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Local-Time-Zone-Indication)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "ONLY_LOCAL_TIME_ZONE_REQUESTED", { .i32=0 }};
+			struct dict_enumval_data        t_2 = { "LOCAL_TIME_ZONE_WITH_LOCATION_INFO_REQUESTED", { .i32=1 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* UDR-Flags */
+		{
+			struct dict_avp_data data = {
+				719,	/* Code */
+				10415,	/* Vendor */
+				"UDR-Flags",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Call-Reference-Number */
+		{
+			struct dict_avp_data data = {
+				721,	/* Code */
+				10415,	/* Vendor */
+				"Call-Reference-Number",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* AS-Number */
+		{
+			struct dict_avp_data data = {
+				722,	/* Code */
+				10415,	/* Vendor */
+				"AS-Number",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* User-Identity */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				700,	/* Code */
+				10415,	/* Vendor */
+				"User-Identity",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* Call-Reference-Info */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				720,	/* Code */
+				10415,	/* Vendor */
+				"Call-Reference-Info",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* Repository-Data-ID */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				715,	/* Code */
+				10415,	/* Vendor */
+				"Repository-Data-ID",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+
+	
+   }
+
+   /* Commands section */
+   {
+
+   }
+
+   return 0;
+}
+
+static int dict_ts29329_avps_load_rules(char * conffile)
+{
+   /* Grouped AVP section */
+   {
+	  /* User-Identity */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "User-Identity"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 10415, .avp_name = "Public-Identity"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "MSISDN"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* Call-Reference-Info */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "Call-Reference-Info"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 10415, .avp_name = "Call-Reference-Number"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "AS-Number"}, RULE_REQUIRED, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* Repository-Data-ID */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "Repository-Data-ID"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 10415, .avp_name = "Service-Indication"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Sequence-Number"}, RULE_REQUIRED, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+
+   }	
+
+   /* Commands section */
+   {
+
+   }
+
+   LOG_D( "Extension 'Dictionary definitions for ts29329_avps (e20)' initialized");
+   return 0;
+}
+
+int dict_entry(char * conffile)
+{
+	dict_ts29329_avps_load_defs(conffile);
+	return dict_ts29329_avps_load_rules(conffile);
+}
+
+const char* dict_ts29329_avps_proto_ver(char * conffile) {
+	return ts29329_avps_proto_ver;
+}
+
+const double dict_ts29329_avps_gen_ts(char * conffile) {
+	return ts29329_avps_gen_date;
+}
+
+EXTENSION_ENTRY2("dict_ts29329_avps", dict_ts29329_avps_load_defs, dict_ts29329_avps_load_rules, "dict_ts29229_avps", "dict_draftload_avps", "dict_rfc7683_avps", "dict_rfc7944_avps");
+
+
+
diff --git a/extensions/dict_ts29329_avps/ts29329_avps.did b/extensions/dict_ts29329_avps/ts29329_avps.did
new file mode 100644
index 0000000..8596274
--- /dev/null
+++ b/extensions/dict_ts29329_avps/ts29329_avps.did
@@ -0,0 +1,9 @@
+dict_etsi283034_avps
+dict_rfc4590_avps
+dict_rfc4004_avps
+dict_rfc7155_avps
+dict_ts29229_avps
+dict_rfc7683_avps
+dict_draftload_avps
+dict_rfc7944_avps
+dict_ts29329_avps
diff --git a/extensions/dict_ts29336_avps/CMakeLists.txt b/extensions/dict_ts29336_avps/CMakeLists.txt
new file mode 100644
index 0000000..e466aa2
--- /dev/null
+++ b/extensions/dict_ts29336_avps/CMakeLists.txt
@@ -0,0 +1,16 @@
+# The dict_ts29336_avps extension
+PROJECT("dict_ts29336_avps library generated by FdGen " C)
+
+# Compile as a module
+FD_ADD_EXTENSION(dict_ts29336_avps dict_ts29336_avps.c)
+
+
+####
+## INSTALL section ##
+
+INSTALL(TARGETS dict_ts29336_avps
+	LIBRARY DESTINATION ${INSTALL_EXTENSIONS_SUFFIX}
+COMPONENT freeDiameter-dictionary-TS29336_AVPS)
+
+
+
diff --git a/extensions/dict_ts29336_avps/dict_ts29336_avps.c b/extensions/dict_ts29336_avps/dict_ts29336_avps.c
new file mode 100644
index 0000000..2295896
--- /dev/null
+++ b/extensions/dict_ts29336_avps/dict_ts29336_avps.c
@@ -0,0 +1,1454 @@
+/*
+* Copyright (c) 2017 Sprint
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*    http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+/****************
+ Generated By: fdtool enhancements to diafuzzer
+ License: same as freeDiameter
+****************/
+
+
+/* 
+ * Dictionary definitions of objects specified in ts29336_avps (e10).
+ */
+#include <freeDiameter/extension.h>
+
+#define PROTO_VER "e10"
+#define GEN_DATE  1508010198.59
+
+const char *ts29336_avps_proto_ver = PROTO_VER;
+const double ts29336_avps_gen_date = GEN_DATE;
+
+/* The content of this file follows the same structure as dict_base_proto.c */
+
+#define CHECK_dict_new( _type, _data, _parent, _ref )                                     \
+{                                                                                         \
+    int _ret = fd_dict_new( fd_g_config->cnf_dict, (_type), (_data), (_parent), (_ref) ); \
+    if ( _ret != 0 && _ret != EEXIST )                                                    \
+       return _ret;                                                                       \
+}
+
+#define CHECK_dict_search( _type, _criteria, _what, _result )		\
+    CHECK_FCT(  fd_dict_search( fd_g_config->cnf_dict, (_type), (_criteria), (_what), (_result), ENOENT) );
+
+struct local_rules_definition {
+    struct dict_avp_request avp_vendor_plus_name;
+    enum rule_position	position;
+    int 			min;
+    int			max;
+};
+
+#define RULE_ORDER( _position ) ((((_position) == RULE_FIXED_HEAD) || ((_position) == RULE_FIXED_TAIL)) ? 1 : 0 )
+
+/* Attention! This version of the macro uses AVP_BY_NAME_AND_VENDOR, in contrast to most other copies! */
+#define PARSE_loc_rules( _rulearray, _parent) {                                                         \
+        int __ar;                                                                                       \
+        for (__ar=0; __ar < sizeof(_rulearray) / sizeof((_rulearray)[0]); __ar++) {                     \
+                struct dict_rule_data __data = { NULL,                                                  \
+                        (_rulearray)[__ar].position,                                                    \
+                        0,                                                                              \
+                        (_rulearray)[__ar].min,                                                         \
+                        (_rulearray)[__ar].max};                                                        \
+                __data.rule_order = RULE_ORDER(__data.rule_position);                                   \
+                CHECK_FCT(  fd_dict_search(                                                             \
+                        fd_g_config->cnf_dict,                                                          \
+                        DICT_AVP,                                                                       \
+                        AVP_BY_NAME_AND_VENDOR,                                                         \
+                        &(_rulearray)[__ar].avp_vendor_plus_name,                                       \
+                        &__data.rule_avp, 0 ) );                                                        \
+                if ( !__data.rule_avp ) {                                                               \
+                        TRACE_DEBUG(INFO, "AVP Not found: '%s'", (_rulearray)[__ar].avp_vendor_plus_name.avp_name);             \
+                        return ENOENT;                                                                  \
+                }                                                                                       \
+                {                                                                                       \
+                         int _ret = fd_dict_new( fd_g_config->cnf_dict, DICT_RULE, &(__data), (_parent), NULL ); \
+                         if ( _ret != 0 && _ret != EEXIST )      {                                      \
+                                TRACE_DEBUG(INFO, "Error on rule with AVP '%s'",                        \
+                                            (_rulearray)[__ar].avp_vendor_plus_name.avp_name);          \
+                                return EINVAL;                                                          \
+                         }                                                                              \
+                }                                                                                       \
+        }                                                                                               \
+}
+
+#define CHECK_vendor_new( _data ) { \
+        struct dict_object * vendor_found; \
+        if (fd_dict_search(fd_g_config->cnf_dict,DICT_VENDOR,VENDOR_BY_ID,&_data.vendor_id,&vendor_found,ENOENT) == ENOENT) { \
+                CHECK_FCT(fd_dict_new(fd_g_config->cnf_dict, DICT_VENDOR, &_data, NULL, NULL)); \
+        } \
+}
+
+#define enumval_def_u32( _val_, _str_ )		\
+    { _str_, 		{ .u32 = _val_ }}
+
+#define enumval_def_os( _len_, _val_, _str_ )				\
+    { _str_, 		{ .os = { .data = (unsigned char *)_val_, .len = _len_ }}}
+
+
+static int dict_ts29336_avps_load_defs(char * conffile)
+{
+   TRACE_ENTRY("%p", conffile);
+	/* Application Section */
+	{
+		/* Create the vendors */		{
+			struct dict_vendor_data vendor_data = { 10415, "3GPP" };
+			CHECK_dict_new(DICT_VENDOR, &vendor_data, NULL, NULL)
+		}
+	}
+
+
+   /* AVP section */
+   {
+		struct dict_object * Address_type;
+		struct dict_object * UTF8String_type;
+		struct dict_object * DiameterIdentity_type;
+		struct dict_object * DiameterURI_type;
+		struct dict_object * Time_type;
+		struct dict_object * IPFilterRule_type;
+
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "Address", &Address_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "UTF8String", &UTF8String_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "DiameterIdentity", &DiameterIdentity_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "DiameterURI", &DiameterURI_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "Time", &Time_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "IPFilterRule", &IPFilterRule_type);
+		/* IP-SM-GW-Number */
+		{
+			struct dict_avp_data data = {
+				3100,	/* Code */
+				10415,	/* Vendor */
+				"IP-SM-GW-Number",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* IP-SM-GW-Name */
+		{
+			struct dict_avp_data data = {
+				3101,	/* Code */
+				10415,	/* Vendor */
+				"IP-SM-GW-Name",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, DiameterIdentity_type, NULL);
+		};
+		/* Service-ID */
+		{
+			struct dict_avp_data data = {
+				3103,	/* Code */
+				10415,	/* Vendor */
+				"Service-ID",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Service-ID)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "DEVICE_TRIGGER", { .i32=0 }};
+			struct dict_enumval_data        t_2 = { "SMS_MO", { .i32=1 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* SCS-Identity */
+		{
+			struct dict_avp_data data = {
+				3104,	/* Code */
+				10415,	/* Vendor */
+				"SCS-Identity",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* HSS-Cause */
+		{
+			struct dict_avp_data data = {
+				3109,	/* Code */
+				10415,	/* Vendor */
+				"HSS-Cause",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* SIR-Flags */
+		{
+			struct dict_avp_data data = {
+				3110,	/* Code */
+				10415,	/* Vendor */
+				"SIR-Flags",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* External-Identifier */
+		{
+			struct dict_avp_data data = {
+				3111,	/* Code */
+				10415,	/* Vendor */
+				"External-Identifier",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, UTF8String_type, NULL);
+		};
+		/* IP-SM-GW-Realm */
+		{
+			struct dict_avp_data data = {
+				3112,	/* Code */
+				10415,	/* Vendor */
+				"IP-SM-GW-Realm",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, DiameterIdentity_type, NULL);
+		};
+		/* Periodic-Communication-Indicator */
+		{
+			struct dict_avp_data data = {
+				3115,	/* Code */
+				10415,	/* Vendor */
+				"Periodic-Communication-Indicator",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Communication-Duration-Time */
+		{
+			struct dict_avp_data data = {
+				3116,	/* Code */
+				10415,	/* Vendor */
+				"Communication-Duration-Time",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Periodic-Time */
+		{
+			struct dict_avp_data data = {
+				3117,	/* Code */
+				10415,	/* Vendor */
+				"Periodic-Time",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Stationary-Indication */
+		{
+			struct dict_avp_data data = {
+				3119,	/* Code */
+				10415,	/* Vendor */
+				"Stationary-Indication",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* SCEF-Reference-ID */
+		{
+			struct dict_avp_data data = {
+				3124,	/* Code */
+				10415,	/* Vendor */
+				"SCEF-Reference-ID",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* SCEF-ID */
+		{
+			struct dict_avp_data data = {
+				3125,	/* Code */
+				10415,	/* Vendor */
+				"SCEF-ID",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, DiameterIdentity_type, NULL);
+		};
+		/* SCEF-Reference-ID-for-Deletion */
+		{
+			struct dict_avp_data data = {
+				3126,	/* Code */
+				10415,	/* Vendor */
+				"SCEF-Reference-ID-for-Deletion",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Monitoring-Type */
+		{
+			struct dict_avp_data data = {
+				3127,	/* Code */
+				10415,	/* Vendor */
+				"Monitoring-Type",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Maximum-Number-of-Reports */
+		{
+			struct dict_avp_data data = {
+				3128,	/* Code */
+				10415,	/* Vendor */
+				"Maximum-Number-of-Reports",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Monitoring-Duration */
+		{
+			struct dict_avp_data data = {
+				3130,	/* Code */
+				10415,	/* Vendor */
+				"Monitoring-Duration",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, Time_type, NULL);
+		};
+		/* Maximum-Detection-Time */
+		{
+			struct dict_avp_data data = {
+				3131,	/* Code */
+				10415,	/* Vendor */
+				"Maximum-Detection-Time",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Reachability-Type */
+		{
+			struct dict_avp_data data = {
+				3132,	/* Code */
+				10415,	/* Vendor */
+				"Reachability-Type",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Maximum-Latency */
+		{
+			struct dict_avp_data data = {
+				3133,	/* Code */
+				10415,	/* Vendor */
+				"Maximum-Latency",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Maximum-Response-Time */
+		{
+			struct dict_avp_data data = {
+				3134,	/* Code */
+				10415,	/* Vendor */
+				"Maximum-Response-Time",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* MONTE-Location-Type */
+		{
+			struct dict_avp_data data = {
+				3136,	/* Code */
+				10415,	/* Vendor */
+				"MONTE-Location-Type",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Accuracy */
+		{
+			struct dict_avp_data data = {
+				3137,	/* Code */
+				10415,	/* Vendor */
+				"Accuracy",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Association-Type */
+		{
+			struct dict_avp_data data = {
+				3138,	/* Code */
+				10415,	/* Vendor */
+				"Association-Type",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Roaming-Information */
+		{
+			struct dict_avp_data data = {
+				3139,	/* Code */
+				10415,	/* Vendor */
+				"Roaming-Information",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Reachability-Information */
+		{
+			struct dict_avp_data data = {
+				3140,	/* Code */
+				10415,	/* Vendor */
+				"Reachability-Information",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* IMEI-Change */
+		{
+			struct dict_avp_data data = {
+				3141,	/* Code */
+				10415,	/* Vendor */
+				"IMEI-Change",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Supported-Monitoring-Events */
+		{
+			struct dict_avp_data data = {
+				3144,	/* Code */
+				10415,	/* Vendor */
+				"Supported-Monitoring-Events",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED64	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* CIR-Flags */
+		{
+			struct dict_avp_data data = {
+				3145,	/* Code */
+				10415,	/* Vendor */
+				"CIR-Flags",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Service-Result-Code */
+		{
+			struct dict_avp_data data = {
+				3147,	/* Code */
+				10415,	/* Vendor */
+				"Service-Result-Code",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Reference-ID-Validity-Time */
+		{
+			struct dict_avp_data data = {
+				3148,	/* Code */
+				10415,	/* Vendor */
+				"Reference-ID-Validity-Time",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, Time_type, NULL);
+		};
+		/* Event-Handling */
+		{
+			struct dict_avp_data data = {
+				3149,	/* Code */
+				10415,	/* Vendor */
+				"Event-Handling",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Node-Type */
+		{
+			struct dict_avp_data data = {
+				3153,	/* Code */
+				10415,	/* Vendor */
+				"Node-Type",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* S6t-HSS-Cause */
+		{
+			struct dict_avp_data data = {
+				3154,	/* Code */
+				10415,	/* Vendor */
+				"S6t-HSS-Cause",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Requested-Validity-Time */
+		{
+			struct dict_avp_data data = {
+				3159,	/* Code */
+				10415,	/* Vendor */
+				"Requested-Validity-Time",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, Time_type, NULL);
+		};
+		/* Granted-Validity-Time */
+		{
+			struct dict_avp_data data = {
+				3160,	/* Code */
+				10415,	/* Vendor */
+				"Granted-Validity-Time",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, Time_type, NULL);
+		};
+		/* Loss-Of-Connectivity-Reason */
+		{
+			struct dict_avp_data data = {
+				3162,	/* Code */
+				10415,	/* Vendor */
+				"Loss-Of-Connectivity-Reason",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Group-Reporting-Guard-Timer */
+		{
+			struct dict_avp_data data = {
+				3163,	/* Code */
+				10415,	/* Vendor */
+				"Group-Reporting-Guard-Timer",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* CIA-Flags */
+		{
+			struct dict_avp_data data = {
+				3164,	/* Code */
+				10415,	/* Vendor */
+				"CIA-Flags",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* RIR-Flags */
+		{
+			struct dict_avp_data data = {
+				3167,	/* Code */
+				10415,	/* Vendor */
+				"RIR-Flags",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Type-Of-External-Identifier */
+		{
+			struct dict_avp_data data = {
+				3168,	/* Code */
+				10415,	/* Vendor */
+				"Type-Of-External-Identifier",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* T4-Parameters */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				3106,	/* Code */
+				10415,	/* Vendor */
+				"T4-Parameters",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* Restricted-PLMN-List */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				3157,	/* Code */
+				10415,	/* Vendor */
+				"Restricted-PLMN-List",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* NIDD-Authorization-Response */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				3151,	/* Code */
+				10415,	/* Vendor */
+				"NIDD-Authorization-Response",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* User-Identifier */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				3102,	/* Code */
+				10415,	/* Vendor */
+				"User-Identifier",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* Scheduled-Communication-Time */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				3118,	/* Code */
+				10415,	/* Vendor */
+				"Scheduled-Communication-Time",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* Allowed-PLMN-List */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				3158,	/* Code */
+				10415,	/* Vendor */
+				"Allowed-PLMN-List",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* NIDD-Authorization-Update */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				3161,	/* Code */
+				10415,	/* Vendor */
+				"NIDD-Authorization-Update",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* Location-Information-Configuration */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				3135,	/* Code */
+				10415,	/* Vendor */
+				"Location-Information-Configuration",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* NIDD-Authorization-Request */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				3150,	/* Code */
+				10415,	/* Vendor */
+				"NIDD-Authorization-Request",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* Supported-Services */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				3143,	/* Code */
+				10415,	/* Vendor */
+				"Supported-Services",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* UE-Reachability-Configuration */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				3129,	/* Code */
+				10415,	/* Vendor */
+				"UE-Reachability-Configuration",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* Service-Result */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				3146,	/* Code */
+				10415,	/* Vendor */
+				"Service-Result",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* Service-Report */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				3152,	/* Code */
+				10415,	/* Vendor */
+				"Service-Report",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* Enhanced-Coverage-Restriction */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				3155,	/* Code */
+				10415,	/* Vendor */
+				"Enhanced-Coverage-Restriction",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* Communication-Pattern-Set */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				3114,	/* Code */
+				10415,	/* Vendor */
+				"Communication-Pattern-Set",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* T4-Data */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				3108,	/* Code */
+				10415,	/* Vendor */
+				"T4-Data",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* Service-Parameters */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				3105,	/* Code */
+				10415,	/* Vendor */
+				"Service-Parameters",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* Monitoring-Event-Configuration */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				3122,	/* Code */
+				10415,	/* Vendor */
+				"Monitoring-Event-Configuration",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* AESE-Error-Report */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				3121,	/* Code */
+				10415,	/* Vendor */
+				"AESE-Error-Report",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* Monitoring-Event-Config-Status */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				3142,	/* Code */
+				10415,	/* Vendor */
+				"Monitoring-Event-Config-Status",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* AESE-Communication-Pattern */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				3113,	/* Code */
+				10415,	/* Vendor */
+				"AESE-Communication-Pattern",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* AESE-Communication-Pattern-Config-Status */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				3120,	/* Code */
+				10415,	/* Vendor */
+				"AESE-Communication-Pattern-Config-Status",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* Service-Data */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				3107,	/* Code */
+				10415,	/* Vendor */
+				"Service-Data",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* Enhanced-Coverage-Restriction-Data */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				3156,	/* Code */
+				10415,	/* Vendor */
+				"Enhanced-Coverage-Restriction-Data",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* Monitoring-Event-Report */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				3123,	/* Code */
+				10415,	/* Vendor */
+				"Monitoring-Event-Report",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* Group-Monitoring-Event-Report-Item */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				3166,	/* Code */
+				10415,	/* Vendor */
+				"Group-Monitoring-Event-Report-Item",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* Group-Monitoring-Event-Report */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				3165,	/* Code */
+				10415,	/* Vendor */
+				"Group-Monitoring-Event-Report",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+
+	
+   }
+
+   /* Commands section */
+   {
+
+   }
+
+   return 0;
+}
+
+static int dict_ts29336_avps_load_rules(char * conffile)
+{
+   /* Grouped AVP section */
+   {
+	  /* T4-Parameters */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "T4-Parameters"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 10415, .avp_name = "Priority-Indication"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "SM-RP-SMEA"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* Restricted-PLMN-List */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "Restricted-PLMN-List"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 10415, .avp_name = "Visited-PLMN-Id"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* NIDD-Authorization-Response */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "NIDD-Authorization-Response"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 10415, .avp_name = "MSISDN"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "User-Name"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "External-Identifier"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Granted-Validity-Time"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* User-Identifier */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "User-Identifier"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 0, .avp_name = "User-Name"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "MSISDN"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "External-Identifier"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Type-Of-External-Identifier"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* Scheduled-Communication-Time */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "Scheduled-Communication-Time"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 0, .avp_name = "Day-Of-Week-Mask"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Time-Of-Day-Start"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Time-Of-Day-End"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* Allowed-PLMN-List */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "Allowed-PLMN-List"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 10415, .avp_name = "Visited-PLMN-Id"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* NIDD-Authorization-Update */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "NIDD-Authorization-Update"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 10415, .avp_name = "MSISDN"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "User-Name"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "External-Identifier"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Granted-Validity-Time"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* Location-Information-Configuration */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "Location-Information-Configuration"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 10415, .avp_name = "MONTE-Location-Type"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Accuracy"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* NIDD-Authorization-Request */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "NIDD-Authorization-Request"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 0, .avp_name = "Service-Selection"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Requested-Validity-Time"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* Supported-Services */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "Supported-Services"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 10415, .avp_name = "Supported-Monitoring-Events"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Node-Type"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* UE-Reachability-Configuration */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "UE-Reachability-Configuration"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 10415, .avp_name = "Reachability-Type"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Maximum-Latency"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Maximum-Response-Time"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* Service-Result */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "Service-Result"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 0, .avp_name = "Vendor-Id"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Service-Result-Code"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* Service-Report */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "Service-Report"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 10415, .avp_name = "Service-Result"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Node-Type"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* Enhanced-Coverage-Restriction */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "Enhanced-Coverage-Restriction"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 10415, .avp_name = "Restricted-PLMN-List"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Allowed-PLMN-List"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* Communication-Pattern-Set */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "Communication-Pattern-Set"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 10415, .avp_name = "Periodic-Communication-Indicator"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Communication-Duration-Time"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Periodic-Time"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Scheduled-Communication-Time"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Stationary-Indication"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Reference-ID-Validity-Time"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* T4-Data */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "T4-Data"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 10415, .avp_name = "HSS-Cause"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Serving-Node"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Additional-Serving-Node"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* Service-Parameters */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "Service-Parameters"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 10415, .avp_name = "T4-Parameters"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Application-Port-Identifier"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* Monitoring-Event-Configuration */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "Monitoring-Event-Configuration"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 10415, .avp_name = "SCEF-Reference-ID"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "SCEF-ID"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Monitoring-Type"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "SCEF-Reference-ID-for-Deletion"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Maximum-Number-of-Reports"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Monitoring-Duration"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Charged-Party"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Maximum-Detection-Time"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "UE-Reachability-Configuration"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Location-Information-Configuration"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Association-Type"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "DL-Buffering-Suggested-Packet-Count"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* AESE-Error-Report */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "AESE-Error-Report"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 10415, .avp_name = "Service-Result"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* Monitoring-Event-Config-Status */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "Monitoring-Event-Config-Status"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 10415, .avp_name = "Service-Report"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "SCEF-Reference-ID"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "SCEF-ID"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* AESE-Communication-Pattern */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "AESE-Communication-Pattern"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 10415, .avp_name = "SCEF-Reference-ID"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "SCEF-ID"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "SCEF-Reference-ID-for-Deletion"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Communication-Pattern-Set"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* AESE-Communication-Pattern-Config-Status */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "AESE-Communication-Pattern-Config-Status"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 10415, .avp_name = "SCEF-Reference-ID"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "SCEF-ID"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "AESE-Error-Report"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* Service-Data */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "Service-Data"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 10415, .avp_name = "T4-Data"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* Enhanced-Coverage-Restriction-Data */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "Enhanced-Coverage-Restriction-Data"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 10415, .avp_name = "Enhanced-Coverage-Restriction"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Visited-PLMN-Id"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* Monitoring-Event-Report */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "Monitoring-Event-Report"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 10415, .avp_name = "SCEF-Reference-ID"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "SCEF-ID"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Visited-PLMN-Id"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Roaming-Information"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "IMEI-Change"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Reachability-Information"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Maximum-UE-Availability-Time"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "EPS-Location-Information"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Monitoring-Type"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Event-Handling"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Service-Report"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Loss-Of-Connectivity-Reason"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* Group-Monitoring-Event-Report-Item */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "Group-Monitoring-Event-Report-Item"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 10415, .avp_name = "User-Identifier"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Visited-PLMN-Id"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Roaming-Information"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Reachability-Information"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Maximum-UE-Availability-Time"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "EPS-Location-Information"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Monitoring-Type"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Service-Report"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "S6t-HSS-Cause"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* Group-Monitoring-Event-Report */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "Group-Monitoring-Event-Report"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 10415, .avp_name = "SCEF-Reference-ID"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "SCEF-ID"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Group-Monitoring-Event-Report-Item"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+
+   }	
+
+   /* Commands section */
+   {
+
+   }
+
+   LOG_D( "Extension 'Dictionary definitions for ts29336_avps (e10)' initialized");
+   return 0;
+}
+
+int dict_entry(char * conffile)
+{
+	dict_ts29336_avps_load_defs(conffile);
+	return dict_ts29336_avps_load_rules(conffile);
+}
+
+const char* dict_proto_ver(char * conffile) {
+	return ts29336_avps_proto_ver;
+}
+
+const double dict_gen_ts(char * conffile) {
+	return ts29336_avps_gen_date;
+}
+
+EXTENSION_ENTRY2("dict_ts29336_avps", dict_ts29336_avps_load_defs, dict_ts29336_avps_load_rules, "dict_ts32299_avps", "dict_ts29272_avps", "dict_ts29338_avps", "dict_ts29329_avps", "dict_ts29368_avps", "dict_ts29229_avps", "dict_ts29217_avps", "dict_ts29173_avps", "dict_rfc5778_avps", "dict_draftload_avps", "dict_rfc5777_avps", "dict_rfc7683_avps", "dict_rfc7944_avps");
+
+
+
diff --git a/extensions/dict_ts29336_avps/ts29336_avps.did b/extensions/dict_ts29336_avps/ts29336_avps.did
new file mode 100644
index 0000000..24bab4c
--- /dev/null
+++ b/extensions/dict_ts29336_avps/ts29336_avps.did
@@ -0,0 +1,37 @@
+dict_rfc6942_avps
+dict_ts29468_avps
+dict_ts29154_avps
+dict_ts29214_avps
+dict_ts29215_avps
+dict_ts29217_avps
+dict_3gpp2_avps
+dict_ts29343_avps
+dict_ts29338_avps
+dict_ts29128_avps
+dict_ts29344_avps
+dict_ts29345_avps
+dict_ts32299_avps
+dict_rfc6734_avps
+dict_rfc5778_avps
+dict_rfc5580_avps
+dict_rfc4072_avps
+dict_ts29273_avps
+dict_rfc5777_avps
+dict_rfc4006bis_avps
+dict_ts29212_avps
+dict_ts29061_avps
+dict_rfc5447_avps
+dict_ts29272_avps
+dict_ts29173_avps
+dict_ts29337_avps
+dict_etsi283034_avps
+dict_rfc4590_avps
+dict_rfc4004_avps
+dict_rfc7155_avps
+dict_ts29229_avps
+dict_rfc7683_avps
+dict_draftload_avps
+dict_rfc7944_avps
+dict_ts29329_avps
+dict_ts29368_avps
+dict_ts29336_avps
diff --git a/extensions/dict_ts29337_avps/CMakeLists.txt b/extensions/dict_ts29337_avps/CMakeLists.txt
new file mode 100644
index 0000000..4c2b69b
--- /dev/null
+++ b/extensions/dict_ts29337_avps/CMakeLists.txt
@@ -0,0 +1,16 @@
+# The dict_ts29337_avps extension
+PROJECT("dict_ts29337_avps library generated by FdGen " C)
+
+# Compile as a module
+FD_ADD_EXTENSION(dict_ts29337_avps dict_ts29337_avps.c)
+
+
+####
+## INSTALL section ##
+
+INSTALL(TARGETS dict_ts29337_avps
+	LIBRARY DESTINATION ${INSTALL_EXTENSIONS_SUFFIX}
+COMPONENT freeDiameter-dictionary-TS29337_AVPS)
+
+
+
diff --git a/extensions/dict_ts29337_avps/dict_ts29337_avps.c b/extensions/dict_ts29337_avps/dict_ts29337_avps.c
new file mode 100644
index 0000000..ae60b55
--- /dev/null
+++ b/extensions/dict_ts29337_avps/dict_ts29337_avps.c
@@ -0,0 +1,248 @@
+/*
+* Copyright (c) 2017 Sprint
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*    http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+/****************
+ Generated By: fdtool enhancements to diafuzzer
+ License: same as freeDiameter
+****************/
+
+
+/* 
+ * Dictionary definitions of objects specified in ts29337_avps (e00).
+ */
+#include <freeDiameter/extension.h>
+
+#define PROTO_VER "e00"
+#define GEN_DATE  1506697153.25
+
+const char *ts29337_avps_proto_ver = PROTO_VER;
+const double ts29337_avps_gen_date = GEN_DATE;
+
+/* The content of this file follows the same structure as dict_base_proto.c */
+
+#define CHECK_dict_new( _type, _data, _parent, _ref )                                     \
+{                                                                                         \
+    int _ret = fd_dict_new( fd_g_config->cnf_dict, (_type), (_data), (_parent), (_ref) ); \
+    if ( _ret != 0 && _ret != EEXIST )                                                    \
+       return _ret;                                                                       \
+}
+
+#define CHECK_dict_search( _type, _criteria, _what, _result )		\
+    CHECK_FCT(  fd_dict_search( fd_g_config->cnf_dict, (_type), (_criteria), (_what), (_result), ENOENT) );
+
+struct local_rules_definition {
+    struct dict_avp_request avp_vendor_plus_name;
+    enum rule_position	position;
+    int 			min;
+    int			max;
+};
+
+#define RULE_ORDER( _position ) ((((_position) == RULE_FIXED_HEAD) || ((_position) == RULE_FIXED_TAIL)) ? 1 : 0 )
+
+/* Attention! This version of the macro uses AVP_BY_NAME_AND_VENDOR, in contrast to most other copies! */
+#define PARSE_loc_rules( _rulearray, _parent) {                                                         \
+        int __ar;                                                                                       \
+        for (__ar=0; __ar < sizeof(_rulearray) / sizeof((_rulearray)[0]); __ar++) {                     \
+                struct dict_rule_data __data = { NULL,                                                  \
+                        (_rulearray)[__ar].position,                                                    \
+                        0,                                                                              \
+                        (_rulearray)[__ar].min,                                                         \
+                        (_rulearray)[__ar].max};                                                        \
+                __data.rule_order = RULE_ORDER(__data.rule_position);                                   \
+                CHECK_FCT(  fd_dict_search(                                                             \
+                        fd_g_config->cnf_dict,                                                          \
+                        DICT_AVP,                                                                       \
+                        AVP_BY_NAME_AND_VENDOR,                                                         \
+                        &(_rulearray)[__ar].avp_vendor_plus_name,                                       \
+                        &__data.rule_avp, 0 ) );                                                        \
+                if ( !__data.rule_avp ) {                                                               \
+                        TRACE_DEBUG(INFO, "AVP Not found: '%s'", (_rulearray)[__ar].avp_vendor_plus_name.avp_name);             \
+                        return ENOENT;                                                                  \
+                }                                                                                       \
+                {                                                                                       \
+                         int _ret = fd_dict_new( fd_g_config->cnf_dict, DICT_RULE, &(__data), (_parent), NULL ); \
+                         if ( _ret != 0 && _ret != EEXIST )      {                                      \
+                                TRACE_DEBUG(INFO, "Error on rule with AVP '%s'",                        \
+                                            (_rulearray)[__ar].avp_vendor_plus_name.avp_name);          \
+                                return EINVAL;                                                          \
+                         }                                                                              \
+                }                                                                                       \
+        }                                                                                               \
+}
+
+#define CHECK_vendor_new( _data ) { \
+        struct dict_object * vendor_found; \
+        if (fd_dict_search(fd_g_config->cnf_dict,DICT_VENDOR,VENDOR_BY_ID,&_data.vendor_id,&vendor_found,ENOENT) == ENOENT) { \
+                CHECK_FCT(fd_dict_new(fd_g_config->cnf_dict, DICT_VENDOR, &_data, NULL, NULL)); \
+        } \
+}
+
+#define enumval_def_u32( _val_, _str_ )		\
+    { _str_, 		{ .u32 = _val_ }}
+
+#define enumval_def_os( _len_, _val_, _str_ )				\
+    { _str_, 		{ .os = { .data = (unsigned char *)_val_, .len = _len_ }}}
+
+
+static int dict_ts29337_avps_load_defs(char * conffile)
+{
+   TRACE_ENTRY("%p", conffile);
+	/* Application Section */
+	{
+		/* Create the vendors */		{
+			struct dict_vendor_data vendor_data = { 10415, "3GPP" };
+			CHECK_dict_new(DICT_VENDOR, &vendor_data, NULL, NULL)
+		}
+	}
+
+
+   /* AVP section */
+   {
+		struct dict_object * Address_type;
+		struct dict_object * UTF8String_type;
+		struct dict_object * DiameterIdentity_type;
+		struct dict_object * DiameterURI_type;
+		struct dict_object * Time_type;
+		struct dict_object * IPFilterRule_type;
+
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "Address", &Address_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "UTF8String", &UTF8String_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "DiameterIdentity", &DiameterIdentity_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "DiameterURI", &DiameterURI_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "Time", &Time_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "IPFilterRule", &IPFilterRule_type);
+		/* SM-Delivery-Outcome-T4 */
+		{
+			struct dict_avp_data data = {
+				3200,	/* Code */
+				10415,	/* Vendor */
+				"SM-Delivery-Outcome-T4",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(SM-Delivery-Outcome-T4)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "ABSENT_SUBSCRIBER", { .i32=0 }};
+			struct dict_enumval_data        t_2 = { "UE_MEMORY_CAPACITY_EXCEEDED", { .i32=1 }};
+			struct dict_enumval_data        t_3 = { "SUCCESSFUL_TRANSFER", { .i32=2 }};
+			struct dict_enumval_data        t_4 = { "VALIDITY_TIME_EXPIRED", { .i32=3 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_3, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_4, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* Absent-Subscriber-Diagnostic-T4 */
+		{
+			struct dict_avp_data data = {
+				3201,	/* Code */
+				10415,	/* Vendor */
+				"Absent-Subscriber-Diagnostic-T4",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Absent-Subscriber-Diagnostic-T4)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "ORIGINAL_MESSAGE_NOT_DELETED", { .i32=0 }};
+			struct dict_enumval_data        t_2 = { "NEW_MESSAGE_NOT_STORED", { .i32=1 }};
+			struct dict_enumval_data        t_3 = { "REPLACE", { .i32=2 }};
+			struct dict_enumval_data        t_4 = { "UE_PURGED", { .i32=3 }};
+			struct dict_enumval_data        t_5 = { "ROAMING_RESTRICTION", { .i32=4 }};
+			struct dict_enumval_data        t_6 = { "UNIDENTIFIED_SUBSCRIBER", { .i32=5 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_3, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_4, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_5, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_6, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* Trigger-Action */
+		{
+			struct dict_avp_data data = {
+				3202,	/* Code */
+				10415,	/* Vendor */
+				"Trigger-Action",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* MTC-Error-Diagnostic */
+		{
+			struct dict_avp_data data = {
+				3203,	/* Code */
+				10415,	/* Vendor */
+				"MTC-Error-Diagnostic",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+
+	
+   }
+
+   /* Commands section */
+   {
+
+   }
+
+   return 0;
+}
+
+static int dict_ts29337_avps_load_rules(char * conffile)
+{
+   /* Grouped AVP section */
+   {
+
+   }	
+
+   /* Commands section */
+   {
+
+   }
+
+   LOG_D( "Extension 'Dictionary definitions for ts29337_avps (e00)' initialized");
+   return 0;
+}
+
+int dict_entry(char * conffile)
+{
+	dict_ts29337_avps_load_defs(conffile);
+	return dict_ts29337_avps_load_rules(conffile);
+}
+
+const char* dict_ts29337_avps_proto_ver(char * conffile) {
+	return ts29337_avps_proto_ver;
+}
+
+const double dict_ts29337_avps_gen_ts(char * conffile) {
+	return ts29337_avps_gen_date;
+}
+
+EXTENSION_ENTRY2("dict_ts29337_avps", dict_ts29337_avps_load_defs, dict_ts29337_avps_load_rules, "dict_ts29336_avps", "dict_ts29338_avps", "dict_ts29272_avps", "dict_ts29368_avps", "dict_ts29229_avps", "dict_ts29173_avps", "dict_rfc4006bis_avps", "dict_rfc7155_avps", "dict_rfc7944_avps");
+
+
+
diff --git a/extensions/dict_ts29337_avps/ts29337_avps.did b/extensions/dict_ts29337_avps/ts29337_avps.did
new file mode 100644
index 0000000..065f753
--- /dev/null
+++ b/extensions/dict_ts29337_avps/ts29337_avps.did
@@ -0,0 +1,37 @@
+dict_rfc6942_avps
+dict_ts29468_avps
+dict_ts29154_avps
+dict_ts29214_avps
+dict_ts29215_avps
+dict_ts29217_avps
+dict_3gpp2_avps
+dict_ts29343_avps
+dict_ts29338_avps
+dict_ts29128_avps
+dict_ts29344_avps
+dict_ts29345_avps
+dict_ts29173_avps
+dict_ts32299_avps
+dict_rfc6734_avps
+dict_rfc5580_avps
+dict_rfc4072_avps
+dict_ts29273_avps
+dict_rfc4006bis_avps
+dict_ts29212_avps
+dict_ts29061_avps
+dict_ts29272_avps
+dict_rfc5447_avps
+dict_rfc5778_avps
+dict_rfc5777_avps
+dict_ts29336_avps
+dict_etsi283034_avps
+dict_rfc4590_avps
+dict_rfc4004_avps
+dict_rfc7155_avps
+dict_ts29229_avps
+dict_rfc7683_avps
+dict_draftload_avps
+dict_rfc7944_avps
+dict_ts29329_avps
+dict_ts29368_avps
+dict_ts29337_avps
diff --git a/extensions/dict_ts29338_avps/CMakeLists.txt b/extensions/dict_ts29338_avps/CMakeLists.txt
new file mode 100644
index 0000000..c58b332
--- /dev/null
+++ b/extensions/dict_ts29338_avps/CMakeLists.txt
@@ -0,0 +1,16 @@
+# The dict_ts29338_avps extension
+PROJECT("dict_ts29338_avps library generated by FdGen " C)
+
+# Compile as a module
+FD_ADD_EXTENSION(dict_ts29338_avps dict_ts29338_avps.c)
+
+
+####
+## INSTALL section ##
+
+INSTALL(TARGETS dict_ts29338_avps
+	LIBRARY DESTINATION ${INSTALL_EXTENSIONS_SUFFIX}
+COMPONENT freeDiameter-dictionary-TS29338_AVPS)
+
+
+
diff --git a/extensions/dict_ts29338_avps/dict_ts29338_avps.c b/extensions/dict_ts29338_avps/dict_ts29338_avps.c
new file mode 100644
index 0000000..a29863f
--- /dev/null
+++ b/extensions/dict_ts29338_avps/dict_ts29338_avps.c
@@ -0,0 +1,732 @@
+/*
+* Copyright (c) 2017 Sprint
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*    http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+/****************
+ Generated By: fdtool enhancements to diafuzzer
+ License: same as freeDiameter
+****************/
+
+
+/* 
+ * Dictionary definitions of objects specified in ts29338_avps (e10).
+ */
+#include <freeDiameter/extension.h>
+
+#define PROTO_VER "e10"
+#define GEN_DATE  1506697156.63
+
+const char *ts29338_avps_proto_ver = PROTO_VER;
+const double ts29338_avps_gen_date = GEN_DATE;
+
+/* The content of this file follows the same structure as dict_base_proto.c */
+
+#define CHECK_dict_new( _type, _data, _parent, _ref )                                     \
+{                                                                                         \
+    int _ret = fd_dict_new( fd_g_config->cnf_dict, (_type), (_data), (_parent), (_ref) ); \
+    if ( _ret != 0 && _ret != EEXIST )                                                    \
+       return _ret;                                                                       \
+}
+
+#define CHECK_dict_search( _type, _criteria, _what, _result )		\
+    CHECK_FCT(  fd_dict_search( fd_g_config->cnf_dict, (_type), (_criteria), (_what), (_result), ENOENT) );
+
+struct local_rules_definition {
+    struct dict_avp_request avp_vendor_plus_name;
+    enum rule_position	position;
+    int 			min;
+    int			max;
+};
+
+#define RULE_ORDER( _position ) ((((_position) == RULE_FIXED_HEAD) || ((_position) == RULE_FIXED_TAIL)) ? 1 : 0 )
+
+/* Attention! This version of the macro uses AVP_BY_NAME_AND_VENDOR, in contrast to most other copies! */
+#define PARSE_loc_rules( _rulearray, _parent) {                                                         \
+        int __ar;                                                                                       \
+        for (__ar=0; __ar < sizeof(_rulearray) / sizeof((_rulearray)[0]); __ar++) {                     \
+                struct dict_rule_data __data = { NULL,                                                  \
+                        (_rulearray)[__ar].position,                                                    \
+                        0,                                                                              \
+                        (_rulearray)[__ar].min,                                                         \
+                        (_rulearray)[__ar].max};                                                        \
+                __data.rule_order = RULE_ORDER(__data.rule_position);                                   \
+                CHECK_FCT(  fd_dict_search(                                                             \
+                        fd_g_config->cnf_dict,                                                          \
+                        DICT_AVP,                                                                       \
+                        AVP_BY_NAME_AND_VENDOR,                                                         \
+                        &(_rulearray)[__ar].avp_vendor_plus_name,                                       \
+                        &__data.rule_avp, 0 ) );                                                        \
+                if ( !__data.rule_avp ) {                                                               \
+                        TRACE_DEBUG(INFO, "AVP Not found: '%s'", (_rulearray)[__ar].avp_vendor_plus_name.avp_name);             \
+                        return ENOENT;                                                                  \
+                }                                                                                       \
+                {                                                                                       \
+                         int _ret = fd_dict_new( fd_g_config->cnf_dict, DICT_RULE, &(__data), (_parent), NULL ); \
+                         if ( _ret != 0 && _ret != EEXIST )      {                                      \
+                                TRACE_DEBUG(INFO, "Error on rule with AVP '%s'",                        \
+                                            (_rulearray)[__ar].avp_vendor_plus_name.avp_name);          \
+                                return EINVAL;                                                          \
+                         }                                                                              \
+                }                                                                                       \
+        }                                                                                               \
+}
+
+#define CHECK_vendor_new( _data ) { \
+        struct dict_object * vendor_found; \
+        if (fd_dict_search(fd_g_config->cnf_dict,DICT_VENDOR,VENDOR_BY_ID,&_data.vendor_id,&vendor_found,ENOENT) == ENOENT) { \
+                CHECK_FCT(fd_dict_new(fd_g_config->cnf_dict, DICT_VENDOR, &_data, NULL, NULL)); \
+        } \
+}
+
+#define enumval_def_u32( _val_, _str_ )		\
+    { _str_, 		{ .u32 = _val_ }}
+
+#define enumval_def_os( _len_, _val_, _str_ )				\
+    { _str_, 		{ .os = { .data = (unsigned char *)_val_, .len = _len_ }}}
+
+
+static int dict_ts29338_avps_load_defs(char * conffile)
+{
+   TRACE_ENTRY("%p", conffile);
+	/* Application Section */
+	{
+		/* Create the vendors */		{
+			struct dict_vendor_data vendor_data = { 10415, "3GPP" };
+			CHECK_dict_new(DICT_VENDOR, &vendor_data, NULL, NULL)
+		}
+	}
+
+
+   /* AVP section */
+   {
+		struct dict_object * Address_type;
+		struct dict_object * UTF8String_type;
+		struct dict_object * DiameterIdentity_type;
+		struct dict_object * DiameterURI_type;
+		struct dict_object * Time_type;
+		struct dict_object * IPFilterRule_type;
+
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "Address", &Address_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "UTF8String", &UTF8String_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "DiameterIdentity", &DiameterIdentity_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "DiameterURI", &DiameterURI_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "Time", &Time_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "IPFilterRule", &IPFilterRule_type);
+		/* SM-RP-MTI */
+		{
+			struct dict_avp_data data = {
+				3308,	/* Code */
+				10415,	/* Vendor */
+				"SM-RP-MTI",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(SM-RP-MTI)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "SM_DELIVER", { .i32=0 }};
+			struct dict_enumval_data        t_2 = { "SM_STATUS_REPORT", { .i32=1 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* SM-RP-SMEA */
+		{
+			struct dict_avp_data data = {
+				3309,	/* Code */
+				10415,	/* Vendor */
+				"SM-RP-SMEA",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* SRR-Flags */
+		{
+			struct dict_avp_data data = {
+				3310,	/* Code */
+				10415,	/* Vendor */
+				"SRR-Flags",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* SM-Delivery-Not-Intended */
+		{
+			struct dict_avp_data data = {
+				3311,	/* Code */
+				10415,	/* Vendor */
+				"SM-Delivery-Not-Intended",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(SM-Delivery-Not-Intended)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "ONLY_IMSI_REQUESTED", { .i32=0 }};
+			struct dict_enumval_data        t_2 = { "ONLY_MCC_MNC_REQUESTED", { .i32=1 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* MWD-Status */
+		{
+			struct dict_avp_data data = {
+				3312,	/* Code */
+				10415,	/* Vendor */
+				"MWD-Status",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* MME-Absent-User-Diagnostic-SM */
+		{
+			struct dict_avp_data data = {
+				3313,	/* Code */
+				10415,	/* Vendor */
+				"MME-Absent-User-Diagnostic-SM",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* MSC-Absent-User-Diagnostic-SM */
+		{
+			struct dict_avp_data data = {
+				3314,	/* Code */
+				10415,	/* Vendor */
+				"MSC-Absent-User-Diagnostic-SM",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* SGSN-Absent-User-Diagnostic-SM */
+		{
+			struct dict_avp_data data = {
+				3315,	/* Code */
+				10415,	/* Vendor */
+				"SGSN-Absent-User-Diagnostic-SM",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* SM-Delivery-Cause */
+		{
+			struct dict_avp_data data = {
+				3321,	/* Code */
+				10415,	/* Vendor */
+				"SM-Delivery-Cause",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(SM-Delivery-Cause)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "MEMORY_CAPACITY_EXCEEDED", { .i32=0 }};
+			struct dict_enumval_data        t_2 = { "ABSENT_USER", { .i32=1 }};
+			struct dict_enumval_data        t_3 = { "SUCCESSFUL_TRANSFER", { .i32=2 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_3, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* Absent-User-Diagnostic-SM */
+		{
+			struct dict_avp_data data = {
+				3322,	/* Code */
+				10415,	/* Vendor */
+				"Absent-User-Diagnostic-SM",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* RDR-Flags */
+		{
+			struct dict_avp_data data = {
+				3323,	/* Code */
+				10415,	/* Vendor */
+				"RDR-Flags",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Maximum-UE-Availability-Time */
+		{
+			struct dict_avp_data data = {
+				3329,	/* Code */
+				10415,	/* Vendor */
+				"Maximum-UE-Availability-Time",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, Time_type, NULL);
+		};
+		/* SMS-GMSC-Alert-Event */
+		{
+			struct dict_avp_data data = {
+				3333,	/* Code */
+				10415,	/* Vendor */
+				"SMS-GMSC-Alert-Event",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* SC-Address */
+		{
+			struct dict_avp_data data = {
+				3300,	/* Code */
+				10415,	/* Vendor */
+				"SC-Address",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* SM-RP-UI */
+		{
+			struct dict_avp_data data = {
+				3301,	/* Code */
+				10415,	/* Vendor */
+				"SM-RP-UI",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* TFR-Flags */
+		{
+			struct dict_avp_data data = {
+				3302,	/* Code */
+				10415,	/* Vendor */
+				"TFR-Flags",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* SM-Enumerated-Delivery-Failure-Cause */
+		{
+			struct dict_avp_data data = {
+				3304,	/* Code */
+				10415,	/* Vendor */
+				"SM-Enumerated-Delivery-Failure-Cause",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(SM-Enumerated-Delivery-Failure-Cause)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "MEMORY_CAPACITY_EXCEEDED", { .i32=0 }};
+			struct dict_enumval_data        t_2 = { "EQUIPMENT_PROTOCOL_ERROR", { .i32=1 }};
+			struct dict_enumval_data        t_3 = { "EQUIPMENT_NOT_SM_EQUIPPED", { .i32=2 }};
+			struct dict_enumval_data        t_4 = { "UNKNOWN_SERVICE_CENTRE", { .i32=3 }};
+			struct dict_enumval_data        t_5 = { "SC_CONGESTION", { .i32=4 }};
+			struct dict_enumval_data        t_6 = { "INVALID_SME_ADDRESS", { .i32=5 }};
+			struct dict_enumval_data        t_7 = { "USER_NOT_SC_USER", { .i32=6 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_3, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_4, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_5, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_6, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_7, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* SM-Diagnostic-Info */
+		{
+			struct dict_avp_data data = {
+				3305,	/* Code */
+				10415,	/* Vendor */
+				"SM-Diagnostic-Info",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* SM-Delivery-Timer */
+		{
+			struct dict_avp_data data = {
+				3306,	/* Code */
+				10415,	/* Vendor */
+				"SM-Delivery-Timer",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* SM-Delivery-Start-Time */
+		{
+			struct dict_avp_data data = {
+				3307,	/* Code */
+				10415,	/* Vendor */
+				"SM-Delivery-Start-Time",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, Time_type, NULL);
+		};
+		/* HSS-ID */
+		{
+			struct dict_avp_data data = {
+				3325,	/* Code */
+				10415,	/* Vendor */
+				"HSS-ID",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Originating-SIP-URI */
+		{
+			struct dict_avp_data data = {
+				3326,	/* Code */
+				10415,	/* Vendor */
+				"Originating-SIP-URI",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, UTF8String_type, NULL);
+		};
+		/* Destination-SIP-URI */
+		{
+			struct dict_avp_data data = {
+				3327,	/* Code */
+				10415,	/* Vendor */
+				"Destination-SIP-URI",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, UTF8String_type, NULL);
+		};
+		/* OFR-Flags */
+		{
+			struct dict_avp_data data = {
+				3328,	/* Code */
+				10415,	/* Vendor */
+				"OFR-Flags",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Maximum-Retransmission-Time */
+		{
+			struct dict_avp_data data = {
+				3330,	/* Code */
+				10415,	/* Vendor */
+				"Maximum-Retransmission-Time",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, Time_type, NULL);
+		};
+		/* Requested-Retransmission-Time */
+		{
+			struct dict_avp_data data = {
+				3331,	/* Code */
+				10415,	/* Vendor */
+				"Requested-Retransmission-Time",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, Time_type, NULL);
+		};
+		/* SMS-GMSC-Address */
+		{
+			struct dict_avp_data data = {
+				3332,	/* Code */
+				10415,	/* Vendor */
+				"SMS-GMSC-Address",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* SGSN-SM-Delivery-Outcome */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				3319,	/* Code */
+				10415,	/* Vendor */
+				"SGSN-SM-Delivery-Outcome",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* SM-Delivery-Failure-Cause */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				3303,	/* Code */
+				10415,	/* Vendor */
+				"SM-Delivery-Failure-Cause",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* SMSMI-Correlation-ID */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				3324,	/* Code */
+				10415,	/* Vendor */
+				"SMSMI-Correlation-ID",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* IP-SM-GW-SM-Delivery-Outcome */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				3320,	/* Code */
+				10415,	/* Vendor */
+				"IP-SM-GW-SM-Delivery-Outcome",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* MSC-SM-Delivery-Outcome */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				3318,	/* Code */
+				10415,	/* Vendor */
+				"MSC-SM-Delivery-Outcome",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* MME-SM-Delivery-Outcome */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				3317,	/* Code */
+				10415,	/* Vendor */
+				"MME-SM-Delivery-Outcome",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* SM-Delivery-Outcome */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				3316,	/* Code */
+				10415,	/* Vendor */
+				"SM-Delivery-Outcome",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+
+	
+   }
+
+   /* Commands section */
+   {
+
+   }
+
+   return 0;
+}
+
+static int dict_ts29338_avps_load_rules(char * conffile)
+{
+   /* Grouped AVP section */
+   {
+	  /* SGSN-SM-Delivery-Outcome */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "SGSN-SM-Delivery-Outcome"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 10415, .avp_name = "SM-Delivery-Cause"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Absent-User-Diagnostic-SM"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* SM-Delivery-Failure-Cause */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "SM-Delivery-Failure-Cause"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 10415, .avp_name = "SM-Enumerated-Delivery-Failure-Cause"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "SM-Diagnostic-Info"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* SMSMI-Correlation-ID */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "SMSMI-Correlation-ID"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 10415, .avp_name = "HSS-ID"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Originating-SIP-URI"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Destination-SIP-URI"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* IP-SM-GW-SM-Delivery-Outcome */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "IP-SM-GW-SM-Delivery-Outcome"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 10415, .avp_name = "SM-Delivery-Cause"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Absent-User-Diagnostic-SM"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* MSC-SM-Delivery-Outcome */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "MSC-SM-Delivery-Outcome"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 10415, .avp_name = "SM-Delivery-Cause"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Absent-User-Diagnostic-SM"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* MME-SM-Delivery-Outcome */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "MME-SM-Delivery-Outcome"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 10415, .avp_name = "SM-Delivery-Cause"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Absent-User-Diagnostic-SM"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* SM-Delivery-Outcome */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "SM-Delivery-Outcome"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 10415, .avp_name = "MME-SM-Delivery-Outcome"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "MSC-SM-Delivery-Outcome"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "SGSN-SM-Delivery-Outcome"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "IP-SM-GW-SM-Delivery-Outcome"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+
+   }	
+
+   /* Commands section */
+   {
+
+   }
+
+   LOG_D( "Extension 'Dictionary definitions for ts29338_avps (e10)' initialized");
+   return 0;
+}
+
+int dict_entry(char * conffile)
+{
+	dict_ts29338_avps_load_defs(conffile);
+	return dict_ts29338_avps_load_rules(conffile);
+}
+
+const char* dict_ts29338_avps_proto_ver(char * conffile) {
+	return ts29338_avps_proto_ver;
+}
+
+const double dict_ts29338_avps_gen_ts(char * conffile) {
+	return ts29338_avps_gen_date;
+}
+
+EXTENSION_ENTRY2("dict_ts29338_avps", dict_ts29338_avps_load_defs, dict_ts29338_avps_load_rules, "dict_ts29272_avps", "dict_ts29336_avps", "dict_ts29173_avps", "dict_ts29329_avps", "dict_ts29229_avps", "dict_rfc7944_avps");
+
+
+
diff --git a/extensions/dict_ts29338_avps/ts29338_avps.did b/extensions/dict_ts29338_avps/ts29338_avps.did
new file mode 100644
index 0000000..7319bee
--- /dev/null
+++ b/extensions/dict_ts29338_avps/ts29338_avps.did
@@ -0,0 +1,37 @@
+dict_rfc6942_avps
+dict_ts29468_avps
+dict_ts29154_avps
+dict_ts29214_avps
+dict_ts29215_avps
+dict_ts29217_avps
+dict_3gpp2_avps
+dict_ts29343_avps
+dict_ts29128_avps
+dict_ts29344_avps
+dict_ts29345_avps
+dict_ts32299_avps
+dict_rfc6734_avps
+dict_rfc5778_avps
+dict_rfc5580_avps
+dict_rfc4072_avps
+dict_ts29273_avps
+dict_rfc5777_avps
+dict_rfc4006bis_avps
+dict_ts29212_avps
+dict_ts29061_avps
+dict_rfc5447_avps
+dict_ts29272_avps
+dict_ts29173_avps
+dict_ts29337_avps
+dict_ts29368_avps
+dict_ts29336_avps
+dict_etsi283034_avps
+dict_rfc4590_avps
+dict_rfc4004_avps
+dict_rfc7155_avps
+dict_ts29229_avps
+dict_rfc7683_avps
+dict_draftload_avps
+dict_rfc7944_avps
+dict_ts29329_avps
+dict_ts29338_avps
diff --git a/extensions/dict_ts29343_avps/CMakeLists.txt b/extensions/dict_ts29343_avps/CMakeLists.txt
new file mode 100644
index 0000000..320d3cf
--- /dev/null
+++ b/extensions/dict_ts29343_avps/CMakeLists.txt
@@ -0,0 +1,16 @@
+# The dict_ts29343_avps extension
+PROJECT("dict_ts29343_avps library generated by FdGen " C)
+
+# Compile as a module
+FD_ADD_EXTENSION(dict_ts29343_avps dict_ts29343_avps.c)
+
+
+####
+## INSTALL section ##
+
+INSTALL(TARGETS dict_ts29343_avps
+	LIBRARY DESTINATION ${INSTALL_EXTENSIONS_SUFFIX}
+COMPONENT freeDiameter-dictionary-TS29343_AVPS)
+
+
+
diff --git a/extensions/dict_ts29343_avps/dict_ts29343_avps.c b/extensions/dict_ts29343_avps/dict_ts29343_avps.c
new file mode 100644
index 0000000..c128ba5
--- /dev/null
+++ b/extensions/dict_ts29343_avps/dict_ts29343_avps.c
@@ -0,0 +1,375 @@
+/*
+* Copyright (c) 2017 Sprint
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*    http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+/****************
+ Generated By: fdtool enhancements to diafuzzer
+ License: same as freeDiameter
+****************/
+
+
+/* 
+ * Dictionary definitions of objects specified in ts29343_avps (e10).
+ */
+#include <freeDiameter/extension.h>
+
+#define PROTO_VER "e10"
+#define GEN_DATE  1506697159.87
+
+const char *ts29343_avps_proto_ver = PROTO_VER;
+const double ts29343_avps_gen_date = GEN_DATE;
+
+/* The content of this file follows the same structure as dict_base_proto.c */
+
+#define CHECK_dict_new( _type, _data, _parent, _ref )                                     \
+{                                                                                         \
+    int _ret = fd_dict_new( fd_g_config->cnf_dict, (_type), (_data), (_parent), (_ref) ); \
+    if ( _ret != 0 && _ret != EEXIST )                                                    \
+       return _ret;                                                                       \
+}
+
+#define CHECK_dict_search( _type, _criteria, _what, _result )		\
+    CHECK_FCT(  fd_dict_search( fd_g_config->cnf_dict, (_type), (_criteria), (_what), (_result), ENOENT) );
+
+struct local_rules_definition {
+    struct dict_avp_request avp_vendor_plus_name;
+    enum rule_position	position;
+    int 			min;
+    int			max;
+};
+
+#define RULE_ORDER( _position ) ((((_position) == RULE_FIXED_HEAD) || ((_position) == RULE_FIXED_TAIL)) ? 1 : 0 )
+
+/* Attention! This version of the macro uses AVP_BY_NAME_AND_VENDOR, in contrast to most other copies! */
+#define PARSE_loc_rules( _rulearray, _parent) {                                                         \
+        int __ar;                                                                                       \
+        for (__ar=0; __ar < sizeof(_rulearray) / sizeof((_rulearray)[0]); __ar++) {                     \
+                struct dict_rule_data __data = { NULL,                                                  \
+                        (_rulearray)[__ar].position,                                                    \
+                        0,                                                                              \
+                        (_rulearray)[__ar].min,                                                         \
+                        (_rulearray)[__ar].max};                                                        \
+                __data.rule_order = RULE_ORDER(__data.rule_position);                                   \
+                CHECK_FCT(  fd_dict_search(                                                             \
+                        fd_g_config->cnf_dict,                                                          \
+                        DICT_AVP,                                                                       \
+                        AVP_BY_NAME_AND_VENDOR,                                                         \
+                        &(_rulearray)[__ar].avp_vendor_plus_name,                                       \
+                        &__data.rule_avp, 0 ) );                                                        \
+                if ( !__data.rule_avp ) {                                                               \
+                        TRACE_DEBUG(INFO, "AVP Not found: '%s'", (_rulearray)[__ar].avp_vendor_plus_name.avp_name);             \
+                        return ENOENT;                                                                  \
+                }                                                                                       \
+                {                                                                                       \
+                         int _ret = fd_dict_new( fd_g_config->cnf_dict, DICT_RULE, &(__data), (_parent), NULL ); \
+                         if ( _ret != 0 && _ret != EEXIST )      {                                      \
+                                TRACE_DEBUG(INFO, "Error on rule with AVP '%s'",                        \
+                                            (_rulearray)[__ar].avp_vendor_plus_name.avp_name);          \
+                                return EINVAL;                                                          \
+                         }                                                                              \
+                }                                                                                       \
+        }                                                                                               \
+}
+
+#define CHECK_vendor_new( _data ) { \
+        struct dict_object * vendor_found; \
+        if (fd_dict_search(fd_g_config->cnf_dict,DICT_VENDOR,VENDOR_BY_ID,&_data.vendor_id,&vendor_found,ENOENT) == ENOENT) { \
+                CHECK_FCT(fd_dict_new(fd_g_config->cnf_dict, DICT_VENDOR, &_data, NULL, NULL)); \
+        } \
+}
+
+#define enumval_def_u32( _val_, _str_ )		\
+    { _str_, 		{ .u32 = _val_ }}
+
+#define enumval_def_os( _len_, _val_, _str_ )				\
+    { _str_, 		{ .os = { .data = (unsigned char *)_val_, .len = _len_ }}}
+
+
+static int dict_ts29343_avps_load_defs(char * conffile)
+{
+   TRACE_ENTRY("%p", conffile);
+	/* Application Section */
+	{
+		/* Create the vendors */		{
+			struct dict_vendor_data vendor_data = { 10415, "3GPP" };
+			CHECK_dict_new(DICT_VENDOR, &vendor_data, NULL, NULL)
+		}
+	}
+
+
+   /* AVP section */
+   {
+		struct dict_object * Address_type;
+		struct dict_object * UTF8String_type;
+		struct dict_object * DiameterIdentity_type;
+		struct dict_object * DiameterURI_type;
+		struct dict_object * Time_type;
+		struct dict_object * IPFilterRule_type;
+
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "Address", &Address_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "UTF8String", &UTF8String_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "DiameterIdentity", &DiameterIdentity_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "DiameterURI", &DiameterURI_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "Time", &Time_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "IPFilterRule", &IPFilterRule_type);
+		/* Origin-App-Layer-User-Id */
+		{
+			struct dict_avp_data data = {
+				3600,	/* Code */
+				10415,	/* Vendor */
+				"Origin-App-Layer-User-Id",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, UTF8String_type, NULL);
+		};
+		/* Target-App-Layer-User-Id */
+		{
+			struct dict_avp_data data = {
+				3601,	/* Code */
+				10415,	/* Vendor */
+				"Target-App-Layer-User-Id",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, UTF8String_type, NULL);
+		};
+		/* ProSe-Function-ID */
+		{
+			struct dict_avp_data data = {
+				3602,	/* Code */
+				10415,	/* Vendor */
+				"ProSe-Function-ID",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* ProSe-Request-Type */
+		{
+			struct dict_avp_data data = {
+				3603,	/* Code */
+				10415,	/* Vendor */
+				"ProSe-Request-Type",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* PDUID */
+		{
+			struct dict_avp_data data = {
+				3604,	/* Code */
+				10415,	/* Vendor */
+				"PDUID",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Application-Data */
+		{
+			struct dict_avp_data data = {
+				3605,	/* Code */
+				10415,	/* Vendor */
+				"Application-Data",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, UTF8String_type, NULL);
+		};
+		/* Allowed-Suffixes-Number */
+		{
+			struct dict_avp_data data = {
+				3606,	/* Code */
+				10415,	/* Vendor */
+				"Allowed-Suffixes-Number",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Suffix-Code */
+		{
+			struct dict_avp_data data = {
+				3609,	/* Code */
+				10415,	/* Vendor */
+				"Suffix-Code",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Suffix-Mask */
+		{
+			struct dict_avp_data data = {
+				3610,	/* Code */
+				10415,	/* Vendor */
+				"Suffix-Mask",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Metadata-Indicator */
+		{
+			struct dict_avp_data data = {
+				3612,	/* Code */
+				10415,	/* Vendor */
+				"Metadata-Indicator",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* ProSe-Code-Suffix-Mask */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				3608,	/* Code */
+				10415,	/* Vendor */
+				"ProSe-Code-Suffix-Mask",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* Banned-User-Target */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				3611,	/* Code */
+				10415,	/* Vendor */
+				"Banned-User-Target",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* Monitor-Target */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				3607,	/* Code */
+				10415,	/* Vendor */
+				"Monitor-Target",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+
+	
+   }
+
+   /* Commands section */
+   {
+
+   }
+
+   return 0;
+}
+
+static int dict_ts29343_avps_load_rules(char * conffile)
+{
+   /* Grouped AVP section */
+   {
+	  /* ProSe-Code-Suffix-Mask */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "ProSe-Code-Suffix-Mask"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 10415, .avp_name = "Suffix-Code"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Suffix-Mask"}, RULE_REQUIRED, 1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* Banned-User-Target */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "Banned-User-Target"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 10415, .avp_name = "Target-RPAUID"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Target-PDUID"}, RULE_REQUIRED, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* Monitor-Target */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "Monitor-Target"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 10415, .avp_name = "Target-RPAUID"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "PDUID"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Metadata-Indicator"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "ProSe-Code-Suffix-Mask"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+
+   }	
+
+   /* Commands section */
+   {
+
+   }
+
+   LOG_D( "Extension 'Dictionary definitions for ts29343_avps (e10)' initialized");
+   return 0;
+}
+
+int dict_entry(char * conffile)
+{
+	dict_ts29343_avps_load_defs(conffile);
+	return dict_ts29343_avps_load_rules(conffile);
+}
+
+const char* dict_ts29343_avps_proto_ver(char * conffile) {
+	return ts29343_avps_proto_ver;
+}
+
+const double dict_ts29343_avps_gen_ts(char * conffile) {
+	return ts29343_avps_gen_date;
+}
+
+EXTENSION_ENTRY2("dict_ts29343_avps", dict_ts29343_avps_load_defs, dict_ts29343_avps_load_rules, "dict_ts29345_avps", "dict_draftload_avps");
+
+
+
diff --git a/extensions/dict_ts29343_avps/ts29343_avps.did b/extensions/dict_ts29343_avps/ts29343_avps.did
new file mode 100644
index 0000000..0a43883
--- /dev/null
+++ b/extensions/dict_ts29343_avps/ts29343_avps.did
@@ -0,0 +1,37 @@
+dict_rfc6942_avps
+dict_ts29468_avps
+dict_ts29128_avps
+dict_ts29337_avps
+dict_3gpp2_avps
+dict_ts29154_avps
+dict_ts29214_avps
+dict_ts29215_avps
+dict_ts29217_avps
+dict_ts29338_avps
+dict_ts29336_avps
+dict_ts29368_avps
+dict_ts32299_avps
+dict_rfc6734_avps
+dict_rfc5778_avps
+dict_rfc5580_avps
+dict_ts29273_avps
+dict_rfc5777_avps
+dict_rfc4006bis_avps
+dict_ts29212_avps
+dict_ts29061_avps
+dict_rfc5447_avps
+dict_ts29272_avps
+dict_etsi283034_avps
+dict_rfc4590_avps
+dict_ts29229_avps
+dict_draftload_avps
+dict_ts29329_avps
+dict_ts29173_avps
+dict_rfc7683_avps
+dict_rfc7944_avps
+dict_ts29344_avps
+dict_rfc4004_avps
+dict_rfc7155_avps
+dict_rfc4072_avps
+dict_ts29345_avps
+dict_ts29343_avps
diff --git a/extensions/dict_ts29344_avps/CMakeLists.txt b/extensions/dict_ts29344_avps/CMakeLists.txt
new file mode 100644
index 0000000..657962e
--- /dev/null
+++ b/extensions/dict_ts29344_avps/CMakeLists.txt
@@ -0,0 +1,16 @@
+# The dict_ts29344_avps extension
+PROJECT("dict_ts29344_avps library generated by FdGen " C)
+
+# Compile as a module
+FD_ADD_EXTENSION(dict_ts29344_avps dict_ts29344_avps.c)
+
+
+####
+## INSTALL section ##
+
+INSTALL(TARGETS dict_ts29344_avps
+	LIBRARY DESTINATION ${INSTALL_EXTENSIONS_SUFFIX}
+COMPONENT freeDiameter-dictionary-TS29344_AVPS)
+
+
+
diff --git a/extensions/dict_ts29344_avps/dict_ts29344_avps.c b/extensions/dict_ts29344_avps/dict_ts29344_avps.c
new file mode 100644
index 0000000..e0a0aa6
--- /dev/null
+++ b/extensions/dict_ts29344_avps/dict_ts29344_avps.c
@@ -0,0 +1,317 @@
+/*
+* Copyright (c) 2017 Sprint
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*    http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+/****************
+ Generated By: fdtool enhancements to diafuzzer
+ License: same as freeDiameter
+****************/
+
+
+/* 
+ * Dictionary definitions of objects specified in ts29344_avps (e10).
+ */
+#include <freeDiameter/extension.h>
+
+#define PROTO_VER "e10"
+#define GEN_DATE  1506697162.59
+
+const char *ts29344_avps_proto_ver = PROTO_VER;
+const double ts29344_avps_gen_date = GEN_DATE;
+
+/* The content of this file follows the same structure as dict_base_proto.c */
+
+#define CHECK_dict_new( _type, _data, _parent, _ref )                                     \
+{                                                                                         \
+    int _ret = fd_dict_new( fd_g_config->cnf_dict, (_type), (_data), (_parent), (_ref) ); \
+    if ( _ret != 0 && _ret != EEXIST )                                                    \
+       return _ret;                                                                       \
+}
+
+#define CHECK_dict_search( _type, _criteria, _what, _result )		\
+    CHECK_FCT(  fd_dict_search( fd_g_config->cnf_dict, (_type), (_criteria), (_what), (_result), ENOENT) );
+
+struct local_rules_definition {
+    struct dict_avp_request avp_vendor_plus_name;
+    enum rule_position	position;
+    int 			min;
+    int			max;
+};
+
+#define RULE_ORDER( _position ) ((((_position) == RULE_FIXED_HEAD) || ((_position) == RULE_FIXED_TAIL)) ? 1 : 0 )
+
+/* Attention! This version of the macro uses AVP_BY_NAME_AND_VENDOR, in contrast to most other copies! */
+#define PARSE_loc_rules( _rulearray, _parent) {                                                         \
+        int __ar;                                                                                       \
+        for (__ar=0; __ar < sizeof(_rulearray) / sizeof((_rulearray)[0]); __ar++) {                     \
+                struct dict_rule_data __data = { NULL,                                                  \
+                        (_rulearray)[__ar].position,                                                    \
+                        0,                                                                              \
+                        (_rulearray)[__ar].min,                                                         \
+                        (_rulearray)[__ar].max};                                                        \
+                __data.rule_order = RULE_ORDER(__data.rule_position);                                   \
+                CHECK_FCT(  fd_dict_search(                                                             \
+                        fd_g_config->cnf_dict,                                                          \
+                        DICT_AVP,                                                                       \
+                        AVP_BY_NAME_AND_VENDOR,                                                         \
+                        &(_rulearray)[__ar].avp_vendor_plus_name,                                       \
+                        &__data.rule_avp, 0 ) );                                                        \
+                if ( !__data.rule_avp ) {                                                               \
+                        TRACE_DEBUG(INFO, "AVP Not found: '%s'", (_rulearray)[__ar].avp_vendor_plus_name.avp_name);             \
+                        return ENOENT;                                                                  \
+                }                                                                                       \
+                {                                                                                       \
+                         int _ret = fd_dict_new( fd_g_config->cnf_dict, DICT_RULE, &(__data), (_parent), NULL ); \
+                         if ( _ret != 0 && _ret != EEXIST )      {                                      \
+                                TRACE_DEBUG(INFO, "Error on rule with AVP '%s'",                        \
+                                            (_rulearray)[__ar].avp_vendor_plus_name.avp_name);          \
+                                return EINVAL;                                                          \
+                         }                                                                              \
+                }                                                                                       \
+        }                                                                                               \
+}
+
+#define CHECK_vendor_new( _data ) { \
+        struct dict_object * vendor_found; \
+        if (fd_dict_search(fd_g_config->cnf_dict,DICT_VENDOR,VENDOR_BY_ID,&_data.vendor_id,&vendor_found,ENOENT) == ENOENT) { \
+                CHECK_FCT(fd_dict_new(fd_g_config->cnf_dict, DICT_VENDOR, &_data, NULL, NULL)); \
+        } \
+}
+
+#define enumval_def_u32( _val_, _str_ )		\
+    { _str_, 		{ .u32 = _val_ }}
+
+#define enumval_def_os( _len_, _val_, _str_ )				\
+    { _str_, 		{ .os = { .data = (unsigned char *)_val_, .len = _len_ }}}
+
+
+static int dict_ts29344_avps_load_defs(char * conffile)
+{
+   TRACE_ENTRY("%p", conffile);
+	/* Application Section */
+	{
+		/* Create the vendors */		{
+			struct dict_vendor_data vendor_data = { 10415, "3GPP" };
+			CHECK_dict_new(DICT_VENDOR, &vendor_data, NULL, NULL)
+		}
+	}
+
+
+   /* AVP section */
+   {
+		struct dict_object * Address_type;
+		struct dict_object * UTF8String_type;
+		struct dict_object * DiameterIdentity_type;
+		struct dict_object * DiameterURI_type;
+		struct dict_object * Time_type;
+		struct dict_object * IPFilterRule_type;
+
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "Address", &Address_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "UTF8String", &UTF8String_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "DiameterIdentity", &DiameterIdentity_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "DiameterURI", &DiameterURI_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "Time", &Time_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "IPFilterRule", &IPFilterRule_type);
+		/* ProSe-Permission */
+		{
+			struct dict_avp_data data = {
+				3702,	/* Code */
+				10415,	/* Vendor */
+				"ProSe-Permission",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* ProSe-Direct-Allowed */
+		{
+			struct dict_avp_data data = {
+				3704,	/* Code */
+				10415,	/* Vendor */
+				"ProSe-Direct-Allowed",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* UPR-Flags */
+		{
+			struct dict_avp_data data = {
+				3705,	/* Code */
+				10415,	/* Vendor */
+				"UPR-Flags",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* PNR-Flags */
+		{
+			struct dict_avp_data data = {
+				3706,	/* Code */
+				10415,	/* Vendor */
+				"PNR-Flags",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Authorized-Discovery-Range */
+		{
+			struct dict_avp_data data = {
+				3708,	/* Code */
+				10415,	/* Vendor */
+				"Authorized-Discovery-Range",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* ProSe-Initial-Location-Information */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				3707,	/* Code */
+				10415,	/* Vendor */
+				"ProSe-Initial-Location-Information",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* ProSe-Allowed-PLMN */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				3703,	/* Code */
+				10415,	/* Vendor */
+				"ProSe-Allowed-PLMN",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* ProSe-Subscription-Data */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				3701,	/* Code */
+				10415,	/* Vendor */
+				"ProSe-Subscription-Data",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+
+	
+   }
+
+   /* Commands section */
+   {
+
+   }
+
+   return 0;
+}
+
+static int dict_ts29344_avps_load_rules(char * conffile)
+{
+   /* Grouped AVP section */
+   {
+	  /* ProSe-Initial-Location-Information */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "ProSe-Initial-Location-Information"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 10415, .avp_name = "MME-Name"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "E-UTRAN-Cell-Global-Identity"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Tracking-Area-Identity"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Age-Of-Location-Information"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* ProSe-Allowed-PLMN */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "ProSe-Allowed-PLMN"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 10415, .avp_name = "Visited-PLMN-Id"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Authorized-Discovery-Range"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "ProSe-Direct-Allowed"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* ProSe-Subscription-Data */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "ProSe-Subscription-Data"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 10415, .avp_name = "ProSe-Permission"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "ProSe-Allowed-PLMN"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "3GPP-Charging-Characteristics"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+
+   }	
+
+   /* Commands section */
+   {
+
+   }
+
+   LOG_D( "Extension 'Dictionary definitions for ts29344_avps (e10)' initialized");
+   return 0;
+}
+
+int dict_entry(char * conffile)
+{
+	dict_ts29344_avps_load_defs(conffile);
+	return dict_ts29344_avps_load_rules(conffile);
+}
+
+const char* dict_ts29344_avps_proto_ver(char * conffile) {
+	return ts29344_avps_proto_ver;
+}
+
+const double dict_ts29344_avps_gen_ts(char * conffile) {
+	return ts29344_avps_gen_date;
+}
+
+EXTENSION_ENTRY2("dict_ts29344_avps", dict_ts29344_avps_load_defs, dict_ts29344_avps_load_rules, "dict_ts29272_avps", "dict_ts29329_avps", "dict_ts29229_avps", "dict_ts29173_avps", "dict_ts29061_avps", "dict_draftload_avps", "dict_rfc7683_avps", "dict_rfc7944_avps");
+
+
+
diff --git a/extensions/dict_ts29344_avps/ts29344_avps.did b/extensions/dict_ts29344_avps/ts29344_avps.did
new file mode 100644
index 0000000..b548b53
--- /dev/null
+++ b/extensions/dict_ts29344_avps/ts29344_avps.did
@@ -0,0 +1,37 @@
+dict_rfc6942_avps
+dict_ts29468_avps
+dict_ts29343_avps
+dict_ts29128_avps
+dict_ts29345_avps
+dict_ts29337_avps
+dict_3gpp2_avps
+dict_ts29154_avps
+dict_ts29214_avps
+dict_ts29215_avps
+dict_ts29217_avps
+dict_ts29338_avps
+dict_ts29336_avps
+dict_ts29368_avps
+dict_ts32299_avps
+dict_rfc6734_avps
+dict_rfc5778_avps
+dict_rfc5580_avps
+dict_rfc4072_avps
+dict_ts29273_avps
+dict_rfc5777_avps
+dict_rfc4006bis_avps
+dict_ts29212_avps
+dict_ts29061_avps
+dict_rfc5447_avps
+dict_ts29272_avps
+dict_etsi283034_avps
+dict_rfc4590_avps
+dict_rfc4004_avps
+dict_rfc7155_avps
+dict_ts29229_avps
+dict_draftload_avps
+dict_ts29329_avps
+dict_ts29173_avps
+dict_rfc7683_avps
+dict_rfc7944_avps
+dict_ts29344_avps
diff --git a/extensions/dict_ts29345_avps/CMakeLists.txt b/extensions/dict_ts29345_avps/CMakeLists.txt
new file mode 100644
index 0000000..52410c9
--- /dev/null
+++ b/extensions/dict_ts29345_avps/CMakeLists.txt
@@ -0,0 +1,16 @@
+# The dict_ts29345_avps extension
+PROJECT("dict_ts29345_avps library generated by FdGen " C)
+
+# Compile as a module
+FD_ADD_EXTENSION(dict_ts29345_avps dict_ts29345_avps.c)
+
+
+####
+## INSTALL section ##
+
+INSTALL(TARGETS dict_ts29345_avps
+	LIBRARY DESTINATION ${INSTALL_EXTENSIONS_SUFFIX}
+COMPONENT freeDiameter-dictionary-TS29345_AVPS)
+
+
+
diff --git a/extensions/dict_ts29345_avps/dict_ts29345_avps.c b/extensions/dict_ts29345_avps/dict_ts29345_avps.c
new file mode 100644
index 0000000..f3991d4
--- /dev/null
+++ b/extensions/dict_ts29345_avps/dict_ts29345_avps.c
@@ -0,0 +1,1300 @@
+/*
+* Copyright (c) 2017 Sprint
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*    http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+/****************
+ Generated By: fdtool enhancements to diafuzzer
+ License: same as freeDiameter
+****************/
+
+
+/* 
+ * Dictionary definitions of objects specified in ts29345_avps (e10).
+ */
+#include <freeDiameter/extension.h>
+
+#define PROTO_VER "e10"
+#define GEN_DATE  1506697165.68
+
+const char *ts29345_avps_proto_ver = PROTO_VER;
+const double ts29345_avps_gen_date = GEN_DATE;
+
+/* The content of this file follows the same structure as dict_base_proto.c */
+
+#define CHECK_dict_new( _type, _data, _parent, _ref )                                     \
+{                                                                                         \
+    int _ret = fd_dict_new( fd_g_config->cnf_dict, (_type), (_data), (_parent), (_ref) ); \
+    if ( _ret != 0 && _ret != EEXIST )                                                    \
+       return _ret;                                                                       \
+}
+
+#define CHECK_dict_search( _type, _criteria, _what, _result )		\
+    CHECK_FCT(  fd_dict_search( fd_g_config->cnf_dict, (_type), (_criteria), (_what), (_result), ENOENT) );
+
+struct local_rules_definition {
+    struct dict_avp_request avp_vendor_plus_name;
+    enum rule_position	position;
+    int 			min;
+    int			max;
+};
+
+#define RULE_ORDER( _position ) ((((_position) == RULE_FIXED_HEAD) || ((_position) == RULE_FIXED_TAIL)) ? 1 : 0 )
+
+/* Attention! This version of the macro uses AVP_BY_NAME_AND_VENDOR, in contrast to most other copies! */
+#define PARSE_loc_rules( _rulearray, _parent) {                                                         \
+        int __ar;                                                                                       \
+        for (__ar=0; __ar < sizeof(_rulearray) / sizeof((_rulearray)[0]); __ar++) {                     \
+                struct dict_rule_data __data = { NULL,                                                  \
+                        (_rulearray)[__ar].position,                                                    \
+                        0,                                                                              \
+                        (_rulearray)[__ar].min,                                                         \
+                        (_rulearray)[__ar].max};                                                        \
+                __data.rule_order = RULE_ORDER(__data.rule_position);                                   \
+                CHECK_FCT(  fd_dict_search(                                                             \
+                        fd_g_config->cnf_dict,                                                          \
+                        DICT_AVP,                                                                       \
+                        AVP_BY_NAME_AND_VENDOR,                                                         \
+                        &(_rulearray)[__ar].avp_vendor_plus_name,                                       \
+                        &__data.rule_avp, 0 ) );                                                        \
+                if ( !__data.rule_avp ) {                                                               \
+                        TRACE_DEBUG(INFO, "AVP Not found: '%s'", (_rulearray)[__ar].avp_vendor_plus_name.avp_name);             \
+                        return ENOENT;                                                                  \
+                }                                                                                       \
+                {                                                                                       \
+                         int _ret = fd_dict_new( fd_g_config->cnf_dict, DICT_RULE, &(__data), (_parent), NULL ); \
+                         if ( _ret != 0 && _ret != EEXIST )      {                                      \
+                                TRACE_DEBUG(INFO, "Error on rule with AVP '%s'",                        \
+                                            (_rulearray)[__ar].avp_vendor_plus_name.avp_name);          \
+                                return EINVAL;                                                          \
+                         }                                                                              \
+                }                                                                                       \
+        }                                                                                               \
+}
+
+#define CHECK_vendor_new( _data ) { \
+        struct dict_object * vendor_found; \
+        if (fd_dict_search(fd_g_config->cnf_dict,DICT_VENDOR,VENDOR_BY_ID,&_data.vendor_id,&vendor_found,ENOENT) == ENOENT) { \
+                CHECK_FCT(fd_dict_new(fd_g_config->cnf_dict, DICT_VENDOR, &_data, NULL, NULL)); \
+        } \
+}
+
+#define enumval_def_u32( _val_, _str_ )		\
+    { _str_, 		{ .u32 = _val_ }}
+
+#define enumval_def_os( _len_, _val_, _str_ )				\
+    { _str_, 		{ .os = { .data = (unsigned char *)_val_, .len = _len_ }}}
+
+
+static int dict_ts29345_avps_load_defs(char * conffile)
+{
+   TRACE_ENTRY("%p", conffile);
+	/* Application Section */
+	{
+		/* Create the vendors */		{
+			struct dict_vendor_data vendor_data = { 10415, "3GPP" };
+			CHECK_dict_new(DICT_VENDOR, &vendor_data, NULL, NULL)
+		}
+	}
+
+
+   /* AVP section */
+   {
+		struct dict_object * Address_type;
+		struct dict_object * UTF8String_type;
+		struct dict_object * DiameterIdentity_type;
+		struct dict_object * DiameterURI_type;
+		struct dict_object * Time_type;
+		struct dict_object * IPFilterRule_type;
+
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "Address", &Address_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "UTF8String", &UTF8String_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "DiameterIdentity", &DiameterIdentity_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "DiameterURI", &DiameterURI_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "Time", &Time_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "IPFilterRule", &IPFilterRule_type);
+		/* App-Layer-User-Id */
+		{
+			struct dict_avp_data data = {
+				3801,	/* Code */
+				10415,	/* Vendor */
+				"App-Layer-User-Id",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, UTF8String_type, NULL);
+		};
+		/* Assistance-Info-Validity-Timer */
+		{
+			struct dict_avp_data data = {
+				3803,	/* Code */
+				10415,	/* Vendor */
+				"Assistance-Info-Validity-Timer",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Discovery-Type */
+		{
+			struct dict_avp_data data = {
+				3804,	/* Code */
+				10415,	/* Vendor */
+				"Discovery-Type",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Filter-Id */
+		{
+			struct dict_avp_data data = {
+				3805,	/* Code */
+				10415,	/* Vendor */
+				"Filter-Id",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* MAC-Address */
+		{
+			struct dict_avp_data data = {
+				3806,	/* Code */
+				10415,	/* Vendor */
+				"MAC-Address",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, UTF8String_type, NULL);
+		};
+		/* Operating-Channel */
+		{
+			struct dict_avp_data data = {
+				3808,	/* Code */
+				10415,	/* Vendor */
+				"Operating-Channel",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* P2P-Features */
+		{
+			struct dict_avp_data data = {
+				3809,	/* Code */
+				10415,	/* Vendor */
+				"P2P-Features",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* ProSe-App-Code */
+		{
+			struct dict_avp_data data = {
+				3810,	/* Code */
+				10415,	/* Vendor */
+				"ProSe-App-Code",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* ProSe-App-Id */
+		{
+			struct dict_avp_data data = {
+				3811,	/* Code */
+				10415,	/* Vendor */
+				"ProSe-App-Id",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, UTF8String_type, NULL);
+		};
+		/* ProSe-App-Mask */
+		{
+			struct dict_avp_data data = {
+				3812,	/* Code */
+				10415,	/* Vendor */
+				"ProSe-App-Mask",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* PRR-Flags */
+		{
+			struct dict_avp_data data = {
+				3814,	/* Code */
+				10415,	/* Vendor */
+				"PRR-Flags",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* ProSe-Validity-Timer */
+		{
+			struct dict_avp_data data = {
+				3815,	/* Code */
+				10415,	/* Vendor */
+				"ProSe-Validity-Timer",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Requesting-EPUID */
+		{
+			struct dict_avp_data data = {
+				3816,	/* Code */
+				10415,	/* Vendor */
+				"Requesting-EPUID",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, UTF8String_type, NULL);
+		};
+		/* Targeted-EPUID */
+		{
+			struct dict_avp_data data = {
+				3817,	/* Code */
+				10415,	/* Vendor */
+				"Targeted-EPUID",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, UTF8String_type, NULL);
+		};
+		/* Time-Window */
+		{
+			struct dict_avp_data data = {
+				3818,	/* Code */
+				10415,	/* Vendor */
+				"Time-Window",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* WLAN-Link-Layer-Id */
+		{
+			struct dict_avp_data data = {
+				3821,	/* Code */
+				10415,	/* Vendor */
+				"WLAN-Link-Layer-Id",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Location-Update-Event-Type */
+		{
+			struct dict_avp_data data = {
+				3824,	/* Code */
+				10415,	/* Vendor */
+				"Location-Update-Event-Type",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Location-Update-Event-Trigger */
+		{
+			struct dict_avp_data data = {
+				3826,	/* Code */
+				10415,	/* Vendor */
+				"Location-Update-Event-Trigger",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Report-Cardinality */
+		{
+			struct dict_avp_data data = {
+				3827,	/* Code */
+				10415,	/* Vendor */
+				"Report-Cardinality",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Report-Cardinality)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "SINGLE", { .i32=0 }};
+			struct dict_enumval_data        t_2 = { "MULTIPLE", { .i32=1 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* Minimum-Interval-Time */
+		{
+			struct dict_avp_data data = {
+				3828,	/* Code */
+				10415,	/* Vendor */
+				"Minimum-Interval-Time",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Location-Report-Interval-Time */
+		{
+			struct dict_avp_data data = {
+				3830,	/* Code */
+				10415,	/* Vendor */
+				"Location-Report-Interval-Time",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Total-Number-Of-Reports */
+		{
+			struct dict_avp_data data = {
+				3831,	/* Code */
+				10415,	/* Vendor */
+				"Total-Number-Of-Reports",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Validity-Time-Announce */
+		{
+			struct dict_avp_data data = {
+				3832,	/* Code */
+				10415,	/* Vendor */
+				"Validity-Time-Announce",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Validity-Time-Monitor */
+		{
+			struct dict_avp_data data = {
+				3833,	/* Code */
+				10415,	/* Vendor */
+				"Validity-Time-Monitor",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Validity-Time-Communication */
+		{
+			struct dict_avp_data data = {
+				3834,	/* Code */
+				10415,	/* Vendor */
+				"Validity-Time-Communication",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* MIC */
+		{
+			struct dict_avp_data data = {
+				3836,	/* Code */
+				10415,	/* Vendor */
+				"MIC",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* UTC-based-Counter */
+		{
+			struct dict_avp_data data = {
+				3837,	/* Code */
+				10415,	/* Vendor */
+				"UTC-based-Counter",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* ProSe-Match-Refresh-Timer */
+		{
+			struct dict_avp_data data = {
+				3838,	/* Code */
+				10415,	/* Vendor */
+				"ProSe-Match-Refresh-Timer",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* ProSe-Metadata-Index-Mask */
+		{
+			struct dict_avp_data data = {
+				3839,	/* Code */
+				10415,	/* Vendor */
+				"ProSe-Metadata-Index-Mask",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* OS-ID */
+		{
+			struct dict_avp_data data = {
+				3841,	/* Code */
+				10415,	/* Vendor */
+				"OS-ID",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* OS-App-ID */
+		{
+			struct dict_avp_data data = {
+				3842,	/* Code */
+				10415,	/* Vendor */
+				"OS-App-ID",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, UTF8String_type, NULL);
+		};
+		/* Requesting-RPAUID */
+		{
+			struct dict_avp_data data = {
+				3843,	/* Code */
+				10415,	/* Vendor */
+				"Requesting-RPAUID",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, UTF8String_type, NULL);
+		};
+		/* Target-RPAUID */
+		{
+			struct dict_avp_data data = {
+				3844,	/* Code */
+				10415,	/* Vendor */
+				"Target-RPAUID",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, UTF8String_type, NULL);
+		};
+		/* Target-PDUID */
+		{
+			struct dict_avp_data data = {
+				3845,	/* Code */
+				10415,	/* Vendor */
+				"Target-PDUID",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* ProSe-Restricted-Code */
+		{
+			struct dict_avp_data data = {
+				3846,	/* Code */
+				10415,	/* Vendor */
+				"ProSe-Restricted-Code",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* ProSe-Restricted-Code-Suffix-Range */
+		{
+			struct dict_avp_data data = {
+				3847,	/* Code */
+				10415,	/* Vendor */
+				"ProSe-Restricted-Code-Suffix-Range",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Beginning-Suffix */
+		{
+			struct dict_avp_data data = {
+				3848,	/* Code */
+				10415,	/* Vendor */
+				"Beginning-Suffix",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Ending-Suffix */
+		{
+			struct dict_avp_data data = {
+				3849,	/* Code */
+				10415,	/* Vendor */
+				"Ending-Suffix",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Discovery-Entry-ID */
+		{
+			struct dict_avp_data data = {
+				3850,	/* Code */
+				10415,	/* Vendor */
+				"Discovery-Entry-ID",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Match-Timestamp */
+		{
+			struct dict_avp_data data = {
+				3851,	/* Code */
+				10415,	/* Vendor */
+				"Match-Timestamp",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, Time_type, NULL);
+		};
+		/* PMR-Flags */
+		{
+			struct dict_avp_data data = {
+				3852,	/* Code */
+				10415,	/* Vendor */
+				"PMR-Flags",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* ProSe-Application-Metadata */
+		{
+			struct dict_avp_data data = {
+				3853,	/* Code */
+				10415,	/* Vendor */
+				"ProSe-Application-Metadata",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, UTF8String_type, NULL);
+		};
+		/* Banned-RPAUID */
+		{
+			struct dict_avp_data data = {
+				3858,	/* Code */
+				10415,	/* Vendor */
+				"Banned-RPAUID",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, UTF8String_type, NULL);
+		};
+		/* Banned-PDUID */
+		{
+			struct dict_avp_data data = {
+				3859,	/* Code */
+				10415,	/* Vendor */
+				"Banned-PDUID",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* DUSK */
+		{
+			struct dict_avp_data data = {
+				3862,	/* Code */
+				10415,	/* Vendor */
+				"DUSK",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* DUIK */
+		{
+			struct dict_avp_data data = {
+				3863,	/* Code */
+				10415,	/* Vendor */
+				"DUIK",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* DUCK */
+		{
+			struct dict_avp_data data = {
+				3864,	/* Code */
+				10415,	/* Vendor */
+				"DUCK",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* MIC-Check-Indicator */
+		{
+			struct dict_avp_data data = {
+				3865,	/* Code */
+				10415,	/* Vendor */
+				"MIC-Check-Indicator",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Encrypted-Bitmask */
+		{
+			struct dict_avp_data data = {
+				3866,	/* Code */
+				10415,	/* Vendor */
+				"Encrypted-Bitmask",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* ProSe-App-Code-Suffix-Range */
+		{
+			struct dict_avp_data data = {
+				3867,	/* Code */
+				10415,	/* Vendor */
+				"ProSe-App-Code-Suffix-Range",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* ProSe-Query-Code */
+		{
+			struct dict_avp_data data = {
+				9900,	/* Code */
+				10415,	/* Vendor */
+				"ProSe-Query-Code",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* ProSe-Response-Code */
+		{
+			struct dict_avp_data data = {
+				9901,	/* Code */
+				10415,	/* Vendor */
+				"ProSe-Response-Code",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Periodic-Location-Type */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				3829,	/* Code */
+				10415,	/* Vendor */
+				"Periodic-Location-Type",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* Code-Receiving-Security-Material */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				3860,	/* Code */
+				10415,	/* Vendor */
+				"Code-Receiving-Security-Material",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* Code-Sending-Security-Material */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				3861,	/* Code */
+				10415,	/* Vendor */
+				"Code-Sending-Security-Material",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* Change-Of-Area-Type */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				3825,	/* Code */
+				10415,	/* Vendor */
+				"Change-Of-Area-Type",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* WLAN-Link-Layer-Id-List */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				3822,	/* Code */
+				10415,	/* Vendor */
+				"WLAN-Link-Layer-Id-List",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* Match-Request */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				3856,	/* Code */
+				10415,	/* Vendor */
+				"Match-Request",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* ProSe-App-Code-Info */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				3835,	/* Code */
+				10415,	/* Vendor */
+				"ProSe-App-Code-Info",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* App-Identifier */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				3840,	/* Code */
+				10415,	/* Vendor */
+				"App-Identifier",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* Match-Report */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				3807,	/* Code */
+				10415,	/* Vendor */
+				"Match-Report",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* ProSe-Discovery-Filter */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				3813,	/* Code */
+				10415,	/* Vendor */
+				"ProSe-Discovery-Filter",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* Discovery-Auth-Request */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				3854,	/* Code */
+				10415,	/* Vendor */
+				"Discovery-Auth-Request",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* Match-Report-Info */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				3857,	/* Code */
+				10415,	/* Vendor */
+				"Match-Report-Info",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* Location-Update-Trigger */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				3823,	/* Code */
+				10415,	/* Vendor */
+				"Location-Update-Trigger",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* WiFi-P2P-Assistance-Info */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				3819,	/* Code */
+				10415,	/* Vendor */
+				"WiFi-P2P-Assistance-Info",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* Discovery-Auth-Response */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				3855,	/* Code */
+				10415,	/* Vendor */
+				"Discovery-Auth-Response",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* WLAN-Assistance-Info */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				3820,	/* Code */
+				10415,	/* Vendor */
+				"WLAN-Assistance-Info",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* Assistance-Info */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				3802,	/* Code */
+				10415,	/* Vendor */
+				"Assistance-Info",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+
+	
+   }
+
+   /* Commands section */
+   {
+
+   }
+
+   return 0;
+}
+
+static int dict_ts29345_avps_load_rules(char * conffile)
+{
+   /* Grouped AVP section */
+   {
+	  /* Periodic-Location-Type */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "Periodic-Location-Type"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 10415, .avp_name = "Location-Report-Interval-Time"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Total-Number-Of-Reports"}, RULE_REQUIRED, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* Code-Receiving-Security-Material */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "Code-Receiving-Security-Material"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 10415, .avp_name = "DUSK"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "DUIK"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "MIC-Check-Indicator"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "DUCK"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Encrypted-Bitmask"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* Code-Sending-Security-Material */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "Code-Sending-Security-Material"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 10415, .avp_name = "DUSK"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "DUIK"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "DUCK"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Encrypted-Bitmask"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* Change-Of-Area-Type */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "Change-Of-Area-Type"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 10415, .avp_name = "Location-Update-Event-Trigger"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Report-Cardinality"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Minimum-Interval-Time"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* WLAN-Link-Layer-Id-List */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "WLAN-Link-Layer-Id-List"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 10415, .avp_name = "WLAN-Link-Layer-Id"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* Match-Request */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "Match-Request"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 10415, .avp_name = "Discovery-Type"}, RULE_REQUIRED, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* ProSe-App-Code-Info */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "ProSe-App-Code-Info"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 10415, .avp_name = "ProSe-App-Code"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "MIC"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "UTC-based-Counter"}, RULE_REQUIRED, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* App-Identifier */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "App-Identifier"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 10415, .avp_name = "OS-ID"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "OS-App-ID"}, RULE_REQUIRED, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* Match-Report */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "Match-Report"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 10415, .avp_name = "Discovery-Type"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "ProSe-App-Code"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "ProSe-Metadata-Index-Mask"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "ProSe-App-Id"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "ProSe-Validity-Timer"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "ProSe-Match-Refresh-Timer"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "ProSe-Application-Metadata"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* ProSe-Discovery-Filter */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "ProSe-Discovery-Filter"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 10415, .avp_name = "Filter-Id"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "ProSe-App-Id"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "ProSe-Validity-Timer"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "ProSe-App-Code"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "ProSe-App-Mask"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* Discovery-Auth-Request */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "Discovery-Auth-Request"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 10415, .avp_name = "Discovery-Type"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "User-Identity"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "ProSe-App-Id"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "ProSe-App-Code"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "ProSe-App-Code-Suffix-Range"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "ProSe-Validity-Timer"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "App-Identifier"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Requesting-RPAUID"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Target-RPAUID"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Target-PDUID"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "ProSe-Restricted-Code"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "ProSe-Query-Code"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "ProSe-Response-Code"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "ProSe-Restricted-Code-Suffix-Range"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Banned-RPAUID"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Banned-PDUID"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Service-Result"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* Match-Report-Info */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "Match-Report-Info"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 10415, .avp_name = "Discovery-Type"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "User-Identity"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "ProSe-App-Id"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* Location-Update-Trigger */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "Location-Update-Trigger"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 10415, .avp_name = "Location-Update-Event-Type"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Change-Of-Area-Type"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Periodic-Location-Type"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* WiFi-P2P-Assistance-Info */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "WiFi-P2P-Assistance-Info"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 10415, .avp_name = "SSID"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "EAP-Master-Session-Key"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "P2P-Features"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "WLAN-Link-Layer-Id-List"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "WLAN-Link-Layer-Id-List"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Operating-Channel"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Assistance-Info-Validity-Timer"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* Discovery-Auth-Response */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "Discovery-Auth-Response"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 10415, .avp_name = "Discovery-Type"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "ProSe-Discovery-Filter"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Visited-PLMN-Id"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "ProSe-Restricted-Code"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "ProSe-Query-Code"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "ProSe-Response-Code"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* WLAN-Assistance-Info */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "WLAN-Assistance-Info"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 10415, .avp_name = "WiFi-P2P-Assistance-Info"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* Assistance-Info */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "Assistance-Info"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 10415, .avp_name = "WLAN-Assistance-Info"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+
+   }	
+
+   /* Commands section */
+   {
+
+   }
+
+   LOG_D( "Extension 'Dictionary definitions for ts29345_avps (e10)' initialized");
+   return 0;
+}
+
+int dict_entry(char * conffile)
+{
+	dict_ts29345_avps_load_defs(conffile);
+	return dict_ts29345_avps_load_rules(conffile);
+}
+
+const char* dict_ts29345_avps_proto_ver(char * conffile) {
+	return ts29345_avps_proto_ver;
+}
+
+const double dict_ts29345_avps_gen_ts(char * conffile) {
+	return ts29345_avps_gen_date;
+}
+
+EXTENSION_ENTRY2("dict_ts29345_avps", dict_ts29345_avps_load_defs, dict_ts29345_avps_load_rules, "dict_ts32299_avps", "dict_ts29272_avps", "dict_ts29273_avps", "dict_ts29336_avps", "dict_ts29344_avps", "dict_ts29329_avps", "dict_ts29229_avps", "dict_draftload_avps", "dict_rfc7683_avps", "dict_rfc4072_avps", "dict_rfc7944_avps");
+
+
+
diff --git a/extensions/dict_ts29345_avps/ts29345_avps.did b/extensions/dict_ts29345_avps/ts29345_avps.did
new file mode 100644
index 0000000..3108b3a
--- /dev/null
+++ b/extensions/dict_ts29345_avps/ts29345_avps.did
@@ -0,0 +1,37 @@
+dict_rfc6942_avps
+dict_ts29468_avps
+dict_ts29343_avps
+dict_ts29128_avps
+dict_ts29337_avps
+dict_3gpp2_avps
+dict_ts29154_avps
+dict_ts29214_avps
+dict_ts29215_avps
+dict_ts29217_avps
+dict_ts29338_avps
+dict_ts29336_avps
+dict_ts29368_avps
+dict_ts32299_avps
+dict_rfc6734_avps
+dict_rfc5778_avps
+dict_rfc5580_avps
+dict_ts29273_avps
+dict_rfc5777_avps
+dict_rfc4006bis_avps
+dict_ts29212_avps
+dict_ts29061_avps
+dict_rfc5447_avps
+dict_ts29272_avps
+dict_etsi283034_avps
+dict_rfc4590_avps
+dict_ts29229_avps
+dict_draftload_avps
+dict_ts29329_avps
+dict_ts29173_avps
+dict_rfc7683_avps
+dict_rfc7944_avps
+dict_ts29344_avps
+dict_rfc4004_avps
+dict_rfc7155_avps
+dict_rfc4072_avps
+dict_ts29345_avps
diff --git a/extensions/dict_ts29368_avps/CMakeLists.txt b/extensions/dict_ts29368_avps/CMakeLists.txt
new file mode 100644
index 0000000..47f7169
--- /dev/null
+++ b/extensions/dict_ts29368_avps/CMakeLists.txt
@@ -0,0 +1,16 @@
+# The dict_ts29368_avps extension
+PROJECT("dict_ts29368_avps library generated by FdGen " C)
+
+# Compile as a module
+FD_ADD_EXTENSION(dict_ts29368_avps dict_ts29368_avps.c)
+
+
+####
+## INSTALL section ##
+
+INSTALL(TARGETS dict_ts29368_avps
+	LIBRARY DESTINATION ${INSTALL_EXTENSIONS_SUFFIX}
+COMPONENT freeDiameter-dictionary-TS29368_AVPS)
+
+
+
diff --git a/extensions/dict_ts29368_avps/dict_ts29368_avps.c b/extensions/dict_ts29368_avps/dict_ts29368_avps.c
new file mode 100644
index 0000000..4ced331
--- /dev/null
+++ b/extensions/dict_ts29368_avps/dict_ts29368_avps.c
@@ -0,0 +1,446 @@
+/*
+* Copyright (c) 2017 Sprint
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*    http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+/****************
+ Generated By: fdtool enhancements to diafuzzer
+ License: same as freeDiameter
+****************/
+
+
+/* 
+ * Dictionary definitions of objects specified in ts29368_avps (e10).
+ */
+#include <freeDiameter/extension.h>
+
+#define PROTO_VER "e10"
+#define GEN_DATE  1506697146.83
+
+const char *ts29368_avps_proto_ver = PROTO_VER;
+const double ts29368_avps_gen_date = GEN_DATE;
+
+/* The content of this file follows the same structure as dict_base_proto.c */
+
+#define CHECK_dict_new( _type, _data, _parent, _ref )                                     \
+{                                                                                         \
+    int _ret = fd_dict_new( fd_g_config->cnf_dict, (_type), (_data), (_parent), (_ref) ); \
+    if ( _ret != 0 && _ret != EEXIST )                                                    \
+       return _ret;                                                                       \
+}
+
+#define CHECK_dict_search( _type, _criteria, _what, _result )		\
+    CHECK_FCT(  fd_dict_search( fd_g_config->cnf_dict, (_type), (_criteria), (_what), (_result), ENOENT) );
+
+struct local_rules_definition {
+    struct dict_avp_request avp_vendor_plus_name;
+    enum rule_position	position;
+    int 			min;
+    int			max;
+};
+
+#define RULE_ORDER( _position ) ((((_position) == RULE_FIXED_HEAD) || ((_position) == RULE_FIXED_TAIL)) ? 1 : 0 )
+
+/* Attention! This version of the macro uses AVP_BY_NAME_AND_VENDOR, in contrast to most other copies! */
+#define PARSE_loc_rules( _rulearray, _parent) {                                                         \
+        int __ar;                                                                                       \
+        for (__ar=0; __ar < sizeof(_rulearray) / sizeof((_rulearray)[0]); __ar++) {                     \
+                struct dict_rule_data __data = { NULL,                                                  \
+                        (_rulearray)[__ar].position,                                                    \
+                        0,                                                                              \
+                        (_rulearray)[__ar].min,                                                         \
+                        (_rulearray)[__ar].max};                                                        \
+                __data.rule_order = RULE_ORDER(__data.rule_position);                                   \
+                CHECK_FCT(  fd_dict_search(                                                             \
+                        fd_g_config->cnf_dict,                                                          \
+                        DICT_AVP,                                                                       \
+                        AVP_BY_NAME_AND_VENDOR,                                                         \
+                        &(_rulearray)[__ar].avp_vendor_plus_name,                                       \
+                        &__data.rule_avp, 0 ) );                                                        \
+                if ( !__data.rule_avp ) {                                                               \
+                        TRACE_DEBUG(INFO, "AVP Not found: '%s'", (_rulearray)[__ar].avp_vendor_plus_name.avp_name);             \
+                        return ENOENT;                                                                  \
+                }                                                                                       \
+                {                                                                                       \
+                         int _ret = fd_dict_new( fd_g_config->cnf_dict, DICT_RULE, &(__data), (_parent), NULL ); \
+                         if ( _ret != 0 && _ret != EEXIST )      {                                      \
+                                TRACE_DEBUG(INFO, "Error on rule with AVP '%s'",                        \
+                                            (_rulearray)[__ar].avp_vendor_plus_name.avp_name);          \
+                                return EINVAL;                                                          \
+                         }                                                                              \
+                }                                                                                       \
+        }                                                                                               \
+}
+
+#define CHECK_vendor_new( _data ) { \
+        struct dict_object * vendor_found; \
+        if (fd_dict_search(fd_g_config->cnf_dict,DICT_VENDOR,VENDOR_BY_ID,&_data.vendor_id,&vendor_found,ENOENT) == ENOENT) { \
+                CHECK_FCT(fd_dict_new(fd_g_config->cnf_dict, DICT_VENDOR, &_data, NULL, NULL)); \
+        } \
+}
+
+#define enumval_def_u32( _val_, _str_ )		\
+    { _str_, 		{ .u32 = _val_ }}
+
+#define enumval_def_os( _len_, _val_, _str_ )				\
+    { _str_, 		{ .os = { .data = (unsigned char *)_val_, .len = _len_ }}}
+
+
+static int dict_ts29368_avps_load_defs(char * conffile)
+{
+   TRACE_ENTRY("%p", conffile);
+	/* Application Section */
+	{
+		/* Create the vendors */		{
+			struct dict_vendor_data vendor_data = { 10415, "3GPP" };
+			CHECK_dict_new(DICT_VENDOR, &vendor_data, NULL, NULL)
+		}
+	}
+
+
+   /* AVP section */
+   {
+		struct dict_object * Address_type;
+		struct dict_object * UTF8String_type;
+		struct dict_object * DiameterIdentity_type;
+		struct dict_object * DiameterURI_type;
+		struct dict_object * Time_type;
+		struct dict_object * IPFilterRule_type;
+
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "Address", &Address_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "UTF8String", &UTF8String_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "DiameterIdentity", &DiameterIdentity_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "DiameterURI", &DiameterURI_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "Time", &Time_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "IPFilterRule", &IPFilterRule_type);
+		/* Payload */
+		{
+			struct dict_avp_data data = {
+				3004,	/* Code */
+				10415,	/* Vendor */
+				"Payload",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Action-Type */
+		{
+			struct dict_avp_data data = {
+				3005,	/* Code */
+				10415,	/* Vendor */
+				"Action-Type",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Action-Type)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "Non_Priority", { .i32=0 }};
+			struct dict_enumval_data        t_2 = { "Priority", { .i32=1 }};
+			struct dict_enumval_data        t_3 = { "Report", { .i32=2 }};
+			struct dict_enumval_data        t_4 = { "Recall", { .i32=3 }};
+			struct dict_enumval_data        t_5 = { "Replace", { .i32=4 }};
+			struct dict_enumval_data        t_6 = { "Delivery", { .i32=5 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_3, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_4, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_5, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_6, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* Priority-Indication */
+		{
+			struct dict_avp_data data = {
+				3006,	/* Code */
+				10415,	/* Vendor */
+				"Priority-Indication",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Priority-Indication)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "Non-Priority", { .i32=0 }};
+			struct dict_enumval_data        t_2 = { "Priority", { .i32=1 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* Reference-Number */
+		{
+			struct dict_avp_data data = {
+				3007,	/* Code */
+				10415,	/* Vendor */
+				"Reference-Number",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Request-Status */
+		{
+			struct dict_avp_data data = {
+				3008,	/* Code */
+				10415,	/* Vendor */
+				"Request-Status",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Request-Status)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "SUCCESS", { .i32=0 }};
+			struct dict_enumval_data        t_2 = { "INVPAYLOAD", { .i32=101 }};
+			struct dict_enumval_data        t_3 = { "INVEXTID", { .i32=102 }};
+			struct dict_enumval_data        t_4 = { "INVSCSID", { .i32=103 }};
+			struct dict_enumval_data        t_5 = { "INVPERIOD", { .i32=104 }};
+			struct dict_enumval_data        t_6 = { "NOTAUTHORIZED", { .i32=105 }};
+			struct dict_enumval_data        t_7 = { "SERVICEUNAVAILABLE", { .i32=106 }};
+			struct dict_enumval_data        t_8 = { "PERMANENTERROR", { .i32=107 }};
+			struct dict_enumval_data        t_9 = { "QUOTAEXCEEDED", { .i32=108 }};
+			struct dict_enumval_data        t_10 = { "RATEEXCEEDED", { .i32=109 }};
+			struct dict_enumval_data        t_11 = { "REPLACEFAIL", { .i32=110 }};
+			struct dict_enumval_data        t_12 = { "RECALLFAIL", { .i32=111 }};
+			struct dict_enumval_data        t_13 = { "ORIGINALMESSAGESENT", { .i32=112 }};
+			struct dict_enumval_data        t_14 = { "TEMPORARYERROR", { .i32=201 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_3, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_4, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_5, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_6, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_7, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_8, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_9, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_10, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_11, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_12, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_13, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_14, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* Delivery-Outcome */
+		{
+			struct dict_avp_data data = {
+				3009,	/* Code */
+				10415,	/* Vendor */
+				"Delivery-Outcome",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Delivery-Outcome)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "SUCCESS", { .i32=0 }};
+			struct dict_enumval_data        t_2 = { "EXPIRED", { .i32=1 }};
+			struct dict_enumval_data        t_3 = { "TEMPORARYERROR", { .i32=2 }};
+			struct dict_enumval_data        t_4 = { "UNDELIVERABLE", { .i32=3 }};
+			struct dict_enumval_data        t_5 = { "UNCONFIRMED", { .i32=4 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_3, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_4, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_5, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* Application-Port-Identifier */
+		{
+			struct dict_avp_data data = {
+				3010,	/* Code */
+				10415,	/* Vendor */
+				"Application-Port-Identifier",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Old-Reference-Number */
+		{
+			struct dict_avp_data data = {
+				3011,	/* Code */
+				10415,	/* Vendor */
+				"Old-Reference-Number",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Feature-Supported-In-Final-Target */
+		{
+			struct dict_avp_data data = {
+				3012,	/* Code */
+				10415,	/* Vendor */
+				"Feature-Supported-In-Final-Target",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Trigger-Data */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				3003,	/* Code */
+				10415,	/* Vendor */
+				"Trigger-Data",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* Device-Notification */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				3002,	/* Code */
+				10415,	/* Vendor */
+				"Device-Notification",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* Device-Action */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				3001,	/* Code */
+				10415,	/* Vendor */
+				"Device-Action",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+
+	
+   }
+
+   /* Commands section */
+   {
+
+   }
+
+   return 0;
+}
+
+static int dict_ts29368_avps_load_rules(char * conffile)
+{
+   /* Grouped AVP section */
+   {
+	  /* Trigger-Data */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "Trigger-Data"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 10415, .avp_name = "Payload"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Priority-Indication"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Application-Port-Identifier"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* Device-Notification */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "Device-Notification"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 10415, .avp_name = "External-Identifier"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "MSISDN"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "SCS-Identity"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Reference-Number"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Action-Type"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Request-Status"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "MTC-Error-Diagnostic"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Delivery-Outcome"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "SM-RP-UI"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Application-Port-Identifier"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* Device-Action */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "Device-Action"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 10415, .avp_name = "External-Identifier"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "MSISDN"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "SCS-Identity"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Reference-Number"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Old-Reference-Number"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Action-Type"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Trigger-Data"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Validity-Time"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+
+   }	
+
+   /* Commands section */
+   {
+
+   }
+
+   LOG_D( "Extension 'Dictionary definitions for ts29368_avps (e10)' initialized");
+   return 0;
+}
+
+int dict_entry(char * conffile)
+{
+	dict_ts29368_avps_load_defs(conffile);
+	return dict_ts29368_avps_load_rules(conffile);
+}
+
+const char* dict_ts29368_avps_proto_ver(char * conffile) {
+	return ts29368_avps_proto_ver;
+}
+
+const double dict_ts29368_avps_gen_ts(char * conffile) {
+	return ts29368_avps_gen_date;
+}
+
+EXTENSION_ENTRY2("dict_ts29368_avps", dict_ts29368_avps_load_defs, dict_ts29368_avps_load_rules, "dict_ts29337_avps", "dict_ts29336_avps", "dict_ts29338_avps", "dict_ts29329_avps", "dict_ts29229_avps", "dict_draftload_avps", "dict_rfc4006bis_avps");
+
+
+
diff --git a/extensions/dict_ts29368_avps/ts29368_avps.did b/extensions/dict_ts29368_avps/ts29368_avps.did
new file mode 100644
index 0000000..6f87787
--- /dev/null
+++ b/extensions/dict_ts29368_avps/ts29368_avps.did
@@ -0,0 +1,37 @@
+dict_rfc6942_avps
+dict_ts29468_avps
+dict_ts29154_avps
+dict_ts29214_avps
+dict_ts29215_avps
+dict_ts29217_avps
+dict_3gpp2_avps
+dict_ts29337_avps
+dict_ts29343_avps
+dict_ts29338_avps
+dict_ts29128_avps
+dict_ts29344_avps
+dict_ts29345_avps
+dict_ts29173_avps
+dict_ts32299_avps
+dict_rfc6734_avps
+dict_rfc5580_avps
+dict_rfc4072_avps
+dict_ts29273_avps
+dict_rfc4006bis_avps
+dict_ts29212_avps
+dict_ts29061_avps
+dict_ts29272_avps
+dict_rfc5447_avps
+dict_rfc5778_avps
+dict_rfc5777_avps
+dict_ts29336_avps
+dict_etsi283034_avps
+dict_rfc4590_avps
+dict_rfc4004_avps
+dict_rfc7155_avps
+dict_ts29229_avps
+dict_rfc7683_avps
+dict_draftload_avps
+dict_rfc7944_avps
+dict_ts29329_avps
+dict_ts29368_avps
diff --git a/extensions/dict_ts29468_avps/CMakeLists.txt b/extensions/dict_ts29468_avps/CMakeLists.txt
new file mode 100644
index 0000000..0c54916
--- /dev/null
+++ b/extensions/dict_ts29468_avps/CMakeLists.txt
@@ -0,0 +1,16 @@
+# The dict_ts29468_avps extension
+PROJECT("dict_ts29468_avps library generated by FdGen " C)
+
+# Compile as a module
+FD_ADD_EXTENSION(dict_ts29468_avps dict_ts29468_avps.c)
+
+
+####
+## INSTALL section ##
+
+INSTALL(TARGETS dict_ts29468_avps
+	LIBRARY DESTINATION ${INSTALL_EXTENSIONS_SUFFIX}
+COMPONENT freeDiameter-dictionary-TS29468_AVPS)
+
+
+
diff --git a/extensions/dict_ts29468_avps/dict_ts29468_avps.c b/extensions/dict_ts29468_avps/dict_ts29468_avps.c
new file mode 100644
index 0000000..15fd2bb
--- /dev/null
+++ b/extensions/dict_ts29468_avps/dict_ts29468_avps.c
@@ -0,0 +1,639 @@
+/*
+* Copyright (c) 2017 Sprint
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*    http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+/****************
+ Generated By: fdtool enhancements to diafuzzer
+ License: same as freeDiameter
+****************/
+
+
+/* 
+ * Dictionary definitions of objects specified in ts29468_avps (e10).
+ */
+#include <freeDiameter/extension.h>
+
+#define PROTO_VER "e10"
+#define GEN_DATE  1506697168.73
+
+const char *ts29468_avps_proto_ver = PROTO_VER;
+const double ts29468_avps_gen_date = GEN_DATE;
+
+/* The content of this file follows the same structure as dict_base_proto.c */
+
+#define CHECK_dict_new( _type, _data, _parent, _ref )                                     \
+{                                                                                         \
+    int _ret = fd_dict_new( fd_g_config->cnf_dict, (_type), (_data), (_parent), (_ref) ); \
+    if ( _ret != 0 && _ret != EEXIST )                                                    \
+       return _ret;                                                                       \
+}
+
+#define CHECK_dict_search( _type, _criteria, _what, _result )		\
+    CHECK_FCT(  fd_dict_search( fd_g_config->cnf_dict, (_type), (_criteria), (_what), (_result), ENOENT) );
+
+struct local_rules_definition {
+    struct dict_avp_request avp_vendor_plus_name;
+    enum rule_position	position;
+    int 			min;
+    int			max;
+};
+
+#define RULE_ORDER( _position ) ((((_position) == RULE_FIXED_HEAD) || ((_position) == RULE_FIXED_TAIL)) ? 1 : 0 )
+
+/* Attention! This version of the macro uses AVP_BY_NAME_AND_VENDOR, in contrast to most other copies! */
+#define PARSE_loc_rules( _rulearray, _parent) {                                                         \
+        int __ar;                                                                                       \
+        for (__ar=0; __ar < sizeof(_rulearray) / sizeof((_rulearray)[0]); __ar++) {                     \
+                struct dict_rule_data __data = { NULL,                                                  \
+                        (_rulearray)[__ar].position,                                                    \
+                        0,                                                                              \
+                        (_rulearray)[__ar].min,                                                         \
+                        (_rulearray)[__ar].max};                                                        \
+                __data.rule_order = RULE_ORDER(__data.rule_position);                                   \
+                CHECK_FCT(  fd_dict_search(                                                             \
+                        fd_g_config->cnf_dict,                                                          \
+                        DICT_AVP,                                                                       \
+                        AVP_BY_NAME_AND_VENDOR,                                                         \
+                        &(_rulearray)[__ar].avp_vendor_plus_name,                                       \
+                        &__data.rule_avp, 0 ) );                                                        \
+                if ( !__data.rule_avp ) {                                                               \
+                        TRACE_DEBUG(INFO, "AVP Not found: '%s'", (_rulearray)[__ar].avp_vendor_plus_name.avp_name);             \
+                        return ENOENT;                                                                  \
+                }                                                                                       \
+                {                                                                                       \
+                         int _ret = fd_dict_new( fd_g_config->cnf_dict, DICT_RULE, &(__data), (_parent), NULL ); \
+                         if ( _ret != 0 && _ret != EEXIST )      {                                      \
+                                TRACE_DEBUG(INFO, "Error on rule with AVP '%s'",                        \
+                                            (_rulearray)[__ar].avp_vendor_plus_name.avp_name);          \
+                                return EINVAL;                                                          \
+                         }                                                                              \
+                }                                                                                       \
+        }                                                                                               \
+}
+
+#define CHECK_vendor_new( _data ) { \
+        struct dict_object * vendor_found; \
+        if (fd_dict_search(fd_g_config->cnf_dict,DICT_VENDOR,VENDOR_BY_ID,&_data.vendor_id,&vendor_found,ENOENT) == ENOENT) { \
+                CHECK_FCT(fd_dict_new(fd_g_config->cnf_dict, DICT_VENDOR, &_data, NULL, NULL)); \
+        } \
+}
+
+#define enumval_def_u32( _val_, _str_ )		\
+    { _str_, 		{ .u32 = _val_ }}
+
+#define enumval_def_os( _len_, _val_, _str_ )				\
+    { _str_, 		{ .os = { .data = (unsigned char *)_val_, .len = _len_ }}}
+
+
+static int dict_ts29468_avps_load_defs(char * conffile)
+{
+   TRACE_ENTRY("%p", conffile);
+	/* Application Section */
+	{
+		/* Create the vendors */		{
+			struct dict_vendor_data vendor_data = { 10415, "3GPP" };
+			CHECK_dict_new(DICT_VENDOR, &vendor_data, NULL, NULL)
+		}
+	}
+
+
+   /* AVP section */
+   {
+		struct dict_object * Address_type;
+		struct dict_object * UTF8String_type;
+		struct dict_object * DiameterIdentity_type;
+		struct dict_object * DiameterURI_type;
+		struct dict_object * Time_type;
+		struct dict_object * IPFilterRule_type;
+
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "Address", &Address_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "UTF8String", &UTF8String_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "DiameterIdentity", &DiameterIdentity_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "DiameterURI", &DiameterURI_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "Time", &Time_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "IPFilterRule", &IPFilterRule_type);
+		/* BMSC-Address */
+		{
+			struct dict_avp_data data = {
+				3500,	/* Code */
+				10415,	/* Vendor */
+				"BMSC-Address",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, Address_type, NULL);
+		};
+		/* BMSC-Port */
+		{
+			struct dict_avp_data data = {
+				3501,	/* Code */
+				10415,	/* Vendor */
+				"BMSC-Port",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Common-Tunnel-Endpoint-Identifier */
+		{
+			struct dict_avp_data data = {
+				3524,	/* Code */
+				10415,	/* Vendor */
+				"Common-Tunnel-Endpoint-Identifier",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* MB2U-Security */
+		{
+			struct dict_avp_data data = {
+				3517,	/* Code */
+				10415,	/* Vendor */
+				"MB2U-Security",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* MBMS-Bearer-Event */
+		{
+			struct dict_avp_data data = {
+				3502,	/* Code */
+				10415,	/* Vendor */
+				"MBMS-Bearer-Event",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* MBMS-Bearer-Result */
+		{
+			struct dict_avp_data data = {
+				3506,	/* Code */
+				10415,	/* Vendor */
+				"MBMS-Bearer-Result",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* MBMS-eNB-IP-Multicast-Address */
+		{
+			struct dict_avp_data data = {
+				3520,	/* Code */
+				10415,	/* Vendor */
+				"MBMS-eNB-IP-Multicast-Address",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, Address_type, NULL);
+		};
+		/* MBMS-eNB-IPv6-Multicast-Address */
+		{
+			struct dict_avp_data data = {
+				3521,	/* Code */
+				10415,	/* Vendor */
+				"MBMS-eNB-IPv6-Multicast-Address",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, Address_type, NULL);
+		};
+		/* MBMS-GW-SSM-IP-Address */
+		{
+			struct dict_avp_data data = {
+				3522,	/* Code */
+				10415,	/* Vendor */
+				"MBMS-GW-SSM-IP-Address",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, Address_type, NULL);
+		};
+		/* MBMS-GW-SSM-IPv6-Address */
+		{
+			struct dict_avp_data data = {
+				3523,	/* Code */
+				10415,	/* Vendor */
+				"MBMS-GW-SSM-IPv6-Address",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, Address_type, NULL);
+		};
+		/* MBMS-Start-Time */
+		{
+			struct dict_avp_data data = {
+				3507,	/* Code */
+				10415,	/* Vendor */
+				"MBMS-Start-Time",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, Time_type, NULL);
+		};
+		/* Radio-Frequency */
+		{
+			struct dict_avp_data data = {
+				3508,	/* Code */
+				10415,	/* Vendor */
+				"Radio-Frequency",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* TMGI-Allocation-Result */
+		{
+			struct dict_avp_data data = {
+				3511,	/* Code */
+				10415,	/* Vendor */
+				"TMGI-Allocation-Result",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* TMGI-Deallocation-Result */
+		{
+			struct dict_avp_data data = {
+				3514,	/* Code */
+				10415,	/* Vendor */
+				"TMGI-Deallocation-Result",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* TMGI-Number */
+		{
+			struct dict_avp_data data = {
+				3516,	/* Code */
+				10415,	/* Vendor */
+				"TMGI-Number",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* TMGI-Expiry */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				3515,	/* Code */
+				10415,	/* Vendor */
+				"TMGI-Expiry",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* Local-MB2-U-Information */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				3519,	/* Code */
+				10415,	/* Vendor */
+				"Local-MB2-U-Information",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* MBMS-Bearer-Event-Notification */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				3503,	/* Code */
+				10415,	/* Vendor */
+				"MBMS-Bearer-Event-Notification",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* MBMS-Bearer-Response */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				3505,	/* Code */
+				10415,	/* Vendor */
+				"MBMS-Bearer-Response",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* TMGI-Deallocation-Response */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				3513,	/* Code */
+				10415,	/* Vendor */
+				"TMGI-Deallocation-Response",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* TMGI-Allocation-Request */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				3509,	/* Code */
+				10415,	/* Vendor */
+				"TMGI-Allocation-Request",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* TMGI-Deallocation-Request */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				3512,	/* Code */
+				10415,	/* Vendor */
+				"TMGI-Deallocation-Request",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* Local-M1-Information */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				3518,	/* Code */
+				10415,	/* Vendor */
+				"Local-M1-Information",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* TMGI-Allocation-Response */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				3510,	/* Code */
+				10415,	/* Vendor */
+				"TMGI-Allocation-Response",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* MBMS-Bearer-Request */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				3504,	/* Code */
+				10415,	/* Vendor */
+				"MBMS-Bearer-Request",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+
+	
+   }
+
+   /* Commands section */
+   {
+
+   }
+
+   return 0;
+}
+
+static int dict_ts29468_avps_load_rules(char * conffile)
+{
+   /* Grouped AVP section */
+   {
+	  /* TMGI-Expiry */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "TMGI-Expiry"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 10415, .avp_name = "TMGI"}, RULE_REQUIRED, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* Local-MB2-U-Information */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "Local-MB2-U-Information"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 10415, .avp_name = "BMSC-Address"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "BMSC-Port"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* MBMS-Bearer-Event-Notification */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "MBMS-Bearer-Event-Notification"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 10415, .avp_name = "TMGI"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "MBMS-Flow-Identifier"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "MBMS-Bearer-Event"}, RULE_REQUIRED, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* MBMS-Bearer-Response */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "MBMS-Bearer-Response"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 10415, .avp_name = "TMGI"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "MBMS-Flow-Identifier"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "MBMS-Session-Duration"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "MBMS-Bearer-Result"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "BMSC-Address"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "BMSC-Port"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "MB2U-Security"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Radio-Frequency"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* TMGI-Deallocation-Response */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "TMGI-Deallocation-Response"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 10415, .avp_name = "TMGI"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "TMGI-Deallocation-Result"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* TMGI-Allocation-Request */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "TMGI-Allocation-Request"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 10415, .avp_name = "TMGI-Number"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "TMGI"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* TMGI-Deallocation-Request */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "TMGI-Deallocation-Request"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 10415, .avp_name = "TMGI"}, RULE_REQUIRED, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* Local-M1-Information */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "Local-M1-Information"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 10415, .avp_name = "MBMS-eNB-IP-Multicast-Address"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "MBMS-eNB-IPv6-Multicast-Address"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "MBMS-GW-SSM-IP-Address"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "MBMS-GW-SSM-IPv6-Address"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Common-Tunnel-Endpoint-Identifier"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* TMGI-Allocation-Response */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "TMGI-Allocation-Response"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 10415, .avp_name = "TMGI"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "MBMS-Session-Duration"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "TMGI-Allocation-Result"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* MBMS-Bearer-Request */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "MBMS-Bearer-Request"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 10415, .avp_name = "MBMS-StartStop-Indication"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "TMGI"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "MBMS-Flow-Identifier"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "QoS-Information"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "MBMS-Service-Area"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "MBMS-Start-Time"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "MB2U-Security"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "MBMS-Cell-List"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Local-M1-Information"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Local-MB2-U-Information"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+
+   }	
+
+   /* Commands section */
+   {
+
+   }
+
+   LOG_D( "Extension 'Dictionary definitions for ts29468_avps (e10)' initialized");
+   return 0;
+}
+
+int dict_entry(char * conffile)
+{
+	dict_ts29468_avps_load_defs(conffile);
+	return dict_ts29468_avps_load_rules(conffile);
+}
+
+const char* dict_ts29468_avps_proto_ver(char * conffile) {
+	return ts29468_avps_proto_ver;
+}
+
+const double dict_ts29468_avps_gen_ts(char * conffile) {
+	return ts29468_avps_gen_date;
+}
+
+EXTENSION_ENTRY2("dict_ts29468_avps", dict_ts29468_avps_load_defs, dict_ts29468_avps_load_rules, "dict_ts29212_avps", "dict_ts29229_avps", "dict_ts29061_avps", "dict_draftload_avps", "dict_rfc7944_avps");
+
+
+
diff --git a/extensions/dict_ts29468_avps/ts29468_avps.did b/extensions/dict_ts29468_avps/ts29468_avps.did
new file mode 100644
index 0000000..3b6a01f
--- /dev/null
+++ b/extensions/dict_ts29468_avps/ts29468_avps.did
@@ -0,0 +1,37 @@
+dict_rfc6942_avps
+dict_ts29154_avps
+dict_ts29214_avps
+dict_ts29215_avps
+dict_ts29217_avps
+dict_3gpp2_avps
+dict_ts29343_avps
+dict_ts29338_avps
+dict_ts29128_avps
+dict_ts29344_avps
+dict_ts29345_avps
+dict_ts32299_avps
+dict_rfc6734_avps
+dict_rfc5778_avps
+dict_rfc5580_avps
+dict_rfc4072_avps
+dict_ts29273_avps
+dict_ts29173_avps
+dict_ts29337_avps
+dict_etsi283034_avps
+dict_rfc4590_avps
+dict_ts29229_avps
+dict_draftload_avps
+dict_ts29329_avps
+dict_ts29368_avps
+dict_ts29336_avps
+dict_ts29061_avps
+dict_rfc5447_avps
+dict_ts29272_avps
+dict_rfc7683_avps
+dict_rfc7944_avps
+dict_rfc5777_avps
+dict_rfc4006bis_avps
+dict_rfc4004_avps
+dict_rfc7155_avps
+dict_ts29212_avps
+dict_ts29468_avps
diff --git a/extensions/dict_ts32299_avps/CMakeLists.txt b/extensions/dict_ts32299_avps/CMakeLists.txt
new file mode 100644
index 0000000..3ee6973
--- /dev/null
+++ b/extensions/dict_ts32299_avps/CMakeLists.txt
@@ -0,0 +1,16 @@
+# The dict_ts32299_avps extension
+PROJECT("dict_ts32299_avps library generated by FdGen " C)
+
+# Compile as a module
+FD_ADD_EXTENSION(dict_ts32299_avps dict_ts32299_avps.c)
+
+
+####
+## INSTALL section ##
+
+INSTALL(TARGETS dict_ts32299_avps
+	LIBRARY DESTINATION ${INSTALL_EXTENSIONS_SUFFIX}
+COMPONENT freeDiameter-dictionary-TS32299_AVPS)
+
+
+
diff --git a/extensions/dict_ts32299_avps/dict_ts32299_avps.c b/extensions/dict_ts32299_avps/dict_ts32299_avps.c
new file mode 100644
index 0000000..d81140a
--- /dev/null
+++ b/extensions/dict_ts32299_avps/dict_ts32299_avps.c
@@ -0,0 +1,7604 @@
+/*
+* Copyright (c) 2017 Sprint
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*    http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+/****************
+ Generated By: fdtool enhancements to diafuzzer
+ License: same as freeDiameter
+****************/
+
+
+/* 
+ * Dictionary definitions of objects specified in ts32299_avps (e30).
+ */
+#include <freeDiameter/extension.h>
+
+#define PROTO_VER "e30"
+#define GEN_DATE  1506697143.39
+
+const char *ts32299_avps_proto_ver = PROTO_VER;
+const double ts32299_avps_gen_date = GEN_DATE;
+
+/* The content of this file follows the same structure as dict_base_proto.c */
+
+#define CHECK_dict_new( _type, _data, _parent, _ref )                                     \
+{                                                                                         \
+    int _ret = fd_dict_new( fd_g_config->cnf_dict, (_type), (_data), (_parent), (_ref) ); \
+    if ( _ret != 0 && _ret != EEXIST )                                                    \
+       return _ret;                                                                       \
+}
+
+#define CHECK_dict_search( _type, _criteria, _what, _result )		\
+    CHECK_FCT(  fd_dict_search( fd_g_config->cnf_dict, (_type), (_criteria), (_what), (_result), ENOENT) );
+
+struct local_rules_definition {
+    struct dict_avp_request avp_vendor_plus_name;
+    enum rule_position	position;
+    int 			min;
+    int			max;
+};
+
+#define RULE_ORDER( _position ) ((((_position) == RULE_FIXED_HEAD) || ((_position) == RULE_FIXED_TAIL)) ? 1 : 0 )
+
+/* Attention! This version of the macro uses AVP_BY_NAME_AND_VENDOR, in contrast to most other copies! */
+#define PARSE_loc_rules( _rulearray, _parent) {                                                         \
+        int __ar;                                                                                       \
+        for (__ar=0; __ar < sizeof(_rulearray) / sizeof((_rulearray)[0]); __ar++) {                     \
+                struct dict_rule_data __data = { NULL,                                                  \
+                        (_rulearray)[__ar].position,                                                    \
+                        0,                                                                              \
+                        (_rulearray)[__ar].min,                                                         \
+                        (_rulearray)[__ar].max};                                                        \
+                __data.rule_order = RULE_ORDER(__data.rule_position);                                   \
+                CHECK_FCT(  fd_dict_search(                                                             \
+                        fd_g_config->cnf_dict,                                                          \
+                        DICT_AVP,                                                                       \
+                        AVP_BY_NAME_AND_VENDOR,                                                         \
+                        &(_rulearray)[__ar].avp_vendor_plus_name,                                       \
+                        &__data.rule_avp, 0 ) );                                                        \
+                if ( !__data.rule_avp ) {                                                               \
+                        TRACE_DEBUG(INFO, "AVP Not found: '%s'", (_rulearray)[__ar].avp_vendor_plus_name.avp_name);             \
+                        return ENOENT;                                                                  \
+                }                                                                                       \
+                {                                                                                       \
+                         int _ret = fd_dict_new( fd_g_config->cnf_dict, DICT_RULE, &(__data), (_parent), NULL ); \
+                         if ( _ret != 0 && _ret != EEXIST )      {                                      \
+                                TRACE_DEBUG(INFO, "Error on rule with AVP '%s'",                        \
+                                            (_rulearray)[__ar].avp_vendor_plus_name.avp_name);          \
+                                return EINVAL;                                                          \
+                         }                                                                              \
+                }                                                                                       \
+        }                                                                                               \
+}
+
+#define CHECK_vendor_new( _data ) { \
+        struct dict_object * vendor_found; \
+        if (fd_dict_search(fd_g_config->cnf_dict,DICT_VENDOR,VENDOR_BY_ID,&_data.vendor_id,&vendor_found,ENOENT) == ENOENT) { \
+                CHECK_FCT(fd_dict_new(fd_g_config->cnf_dict, DICT_VENDOR, &_data, NULL, NULL)); \
+        } \
+}
+
+#define enumval_def_u32( _val_, _str_ )		\
+    { _str_, 		{ .u32 = _val_ }}
+
+#define enumval_def_os( _len_, _val_, _str_ )				\
+    { _str_, 		{ .os = { .data = (unsigned char *)_val_, .len = _len_ }}}
+
+
+static int dict_ts32299_avps_load_defs(char * conffile)
+{
+   TRACE_ENTRY("%p", conffile);
+	/* Application Section */
+	{
+		/* Create the vendors */		{
+			struct dict_vendor_data vendor_data = { 10415, "3GPP" };
+			CHECK_dict_new(DICT_VENDOR, &vendor_data, NULL, NULL)
+		}
+	}
+
+
+   /* AVP section */
+   {
+		struct dict_object * Address_type;
+		struct dict_object * UTF8String_type;
+		struct dict_object * DiameterIdentity_type;
+		struct dict_object * DiameterURI_type;
+		struct dict_object * Time_type;
+		struct dict_object * IPFilterRule_type;
+
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "Address", &Address_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "UTF8String", &UTF8String_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "DiameterIdentity", &DiameterIdentity_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "DiameterURI", &DiameterURI_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "Time", &Time_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "IPFilterRule", &IPFilterRule_type);
+		/* 3GPP-PS-Data-Off-Status */
+		{
+			struct dict_avp_data data = {
+				4406,	/* Code */
+				10415,	/* Vendor */
+				"3GPP-PS-Data-Off-Status",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(3GPP-PS-Data-Off-Status)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "Active", { .i32=0 }};
+			struct dict_enumval_data        t_2 = { "Inactive", { .i32=1 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* Access-Network-Information */
+		{
+			struct dict_avp_data data = {
+				1263,	/* Code */
+				10415,	/* Vendor */
+				"Access-Network-Information",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Access-Transfer-Type */
+		{
+			struct dict_avp_data data = {
+				2710,	/* Code */
+				10415,	/* Vendor */
+				"Access-Transfer-Type",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Access-Transfer-Type)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "PS_to_CS_Transfer", { .i32=0 }};
+			struct dict_enumval_data        t_2 = { "CS_to_PS_Transfer", { .i32=1 }};
+			struct dict_enumval_data        t_3 = { "PS_to_PS_Transfer", { .i32=2 }};
+			struct dict_enumval_data        t_4 = { "CS_to_CS_Transfer", { .i32=3 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_3, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_4, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* Account-Expiration */
+		{
+			struct dict_avp_data data = {
+				2309,	/* Code */
+				10415,	/* Vendor */
+				"Account-Expiration",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, Time_type, NULL);
+		};
+		/* Adaptations */
+		{
+			struct dict_avp_data data = {
+				1217,	/* Code */
+				10415,	/* Vendor */
+				"Adaptations",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Adaptations)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "Yes", { .i32=0 }};
+			struct dict_enumval_data        t_2 = { "No", { .i32=1 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* Additional-Exception-Reports */
+		{
+			struct dict_avp_data data = {
+				3936,	/* Code */
+				10415,	/* Vendor */
+				"Additional-Exception-Reports",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Additional-Exception-Reports)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "Not_allowed", { .i32=0 }};
+			struct dict_enumval_data        t_2 = { "Allowed", { .i32=1 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* Additional-Type-Information */
+		{
+			struct dict_avp_data data = {
+				1205,	/* Code */
+				10415,	/* Vendor */
+				"Additional-Type-Information",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, UTF8String_type, NULL);
+		};
+		/* Address-Data */
+		{
+			struct dict_avp_data data = {
+				897,	/* Code */
+				10415,	/* Vendor */
+				"Address-Data",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, UTF8String_type, NULL);
+		};
+		/* Addressee-Type */
+		{
+			struct dict_avp_data data = {
+				1208,	/* Code */
+				10415,	/* Vendor */
+				"Addressee-Type",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Addressee-Type)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "TO", { .i32=0 }};
+			struct dict_enumval_data        t_2 = { "CC", { .i32=1 }};
+			struct dict_enumval_data        t_3 = { "BCC", { .i32=2 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_3, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* Address-Type */
+		{
+			struct dict_avp_data data = {
+				899,	/* Code */
+				10415,	/* Vendor */
+				"Address-Type",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Address-Type)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "e_mail_address", { .i32=0 }};
+			struct dict_enumval_data        t_2 = { "MSISDN", { .i32=1 }};
+			struct dict_enumval_data        t_3 = { "IPv4_Address", { .i32=2 }};
+			struct dict_enumval_data        t_4 = { "IPv6_Address", { .i32=3 }};
+			struct dict_enumval_data        t_5 = { "Numeric_Shortcode", { .i32=4 }};
+			struct dict_enumval_data        t_6 = { "Alphanumeric_Shortcode", { .i32=5 }};
+			struct dict_enumval_data        t_7 = { "Other", { .i32=6 }};
+			struct dict_enumval_data        t_8 = { "IMSI", { .i32=7 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_3, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_4, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_5, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_6, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_7, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_8, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* Alternate-Charged-Party-Address */
+		{
+			struct dict_avp_data data = {
+				1280,	/* Code */
+				10415,	/* Vendor */
+				"Alternate-Charged-Party-Address",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, UTF8String_type, NULL);
+		};
+		/* Announcement-Identifier */
+		{
+			struct dict_avp_data data = {
+				3905,	/* Code */
+				10415,	/* Vendor */
+				"Announcement-Identifier",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Announcement-Order */
+		{
+			struct dict_avp_data data = {
+				3906,	/* Code */
+				10415,	/* Vendor */
+				"Announcement-Order",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Announcing-UE-HPLMN-Identifier */
+		{
+			struct dict_avp_data data = {
+				3426,	/* Code */
+				10415,	/* Vendor */
+				"Announcing-UE-HPLMN-Identifier",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, UTF8String_type, NULL);
+		};
+		/* Announcing-UE-VPLMN-Identifier */
+		{
+			struct dict_avp_data data = {
+				3427,	/* Code */
+				10415,	/* Vendor */
+				"Announcing-UE-VPLMN-Identifier",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, UTF8String_type, NULL);
+		};
+		/* AoC-Format */
+		{
+			struct dict_avp_data data = {
+				2310,	/* Code */
+				10415,	/* Vendor */
+				"AoC-Format",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(AoC-Format)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "MONETARY", { .i32=0 }};
+			struct dict_enumval_data        t_2 = { "NON_MONETARY", { .i32=1 }};
+			struct dict_enumval_data        t_3 = { "CAI", { .i32=2 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_3, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* AoC-Request-Type */
+		{
+			struct dict_avp_data data = {
+				2055,	/* Code */
+				10415,	/* Vendor */
+				"AoC-Request-Type",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(AoC-Request-Type)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "AoC_NOT_REQUESTED", { .i32=0 }};
+			struct dict_enumval_data        t_2 = { "AoC_FULL", { .i32=1 }};
+			struct dict_enumval_data        t_3 = { "AoC_COST_ONLY", { .i32=2 }};
+			struct dict_enumval_data        t_4 = { "AoC_TARIFF_ONLY", { .i32=3 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_3, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_4, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* AoC-Service-Obligatory-Type */
+		{
+			struct dict_avp_data data = {
+				2312,	/* Code */
+				10415,	/* Vendor */
+				"AoC-Service-Obligatory-Type",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(AoC-Service-Obligatory-Type)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "NON_BINDING", { .i32=0 }};
+			struct dict_enumval_data        t_2 = { "BINDING", { .i32=1 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* AoC-Service-Type */
+		{
+			struct dict_avp_data data = {
+				2313,	/* Code */
+				10415,	/* Vendor */
+				"AoC-Service-Type",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(AoC-Service-Type)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "NONE", { .i32=0 }};
+			struct dict_enumval_data        t_2 = { "AOC-S", { .i32=1 }};
+			struct dict_enumval_data        t_3 = { "AOC-D", { .i32=2 }};
+			struct dict_enumval_data        t_4 = { "AOC-E", { .i32=3 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_3, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_4, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* Applic-ID */
+		{
+			struct dict_avp_data data = {
+				1218,	/* Code */
+				10415,	/* Vendor */
+				"Applic-ID",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, UTF8String_type, NULL);
+		};
+		/* Application-Provided-Called-Party-Address */
+		{
+			struct dict_avp_data data = {
+				837,	/* Code */
+				10415,	/* Vendor */
+				"Application-Provided-Called-Party-Address",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, UTF8String_type, NULL);
+		};
+		/* Application-Server */
+		{
+			struct dict_avp_data data = {
+				836,	/* Code */
+				10415,	/* Vendor */
+				"Application-Server",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, UTF8String_type, NULL);
+		};
+		/* Application-Specific-Data */
+		{
+			struct dict_avp_data data = {
+				3458,	/* Code */
+				10415,	/* Vendor */
+				"Application-Specific-Data",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Associated-Party-Address */
+		{
+			struct dict_avp_data data = {
+				2035,	/* Code */
+				10415,	/* Vendor */
+				"Associated-Party-Address",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, UTF8String_type, NULL);
+		};
+		/* Associated-URI */
+		{
+			struct dict_avp_data data = {
+				856,	/* Code */
+				10415,	/* Vendor */
+				"Associated-URI",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, UTF8String_type, NULL);
+		};
+		/* Authorised-QoS */
+		{
+			struct dict_avp_data data = {
+				849,	/* Code */
+				10415,	/* Vendor */
+				"Authorised-QoS",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, UTF8String_type, NULL);
+		};
+		/* Aux-Applic-Info */
+		{
+			struct dict_avp_data data = {
+				1219,	/* Code */
+				10415,	/* Vendor */
+				"Aux-Applic-Info",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, UTF8String_type, NULL);
+		};
+		/* Base-Time-Interval */
+		{
+			struct dict_avp_data data = {
+				1265,	/* Code */
+				10415,	/* Vendor */
+				"Base-Time-Interval",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Bearer-Capability */
+		{
+			struct dict_avp_data data = {
+				3412,	/* Code */
+				10415,	/* Vendor */
+				"Bearer-Capability",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Bearer-Service */
+		{
+			struct dict_avp_data data = {
+				854,	/* Code */
+				10415,	/* Vendor */
+				"Bearer-Service",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* BSSID */
+		{
+			struct dict_avp_data data = {
+				2716,	/* Code */
+				10415,	/* Vendor */
+				"BSSID",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, UTF8String_type, NULL);
+		};
+		/* Called-Asserted-Identity */
+		{
+			struct dict_avp_data data = {
+				1250,	/* Code */
+				10415,	/* Vendor */
+				"Called-Asserted-Identity",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, UTF8String_type, NULL);
+		};
+		/* Called-Identity */
+		{
+			struct dict_avp_data data = {
+				3916,	/* Code */
+				10415,	/* Vendor */
+				"Called-Identity",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, UTF8String_type, NULL);
+		};
+		/* Called-Party-Address */
+		{
+			struct dict_avp_data data = {
+				832,	/* Code */
+				10415,	/* Vendor */
+				"Called-Party-Address",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, UTF8String_type, NULL);
+		};
+		/* Calling-Party-Address */
+		{
+			struct dict_avp_data data = {
+				831,	/* Code */
+				10415,	/* Vendor */
+				"Calling-Party-Address",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, UTF8String_type, NULL);
+		};
+		/* Carrier-Select-Routing-Information */
+		{
+			struct dict_avp_data data = {
+				2023,	/* Code */
+				10415,	/* Vendor */
+				"Carrier-Select-Routing-Information",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, UTF8String_type, NULL);
+		};
+		/* Cause-Code */
+		{
+			struct dict_avp_data data = {
+				861,	/* Code */
+				10415,	/* Vendor */
+				"Cause-Code",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Cellular-Network-Information */
+		{
+			struct dict_avp_data data = {
+				3924,	/* Code */
+				10415,	/* Vendor */
+				"Cellular-Network-Information",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* CG-Address */
+		{
+			struct dict_avp_data data = {
+				846,	/* Code */
+				10415,	/* Vendor */
+				"CG-Address",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, Address_type, NULL);
+		};
+		/* Change-Condition */
+		{
+			struct dict_avp_data data = {
+				2037,	/* Code */
+				10415,	/* Vendor */
+				"Change-Condition",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Change-Time */
+		{
+			struct dict_avp_data data = {
+				2038,	/* Code */
+				10415,	/* Vendor */
+				"Change-Time",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, Time_type, NULL);
+		};
+		/* Charge-Reason-Code */
+		{
+			struct dict_avp_data data = {
+				2118,	/* Code */
+				10415,	/* Vendor */
+				"Charge-Reason-Code",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Charge-Reason-Code)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "UNKNOWN", { .i32=0 }};
+			struct dict_enumval_data        t_2 = { "USAGE", { .i32=1 }};
+			struct dict_enumval_data        t_3 = { "COMMUNICATION_ATTEMPT_CHARGE", { .i32=2 }};
+			struct dict_enumval_data        t_4 = { "SETUP_CHARGE", { .i32=3 }};
+			struct dict_enumval_data        t_5 = { "ADD_ON_CHARGE", { .i32=4 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_3, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_4, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_5, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* Charged-Party */
+		{
+			struct dict_avp_data data = {
+				857,	/* Code */
+				10415,	/* Vendor */
+				"Charged-Party",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, UTF8String_type, NULL);
+		};
+		/* Charging-Characteristics-Selection-Mode */
+		{
+			struct dict_avp_data data = {
+				2066,	/* Code */
+				10415,	/* Vendor */
+				"Charging-Characteristics-Selection-Mode",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Charging-Characteristics-Selection-Mode)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "Serving_Node_Supplied", { .i32=0 }};
+			struct dict_enumval_data        t_2 = { "Subscription_specific", { .i32=1 }};
+			struct dict_enumval_data        t_3 = { "APN_specific", { .i32=2 }};
+			struct dict_enumval_data        t_4 = { "Home_Default", { .i32=3 }};
+			struct dict_enumval_data        t_5 = { "Roaming_Default", { .i32=4 }};
+			struct dict_enumval_data        t_6 = { "Visiting_Default", { .i32=5 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_3, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_4, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_5, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_6, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* Charging-Per-IP-CAN-Session-Indicator */
+		{
+			struct dict_avp_data data = {
+				4400,	/* Code */
+				10415,	/* Vendor */
+				"Charging-Per-IP-CAN-Session-Indicator",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Charging-Per-IP-CAN-Session-Indicator)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "Inactive", { .i32=0 }};
+			struct dict_enumval_data        t_2 = { "Active", { .i32=1 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* Class-Identifier */
+		{
+			struct dict_avp_data data = {
+				1214,	/* Code */
+				10415,	/* Vendor */
+				"Class-Identifier",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Class-Identifier)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "Personal", { .i32=0 }};
+			struct dict_enumval_data        t_2 = { "Advertisement", { .i32=1 }};
+			struct dict_enumval_data        t_3 = { "Informational", { .i32=2 }};
+			struct dict_enumval_data        t_4 = { "Auto", { .i32=3 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_3, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_4, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* Client-Address */
+		{
+			struct dict_avp_data data = {
+				2018,	/* Code */
+				10415,	/* Vendor */
+				"Client-Address",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, Address_type, NULL);
+		};
+		/* CN-Operator-Selection-Entity */
+		{
+			struct dict_avp_data data = {
+				3421,	/* Code */
+				10415,	/* Vendor */
+				"CN-Operator-Selection-Entity",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(CN-Operator-Selection-Entity)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "The_Serving_Network_has_been_selected_by_the_UE", { .i32=0 }};
+			struct dict_enumval_data        t_2 = { "The_Serving_Network_has_been_selected_by_the_network", { .i32=1 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* Content-Class */
+		{
+			struct dict_avp_data data = {
+				1220,	/* Code */
+				10415,	/* Vendor */
+				"Content-Class",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Content-Class)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "text", { .i32=0 }};
+			struct dict_enumval_data        t_2 = { "image_basic", { .i32=1 }};
+			struct dict_enumval_data        t_3 = { "image_rich", { .i32=2 }};
+			struct dict_enumval_data        t_4 = { "video_basic", { .i32=3 }};
+			struct dict_enumval_data        t_5 = { "video_rich", { .i32=4 }};
+			struct dict_enumval_data        t_6 = { "megapixel", { .i32=5 }};
+			struct dict_enumval_data        t_7 = { "content_basic", { .i32=6 }};
+			struct dict_enumval_data        t_8 = { "content_rich", { .i32=7 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_3, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_4, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_5, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_6, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_7, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_8, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* Content-Disposition */
+		{
+			struct dict_avp_data data = {
+				828,	/* Code */
+				10415,	/* Vendor */
+				"Content-Disposition",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, UTF8String_type, NULL);
+		};
+		/* Content-Length */
+		{
+			struct dict_avp_data data = {
+				827,	/* Code */
+				10415,	/* Vendor */
+				"Content-Length",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Content-Size */
+		{
+			struct dict_avp_data data = {
+				1206,	/* Code */
+				10415,	/* Vendor */
+				"Content-Size",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Content-Type */
+		{
+			struct dict_avp_data data = {
+				826,	/* Code */
+				10415,	/* Vendor */
+				"Content-Type",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, UTF8String_type, NULL);
+		};
+		/* Coverage-Status */
+		{
+			struct dict_avp_data data = {
+				3428,	/* Code */
+				10415,	/* Vendor */
+				"Coverage-Status",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Coverage-Status)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "Out_of_coverage", { .i32=0 }};
+			struct dict_enumval_data        t_2 = { "In_coverage", { .i32=1 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* CP-CIoT-EPS-Optimisation-Indicator */
+		{
+			struct dict_avp_data data = {
+				3930,	/* Code */
+				10415,	/* Vendor */
+				"CP-CIoT-EPS-Optimisation-Indicator",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(CP-CIoT-EPS-Optimisation-Indicator)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "Not_Apply", { .i32=0 }};
+			struct dict_enumval_data        t_2 = { "Apply", { .i32=1 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* CSG-Access-Mode */
+		{
+			struct dict_avp_data data = {
+				2317,	/* Code */
+				10415,	/* Vendor */
+				"CSG-Access-Mode",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(CSG-Access-Mode)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "Closed_mode", { .i32=0 }};
+			struct dict_enumval_data        t_2 = { "Hybrid_Mode", { .i32=1 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* CSG-Membership-Indication */
+		{
+			struct dict_avp_data data = {
+				2318,	/* Code */
+				10415,	/* Vendor */
+				"CSG-Membership-Indication",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(CSG-Membership-Indication)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "Not_CSG_member", { .i32=0 }};
+			struct dict_enumval_data        t_2 = { "CSG_Member", { .i32=1 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* CUG-Information */
+		{
+			struct dict_avp_data data = {
+				2304,	/* Code */
+				10415,	/* Vendor */
+				"CUG-Information",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Data-Coding-Scheme */
+		{
+			struct dict_avp_data data = {
+				2001,	/* Code */
+				10415,	/* Vendor */
+				"Data-Coding-Scheme",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Deferred-Location-Event-Type */
+		{
+			struct dict_avp_data data = {
+				1230,	/* Code */
+				10415,	/* Vendor */
+				"Deferred-Location-Event-Type",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, UTF8String_type, NULL);
+		};
+		/* Delivery-Report-Requested */
+		{
+			struct dict_avp_data data = {
+				1216,	/* Code */
+				10415,	/* Vendor */
+				"Delivery-Report-Requested",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Delivery-Report-Requested)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "No", { .i32=0 }};
+			struct dict_enumval_data        t_2 = { "Yes", { .i32=1 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* Diagnostics */
+		{
+			struct dict_avp_data data = {
+				2039,	/* Code */
+				10415,	/* Vendor */
+				"Diagnostics",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Discoveree-UE-HPLMN-Identifier */
+		{
+			struct dict_avp_data data = {
+				4402,	/* Code */
+				10415,	/* Vendor */
+				"Discoveree-UE-HPLMN-Identifier",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, UTF8String_type, NULL);
+		};
+		/* Discoveree-UE-VPLMN-Identifier */
+		{
+			struct dict_avp_data data = {
+				4403,	/* Code */
+				10415,	/* Vendor */
+				"Discoveree-UE-VPLMN-Identifier",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, UTF8String_type, NULL);
+		};
+		/* Discoverer-UE-HPLMN-Identifier */
+		{
+			struct dict_avp_data data = {
+				4404,	/* Code */
+				10415,	/* Vendor */
+				"Discoverer-UE-HPLMN-Identifier",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, UTF8String_type, NULL);
+		};
+		/* Discoverer-UE-VPLMN-Identifier */
+		{
+			struct dict_avp_data data = {
+				4405,	/* Code */
+				10415,	/* Vendor */
+				"Discoverer-UE-VPLMN-Identifier",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, UTF8String_type, NULL);
+		};
+		/* Domain-Name */
+		{
+			struct dict_avp_data data = {
+				1200,	/* Code */
+				10415,	/* Vendor */
+				"Domain-Name",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, UTF8String_type, NULL);
+		};
+		/* DRM-Content */
+		{
+			struct dict_avp_data data = {
+				1221,	/* Code */
+				10415,	/* Vendor */
+				"DRM-Content",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(DRM-Content)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "No", { .i32=0 }};
+			struct dict_enumval_data        t_2 = { "Yes", { .i32=1 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* Dynamic-Address-Flag */
+		{
+			struct dict_avp_data data = {
+				2051,	/* Code */
+				10415,	/* Vendor */
+				"Dynamic-Address-Flag",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Dynamic-Address-Flag)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "Static", { .i32=0 }};
+			struct dict_enumval_data        t_2 = { "Dynamic", { .i32=1 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* Dynamic-Address-Flag-Extension */
+		{
+			struct dict_avp_data data = {
+				2068,	/* Code */
+				10415,	/* Vendor */
+				"Dynamic-Address-Flag-Extension",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Dynamic-Address-Flag-Extension)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "Static", { .i32=0 }};
+			struct dict_enumval_data        t_2 = { "Dynamic", { .i32=1 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* Envelope-End-Time */
+		{
+			struct dict_avp_data data = {
+				1267,	/* Code */
+				10415,	/* Vendor */
+				"Envelope-End-Time",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, Time_type, NULL);
+		};
+		/* Envelope-Reporting */
+		{
+			struct dict_avp_data data = {
+				1268,	/* Code */
+				10415,	/* Vendor */
+				"Envelope-Reporting",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Envelope-Reporting)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "DO_NOT_REPORT_ENVELOPES", { .i32=0 }};
+			struct dict_enumval_data        t_2 = { "REPORT_ENVELOPES", { .i32=1 }};
+			struct dict_enumval_data        t_3 = { "REPORT_ENVELOPES_WITH_VOLUME", { .i32=2 }};
+			struct dict_enumval_data        t_4 = { "REPORT_ENVELOPES_WITH_EVENTS", { .i32=3 }};
+			struct dict_enumval_data        t_5 = { "REPORT_ENVELOPES_WITH_VOLUME_AND_EVENTS", { .i32=4 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_3, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_4, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_5, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* Envelope-Start-Time */
+		{
+			struct dict_avp_data data = {
+				1269,	/* Code */
+				10415,	/* Vendor */
+				"Envelope-Start-Time",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, Time_type, NULL);
+		};
+		/* EPDG-Address */
+		{
+			struct dict_avp_data data = {
+				3425,	/* Code */
+				10415,	/* Vendor */
+				"EPDG-Address",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, Address_type, NULL);
+		};
+		/* Event */
+		{
+			struct dict_avp_data data = {
+				825,	/* Code */
+				10415,	/* Vendor */
+				"Event",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, UTF8String_type, NULL);
+		};
+		/* Event-Charging-TimeStamp */
+		{
+			struct dict_avp_data data = {
+				1258,	/* Code */
+				10415,	/* Vendor */
+				"Event-Charging-TimeStamp",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, Time_type, NULL);
+		};
+		/* Expires */
+		{
+			struct dict_avp_data data = {
+				888,	/* Code */
+				10415,	/* Vendor */
+				"Expires",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* File-Repair-Supported */
+		{
+			struct dict_avp_data data = {
+				1224,	/* Code */
+				10415,	/* Vendor */
+				"File-Repair-Supported",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(File-Repair-Supported)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "SUPPORTED", { .i32=1 }};
+			struct dict_enumval_data        t_2 = { "NOT_SUPPORTED", { .i32=2 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* Forwarding-Pending */
+		{
+			struct dict_avp_data data = {
+				3415,	/* Code */
+				10415,	/* Vendor */
+				"Forwarding-Pending",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Forwarding-Pending)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "Forwarding_not_pending", { .i32=0 }};
+			struct dict_enumval_data        t_2 = { "Forwarding_pending", { .i32=1 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* From-Address */
+		{
+			struct dict_avp_data data = {
+				2708,	/* Code */
+				10415,	/* Vendor */
+				"From-Address",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, UTF8String_type, NULL);
+		};
+		/* GGSN-Address */
+		{
+			struct dict_avp_data data = {
+				847,	/* Code */
+				10415,	/* Vendor */
+				"GGSN-Address",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, Address_type, NULL);
+		};
+		/* IMS-Application-Reference-Identifier */
+		{
+			struct dict_avp_data data = {
+				2601,	/* Code */
+				10415,	/* Vendor */
+				"IMS-Application-Reference-Identifier",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, UTF8String_type, NULL);
+		};
+		/* IMS-Charging-Identifier */
+		{
+			struct dict_avp_data data = {
+				841,	/* Code */
+				10415,	/* Vendor */
+				"IMS-Charging-Identifier",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, UTF8String_type, NULL);
+		};
+		/* IMS-Communication-Service-Identifier */
+		{
+			struct dict_avp_data data = {
+				1281,	/* Code */
+				10415,	/* Vendor */
+				"IMS-Communication-Service-Identifier",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, UTF8String_type, NULL);
+		};
+		/* IMS-Emergency-Indicator */
+		{
+			struct dict_avp_data data = {
+				2322,	/* Code */
+				10415,	/* Vendor */
+				"IMS-Emergency-Indicator",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(IMS-Emergency-Indicator)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "Non_Emergency", { .i32=0 }};
+			struct dict_enumval_data        t_2 = { "Emergency", { .i32=1 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* IMS-Visited-Network-Identifier */
+		{
+			struct dict_avp_data data = {
+				2713,	/* Code */
+				10415,	/* Vendor */
+				"IMS-Visited-Network-Identifier",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, UTF8String_type, NULL);
+		};
+		/* IMSI-Unauthenticated-Flag */
+		{
+			struct dict_avp_data data = {
+				2308,	/* Code */
+				10415,	/* Vendor */
+				"IMSI-Unauthenticated-Flag",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(IMSI-Unauthenticated-Flag)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "Authenticated", { .i32=0 }};
+			struct dict_enumval_data        t_2 = { "Unauthenticated", { .i32=1 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* Incoming-Trunk-Group-Id */
+		{
+			struct dict_avp_data data = {
+				852,	/* Code */
+				10415,	/* Vendor */
+				"Incoming-Trunk-Group-Id",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, UTF8String_type, NULL);
+		};
+		/* Initial-IMS-Charging-Identifier */
+		{
+			struct dict_avp_data data = {
+				2321,	/* Code */
+				10415,	/* Vendor */
+				"Initial-IMS-Charging-Identifier",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, UTF8String_type, NULL);
+		};
+		/* Instance-Id */
+		{
+			struct dict_avp_data data = {
+				3402,	/* Code */
+				10415,	/* Vendor */
+				"Instance-Id",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, UTF8String_type, NULL);
+		};
+		/* Interface-Id */
+		{
+			struct dict_avp_data data = {
+				2003,	/* Code */
+				10415,	/* Vendor */
+				"Interface-Id",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, UTF8String_type, NULL);
+		};
+		/* Interface-Port */
+		{
+			struct dict_avp_data data = {
+				2004,	/* Code */
+				10415,	/* Vendor */
+				"Interface-Port",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, UTF8String_type, NULL);
+		};
+		/* Interface-Text */
+		{
+			struct dict_avp_data data = {
+				2005,	/* Code */
+				10415,	/* Vendor */
+				"Interface-Text",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, UTF8String_type, NULL);
+		};
+		/* Interface-Type */
+		{
+			struct dict_avp_data data = {
+				2006,	/* Code */
+				10415,	/* Vendor */
+				"Interface-Type",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Interface-Type)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "Unknown", { .i32=0 }};
+			struct dict_enumval_data        t_2 = { "MOBILE_ORIGINATING", { .i32=1 }};
+			struct dict_enumval_data        t_3 = { "MOBILE_TERMINATING", { .i32=2 }};
+			struct dict_enumval_data        t_4 = { "APPLICATION_ORIGINATING", { .i32=3 }};
+			struct dict_enumval_data        t_5 = { "APPLICATION_TERMINATION", { .i32=4 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_3, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_4, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_5, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* Inter-UE-Transfer */
+		{
+			struct dict_avp_data data = {
+				3902,	/* Code */
+				10415,	/* Vendor */
+				"Inter-UE-Transfer",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Inter-UE-Transfer)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "Intra_UE_transfer", { .i32=0 }};
+			struct dict_enumval_data        t_2 = { "Inter_UE_transfer", { .i32=1 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* IP-Realm-Default-Indication */
+		{
+			struct dict_avp_data data = {
+				2603,	/* Code */
+				10415,	/* Vendor */
+				"IP-Realm-Default-Indication",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(IP-Realm-Default-Indication)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "Default_IP_Realm_Not_used", { .i32=0 }};
+			struct dict_enumval_data        t_2 = { "Default_IP_realm_used", { .i32=1 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* ISUP-Cause-Diagnostics */
+		{
+			struct dict_avp_data data = {
+				3422,	/* Code */
+				10415,	/* Vendor */
+				"ISUP-Cause-Diagnostics",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* ISUP-Cause-Location */
+		{
+			struct dict_avp_data data = {
+				3423,	/* Code */
+				10415,	/* Vendor */
+				"ISUP-Cause-Location",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* ISUP-Cause-Value */
+		{
+			struct dict_avp_data data = {
+				3424,	/* Code */
+				10415,	/* Vendor */
+				"ISUP-Cause-Value",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* ISUP-Location-Number */
+		{
+			struct dict_avp_data data = {
+				3414,	/* Code */
+				10415,	/* Vendor */
+				"ISUP-Location-Number",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Language */
+		{
+			struct dict_avp_data data = {
+				3914,	/* Code */
+				10415,	/* Vendor */
+				"Language",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, UTF8String_type, NULL);
+		};
+		/* Layer-2-Group-ID */
+		{
+			struct dict_avp_data data = {
+				3429,	/* Code */
+				10415,	/* Vendor */
+				"Layer-2-Group-ID",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* LCS-APN */
+		{
+			struct dict_avp_data data = {
+				1231,	/* Code */
+				10415,	/* Vendor */
+				"LCS-APN",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, UTF8String_type, NULL);
+		};
+		/* LCS-Client-Dialed-By-MS */
+		{
+			struct dict_avp_data data = {
+				1233,	/* Code */
+				10415,	/* Vendor */
+				"LCS-Client-Dialed-By-MS",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, UTF8String_type, NULL);
+		};
+		/* LCS-Client-External-ID */
+		{
+			struct dict_avp_data data = {
+				1234,	/* Code */
+				10415,	/* Vendor */
+				"LCS-Client-External-ID",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, UTF8String_type, NULL);
+		};
+		/* LCS-Client-Type */
+		{
+			struct dict_avp_data data = {
+				1241,	/* Code */
+				10415,	/* Vendor */
+				"LCS-Client-Type",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(LCS-Client-Type)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "EMERGENCY_SERVICES", { .i32=0 }};
+			struct dict_enumval_data        t_2 = { "VALUE_ADDED_SERVICES", { .i32=1 }};
+			struct dict_enumval_data        t_3 = { "PLMN_OPERATOR_SERVICES", { .i32=2 }};
+			struct dict_enumval_data        t_4 = { "LAWFUL_INTERCEPT_SERVICES", { .i32=3 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_3, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_4, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* LCS-Data-Coding-Scheme */
+		{
+			struct dict_avp_data data = {
+				1236,	/* Code */
+				10415,	/* Vendor */
+				"LCS-Data-Coding-Scheme",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, UTF8String_type, NULL);
+		};
+		/* LCS-Format-Indicator */
+		{
+			struct dict_avp_data data = {
+				1237,	/* Code */
+				10415,	/* Vendor */
+				"LCS-Format-Indicator",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(LCS-Format-Indicator)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "LOGICAL_NAME", { .i32=0 }};
+			struct dict_enumval_data        t_2 = { "EMAIL_ADDRESS", { .i32=1 }};
+			struct dict_enumval_data        t_3 = { "MSISDN", { .i32=2 }};
+			struct dict_enumval_data        t_4 = { "URL", { .i32=3 }};
+			struct dict_enumval_data        t_5 = { "SIP_URL", { .i32=4 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_3, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_4, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_5, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* LCS-Name-String */
+		{
+			struct dict_avp_data data = {
+				1238,	/* Code */
+				10415,	/* Vendor */
+				"LCS-Name-String",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, UTF8String_type, NULL);
+		};
+		/* LCS-Requestor-ID-String */
+		{
+			struct dict_avp_data data = {
+				1240,	/* Code */
+				10415,	/* Vendor */
+				"LCS-Requestor-ID-String",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, UTF8String_type, NULL);
+		};
+		/* Local-GW-Inserted-Indication */
+		{
+			struct dict_avp_data data = {
+				2604,	/* Code */
+				10415,	/* Vendor */
+				"Local-GW-Inserted-Indication",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Local-GW-Inserted-Indication)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "Local_GW_Not_Inserted", { .i32=0 }};
+			struct dict_enumval_data        t_2 = { "Local_GW_Inserted", { .i32=1 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* Local-Sequence-Number */
+		{
+			struct dict_avp_data data = {
+				2063,	/* Code */
+				10415,	/* Vendor */
+				"Local-Sequence-Number",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Location-Estimate */
+		{
+			struct dict_avp_data data = {
+				1242,	/* Code */
+				10415,	/* Vendor */
+				"Location-Estimate",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Location-Estimate-Type */
+		{
+			struct dict_avp_data data = {
+				1243,	/* Code */
+				10415,	/* Vendor */
+				"Location-Estimate-Type",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Location-Estimate-Type)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "CURRENT_LOCATION", { .i32=0 }};
+			struct dict_enumval_data        t_2 = { "CURRENT_LAST_KNOWN_LOCATION", { .i32=1 }};
+			struct dict_enumval_data        t_3 = { "INITIAL_LOCATION", { .i32=2 }};
+			struct dict_enumval_data        t_4 = { "ACTIVATE_DEFERRED_LOCATION", { .i32=3 }};
+			struct dict_enumval_data        t_5 = { "CANCEL_DEFERRED_LOCATION", { .i32=4 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_3, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_4, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_5, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* Low-Balance-Indication */
+		{
+			struct dict_avp_data data = {
+				2020,	/* Code */
+				10415,	/* Vendor */
+				"Low-Balance-Indication",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Low-Balance-Indication)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "NOT_APPLICABLE", { .i32=0 }};
+			struct dict_enumval_data        t_2 = { "YES", { .i32=1 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* Low-Priority-Indicator */
+		{
+			struct dict_avp_data data = {
+				2602,	/* Code */
+				10415,	/* Vendor */
+				"Low-Priority-Indicator",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Low-Priority-Indicator)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "NO", { .i32=0 }};
+			struct dict_enumval_data        t_2 = { "YES", { .i32=1 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* MBMS-Charged-Party */
+		{
+			struct dict_avp_data data = {
+				2323,	/* Code */
+				10415,	/* Vendor */
+				"MBMS-Charged-Party",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(MBMS-Charged-Party)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "Content_Provider", { .i32=0 }};
+			struct dict_enumval_data        t_2 = { "Subscriber", { .i32=1 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* MBMS-GW-Address */
+		{
+			struct dict_avp_data data = {
+				2307,	/* Code */
+				10415,	/* Vendor */
+				"MBMS-GW-Address",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, Address_type, NULL);
+		};
+		/* MBMS-User-Service-Type */
+		{
+			struct dict_avp_data data = {
+				1225,	/* Code */
+				10415,	/* Vendor */
+				"MBMS-User-Service-Type",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(MBMS-User-Service-Type)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "DOWNLOAD", { .i32=1 }};
+			struct dict_enumval_data        t_2 = { "STREAMING", { .i32=2 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* Media-Initiator-Flag */
+		{
+			struct dict_avp_data data = {
+				882,	/* Code */
+				10415,	/* Vendor */
+				"Media-Initiator-Flag",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Media-Initiator-Flag)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "called_party", { .i32=0 }};
+			struct dict_enumval_data        t_2 = { "calling_party", { .i32=1 }};
+			struct dict_enumval_data        t_3 = { "unknown", { .i32=2 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_3, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* Media-Initiator-Party */
+		{
+			struct dict_avp_data data = {
+				1288,	/* Code */
+				10415,	/* Vendor */
+				"Media-Initiator-Party",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, UTF8String_type, NULL);
+		};
+		/* Message-ID */
+		{
+			struct dict_avp_data data = {
+				1210,	/* Code */
+				10415,	/* Vendor */
+				"Message-ID",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, UTF8String_type, NULL);
+		};
+		/* Message-Size */
+		{
+			struct dict_avp_data data = {
+				1212,	/* Code */
+				10415,	/* Vendor */
+				"Message-Size",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Message-Type */
+		{
+			struct dict_avp_data data = {
+				1211,	/* Code */
+				10415,	/* Vendor */
+				"Message-Type",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Message-Type)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "m_send_req", { .i32=1 }};
+			struct dict_enumval_data        t_2 = { "m_forward_req", { .i32=10 }};
+			struct dict_enumval_data        t_3 = { "m_forward_conf", { .i32=11 }};
+			struct dict_enumval_data        t_4 = { "m_mbox_store_conf", { .i32=12 }};
+			struct dict_enumval_data        t_5 = { "m_mbox_view_conf", { .i32=13 }};
+			struct dict_enumval_data        t_6 = { "m_mbox_upload_conf", { .i32=14 }};
+			struct dict_enumval_data        t_7 = { "m_mbox_delete_conf", { .i32=15 }};
+			struct dict_enumval_data        t_8 = { "m_send_conf", { .i32=2 }};
+			struct dict_enumval_data        t_9 = { "m_notification_ind", { .i32=3 }};
+			struct dict_enumval_data        t_10 = { "m_notifyresp_ind", { .i32=4 }};
+			struct dict_enumval_data        t_11 = { "m_retrieve_conf", { .i32=5 }};
+			struct dict_enumval_data        t_12 = { "m_acknowledge_ind", { .i32=6 }};
+			struct dict_enumval_data        t_13 = { "m_delivery_ind", { .i32=7 }};
+			struct dict_enumval_data        t_14 = { "m_read_rec_ind", { .i32=8 }};
+			struct dict_enumval_data        t_15 = { "m_read_orig_ind", { .i32=9 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_3, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_4, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_5, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_6, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_7, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_8, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_9, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_10, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_11, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_12, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_13, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_14, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_15, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* MMBox-Storage-Requested */
+		{
+			struct dict_avp_data data = {
+				1248,	/* Code */
+				10415,	/* Vendor */
+				"MMBox-Storage-Requested",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(MMBox-Storage-Requested)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "No", { .i32=0 }};
+			struct dict_enumval_data        t_2 = { "Yes", { .i32=1 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* MMTel-SService-Type */
+		{
+			struct dict_avp_data data = {
+				2031,	/* Code */
+				10415,	/* Vendor */
+				"MMTel-SService-Type",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Monitored-PLMN-Identifier */
+		{
+			struct dict_avp_data data = {
+				3430,	/* Code */
+				10415,	/* Vendor */
+				"Monitored-PLMN-Identifier",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, UTF8String_type, NULL);
+		};
+		/* Monitoring-Event-Configuration-Activity */
+		{
+			struct dict_avp_data data = {
+				3919,	/* Code */
+				10415,	/* Vendor */
+				"Monitoring-Event-Configuration-Activity",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Monitoring-Event-Functionality */
+		{
+			struct dict_avp_data data = {
+				3922,	/* Code */
+				10415,	/* Vendor */
+				"Monitoring-Event-Functionality",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Monitoring-Event-Report-Number */
+		{
+			struct dict_avp_data data = {
+				3923,	/* Code */
+				10415,	/* Vendor */
+				"Monitoring-Event-Report-Number",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Monitoring-UE-HPLMN-Identifier */
+		{
+			struct dict_avp_data data = {
+				3431,	/* Code */
+				10415,	/* Vendor */
+				"Monitoring-UE-HPLMN-Identifier",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, UTF8String_type, NULL);
+		};
+		/* Monitoring-UE-Identifier */
+		{
+			struct dict_avp_data data = {
+				3432,	/* Code */
+				10415,	/* Vendor */
+				"Monitoring-UE-Identifier",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, UTF8String_type, NULL);
+		};
+		/* Monitoring-UE-VPLMN-Identifier */
+		{
+			struct dict_avp_data data = {
+				3433,	/* Code */
+				10415,	/* Vendor */
+				"Monitoring-UE-VPLMN-Identifier",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, UTF8String_type, NULL);
+		};
+		/* MSC-Address */
+		{
+			struct dict_avp_data data = {
+				3417,	/* Code */
+				10415,	/* Vendor */
+				"MSC-Address",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* MTC-IWF-Address */
+		{
+			struct dict_avp_data data = {
+				3406,	/* Code */
+				10415,	/* Vendor */
+				"MTC-IWF-Address",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, Address_type, NULL);
+		};
+		/* Neighbour-Node-Address */
+		{
+			struct dict_avp_data data = {
+				2705,	/* Code */
+				10415,	/* Vendor */
+				"Neighbour-Node-Address",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, Address_type, NULL);
+		};
+		/* Network-Call-Reference-Number */
+		{
+			struct dict_avp_data data = {
+				3418,	/* Code */
+				10415,	/* Vendor */
+				"Network-Call-Reference-Number",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* NNI-Type */
+		{
+			struct dict_avp_data data = {
+				2704,	/* Code */
+				10415,	/* Vendor */
+				"NNI-Type",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(NNI-Type)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "non_roaming", { .i32=0 }};
+			struct dict_enumval_data        t_2 = { "roaming_without_loopback", { .i32=1 }};
+			struct dict_enumval_data        t_3 = { "roaming_with_loopback", { .i32=2 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_3, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* Node-Functionality */
+		{
+			struct dict_avp_data data = {
+				862,	/* Code */
+				10415,	/* Vendor */
+				"Node-Functionality",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Node-Functionality)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "S-CSCF", { .i32=0 }};
+			struct dict_enumval_data        t_2 = { "P-CSCF", { .i32=1 }};
+			struct dict_enumval_data        t_3 = { "I-CSCF", { .i32=2 }};
+			struct dict_enumval_data        t_4 = { "MRFC", { .i32=3 }};
+			struct dict_enumval_data        t_5 = { "MGCF", { .i32=4 }};
+			struct dict_enumval_data        t_6 = { "BGCF", { .i32=5 }};
+			struct dict_enumval_data        t_7 = { "AS", { .i32=6 }};
+			struct dict_enumval_data        t_8 = { "IBCF", { .i32=7 }};
+			struct dict_enumval_data        t_9 = { "S-GW", { .i32=8 }};
+			struct dict_enumval_data        t_10 = { "P-GW", { .i32=9 }};
+			struct dict_enumval_data        t_11 = { "HSGW", { .i32=10 }};
+			struct dict_enumval_data        t_12 = { "E-CSCF", { .i32=11 }};
+			struct dict_enumval_data        t_13 = { "MME", { .i32=12 }};
+			struct dict_enumval_data        t_14 = { "TRF", { .i32=13 }};
+			struct dict_enumval_data        t_15 = { "TF", { .i32=14 }};
+			struct dict_enumval_data        t_16 = { "ATCF", { .i32=15 }};
+			struct dict_enumval_data        t_17 = { "Proxy-function", { .i32=16 }};
+			struct dict_enumval_data        t_18 = { "ePDG", { .i32=17 }};
+			struct dict_enumval_data        t_19 = { "TDF", { .i32=18 }};
+			struct dict_enumval_data        t_20 = { "TWAG", { .i32=19 }};
+			struct dict_enumval_data        t_21 = { "SCEF", { .i32=20 }};
+			struct dict_enumval_data        t_22 = { "IWK-SCEF", { .i32=21 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_3, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_4, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_5, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_6, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_7, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_8, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_9, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_10, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_11, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_12, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_13, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_14, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_15, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_16, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_17, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_18, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_19, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_20, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_21, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_22, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* Node-Id */
+		{
+			struct dict_avp_data data = {
+				2064,	/* Code */
+				10415,	/* Vendor */
+				"Node-Id",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, UTF8String_type, NULL);
+		};
+		/* Number-Of-Diversions */
+		{
+			struct dict_avp_data data = {
+				2034,	/* Code */
+				10415,	/* Vendor */
+				"Number-Of-Diversions",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Number-Of-Messages-Sent */
+		{
+			struct dict_avp_data data = {
+				2019,	/* Code */
+				10415,	/* Vendor */
+				"Number-Of-Messages-Sent",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Number-Of-Participants */
+		{
+			struct dict_avp_data data = {
+				885,	/* Code */
+				10415,	/* Vendor */
+				"Number-Of-Participants",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Number-Of-Received-Talk-Bursts */
+		{
+			struct dict_avp_data data = {
+				1282,	/* Code */
+				10415,	/* Vendor */
+				"Number-Of-Received-Talk-Bursts",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Number-Of-Talk-Bursts */
+		{
+			struct dict_avp_data data = {
+				1283,	/* Code */
+				10415,	/* Vendor */
+				"Number-Of-Talk-Bursts",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Number-Portability-Routing-Information */
+		{
+			struct dict_avp_data data = {
+				2024,	/* Code */
+				10415,	/* Vendor */
+				"Number-Portability-Routing-Information",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, UTF8String_type, NULL);
+		};
+		/* Online-Charging-Flag */
+		{
+			struct dict_avp_data data = {
+				2303,	/* Code */
+				10415,	/* Vendor */
+				"Online-Charging-Flag",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Online-Charging-Flag)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "ECF_address_not_provided", { .i32=0 }};
+			struct dict_enumval_data        t_2 = { "ECF_address_provided", { .i32=1 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* Originating-IOI */
+		{
+			struct dict_avp_data data = {
+				839,	/* Code */
+				10415,	/* Vendor */
+				"Originating-IOI",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, UTF8String_type, NULL);
+		};
+		/* Originator */
+		{
+			struct dict_avp_data data = {
+				864,	/* Code */
+				10415,	/* Vendor */
+				"Originator",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Originator)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "Calling_Party", { .i32=0 }};
+			struct dict_enumval_data        t_2 = { "Called_Party", { .i32=1 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* Originator-SCCP-Address */
+		{
+			struct dict_avp_data data = {
+				2008,	/* Code */
+				10415,	/* Vendor */
+				"Originator-SCCP-Address",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, Address_type, NULL);
+		};
+		/* Outgoing-Session-Id */
+		{
+			struct dict_avp_data data = {
+				2320,	/* Code */
+				10415,	/* Vendor */
+				"Outgoing-Session-Id",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, UTF8String_type, NULL);
+		};
+		/* Outgoing-Trunk-Group-Id */
+		{
+			struct dict_avp_data data = {
+				853,	/* Code */
+				10415,	/* Vendor */
+				"Outgoing-Trunk-Group-Id",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, UTF8String_type, NULL);
+		};
+		/* Participant-Access-Priority */
+		{
+			struct dict_avp_data data = {
+				1259,	/* Code */
+				10415,	/* Vendor */
+				"Participant-Access-Priority",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Participant-Access-Priority)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "Pre_emptive_priority", { .i32=1 }};
+			struct dict_enumval_data        t_2 = { "High_priority", { .i32=2 }};
+			struct dict_enumval_data        t_3 = { "Normal_priority", { .i32=3 }};
+			struct dict_enumval_data        t_4 = { "Low_priority", { .i32=4 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_3, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_4, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* Participant-Action-Type */
+		{
+			struct dict_avp_data data = {
+				2049,	/* Code */
+				10415,	/* Vendor */
+				"Participant-Action-Type",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Participant-Action-Type)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "CREATE_CONF", { .i32=0 }};
+			struct dict_enumval_data        t_2 = { "JOIN_CONF", { .i32=1 }};
+			struct dict_enumval_data        t_3 = { "INVITE_INTO_CONF", { .i32=2 }};
+			struct dict_enumval_data        t_4 = { "QUIT_CONF", { .i32=3 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_3, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_4, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* Participants-Involved */
+		{
+			struct dict_avp_data data = {
+				887,	/* Code */
+				10415,	/* Vendor */
+				"Participants-Involved",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, UTF8String_type, NULL);
+		};
+		/* PC3-Control-Protocol-Cause */
+		{
+			struct dict_avp_data data = {
+				3434,	/* Code */
+				10415,	/* Vendor */
+				"PC3-Control-Protocol-Cause",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* PC3-EPC-Control-Protocol-Cause */
+		{
+			struct dict_avp_data data = {
+				3435,	/* Code */
+				10415,	/* Vendor */
+				"PC3-EPC-Control-Protocol-Cause",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* PDN-Connection-Charging-ID */
+		{
+			struct dict_avp_data data = {
+				2050,	/* Code */
+				10415,	/* Vendor */
+				"PDN-Connection-Charging-ID",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* PDP-Address */
+		{
+			struct dict_avp_data data = {
+				1227,	/* Code */
+				10415,	/* Vendor */
+				"PDP-Address",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, Address_type, NULL);
+		};
+		/* PDP-Address-Prefix-Length */
+		{
+			struct dict_avp_data data = {
+				2606,	/* Code */
+				10415,	/* Vendor */
+				"PDP-Address-Prefix-Length",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* PDP-Context-Type */
+		{
+			struct dict_avp_data data = {
+				1247,	/* Code */
+				10415,	/* Vendor */
+				"PDP-Context-Type",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(PDP-Context-Type)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "Primary", { .i32=0 }};
+			struct dict_enumval_data        t_2 = { "Secondary", { .i32=1 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* Play-Alternative */
+		{
+			struct dict_avp_data data = {
+				3913,	/* Code */
+				10415,	/* Vendor */
+				"Play-Alternative",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Play-Alternative)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "served_party", { .i32=0 }};
+			struct dict_enumval_data        t_2 = { "remote_party", { .i32=1 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* PoC-Change-Condition */
+		{
+			struct dict_avp_data data = {
+				1261,	/* Code */
+				10415,	/* Vendor */
+				"PoC-Change-Condition",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(PoC-Change-Condition)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "ServiceChange", { .i32=0 }};
+			struct dict_enumval_data        t_2 = { "VolumeLimit", { .i32=1 }};
+			struct dict_enumval_data        t_3 = { "TimeLimit", { .i32=2 }};
+			struct dict_enumval_data        t_4 = { "NumberofTalkBurstLimit", { .i32=3 }};
+			struct dict_enumval_data        t_5 = { "NumberofActiveParticipants", { .i32=4 }};
+			struct dict_enumval_data        t_6 = { "TariffTime", { .i32=5 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_3, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_4, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_5, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_6, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* PoC-Change-Time */
+		{
+			struct dict_avp_data data = {
+				1262,	/* Code */
+				10415,	/* Vendor */
+				"PoC-Change-Time",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, Time_type, NULL);
+		};
+		/* PoC-Controlling-Address */
+		{
+			struct dict_avp_data data = {
+				858,	/* Code */
+				10415,	/* Vendor */
+				"PoC-Controlling-Address",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, UTF8String_type, NULL);
+		};
+		/* PoC-Event-Type */
+		{
+			struct dict_avp_data data = {
+				2025,	/* Code */
+				10415,	/* Vendor */
+				"PoC-Event-Type",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(PoC-Event-Type)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "Normal", { .i32=0 }};
+			struct dict_enumval_data        t_2 = { "Instant_Personal_Alert", { .i32=1 }};
+			struct dict_enumval_data        t_3 = { "PoC_Group_Advertisement", { .i32=2 }};
+			struct dict_enumval_data        t_4 = { "Early_Session_Setting_Up", { .i32=3 }};
+			struct dict_enumval_data        t_5 = { "PoC_Talk_Burst", { .i32=4 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_3, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_4, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_5, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* PoC-Group-Name */
+		{
+			struct dict_avp_data data = {
+				859,	/* Code */
+				10415,	/* Vendor */
+				"PoC-Group-Name",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, UTF8String_type, NULL);
+		};
+		/* PoC-Server-Role */
+		{
+			struct dict_avp_data data = {
+				883,	/* Code */
+				10415,	/* Vendor */
+				"PoC-Server-Role",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(PoC-Server-Role)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "Participating_PoC_Server", { .i32=0 }};
+			struct dict_enumval_data        t_2 = { "Controlling_PoC_Server", { .i32=1 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* PoC-Session-Id */
+		{
+			struct dict_avp_data data = {
+				1229,	/* Code */
+				10415,	/* Vendor */
+				"PoC-Session-Id",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, UTF8String_type, NULL);
+		};
+		/* PoC-Session-Initiation-Type */
+		{
+			struct dict_avp_data data = {
+				1277,	/* Code */
+				10415,	/* Vendor */
+				"PoC-Session-Initiation-Type",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(PoC-Session-Initiation-Type)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "Pre_established", { .i32=0 }};
+			struct dict_enumval_data        t_2 = { "On_demand", { .i32=1 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* PoC-Session-Type */
+		{
+			struct dict_avp_data data = {
+				884,	/* Code */
+				10415,	/* Vendor */
+				"PoC-Session-Type",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(PoC-Session-Type)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "1_to_1_PoC", { .i32=0 }};
+			struct dict_enumval_data        t_2 = { "Chat_PoC_Group", { .i32=1 }};
+			struct dict_enumval_data        t_3 = { "Pre_arranged_PoC_Group", { .i32=2 }};
+			struct dict_enumval_data        t_4 = { "Ad_hoc_PoC_Gropu", { .i32=3 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_3, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_4, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* PoC-User-Role-IDs */
+		{
+			struct dict_avp_data data = {
+				1253,	/* Code */
+				10415,	/* Vendor */
+				"PoC-User-Role-IDs",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, UTF8String_type, NULL);
+		};
+		/* PoC-User-Role-Info-Units */
+		{
+			struct dict_avp_data data = {
+				1254,	/* Code */
+				10415,	/* Vendor */
+				"PoC-User-Role-Info-Units",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(PoC-User-Role-Info-Units)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "Moderator", { .i32=1 }};
+			struct dict_enumval_data        t_2 = { "Dispatcher", { .i32=2 }};
+			struct dict_enumval_data        t_3 = { "Session_Owner", { .i32=3 }};
+			struct dict_enumval_data        t_4 = { "Session_Participant", { .i32=4 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_3, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_4, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* Positioning-Data */
+		{
+			struct dict_avp_data data = {
+				1245,	/* Code */
+				10415,	/* Vendor */
+				"Positioning-Data",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, UTF8String_type, NULL);
+		};
+		/* Preferred-AoC-Currency */
+		{
+			struct dict_avp_data data = {
+				2315,	/* Code */
+				10415,	/* Vendor */
+				"Preferred-AoC-Currency",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Priority */
+		{
+			struct dict_avp_data data = {
+				1209,	/* Code */
+				10415,	/* Vendor */
+				"Priority",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Priority)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "Low", { .i32=0 }};
+			struct dict_enumval_data        t_2 = { "Normal", { .i32=1 }};
+			struct dict_enumval_data        t_3 = { "High", { .i32=2 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_3, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* Privacy-Indicator */
+		{
+			struct dict_avp_data data = {
+				3915,	/* Code */
+				10415,	/* Vendor */
+				"Privacy-Indicator",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Privacy-Indicator)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "NOT_PRIVATE", { .i32=0 }};
+			struct dict_enumval_data        t_2 = { "PRIVATE", { .i32=1 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* ProSe-3rd-Party-Application-ID */
+		{
+			struct dict_avp_data data = {
+				3440,	/* Code */
+				10415,	/* Vendor */
+				"ProSe-3rd-Party-Application-ID",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, UTF8String_type, NULL);
+		};
+		/* ProSe-Direct-Discovery-Model */
+		{
+			struct dict_avp_data data = {
+				3442,	/* Code */
+				10415,	/* Vendor */
+				"ProSe-Direct-Discovery-Model",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(ProSe-Direct-Discovery-Model)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "Model_A", { .i32=0 }};
+			struct dict_enumval_data        t_2 = { "Model_B", { .i32=1 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* ProSe-Event-Type */
+		{
+			struct dict_avp_data data = {
+				3443,	/* Code */
+				10415,	/* Vendor */
+				"ProSe-Event-Type",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(ProSe-Event-Type)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "Annoucing", { .i32=0 }};
+			struct dict_enumval_data        t_2 = { "Monitoring", { .i32=1 }};
+			struct dict_enumval_data        t_3 = { "Match_Report", { .i32=2 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_3, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* ProSe-Function-IP-Address */
+		{
+			struct dict_avp_data data = {
+				3444,	/* Code */
+				10415,	/* Vendor */
+				"ProSe-Function-IP-Address",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, Address_type, NULL);
+		};
+		/* ProSe-Function-PLMN-Identifier */
+		{
+			struct dict_avp_data data = {
+				3457,	/* Code */
+				10415,	/* Vendor */
+				"ProSe-Function-PLMN-Identifier",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, UTF8String_type, NULL);
+		};
+		/* ProSe-Functionality */
+		{
+			struct dict_avp_data data = {
+				3445,	/* Code */
+				10415,	/* Vendor */
+				"ProSe-Functionality",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(ProSe-Functionality)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "Direct_discovery", { .i32=0 }};
+			struct dict_enumval_data        t_2 = { "EPC_level_discovery", { .i32=1 }};
+			struct dict_enumval_data        t_3 = { "Direct_communication", { .i32=2 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_3, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* ProSe-Group-IP-Multicast-Address */
+		{
+			struct dict_avp_data data = {
+				3446,	/* Code */
+				10415,	/* Vendor */
+				"ProSe-Group-IP-Multicast-Address",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, Address_type, NULL);
+		};
+		/* ProSe-Range-Class */
+		{
+			struct dict_avp_data data = {
+				3448,	/* Code */
+				10415,	/* Vendor */
+				"ProSe-Range-Class",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(ProSe-Range-Class)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "Reserved", { .i32=0 }};
+			struct dict_enumval_data        t_2 = { "50_m", { .i32=1 }};
+			struct dict_enumval_data        t_3 = { "100_m", { .i32=2 }};
+			struct dict_enumval_data        t_4 = { "Unused", { .i32=255 }};
+			struct dict_enumval_data        t_5 = { "200_m", { .i32=3 }};
+			struct dict_enumval_data        t_6 = { "500_m", { .i32=4 }};
+			struct dict_enumval_data        t_7 = { "1000_m", { .i32=5 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_3, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_4, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_5, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_6, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_7, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* ProSe-Reason-For-Cancellation */
+		{
+			struct dict_avp_data data = {
+				3449,	/* Code */
+				10415,	/* Vendor */
+				"ProSe-Reason-For-Cancellation",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(ProSe-Reason-For-Cancellation)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "Proximity_Alert_sent", { .i32=0 }};
+			struct dict_enumval_data        t_2 = { "Time_expired_with_no_renewal", { .i32=1 }};
+			struct dict_enumval_data        t_3 = { "Requestor_cancellation", { .i32=2 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_3, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* ProSe-Request-Timestamp */
+		{
+			struct dict_avp_data data = {
+				3450,	/* Code */
+				10415,	/* Vendor */
+				"ProSe-Request-Timestamp",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, Time_type, NULL);
+		};
+		/* ProSe-Role-Of-UE */
+		{
+			struct dict_avp_data data = {
+				3451,	/* Code */
+				10415,	/* Vendor */
+				"ProSe-Role-Of-UE",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(ProSe-Role-Of-UE)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "Announcing_UE", { .i32=0 }};
+			struct dict_enumval_data        t_2 = { "Monitoring_UE", { .i32=1 }};
+			struct dict_enumval_data        t_3 = { "Requestor_UE", { .i32=2 }};
+			struct dict_enumval_data        t_4 = { "Requested_UE", { .i32=3 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_3, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_4, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* ProSe-Source-IP-Address */
+		{
+			struct dict_avp_data data = {
+				3452,	/* Code */
+				10415,	/* Vendor */
+				"ProSe-Source-IP-Address",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, Address_type, NULL);
+		};
+		/* ProSe-UE-ID */
+		{
+			struct dict_avp_data data = {
+				3453,	/* Code */
+				10415,	/* Vendor */
+				"ProSe-UE-ID",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Proximity-Alert-Indication */
+		{
+			struct dict_avp_data data = {
+				3454,	/* Code */
+				10415,	/* Vendor */
+				"Proximity-Alert-Indication",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Proximity-Alert-Indication)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "Alert", { .i32=0 }};
+			struct dict_enumval_data        t_2 = { "No_Alert", { .i32=1 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* Proximity-Alert-Timestamp */
+		{
+			struct dict_avp_data data = {
+				3455,	/* Code */
+				10415,	/* Vendor */
+				"Proximity-Alert-Timestamp",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, Time_type, NULL);
+		};
+		/* Proximity-Cancellation-Timestamp */
+		{
+			struct dict_avp_data data = {
+				3456,	/* Code */
+				10415,	/* Vendor */
+				"Proximity-Cancellation-Timestamp",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, Time_type, NULL);
+		};
+		/* PS-Append-Free-Format-Data */
+		{
+			struct dict_avp_data data = {
+				867,	/* Code */
+				10415,	/* Vendor */
+				"PS-Append-Free-Format-Data",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(PS-Append-Free-Format-Data)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "Append", { .i32=0 }};
+			struct dict_enumval_data        t_2 = { "Overwrite", { .i32=1 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* PS-Free-Format-Data */
+		{
+			struct dict_avp_data data = {
+				866,	/* Code */
+				10415,	/* Vendor */
+				"PS-Free-Format-Data",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Quota-Consumption-Time */
+		{
+			struct dict_avp_data data = {
+				881,	/* Code */
+				10415,	/* Vendor */
+				"Quota-Consumption-Time",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Quota-Holding-Time */
+		{
+			struct dict_avp_data data = {
+				871,	/* Code */
+				10415,	/* Vendor */
+				"Quota-Holding-Time",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Quota-Indicator */
+		{
+			struct dict_avp_data data = {
+				3912,	/* Code */
+				10415,	/* Vendor */
+				"Quota-Indicator",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Quota-Indicator)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "QUOTA_IS_NOT_USED_DURING_PLAYBACK", { .i32=0 }};
+			struct dict_enumval_data        t_2 = { "QUOTA_IS_USED_DURING_PLAYBACK", { .i32=1 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* Radio-Frequency */
+		{
+			struct dict_avp_data data = {
+				3462,	/* Code */
+				10415,	/* Vendor */
+				"Radio-Frequency",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Radio-Parameter-Set-Values */
+		{
+			struct dict_avp_data data = {
+				3464,	/* Code */
+				10415,	/* Vendor */
+				"Radio-Parameter-Set-Values",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Radio-Resources-Indicator */
+		{
+			struct dict_avp_data data = {
+				3465,	/* Code */
+				10415,	/* Vendor */
+				"Radio-Resources-Indicator",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Rate-Control-Max-Message-Size */
+		{
+			struct dict_avp_data data = {
+				3937,	/* Code */
+				10415,	/* Vendor */
+				"Rate-Control-Max-Message-Size",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Rate-Control-Max-Rate */
+		{
+			struct dict_avp_data data = {
+				3938,	/* Code */
+				10415,	/* Vendor */
+				"Rate-Control-Max-Rate",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Rate-Control-Time-Unit */
+		{
+			struct dict_avp_data data = {
+				3939,	/* Code */
+				10415,	/* Vendor */
+				"Rate-Control-Time-Unit",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Read-Reply-Report-Requested */
+		{
+			struct dict_avp_data data = {
+				1222,	/* Code */
+				10415,	/* Vendor */
+				"Read-Reply-Report-Requested",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Read-Reply-Report-Requested)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "No", { .i32=0 }};
+			struct dict_enumval_data        t_2 = { "Yes", { .i32=1 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* Reason-Header */
+		{
+			struct dict_avp_data data = {
+				3401,	/* Code */
+				10415,	/* Vendor */
+				"Reason-Header",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, UTF8String_type, NULL);
+		};
+		/* Received-Talk-Burst-Time */
+		{
+			struct dict_avp_data data = {
+				1284,	/* Code */
+				10415,	/* Vendor */
+				"Received-Talk-Burst-Time",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Received-Talk-Burst-Volume */
+		{
+			struct dict_avp_data data = {
+				1285,	/* Code */
+				10415,	/* Vendor */
+				"Received-Talk-Burst-Volume",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Recipient-SCCP-Address */
+		{
+			struct dict_avp_data data = {
+				2010,	/* Code */
+				10415,	/* Vendor */
+				"Recipient-SCCP-Address",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, Address_type, NULL);
+		};
+		/* Refund-Information */
+		{
+			struct dict_avp_data data = {
+				2022,	/* Code */
+				10415,	/* Vendor */
+				"Refund-Information",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Related-IMS-Charging-Identifier */
+		{
+			struct dict_avp_data data = {
+				2711,	/* Code */
+				10415,	/* Vendor */
+				"Related-IMS-Charging-Identifier",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, UTF8String_type, NULL);
+		};
+		/* Related-IMS-Charging-Identifier-Node */
+		{
+			struct dict_avp_data data = {
+				2712,	/* Code */
+				10415,	/* Vendor */
+				"Related-IMS-Charging-Identifier-Node",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, Address_type, NULL);
+		};
+		/* Relationship-Mode */
+		{
+			struct dict_avp_data data = {
+				2706,	/* Code */
+				10415,	/* Vendor */
+				"Relationship-Mode",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Relationship-Mode)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "trusted", { .i32=0 }};
+			struct dict_enumval_data        t_2 = { "non_trusted", { .i32=1 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* Reply-Applic-ID */
+		{
+			struct dict_avp_data data = {
+				1223,	/* Code */
+				10415,	/* Vendor */
+				"Reply-Applic-ID",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, UTF8String_type, NULL);
+		};
+		/* Reply-Path-Requested */
+		{
+			struct dict_avp_data data = {
+				2011,	/* Code */
+				10415,	/* Vendor */
+				"Reply-Path-Requested",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Reply-Path-Requested)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "No_Reply_Path_Set", { .i32=0 }};
+			struct dict_enumval_data        t_2 = { "Reply_path_Set", { .i32=1 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* Reporting-Reason */
+		{
+			struct dict_avp_data data = {
+				872,	/* Code */
+				10415,	/* Vendor */
+				"Reporting-Reason",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Reporting-Reason)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "THRESHOLD", { .i32=0 }};
+			struct dict_enumval_data        t_2 = { "QHT", { .i32=1 }};
+			struct dict_enumval_data        t_3 = { "FINAL", { .i32=2 }};
+			struct dict_enumval_data        t_4 = { "QUOTA_EXHAUSTED", { .i32=3 }};
+			struct dict_enumval_data        t_5 = { "VALIDITY_TIME", { .i32=4 }};
+			struct dict_enumval_data        t_6 = { "OTHER_QUOTA_TYPE", { .i32=5 }};
+			struct dict_enumval_data        t_7 = { "RATING_CONDITION_CHANGE", { .i32=6 }};
+			struct dict_enumval_data        t_8 = { "FORCED_REAUTHORISATION", { .i32=7 }};
+			struct dict_enumval_data        t_9 = { "POOL_EXHAUSTED", { .i32=8 }};
+			struct dict_enumval_data        t_10 = { "UNUSED_QUOTA_TIMER", { .i32=9 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_3, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_4, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_5, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_6, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_7, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_8, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_9, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_10, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* Requested-Party-Address */
+		{
+			struct dict_avp_data data = {
+				1251,	/* Code */
+				10415,	/* Vendor */
+				"Requested-Party-Address",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, UTF8String_type, NULL);
+		};
+		/* Requested-PLMN-Identifier */
+		{
+			struct dict_avp_data data = {
+				3436,	/* Code */
+				10415,	/* Vendor */
+				"Requested-PLMN-Identifier",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, UTF8String_type, NULL);
+		};
+		/* Requestor-PLMN-Identifier */
+		{
+			struct dict_avp_data data = {
+				3437,	/* Code */
+				10415,	/* Vendor */
+				"Requestor-PLMN-Identifier",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, UTF8String_type, NULL);
+		};
+		/* Role-Of-Node */
+		{
+			struct dict_avp_data data = {
+				829,	/* Code */
+				10415,	/* Vendor */
+				"Role-Of-Node",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Role-Of-Node)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "ORIGINATING_ROLE", { .i32=0 }};
+			struct dict_enumval_data        t_2 = { "TERMINATING_ROLE", { .i32=1 }};
+			struct dict_enumval_data        t_3 = { "FORWARDING_ROLE", { .i32=2 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_3, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* Role-Of-ProSe-Function */
+		{
+			struct dict_avp_data data = {
+				3438,	/* Code */
+				10415,	/* Vendor */
+				"Role-Of-ProSe-Function",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Role-Of-ProSe-Function)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "HPLMN", { .i32=0 }};
+			struct dict_enumval_data        t_2 = { "VPLMN", { .i32=1 }};
+			struct dict_enumval_data        t_3 = { "Local_PLMN", { .i32=2 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_3, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* Route-Header-Received */
+		{
+			struct dict_avp_data data = {
+				3403,	/* Code */
+				10415,	/* Vendor */
+				"Route-Header-Received",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, UTF8String_type, NULL);
+		};
+		/* Route-Header-Transmitted */
+		{
+			struct dict_avp_data data = {
+				3404,	/* Code */
+				10415,	/* Vendor */
+				"Route-Header-Transmitted",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, UTF8String_type, NULL);
+		};
+		/* SCS-Address */
+		{
+			struct dict_avp_data data = {
+				3941,	/* Code */
+				10415,	/* Vendor */
+				"SCS-Address",	/* Name */
+				0,	/* Fixed flags */
+				0,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, Address_type, NULL);
+		};
+		/* SCS-Realm */
+		{
+			struct dict_avp_data data = {
+				3942,	/* Code */
+				10415,	/* Vendor */
+				"SCS-Realm",	/* Name */
+				0,	/* Fixed flags */
+				0,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, DiameterIdentity_type, NULL);
+		};
+		/* SDP-Answer-Timestamp */
+		{
+			struct dict_avp_data data = {
+				1275,	/* Code */
+				10415,	/* Vendor */
+				"SDP-Answer-Timestamp",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, Time_type, NULL);
+		};
+		/* SDP-Media-Description */
+		{
+			struct dict_avp_data data = {
+				845,	/* Code */
+				10415,	/* Vendor */
+				"SDP-Media-Description",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, UTF8String_type, NULL);
+		};
+		/* SDP-Media-Name */
+		{
+			struct dict_avp_data data = {
+				844,	/* Code */
+				10415,	/* Vendor */
+				"SDP-Media-Name",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, UTF8String_type, NULL);
+		};
+		/* SDP-Offer-Timestamp */
+		{
+			struct dict_avp_data data = {
+				1274,	/* Code */
+				10415,	/* Vendor */
+				"SDP-Offer-Timestamp",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, Time_type, NULL);
+		};
+		/* SDP-Session-Description */
+		{
+			struct dict_avp_data data = {
+				842,	/* Code */
+				10415,	/* Vendor */
+				"SDP-Session-Description",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, UTF8String_type, NULL);
+		};
+		/* SDP-Type */
+		{
+			struct dict_avp_data data = {
+				2036,	/* Code */
+				10415,	/* Vendor */
+				"SDP-Type",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(SDP-Type)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "SDP_Offer", { .i32=0 }};
+			struct dict_enumval_data        t_2 = { "SDP_Answer", { .i32=1 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* Serving-Node-Identity */
+		{
+			struct dict_avp_data data = {
+				3929,	/* Code */
+				10415,	/* Vendor */
+				"Serving-Node-Identity",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, DiameterIdentity_type, NULL);
+		};
+		/* Served-Party-IP-Address */
+		{
+			struct dict_avp_data data = {
+				848,	/* Code */
+				10415,	/* Vendor */
+				"Served-Party-IP-Address",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, Address_type, NULL);
+		};
+		/* Service-Id */
+		{
+			struct dict_avp_data data = {
+				855,	/* Code */
+				10415,	/* Vendor */
+				"Service-Id",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, UTF8String_type, NULL);
+		};
+		/* Service-Mode */
+		{
+			struct dict_avp_data data = {
+				2032,	/* Code */
+				10415,	/* Vendor */
+				"Service-Mode",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Service-Specific-Data */
+		{
+			struct dict_avp_data data = {
+				863,	/* Code */
+				10415,	/* Vendor */
+				"Service-Specific-Data",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, UTF8String_type, NULL);
+		};
+		/* Service-Specific-Type */
+		{
+			struct dict_avp_data data = {
+				1257,	/* Code */
+				10415,	/* Vendor */
+				"Service-Specific-Type",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Serving-Node-Type */
+		{
+			struct dict_avp_data data = {
+				2047,	/* Code */
+				10415,	/* Vendor */
+				"Serving-Node-Type",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Serving-Node-Type)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "SGSN", { .i32=0 }};
+			struct dict_enumval_data        t_2 = { "PMIPSGW", { .i32=1 }};
+			struct dict_enumval_data        t_3 = { "GTPSGW", { .i32=2 }};
+			struct dict_enumval_data        t_4 = { "ePDG", { .i32=3 }};
+			struct dict_enumval_data        t_5 = { "hSGW", { .i32=4 }};
+			struct dict_enumval_data        t_6 = { "MME", { .i32=5 }};
+			struct dict_enumval_data        t_7 = { "TWAN", { .i32=6 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_3, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_4, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_5, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_6, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_7, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* Session-Direction */
+		{
+			struct dict_avp_data data = {
+				2707,	/* Code */
+				10415,	/* Vendor */
+				"Session-Direction",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Session-Direction)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "inbound", { .i32=0 }};
+			struct dict_enumval_data        t_2 = { "outbound", { .i32=1 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* SGi-PtP-Tunnelling-Method */
+		{
+			struct dict_avp_data data = {
+				3931,	/* Code */
+				10415,	/* Vendor */
+				"SGi-PtP-Tunnelling-Method",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(SGi-PtP-Tunnelling-Method)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "UDP_IP_based", { .i32=0 }};
+			struct dict_enumval_data        t_2 = { "Others", { .i32=1 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* SGSN-Address */
+		{
+			struct dict_avp_data data = {
+				1228,	/* Code */
+				10415,	/* Vendor */
+				"SGSN-Address",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, Address_type, NULL);
+		};
+		/* SGW-Address */
+		{
+			struct dict_avp_data data = {
+				2067,	/* Code */
+				10415,	/* Vendor */
+				"SGW-Address",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, Address_type, NULL);
+		};
+		/* SGW-Change */
+		{
+			struct dict_avp_data data = {
+				2065,	/* Code */
+				10415,	/* Vendor */
+				"SGW-Change",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(SGW-Change)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "ACR_Start_NOT_due_to_SGW_Change", { .i32=0 }};
+			struct dict_enumval_data        t_2 = { "ACR_Start_due_to_SGW_Change", { .i32=1 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* SIP-Method */
+		{
+			struct dict_avp_data data = {
+				824,	/* Code */
+				10415,	/* Vendor */
+				"SIP-Method",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, UTF8String_type, NULL);
+		};
+		/* SIP-Request-Timestamp */
+		{
+			struct dict_avp_data data = {
+				834,	/* Code */
+				10415,	/* Vendor */
+				"SIP-Request-Timestamp",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, Time_type, NULL);
+		};
+		/* SIP-Request-Timestamp-Fraction */
+		{
+			struct dict_avp_data data = {
+				2301,	/* Code */
+				10415,	/* Vendor */
+				"SIP-Request-Timestamp-Fraction",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* SIP-Response-Timestamp */
+		{
+			struct dict_avp_data data = {
+				835,	/* Code */
+				10415,	/* Vendor */
+				"SIP-Response-Timestamp",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, Time_type, NULL);
+		};
+		/* SIP-Response-Timestamp-Fraction */
+		{
+			struct dict_avp_data data = {
+				2302,	/* Code */
+				10415,	/* Vendor */
+				"SIP-Response-Timestamp-Fraction",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* SM-Device-Trigger-Indicator */
+		{
+			struct dict_avp_data data = {
+				3407,	/* Code */
+				10415,	/* Vendor */
+				"SM-Device-Trigger-Indicator",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(SM-Device-Trigger-Indicator)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "Not_DeviceTrigger", { .i32=0 }};
+			struct dict_enumval_data        t_2 = { "Device_Trigger", { .i32=1 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* SM-Discharge-Time */
+		{
+			struct dict_avp_data data = {
+				2012,	/* Code */
+				10415,	/* Vendor */
+				"SM-Discharge-Time",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, Time_type, NULL);
+		};
+		/* SM-Message-Type */
+		{
+			struct dict_avp_data data = {
+				2007,	/* Code */
+				10415,	/* Vendor */
+				"SM-Message-Type",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(SM-Message-Type)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "SUBMISSION", { .i32=0 }};
+			struct dict_enumval_data        t_2 = { "DELIVERY_REPORT", { .i32=1 }};
+			struct dict_enumval_data        t_3 = { "SM_Service_Request", { .i32=2 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_3, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* SM-Protocol-ID */
+		{
+			struct dict_avp_data data = {
+				2013,	/* Code */
+				10415,	/* Vendor */
+				"SM-Protocol-ID",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* SM-Sequence-Number */
+		{
+			struct dict_avp_data data = {
+				3408,	/* Code */
+				10415,	/* Vendor */
+				"SM-Sequence-Number",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* SM-Service-Type */
+		{
+			struct dict_avp_data data = {
+				2029,	/* Code */
+				10415,	/* Vendor */
+				"SM-Service-Type",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(SM-Service-Type)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "VAS4SMS_Short_Message_content_processing", { .i32=0 }};
+			struct dict_enumval_data        t_2 = { "VAS4SMS_Short_Message_forwarding", { .i32=1 }};
+			struct dict_enumval_data        t_3 = { "VAS4SMS_Short_Message_Deferred_Delivery", { .i32=10 }};
+			struct dict_enumval_data        t_4 = { "VAS4SMS_Short_Message_Forwarding_multiple_subscriptions", { .i32=2 }};
+			struct dict_enumval_data        t_5 = { "VAS4SMS_Short_Message_filtering", { .i32=3 }};
+			struct dict_enumval_data        t_6 = { "VAS4SMS_Short_Message_receipt", { .i32=4 }};
+			struct dict_enumval_data        t_7 = { "VAS4SMS_Short_Message_Network_Storage", { .i32=5 }};
+			struct dict_enumval_data        t_8 = { "VAS4SMS_Short_Message_to_multiple_destinations", { .i32=6 }};
+			struct dict_enumval_data        t_9 = { "VAS4SMS_Short_Message_Auto_Reply", { .i32=8 }};
+			struct dict_enumval_data        t_10 = { "VAS4SMS_Short_Message_Personal_Signature", { .i32=9 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_3, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_4, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_5, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_6, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_7, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_8, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_9, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_10, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* SM-Status */
+		{
+			struct dict_avp_data data = {
+				2014,	/* Code */
+				10415,	/* Vendor */
+				"SM-Status",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* SM-User-Data-Header */
+		{
+			struct dict_avp_data data = {
+				2015,	/* Code */
+				10415,	/* Vendor */
+				"SM-User-Data-Header",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* SMS-Node */
+		{
+			struct dict_avp_data data = {
+				2016,	/* Code */
+				10415,	/* Vendor */
+				"SMS-Node",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(SMS-Node)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "SMS_Router", { .i32=0 }};
+			struct dict_enumval_data        t_2 = { "IP_SM_GW", { .i32=1 }};
+			struct dict_enumval_data        t_3 = { "SMS_Router_and_IP_SM_GW", { .i32=2 }};
+			struct dict_enumval_data        t_4 = { "SMS_SC", { .i32=3 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_3, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_4, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* SMS-Result */
+		{
+			struct dict_avp_data data = {
+				3409,	/* Code */
+				10415,	/* Vendor */
+				"SMS-Result",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* SMSC-Address */
+		{
+			struct dict_avp_data data = {
+				2017,	/* Code */
+				10415,	/* Vendor */
+				"SMSC-Address",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, Address_type, NULL);
+		};
+		/* Start-of-Charging */
+		{
+			struct dict_avp_data data = {
+				3419,	/* Code */
+				10415,	/* Vendor */
+				"Start-of-Charging",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, Time_type, NULL);
+		};
+		/* Start-Time */
+		{
+			struct dict_avp_data data = {
+				2041,	/* Code */
+				10415,	/* Vendor */
+				"Start-Time",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, Time_type, NULL);
+		};
+		/* Status-AS-Code */
+		{
+			struct dict_avp_data data = {
+				2702,	/* Code */
+				10415,	/* Vendor */
+				"Status-AS-Code",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Status-AS-Code)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "4xx", { .i32=0 }};
+			struct dict_enumval_data        t_2 = { "5xx", { .i32=1 }};
+			struct dict_enumval_data        t_3 = { "Timeout", { .i32=2 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_3, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* Stop-Time */
+		{
+			struct dict_avp_data data = {
+				2042,	/* Code */
+				10415,	/* Vendor */
+				"Stop-Time",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, Time_type, NULL);
+		};
+		/* Submission-Time */
+		{
+			struct dict_avp_data data = {
+				1202,	/* Code */
+				10415,	/* Vendor */
+				"Submission-Time",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, Time_type, NULL);
+		};
+		/* Subscriber-Role */
+		{
+			struct dict_avp_data data = {
+				2033,	/* Code */
+				10415,	/* Vendor */
+				"Subscriber-Role",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Subscriber-Role)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "Originating", { .i32=0 }};
+			struct dict_enumval_data        t_2 = { "Terminating", { .i32=1 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* TAD-Identifier */
+		{
+			struct dict_avp_data data = {
+				2717,	/* Code */
+				10415,	/* Vendor */
+				"TAD-Identifier",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(TAD-Identifier)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "CS", { .i32=0 }};
+			struct dict_enumval_data        t_2 = { "PS", { .i32=1 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* Talk-Burst-Time */
+		{
+			struct dict_avp_data data = {
+				1286,	/* Code */
+				10415,	/* Vendor */
+				"Talk-Burst-Time",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Talk-Burst-Volume */
+		{
+			struct dict_avp_data data = {
+				1287,	/* Code */
+				10415,	/* Vendor */
+				"Talk-Burst-Volume",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Tariff-XML */
+		{
+			struct dict_avp_data data = {
+				2306,	/* Code */
+				10415,	/* Vendor */
+				"Tariff-XML",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, UTF8String_type, NULL);
+		};
+		/* Teleservice */
+		{
+			struct dict_avp_data data = {
+				3413,	/* Code */
+				10415,	/* Vendor */
+				"Teleservice",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Terminating-IOI */
+		{
+			struct dict_avp_data data = {
+				840,	/* Code */
+				10415,	/* Vendor */
+				"Terminating-IOI",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, UTF8String_type, NULL);
+		};
+		/* Time-First-Reception */
+		{
+			struct dict_avp_data data = {
+				3466,	/* Code */
+				10415,	/* Vendor */
+				"Time-First-Reception",	/* Name */
+				0,	/* Fixed flags */
+				0,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, Time_type, NULL);
+		};
+		/* Time-First-Transmission */
+		{
+			struct dict_avp_data data = {
+				3467,	/* Code */
+				10415,	/* Vendor */
+				"Time-First-Transmission",	/* Name */
+				0,	/* Fixed flags */
+				0,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, Time_type, NULL);
+		};
+		/* Time-First-Usage */
+		{
+			struct dict_avp_data data = {
+				2043,	/* Code */
+				10415,	/* Vendor */
+				"Time-First-Usage",	/* Name */
+				0,	/* Fixed flags */
+				0,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, Time_type, NULL);
+		};
+		/* Time-Indicator */
+		{
+			struct dict_avp_data data = {
+				3911,	/* Code */
+				10415,	/* Vendor */
+				"Time-Indicator",	/* Name */
+				0,	/* Fixed flags */
+				0,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Time-Last-Usage */
+		{
+			struct dict_avp_data data = {
+				2044,	/* Code */
+				10415,	/* Vendor */
+				"Time-Last-Usage",	/* Name */
+				0,	/* Fixed flags */
+				0,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, Time_type, NULL);
+		};
+		/* Time-Quota-Threshold */
+		{
+			struct dict_avp_data data = {
+				868,	/* Code */
+				10415,	/* Vendor */
+				"Time-Quota-Threshold",	/* Name */
+				0,	/* Fixed flags */
+				0,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Time-Quota-Type */
+		{
+			struct dict_avp_data data = {
+				1271,	/* Code */
+				10415,	/* Vendor */
+				"Time-Quota-Type",	/* Name */
+				0,	/* Fixed flags */
+				0,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Time-Quota-Type)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "DISCRETE_TIME_PERIOD", { .i32=0 }};
+			struct dict_enumval_data        t_2 = { "CONTINUOUS_TIME_PERIOD", { .i32=1 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* Time-Usage */
+		{
+			struct dict_avp_data data = {
+				2045,	/* Code */
+				10415,	/* Vendor */
+				"Time-Usage",	/* Name */
+				0,	/* Fixed flags */
+				0,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Token-Text */
+		{
+			struct dict_avp_data data = {
+				1215,	/* Code */
+				10415,	/* Vendor */
+				"Token-Text",	/* Name */
+				0,	/* Fixed flags */
+				0,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, UTF8String_type, NULL);
+		};
+		/* Transcoder-Inserted-Indication */
+		{
+			struct dict_avp_data data = {
+				2605,	/* Code */
+				10415,	/* Vendor */
+				"Transcoder-Inserted-Indication",	/* Name */
+				0,	/* Fixed flags */
+				0,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Transcoder-Inserted-Indication)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "Transcoder_Not_Inserted", { .i32=0 }};
+			struct dict_enumval_data        t_2 = { "Transcoder_Inserted", { .i32=1 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* Transit-IOI-List */
+		{
+			struct dict_avp_data data = {
+				2701,	/* Code */
+				10415,	/* Vendor */
+				"Transit-IOI-List",	/* Name */
+				0,	/* Fixed flags */
+				0,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, UTF8String_type, NULL);
+		};
+		/* Trigger-Type */
+		{
+			struct dict_avp_data data = {
+				870,	/* Code */
+				10415,	/* Vendor */
+				"Trigger-Type",	/* Name */
+				0,	/* Fixed flags */
+				0,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Trigger-Type)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "CHANGE_IN_SGSN_IP_ADDRESS", { .i32=1 }};
+			struct dict_enumval_data        t_2 = { "CHANGE_IN_QOS", { .i32=2 }};
+			struct dict_enumval_data        t_3 = { "CHANGE_IN_LOCATION", { .i32=3 }};
+			struct dict_enumval_data        t_4 = { "CHANGE_IN_RAT", { .i32=4 }};
+			struct dict_enumval_data        t_5 = { "CHANGE_IN_UE_TIMEZONE", { .i32=5 }};
+			struct dict_enumval_data        t_6 = { "CHANGEINQOS_TRAFFIC_CLASS", { .i32=10 }};
+			struct dict_enumval_data        t_7 = { "CHANGEINQOS_RELIABILITY_CLASS", { .i32=11 }};
+			struct dict_enumval_data        t_8 = { "CHANGEINQOS_DELAY_CLASS", { .i32=12 }};
+			struct dict_enumval_data        t_9 = { "CHANGEINQOS_PEAK_THROUGHPUT", { .i32=13 }};
+			struct dict_enumval_data        t_10 = { "CHANGEINQOS_PRECEDENCE_CLASS", { .i32=14 }};
+			struct dict_enumval_data        t_11 = { "CHANGEINQOS_MEAN_THROUGHPUT", { .i32=15 }};
+			struct dict_enumval_data        t_12 = { "CHANGEINQOS_MAXIMUM_BIT_RATE_FOR_UPLINK", { .i32=16 }};
+			struct dict_enumval_data        t_13 = { "CHANGEINQOS_MAXIMUM_BIT_RATE_FOR_DOWNLINK", { .i32=17 }};
+			struct dict_enumval_data        t_14 = { "CHANGEINQOS_RESIDUAL_BER", { .i32=18 }};
+			struct dict_enumval_data        t_15 = { "CHANGEINQOS_SDU_ERROR_RATIO", { .i32=19 }};
+			struct dict_enumval_data        t_16 = { "CHANGEINQOS_TRANSFER_DELAY", { .i32=20 }};
+			struct dict_enumval_data        t_17 = { "CHANGEINQOS_TRAFFIC_HANDLING_PRIORITY", { .i32=21 }};
+			struct dict_enumval_data        t_18 = { "CHANGEINQOS_GUARANTEED_BIT_RATE_FOR_UPLINK", { .i32=22 }};
+			struct dict_enumval_data        t_19 = { "CHANGEINQOS_GUARANTEED_BIT_RATE_FOR_DOWNLINK", { .i32=23 }};
+			struct dict_enumval_data        t_20 = { "CHANGEINQOS_APN_AGGREGATE_MAXIMUM_BIT_RATE", { .i32=24 }};
+			struct dict_enumval_data        t_21 = { "CHANGEINLOCATION_MCC", { .i32=30 }};
+			struct dict_enumval_data        t_22 = { "CHANGEINLOCATION_MNC", { .i32=31 }};
+			struct dict_enumval_data        t_23 = { "CHANGEINLOCATION_RAC", { .i32=32 }};
+			struct dict_enumval_data        t_24 = { "CHANGEINLOCATION_LAC", { .i32=33 }};
+			struct dict_enumval_data        t_25 = { "CHANGEINLOCATION_CellId", { .i32=34 }};
+			struct dict_enumval_data        t_26 = { "CHANGEINLOCATION_TAC", { .i32=35 }};
+			struct dict_enumval_data        t_27 = { "CHANGEINLOCATION_ECGI", { .i32=36 }};
+			struct dict_enumval_data        t_28 = { "CHANGE_IN_MEDIA_COMPOSITION", { .i32=40 }};
+			struct dict_enumval_data        t_29 = { "CHANGE_IN_PARTICIPANTS_NMB", { .i32=50 }};
+			struct dict_enumval_data        t_30 = { "CHANGE_IN_THRSHLD_OF_PARTICIPANTS_NMB", { .i32=51 }};
+			struct dict_enumval_data        t_31 = { "CHANGE_IN_USER_PARTICIPATING_TYPE", { .i32=52 }};
+			struct dict_enumval_data        t_32 = { "CHANGE_IN_SERVICE_CONDITION", { .i32=60 }};
+			struct dict_enumval_data        t_33 = { "CHANGE_IN_SERVING_NODE", { .i32=61 }};
+			struct dict_enumval_data        t_34 = { "CHANGE_IN_ACCESS_FOR_A_SERVICE_DATA_FLOW", { .i32=62 }};
+			struct dict_enumval_data        t_35 = { "CHANGE_IN_USER_CSG_INFORMATION", { .i32=70 }};
+			struct dict_enumval_data        t_36 = { "CHANGE_IN_HYBRID_SUBSCRIBED_USER_CSG_INFORMATION", { .i32=71 }};
+			struct dict_enumval_data        t_37 = { "CHANGE_IN_HYBRID_UNSUBSCRIBED_USER_CSG_INFORMATION", { .i32=72 }};
+			struct dict_enumval_data        t_38 = { "CHANGE_OF_UE_PRESENCE_IN_PRESENCE_REPORTING_AREA", { .i32=73 }};
+			struct dict_enumval_data        t_39 = { "CHANGE_IN_APN_RATE_CONTROL", { .i32=75 }};
+			struct dict_enumval_data        t_40 = { "CHANGE_IN_3GPP_PS_DATA_OFF", { .i32=76 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_3, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_4, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_5, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_6, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_7, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_8, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_9, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_10, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_11, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_12, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_13, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_14, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_15, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_16, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_17, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_18, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_19, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_20, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_21, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_22, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_23, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_24, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_25, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_26, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_27, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_28, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_29, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_30, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_31, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_32, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_33, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_34, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_35, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_36, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_37, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_38, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_39, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_40, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* TWAG-Address */
+		{
+			struct dict_avp_data data = {
+				3903,	/* Code */
+				10415,	/* Vendor */
+				"TWAG-Address",	/* Name */
+				0,	/* Fixed flags */
+				0,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, Address_type, NULL);
+		};
+		/* Type-Number */
+		{
+			struct dict_avp_data data = {
+				1204,	/* Code */
+				10415,	/* Vendor */
+				"Type-Number",	/* Name */
+				0,	/* Fixed flags */
+				0,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* UNI-PDU-CP-Only-Flag */
+		{
+			struct dict_avp_data data = {
+				3932,	/* Code */
+				10415,	/* Vendor */
+				"UNI-PDU-CP-Only-Flag",	/* Name */
+				0,	/* Fixed flags */
+				0,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(UNI-PDU-CP-Only-Flag)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "UNI_PDU_both_UP_CP", { .i32=0 }};
+			struct dict_enumval_data        t_2 = { "UNI_PDU_CP_Only", { .i32=1 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* Unit-Quota-Threshold */
+		{
+			struct dict_avp_data data = {
+				1226,	/* Code */
+				10415,	/* Vendor */
+				"Unit-Quota-Threshold",	/* Name */
+				0,	/* Fixed flags */
+				0,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Usage-Information-Report-Sequence-Number */
+		{
+			struct dict_avp_data data = {
+				3439,	/* Code */
+				10415,	/* Vendor */
+				"Usage-Information-Report-Sequence-Number",	/* Name */
+				0,	/* Fixed flags */
+				0,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* User-Participating-Type */
+		{
+			struct dict_avp_data data = {
+				1279,	/* Code */
+				10415,	/* Vendor */
+				"User-Participating-Type",	/* Name */
+				0,	/* Fixed flags */
+				0,	/* Fixed flag values */
+				AVP_TYPE_INTEGER32	/* base type of data */
+			};
+			struct dict_object        *type;
+			struct dict_type_data     tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(User-Participating-Type)", NULL, NULL, NULL };
+			struct dict_enumval_data        t_1 = { "Normal", { .i32=0 }};
+			struct dict_enumval_data        t_2 = { "NW_PoC_Box", { .i32=1 }};
+			struct dict_enumval_data        t_3 = { "UE_PoC_Box", { .i32=2 }};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata, NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2, type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_3, type, NULL);
+			CHECK_dict_new( DICT_AVP, &data, type, NULL);
+		};
+		/* User-Session-Id */
+		{
+			struct dict_avp_data data = {
+				830,	/* Code */
+				10415,	/* Vendor */
+				"User-Session-Id",	/* Name */
+				0,	/* Fixed flags */
+				0,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, UTF8String_type, NULL);
+		};
+		/* Variable-Part-Order */
+		{
+			struct dict_avp_data data = {
+				3908,	/* Code */
+				10415,	/* Vendor */
+				"Variable-Part-Order",	/* Name */
+				0,	/* Fixed flags */
+				0,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Variable-Part-Type */
+		{
+			struct dict_avp_data data = {
+				3909,	/* Code */
+				10415,	/* Vendor */
+				"Variable-Part-Type",	/* Name */
+				0,	/* Fixed flags */
+				0,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Variable-Part-Value */
+		{
+			struct dict_avp_data data = {
+				3910,	/* Code */
+				10415,	/* Vendor */
+				"Variable-Part-Value",	/* Name */
+				0,	/* Fixed flags */
+				0,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, UTF8String_type, NULL);
+		};
+		/* VLR-Number */
+		{
+			struct dict_avp_data data = {
+				3420,	/* Code */
+				10415,	/* Vendor */
+				"VLR-Number",	/* Name */
+				0,	/* Fixed flags */
+				0,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Volume-Quota-Threshold */
+		{
+			struct dict_avp_data data = {
+				869,	/* Code */
+				10415,	/* Vendor */
+				"Volume-Quota-Threshold",	/* Name */
+				0,	/* Fixed flags */
+				0,	/* Fixed flag values */
+				AVP_TYPE_UNSIGNED32	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		};
+		/* Submission-Timestamp */
+		{
+			struct dict_avp_data data = {
+				9911,	/* Code */
+				10415,	/* Vendor */
+				"Submission-Timestamp",	/* Name */
+				0,	/* Fixed flags */
+				0,	/* Fixed flag values */
+				AVP_TYPE_OCTETSTRING	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data, Time_type, NULL);
+		};
+		/* Scale-Factor */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				2059,	/* Code */
+				10415,	/* Vendor */
+				"Scale-Factor",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* SDP-Media-Component */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				843,	/* Code */
+				10415,	/* Vendor */
+				"SDP-Media-Component",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* UWAN-User-Location-Info */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				3918,	/* Code */
+				10415,	/* Vendor */
+				"UWAN-User-Location-Info",	/* Name */
+				0,	/* Fixed flags */
+				0,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* Address-Domain */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				898,	/* Code */
+				10415,	/* Vendor */
+				"Address-Domain",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* Location-Info */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				3460,	/* Code */
+				10415,	/* Vendor */
+				"Location-Info",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* MBMS-Information */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				880,	/* Code */
+				10415,	/* Vendor */
+				"MBMS-Information",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* AoC-Service */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				2311,	/* Code */
+				10415,	/* Vendor */
+				"AoC-Service",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* ProSe-Direct-Communication-Transmission-Data-Container */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				3441,	/* Code */
+				10415,	/* Vendor */
+				"ProSe-Direct-Communication-Transmission-Data-Container",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* APN-Rate-Control-Downlink */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				3934,	/* Code */
+				10415,	/* Vendor */
+				"APN-Rate-Control-Downlink",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* PoC-Information */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				879,	/* Code */
+				10415,	/* Vendor */
+				"PoC-Information",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* Supplementary-Service */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				2048,	/* Code */
+				10415,	/* Vendor */
+				"Supplementary-Service",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* Transmitter-Info */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				3468,	/* Code */
+				10415,	/* Vendor */
+				"Transmitter-Info",	/* Name */
+				0,	/* Fixed flags */
+				0,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* Unit-Cost */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				2061,	/* Code */
+				10415,	/* Vendor */
+				"Unit-Cost",	/* Name */
+				0,	/* Fixed flags */
+				0,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* Time-Stamps */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				833,	/* Code */
+				10415,	/* Vendor */
+				"Time-Stamps",	/* Name */
+				0,	/* Fixed flags */
+				0,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* NNI-Information */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				2703,	/* Code */
+				10415,	/* Vendor */
+				"NNI-Information",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* Trigger */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				1264,	/* Code */
+				10415,	/* Vendor */
+				"Trigger",	/* Name */
+				0,	/* Fixed flags */
+				0,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* Related-Trigger */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				3926,	/* Code */
+				10415,	/* Vendor */
+				"Related-Trigger",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* Talk-Burst-Exchange */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				1255,	/* Code */
+				10415,	/* Vendor */
+				"Talk-Burst-Exchange",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* Time-Quota-Mechanism */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				1270,	/* Code */
+				10415,	/* Vendor */
+				"Time-Quota-Mechanism",	/* Name */
+				0,	/* Fixed flags */
+				0,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* Variable-Part */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				3907,	/* Code */
+				10415,	/* Vendor */
+				"Variable-Part",	/* Name */
+				0,	/* Fixed flags */
+				0,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* Additional-Content-Information */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				1207,	/* Code */
+				10415,	/* Vendor */
+				"Additional-Content-Information",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* APN-Rate-Control-Uplink */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				3935,	/* Code */
+				10415,	/* Vendor */
+				"APN-Rate-Control-Uplink",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* Basic-Service-Code */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				3411,	/* Code */
+				10415,	/* Vendor */
+				"Basic-Service-Code",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* Event-Type */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				823,	/* Code */
+				10415,	/* Vendor */
+				"Event-Type",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* ProSe-Direct-Communication-Reception-Data-Container */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				3461,	/* Code */
+				10415,	/* Vendor */
+				"ProSe-Direct-Communication-Reception-Data-Container",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* Originator-Interface */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				2009,	/* Code */
+				10415,	/* Vendor */
+				"Originator-Interface",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* Destination-Interface */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				2002,	/* Code */
+				10415,	/* Vendor */
+				"Destination-Interface",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* ISUP-Cause */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				3416,	/* Code */
+				10415,	/* Vendor */
+				"ISUP-Cause",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* LCS-Requestor-ID */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				1239,	/* Code */
+				10415,	/* Vendor */
+				"LCS-Requestor-ID",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* PS-Furnish-Charging-Information */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				865,	/* Code */
+				10415,	/* Vendor */
+				"PS-Furnish-Charging-Information",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* User-CSG-Information */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				2319,	/* Code */
+				10415,	/* Vendor */
+				"User-CSG-Information",	/* Name */
+				0,	/* Fixed flags */
+				0,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* Called-Identity-Change */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				3917,	/* Code */
+				10415,	/* Vendor */
+				"Called-Identity-Change",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* Service-Specific-Info */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				1249,	/* Code */
+				10415,	/* Vendor */
+				"Service-Specific-Info",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* Accumulated-Cost */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				2052,	/* Code */
+				10415,	/* Vendor */
+				"Accumulated-Cost",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* SCS-AS-Address */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				3940,	/* Code */
+				10415,	/* Vendor */
+				"SCS-AS-Address",	/* Name */
+				0,	/* Fixed flags */
+				0,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* Message-Class */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				1213,	/* Code */
+				10415,	/* Vendor */
+				"Message-Class",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* Location-Type */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				1244,	/* Code */
+				10415,	/* Vendor */
+				"Location-Type",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* Rate-Element */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				2058,	/* Code */
+				10415,	/* Vendor */
+				"Rate-Element",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* Participant-Group */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				1260,	/* Code */
+				10415,	/* Vendor */
+				"Participant-Group",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* Enhanced-Diagnostics */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				3901,	/* Code */
+				10415,	/* Vendor */
+				"Enhanced-Diagnostics",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* Access-Network-Info-Change */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				4401,	/* Code */
+				10415,	/* Vendor */
+				"Access-Network-Info-Change",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* PoC-User-Role */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				1252,	/* Code */
+				10415,	/* Vendor */
+				"PoC-User-Role",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* LCS-Client-Name */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				1235,	/* Code */
+				10415,	/* Vendor */
+				"LCS-Client-Name",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* Message-Body */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				889,	/* Code */
+				10415,	/* Vendor */
+				"Message-Body",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* Radio-Parameter-Set-Info */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				3463,	/* Code */
+				10415,	/* Vendor */
+				"Radio-Parameter-Set-Info",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* SM-Device-Trigger-Information */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				3405,	/* Code */
+				10415,	/* Vendor */
+				"SM-Device-Trigger-Information",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* TWAN-User-Location-Info */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				2714,	/* Code */
+				10415,	/* Vendor */
+				"TWAN-User-Location-Info",	/* Name */
+				0,	/* Fixed flags */
+				0,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* VCS-Information */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				3410,	/* Code */
+				10415,	/* Vendor */
+				"VCS-Information",	/* Name */
+				0,	/* Fixed flags */
+				0,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* Trunk-Group-ID */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				851,	/* Code */
+				10415,	/* Vendor */
+				"Trunk-Group-ID",	/* Name */
+				0,	/* Fixed flags */
+				0,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* Incremental-Cost */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				2062,	/* Code */
+				10415,	/* Vendor */
+				"Incremental-Cost",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* SDP-TimeStamps */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				1273,	/* Code */
+				10415,	/* Vendor */
+				"SDP-TimeStamps",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* Inter-Operator-Identifier */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				838,	/* Code */
+				10415,	/* Vendor */
+				"Inter-Operator-Identifier",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* NIDD-Submission */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				3928,	/* Code */
+				10415,	/* Vendor */
+				"NIDD-Submission",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* Application-Server-Information */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				850,	/* Code */
+				10415,	/* Vendor */
+				"Application-Server-Information",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* CPDT-Information */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				3927,	/* Code */
+				10415,	/* Vendor */
+				"CPDT-Information",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* Envelope */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				1266,	/* Code */
+				10415,	/* Vendor */
+				"Envelope",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* Related-Change-Condition-Information */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				3925,	/* Code */
+				10415,	/* Vendor */
+				"Related-Change-Condition-Information",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* LCS-Client-Id */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				1232,	/* Code */
+				10415,	/* Vendor */
+				"LCS-Client-Id",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* Early-Media-Description */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				1272,	/* Code */
+				10415,	/* Vendor */
+				"Early-Media-Description",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* AoC-Subscription-Information */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				2314,	/* Code */
+				10415,	/* Vendor */
+				"AoC-Subscription-Information",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* Current-Tariff */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				2056,	/* Code */
+				10415,	/* Vendor */
+				"Current-Tariff",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* APN-Rate-Control */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				3933,	/* Code */
+				10415,	/* Vendor */
+				"APN-Rate-Control",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* Access-Transfer-Information */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				2709,	/* Code */
+				10415,	/* Vendor */
+				"Access-Transfer-Information",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* Recipient-Received-Address */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				2028,	/* Code */
+				10415,	/* Vendor */
+				"Recipient-Received-Address",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* AoC-Cost-Information */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				2053,	/* Code */
+				10415,	/* Vendor */
+				"AoC-Cost-Information",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* Originator-Address */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				886,	/* Code */
+				10415,	/* Vendor */
+				"Originator-Address",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* Originator-Received-Address */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				2027,	/* Code */
+				10415,	/* Vendor */
+				"Originator-Received-Address",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* Remaining-Balance */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				2021,	/* Code */
+				10415,	/* Vendor */
+				"Remaining-Balance",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* AF-Correlation-Information */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				1276,	/* Code */
+				10415,	/* Vendor */
+				"AF-Correlation-Information",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* Recipient-Address */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				1201,	/* Code */
+				10415,	/* Vendor */
+				"Recipient-Address",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* Next-Tariff */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				2057,	/* Code */
+				10415,	/* Vendor */
+				"Next-Tariff",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* Coverage-Info */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				3459,	/* Code */
+				10415,	/* Vendor */
+				"Coverage-Info",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* Announcement-Information */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				3904,	/* Code */
+				10415,	/* Vendor */
+				"Announcement-Information",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* MM-Content-Type */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				1203,	/* Code */
+				10415,	/* Vendor */
+				"MM-Content-Type",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* MMTel-Information */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				2030,	/* Code */
+				10415,	/* Vendor */
+				"MMTel-Information",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* Service-Data-Container */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				2040,	/* Code */
+				10415,	/* Vendor */
+				"Service-Data-Container",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* MMS-Information */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				877,	/* Code */
+				10415,	/* Vendor */
+				"MMS-Information",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* Recipient-Info */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				2026,	/* Code */
+				10415,	/* Vendor */
+				"Recipient-Info",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* Traffic-Data-Volumes */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				2046,	/* Code */
+				10415,	/* Vendor */
+				"Traffic-Data-Volumes",	/* Name */
+				0,	/* Fixed flags */
+				0,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* LCS-Information */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				878,	/* Code */
+				10415,	/* Vendor */
+				"LCS-Information",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* Tariff-Information */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				2060,	/* Code */
+				10415,	/* Vendor */
+				"Tariff-Information",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* ProSe-Information */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				3447,	/* Code */
+				10415,	/* Vendor */
+				"ProSe-Information",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* SMS-Information */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				2000,	/* Code */
+				10415,	/* Vendor */
+				"SMS-Information",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* Real-Time-Tariff-Information */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				2305,	/* Code */
+				10415,	/* Vendor */
+				"Real-Time-Tariff-Information",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* AoC-Information */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				2054,	/* Code */
+				10415,	/* Vendor */
+				"AoC-Information",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* Monitoring-Event-Report-Data */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				3920,	/* Code */
+				10415,	/* Vendor */
+				"Monitoring-Event-Report-Data",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* Offline-Charging */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				1278,	/* Code */
+				10415,	/* Vendor */
+				"Offline-Charging",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* IMS-Information */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				876,	/* Code */
+				10415,	/* Vendor */
+				"IMS-Information",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* Monitoring-Event-Information */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				3921,	/* Code */
+				10415,	/* Vendor */
+				"Monitoring-Event-Information",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* PS-Information */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				874,	/* Code */
+				10415,	/* Vendor */
+				"PS-Information",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+		/* Service-Information */
+		{
+			/* Grouped */
+			struct dict_object * avp;
+			struct dict_avp_data data = {
+				873,	/* Code */
+				10415,	/* Vendor */
+				"Service-Information",	/* Name */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flags */
+				AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	/* Fixed flag values */
+				AVP_TYPE_GROUPED	/* base type of data */
+			};
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+		}
+
+	
+   }
+
+   /* Commands section */
+   {
+
+   }
+
+   return 0;
+}
+
+static int dict_ts32299_avps_load_rules(char * conffile)
+{
+   /* Grouped AVP section */
+   {
+	  /* Scale-Factor */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "Scale-Factor"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 0, .avp_name = "Value-Digits"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Exponent"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* SDP-Media-Component */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "SDP-Media-Component"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 10415, .avp_name = "SDP-Media-Name"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "SDP-Media-Description"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Local-GW-Inserted-Indication"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "IP-Realm-Default-Indication"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Transcoder-Inserted-Indication"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Media-Initiator-Flag"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Media-Initiator-Party"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "3GPP-Charging-Id"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Access-Network-Charging-Identifier-Value"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "SDP-Type"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* UWAN-User-Location-Info */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "UWAN-User-Location-Info"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 10415, .avp_name = "UE-Local-IP-Address"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "UDP-Source-Port"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "SSID"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "BSSID"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* Address-Domain */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "Address-Domain"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 10415, .avp_name = "Domain-Name"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "3GPP-IMSI-MCC-MNC"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* Location-Info */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "Location-Info"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 10415, .avp_name = "3GPP-User-Location-Info"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Change-Time"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* MBMS-Information */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "MBMS-Information"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 10415, .avp_name = "TMGI"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "MBMS-Service-Type"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "MBMS-User-Service-Type"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "File-Repair-Supported"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Required-MBMS-Bearer-Capabilities"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "MBMS-2G-3G-Indicator"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "RAI"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "MBMS-Service-Area"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "MBMS-Session-Identity"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "CN-IP-Multicast-Distribution"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "MBMS-GW-Address"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "MBMS-Charged-Party"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "MSISDN"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "MBMS-Data-Transfer-Start"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "MBMS-Data-Transfer-Stop"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* AoC-Service */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "AoC-Service"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 10415, .avp_name = "AoC-Service-Obligatory-Type"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "AoC-Service-Type"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* ProSe-Direct-Communication-Transmission-Data-Container */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "ProSe-Direct-Communication-Transmission-Data-Container"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 10415, .avp_name = "Local-Sequence-Number"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Coverage-Status"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "3GPP-User-Location-Info"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Accounting-Output-Octets"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Change-Time"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Change-Condition"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Visited-PLMN-Id"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Usage-Information-Report-Sequence-Number"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Radio-Resources-Indicator"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Radio-Frequency"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* APN-Rate-Control-Downlink */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "APN-Rate-Control-Downlink"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 10415, .avp_name = "Rate-Control-Time-Unit"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Rate-Control-Max-Rate"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Rate-Control-Max-Message-Size"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* PoC-Information */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "PoC-Information"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 10415, .avp_name = "PoC-Server-Role"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* Supplementary-Service */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "Supplementary-Service"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 10415, .avp_name = "MMTel-SService-Type"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Service-Mode"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* Transmitter-Info */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "Transmitter-Info"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 10415, .avp_name = "ProSe-Source-IP-Address"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "ProSe-UE-ID"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* Unit-Cost */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "Unit-Cost"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 0, .avp_name = "Value-Digits"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Exponent"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* Time-Stamps */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "Time-Stamps"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 10415, .avp_name = "SIP-Request-Timestamp"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* NNI-Information */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "NNI-Information"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 10415, .avp_name = "Session-Direction"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "NNI-Type"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Relationship-Mode"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Neighbour-Node-Address"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* Trigger */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "Trigger"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 10415, .avp_name = "Trigger-Type"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* Related-Trigger */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "Related-Trigger"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 10415, .avp_name = "Trigger-Type"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* Talk-Burst-Exchange */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "Talk-Burst-Exchange"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 10415, .avp_name = "PoC-Change-Time"}, RULE_REQUIRED, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* Time-Quota-Mechanism */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "Time-Quota-Mechanism"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 10415, .avp_name = "Time-Quota-Type"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Base-Time-Interval"}, RULE_REQUIRED, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* Variable-Part */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "Variable-Part"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 10415, .avp_name = "Variable-Part-Order"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Variable-Part-Type"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Variable-Part-Value"}, RULE_REQUIRED, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* Additional-Content-Information */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "Additional-Content-Information"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 10415, .avp_name = "Type-Number"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Additional-Type-Information"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Content-Size"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* APN-Rate-Control-Uplink */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "APN-Rate-Control-Uplink"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 10415, .avp_name = "Additional-Exception-Reports"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Rate-Control-Time-Unit"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Rate-Control-Max-Rate"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* Basic-Service-Code */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "Basic-Service-Code"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 10415, .avp_name = "Bearer-Service"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Teleservice"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* Event-Type */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "Event-Type"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 10415, .avp_name = "SIP-Method"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Event"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Expires"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* ProSe-Direct-Communication-Reception-Data-Container */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "ProSe-Direct-Communication-Reception-Data-Container"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 10415, .avp_name = "Local-Sequence-Number"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Coverage-Status"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "3GPP-User-Location-Info"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Accounting-Input-Octets"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Change-Time"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Change-Condition"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Visited-PLMN-Id"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Usage-Information-Report-Sequence-Number"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Radio-Resources-Indicator"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Radio-Frequency"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* Originator-Interface */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "Originator-Interface"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 10415, .avp_name = "Interface-Id"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Interface-Text"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Interface-Port"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Interface-Type"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* Destination-Interface */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "Destination-Interface"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 10415, .avp_name = "Interface-Id"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Interface-Text"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Interface-Port"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Interface-Type"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* ISUP-Cause */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "ISUP-Cause"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 10415, .avp_name = "ISUP-Cause-Location"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* LCS-Requestor-ID */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "LCS-Requestor-ID"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 10415, .avp_name = "LCS-Data-Coding-Scheme"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "LCS-Requestor-ID-String"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* PS-Furnish-Charging-Information */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "PS-Furnish-Charging-Information"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 10415, .avp_name = "3GPP-Charging-Id"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "PS-Free-Format-Data"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "PS-Append-Free-Format-Data"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* User-CSG-Information */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "User-CSG-Information"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 10415, .avp_name = "CSG-Id"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "CSG-Access-Mode"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "CSG-Membership-Indication"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* Called-Identity-Change */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "Called-Identity-Change"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 10415, .avp_name = "Called-Identity"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Change-Time"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* Service-Specific-Info */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "Service-Specific-Info"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 10415, .avp_name = "Service-Specific-Data"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* Accumulated-Cost */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "Accumulated-Cost"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 0, .avp_name = "Value-Digits"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Exponent"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* SCS-AS-Address */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "SCS-AS-Address"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 10415, .avp_name = "SCS-Realm"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "SCS-Address"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* Message-Class */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "Message-Class"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 10415, .avp_name = "Class-Identifier"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Token-Text"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* Location-Type */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "Location-Type"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 10415, .avp_name = "Location-Estimate-Type"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Deferred-Location-Event-Type"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* Rate-Element */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "Rate-Element"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 0, .avp_name = "CC-Unit-Type"}, RULE_REQUIRED, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* Participant-Group */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "Participant-Group"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 10415, .avp_name = "Called-Party-Address"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Participant-Access-Priority"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "User-Participating-Type"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* Enhanced-Diagnostics */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "Enhanced-Diagnostics"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 10415, .avp_name = "RAN-NAS-Release-Cause"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* Access-Network-Info-Change */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "Access-Network-Info-Change"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 10415, .avp_name = "Access-Network-Information"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Cellular-Network-Information"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Change-Time"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* PoC-User-Role */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "PoC-User-Role"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 10415, .avp_name = "PoC-User-Role-IDs"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* LCS-Client-Name */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "LCS-Client-Name"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 10415, .avp_name = "LCS-Data-Coding-Scheme"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "LCS-Name-String"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "LCS-Format-Indicator"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* Message-Body */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "Message-Body"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 10415, .avp_name = "Content-Type"}, RULE_REQUIRED, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* Radio-Parameter-Set-Info */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "Radio-Parameter-Set-Info"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 10415, .avp_name = "Radio-Parameter-Set-Values"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Change-Time"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* SM-Device-Trigger-Information */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "SM-Device-Trigger-Information"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 10415, .avp_name = "MTC-IWF-Address"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Reference-Number"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* TWAN-User-Location-Info */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "TWAN-User-Location-Info"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 10415, .avp_name = "SSID"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "BSSID"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* VCS-Information */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "VCS-Information"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 10415, .avp_name = "Bearer-Capability"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Network-Call-Reference-Number"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "MSC-Address"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* Trunk-Group-ID */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "Trunk-Group-ID"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 10415, .avp_name = "Incoming-Trunk-Group-Id"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* Incremental-Cost */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "Incremental-Cost"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 0, .avp_name = "Value-Digits"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Exponent"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* SDP-TimeStamps */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "SDP-TimeStamps"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 10415, .avp_name = "SDP-Offer-Timestamp"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "SDP-Answer-Timestamp"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* Inter-Operator-Identifier */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "Inter-Operator-Identifier"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 10415, .avp_name = "Originating-IOI"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Terminating-IOI"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* NIDD-Submission */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "NIDD-Submission"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 10415, .avp_name = "Submission-Timestamp"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Event-Timestamp"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Accounting-Input-Octets"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Accounting-Output-Octets"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Change-Condition"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* Application-Server-Information */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "Application-Server-Information"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 10415, .avp_name = "Application-Server"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* CPDT-Information */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "CPDT-Information"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 10415, .avp_name = "External-Identifier"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "SCEF-ID"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* Envelope */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "Envelope"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 10415, .avp_name = "Envelope-Start-Time"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Envelope-End-Time"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "CC-Total-Octets"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "CC-Input-Octets"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "CC-Output-Octets"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "CC-Service-Specific-Units"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* Related-Change-Condition-Information */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "Related-Change-Condition-Information"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 10415, .avp_name = "SGSN-Address"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Change-Condition"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "3GPP-User-Location-Info"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 5535, .avp_name = "3GPP2-BSID"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "UWAN-User-Location-Info"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Presence-Reporting-Area-Status"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "User-CSG-Information"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "3GPP-RAT-Type"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* LCS-Client-Id */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "LCS-Client-Id"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 10415, .avp_name = "LCS-Client-Type"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "LCS-Client-External-ID"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "LCS-Client-Dialed-By-MS"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "LCS-Client-Name"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "LCS-APN"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "LCS-Requestor-ID"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* Early-Media-Description */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "Early-Media-Description"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 10415, .avp_name = "SDP-TimeStamps"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "SDP-Media-Component"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "SDP-Session-Description"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* AoC-Subscription-Information */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "AoC-Subscription-Information"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 10415, .avp_name = "AoC-Service"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "AoC-Format"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Preferred-AoC-Currency"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* Current-Tariff */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "Current-Tariff"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 0, .avp_name = "Currency-Code"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Scale-Factor"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Rate-Element"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* APN-Rate-Control */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "APN-Rate-Control"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 10415, .avp_name = "APN-Rate-Control-Uplink"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "APN-Rate-Control-Downlink"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* Access-Transfer-Information */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "Access-Transfer-Information"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 10415, .avp_name = "Access-Transfer-Type"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Access-Network-Information"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Cellular-Network-Information"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Inter-UE-Transfer"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "User-Equipment-Info"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Instance-Id"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Related-IMS-Charging-Identifier"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Related-IMS-Charging-Identifier-Node"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Change-Time"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* Recipient-Received-Address */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "Recipient-Received-Address"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 10415, .avp_name = "Address-Type"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Address-Data"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Address-Domain"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* AoC-Cost-Information */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "AoC-Cost-Information"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 10415, .avp_name = "Accumulated-Cost"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Incremental-Cost"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Currency-Code"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* Originator-Address */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "Originator-Address"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 10415, .avp_name = "Address-Type"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Address-Data"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Address-Domain"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* Originator-Received-Address */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "Originator-Received-Address"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 10415, .avp_name = "Address-Type"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Address-Data"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Address-Domain"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* Remaining-Balance */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "Remaining-Balance"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 0, .avp_name = "Unit-Value"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Currency-Code"}, RULE_REQUIRED, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* AF-Correlation-Information */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "AF-Correlation-Information"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 10415, .avp_name = "AF-Charging-Identifier"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Flows"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* Recipient-Address */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "Recipient-Address"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 10415, .avp_name = "Address-Type"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Address-Data"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Address-Domain"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Addressee-Type"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* Next-Tariff */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "Next-Tariff"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 0, .avp_name = "Currency-Code"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Scale-Factor"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Rate-Element"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* Coverage-Info */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "Coverage-Info"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 10415, .avp_name = "Coverage-Status"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Change-Time"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Location-Info"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* Announcement-Information */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "Announcement-Information"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 10415, .avp_name = "Announcement-Identifier"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Variable-Part"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Time-Indicator"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Quota-Indicator"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Announcement-Order"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Play-Alternative"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Privacy-Indicator"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Language"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* MM-Content-Type */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "MM-Content-Type"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 10415, .avp_name = "Type-Number"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Additional-Type-Information"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Content-Size"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Additional-Content-Information"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* MMTel-Information */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "MMTel-Information"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 10415, .avp_name = "Supplementary-Service"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* Service-Data-Container */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "Service-Data-Container"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 10415, .avp_name = "AF-Correlation-Information"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Charging-Rule-Base-Name"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Accounting-Input-Octets"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Accounting-Output-Octets"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Local-Sequence-Number"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "QoS-Information"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Rating-Group"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Change-Time"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Service-Identifier"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Service-Specific-Info"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "ADC-Rule-Base-Name"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "SGSN-Address"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Time-First-Usage"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Time-Last-Usage"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Time-Usage"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Change-Condition"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "3GPP-User-Location-Info"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 5535, .avp_name = "3GPP2-BSID"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "UWAN-User-Location-Info"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Sponsor-Identity"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Application-Service-Provider-Identity"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Presence-Reporting-Area-Information"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Presence-Reporting-Area-Status"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "User-CSG-Information"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "3GPP-RAT-Type"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Related-Change-Condition-Information"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Serving-PLMN-Rate-Control"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "APN-Rate-Control"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "3GPP-PS-Data-Off-Status"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* MMS-Information */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "MMS-Information"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 10415, .avp_name = "Originator-Address"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Recipient-Address"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Submission-Time"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "MM-Content-Type"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Priority"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Message-ID"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Message-Type"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Message-Size"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Message-Class"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Delivery-Report-Requested"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Read-Reply-Report-Requested"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "MMBox-Storage-Requested"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Applic-ID"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Reply-Applic-ID"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Aux-Applic-Info"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Content-Class"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "DRM-Content"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Adaptations"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* Recipient-Info */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "Recipient-Info"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 10415, .avp_name = "Destination-Interface"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Recipient-Address"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Recipient-Received-Address"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Recipient-SCCP-Address"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "SM-Protocol-ID"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* Traffic-Data-Volumes */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "Traffic-Data-Volumes"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 10415, .avp_name = "QoS-Information"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Accounting-Input-Octets"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Accounting-Output-Octets"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Change-Condition"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Change-Time"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "3GPP-User-Location-Info"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "UWAN-User-Location-Info"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "3GPP-Charging-Id"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Presence-Reporting-Area-Status"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "User-CSG-Information"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "3GPP-RAT-Type"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* LCS-Information */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "LCS-Information"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 10415, .avp_name = "LCS-Client-Id"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Location-Type"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Location-Estimate"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Positioning-Data"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "3GPP-IMSI"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "MSISDN"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* Tariff-Information */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "Tariff-Information"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 10415, .avp_name = "Current-Tariff"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Tariff-Time-Change"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Next-Tariff"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* ProSe-Information */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "ProSe-Information"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 10415, .avp_name = "Announcing-UE-HPLMN-Identifier"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Announcing-UE-VPLMN-Identifier"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Monitoring-UE-HPLMN-Identifier"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Monitoring-UE-VPLMN-Identifier"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Role-Of-ProSe-Function"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "ProSe-App-Id"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "ProSe-3rd-Party-Application-ID"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Application-Specific-Data"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "ProSe-Event-Type"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "ProSe-Direct-Discovery-Model"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "ProSe-Function-IP-Address"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "ProSe-Function-ID"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "ProSe-Validity-Timer"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "ProSe-Role-Of-UE"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "ProSe-Request-Timestamp"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "PC3-Control-Protocol-Cause"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Monitoring-UE-Identifier"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Requestor-PLMN-Identifier"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Origin-App-Layer-User-Id"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "WLAN-Link-Layer-Id"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Requesting-EPUID"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Target-App-Layer-User-Id"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Requested-PLMN-Identifier"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Time-Window"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "ProSe-Range-Class"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Proximity-Alert-Indication"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Proximity-Alert-Timestamp"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Proximity-Cancellation-Timestamp"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "ProSe-Reason-For-Cancellation"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "PC3-EPC-Control-Protocol-Cause"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "ProSe-UE-ID"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "ProSe-Source-IP-Address"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Layer-2-Group-ID"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "ProSe-Group-IP-Multicast-Address"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Coverage-Info"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Radio-Parameter-Set-Info"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Transmitter-Info"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Time-First-Transmission"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Time-First-Reception"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "ProSe-Direct-Communication-Transmission-Data-Container"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "ProSe-Direct-Communication-Reception-Data-Container"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* SMS-Information */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "SMS-Information"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 10415, .avp_name = "SMS-Node"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Client-Address"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Originator-SCCP-Address"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "SMSC-Address"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Data-Coding-Scheme"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "SM-Discharge-Time"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "SM-Message-Type"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Originator-Interface"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "SM-Protocol-ID"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Reply-Path-Requested"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "SM-Status"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "SM-User-Data-Header"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Number-Of-Messages-Sent"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "SM-Sequence-Number"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Recipient-Info"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Originator-Received-Address"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "SM-Service-Type"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "SMS-Result"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "SM-Device-Trigger-Indicator"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "SM-Device-Trigger-Information"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* Real-Time-Tariff-Information */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "Real-Time-Tariff-Information"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 10415, .avp_name = "Tariff-Information"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Tariff-XML"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* AoC-Information */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "AoC-Information"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 10415, .avp_name = "AoC-Cost-Information"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Tariff-Information"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "AoC-Subscription-Information"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* Monitoring-Event-Report-Data */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "Monitoring-Event-Report-Data"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 0, .avp_name = "Event-Timestamp"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "SCEF-Reference-ID"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "SCEF-ID"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Monitoring-Event-Report-Number"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Charged-Party"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Subscription-Id"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Monitoring-Type"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Reachability-Information"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "EPS-Location-Information"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Communication-Failure-Information"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Number-Of-UE-Per-Location-Report"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* Offline-Charging */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "Offline-Charging"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 10415, .avp_name = "Quota-Consumption-Time"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Time-Quota-Mechanism"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Envelope-Reporting"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Multiple-Services-Credit-Control"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* IMS-Information */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "IMS-Information"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 10415, .avp_name = "Event-Type"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Role-Of-Node"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Node-Functionality"}, RULE_REQUIRED, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "User-Session-Id"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Outgoing-Session-Id"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Session-Priority"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Calling-Party-Address"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Called-Party-Address"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Called-Asserted-Identity"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Called-Identity-Change"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Number-Portability-Routing-Information"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Carrier-Select-Routing-Information"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Alternate-Charged-Party-Address"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Requested-Party-Address"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Associated-URI"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Time-Stamps"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Application-Server-Information"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Inter-Operator-Identifier"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Transit-IOI-List"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "IMS-Charging-Identifier"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "SDP-Session-Description"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "SDP-Media-Component"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Served-Party-IP-Address"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Server-Capabilities"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Trunk-Group-ID"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Bearer-Service"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Service-Id"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Service-Specific-Info"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Message-Body"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Cause-Code"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Reason-Header"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Access-Network-Information"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Cellular-Network-Information"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Early-Media-Description"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "IMS-Communication-Service-Identifier"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "IMS-Application-Reference-Identifier"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Online-Charging-Flag"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Real-Time-Tariff-Information"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Account-Expiration"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Initial-IMS-Charging-Identifier"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "NNI-Information"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "From-Address"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "IMS-Emergency-Indicator"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "IMS-Visited-Network-Identifier"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Access-Network-Info-Change"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Access-Transfer-Information"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Related-IMS-Charging-Identifier"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Related-IMS-Charging-Identifier-Node"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Route-Header-Received"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Route-Header-Transmitted"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Instance-Id"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "TAD-Identifier"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* Monitoring-Event-Information */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "Monitoring-Event-Information"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 10415, .avp_name = "Monitoring-Event-Functionality"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Event-Timestamp"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Monitoring-Event-Configuration-Activity"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "SCEF-Reference-ID"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "SCEF-ID"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Monitoring-Type"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Maximum-Number-of-Reports"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Monitoring-Duration"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Charged-Party"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Maximum-Detection-Time"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "UE-Reachability-Configuration"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "MONTE-Location-Type"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Accuracy"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Number-Of-UE-Per-Location-Configuration"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Monitoring-Event-Report"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* PS-Information */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "PS-Information"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 10415, .avp_name = "3GPP-Charging-Id"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "PDN-Connection-Charging-ID"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Node-Id"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "3GPP-PDP-Type"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "PDP-Address"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "PDP-Address-Prefix-Length"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Dynamic-Address-Flag"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Dynamic-Address-Flag-Extension"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "QoS-Information"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "SGSN-Address"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "GGSN-Address"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "TDF-IP-Address"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "SGW-Address"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "EPDG-Address"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "TWAG-Address"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "CG-Address"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Serving-Node-Type"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "SGW-Change"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "3GPP-IMSI-MCC-MNC"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "IMSI-Unauthenticated-Flag"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "3GPP-GGSN-MCC-MNC"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "3GPP-NSAPI"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "Called-Station-Id"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "3GPP-Selection-Mode"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "3GPP-Charging-Characteristics"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Charging-Characteristics-Selection-Mode"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "3GPP-SGSN-MCC-MNC"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "3GPP-MS-TimeZone"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Charging-Rule-Base-Name"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "ADC-Rule-Base-Name"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "3GPP-User-Location-Info"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "User-Location-Info-Time"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "User-CSG-Information"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Presence-Reporting-Area-Information"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 5535, .avp_name = "3GPP2-BSID"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "TWAN-User-Location-Info"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "UWAN-User-Location-Info"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "3GPP-RAT-Type"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "PS-Furnish-Charging-Information"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "PDP-Context-Type"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Offline-Charging"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Traffic-Data-Volumes"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Service-Data-Container"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 0, .avp_name = "User-Equipment-Info"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Terminal-Information"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Start-Time"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Stop-Time"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Change-Condition"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Diagnostics"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Low-Priority-Indicator"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "NBIFOM-Mode"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "NBIFOM-Support"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "MME-Number-for-MT-SMS"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "MME-Name"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "MME-Realm"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 13019, .avp_name = "Logical-Access-Id"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 13019, .avp_name = "Physical-Access-Id"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Fixed-User-Location-Info"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "CN-Operator-Selection-Entity"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Enhanced-Diagnostics"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "SGi-PtP-Tunnelling-Method"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "CP-CIoT-EPS-Optimisation-Indicator"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "UNI-PDU-CP-Only-Flag"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Serving-PLMN-Rate-Control"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "APN-Rate-Control"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "Charging-Per-IP-CAN-Session-Indicator"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "RRC-Cause-Counter"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "3GPP-PS-Data-Off-Status"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "SCS-AS-Address"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+	  /* Service-Information */
+	  {
+		/* Grouped */
+		struct dict_object * avp;
+		struct dict_avp_request avp_vendor_plus_name =  { .avp_vendor = 10415, .avp_name = "Service-Information"};
+		CHECK_dict_search(DICT_AVP,  AVP_BY_NAME_AND_VENDOR, &avp_vendor_plus_name, &avp)
+		struct local_rules_definition rules[] =
+		{
+			{ { .avp_vendor = 0, .avp_name = "Subscription-Id"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "AoC-Information"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "PS-Information"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "IMS-Information"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "MMS-Information"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "LCS-Information"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "PoC-Information"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "MBMS-Information"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "SMS-Information"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "VCS-Information"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "MMTel-Information"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "ProSe-Information"}, RULE_OPTIONAL, -1, -1 },
+			{ { .avp_vendor = 10415, .avp_name = "CPDT-Information"}, RULE_OPTIONAL, -1, -1 }
+		};
+		PARSE_loc_rules( rules, avp );
+	  }
+
+   }	
+
+   /* Commands section */
+   {
+
+   }
+
+   LOG_D( "Extension 'Dictionary definitions for ts32299_avps (e30)' initialized");
+   return 0;
+}
+
+int dict_entry(char * conffile)
+{
+	dict_ts32299_avps_load_defs(conffile);
+	return dict_ts32299_avps_load_rules(conffile);
+}
+
+const char* dict_ts32299_avps_proto_ver(char * conffile) {
+	return ts32299_avps_proto_ver;
+}
+
+const double dict_ts32299_avps_gen_ts(char * conffile) {
+	return ts32299_avps_gen_date;
+}
+
+EXTENSION_ENTRY2("dict_ts32299_avps", dict_ts32299_avps_load_defs, dict_ts32299_avps_load_rules, "dict_ts29272_avps", "dict_ts29273_avps", "dict_ts29212_avps", "dict_ts29336_avps", "dict_ts29128_avps", "dict_ts29214_avps", "dict_ts29345_avps", "dict_ts29337_avps", "dict_ts29344_avps", "dict_ts29368_avps", "dict_ts29217_avps", "dict_ts29229_avps", "dict_ts29338_avps", "dict_ts29468_avps", "dict_ts29329_avps", "dict_ts29061_avps", "dict_rfc5778_avps", "dict_ts29173_avps", "dict_rfc4006bis_avps", "dict_ts29343_avps", "dict_rfc7155_avps", "dict_rfc5447_avps", "dict_rfc7683_avps", "dict_rfc4590_avps", "dict_draftload_avps", "dict_rfc4004_avps", "dict_rfc5777_avps", "dict_etsi283034_avps", "dict_3gpp2_avps", "dict_rfc7944_avps");
+
+
+
diff --git a/extensions/dict_ts32299_avps/ts32299_avps.did b/extensions/dict_ts32299_avps/ts32299_avps.did
new file mode 100644
index 0000000..9bb29ee
--- /dev/null
+++ b/extensions/dict_ts32299_avps/ts32299_avps.did
@@ -0,0 +1,37 @@
+dict_ts29343_avps
+dict_ts29128_avps
+dict_ts29345_avps
+dict_ts29337_avps
+dict_ts29217_avps
+dict_ts29344_avps
+dict_ts29173_avps
+dict_ts29338_avps
+dict_ts29468_avps
+dict_3gpp2_avps
+dict_ts29215_avps
+dict_ts29154_avps
+dict_ts29214_avps
+dict_rfc6942_avps
+dict_rfc6734_avps
+dict_rfc5580_avps
+dict_rfc4072_avps
+dict_ts29273_avps
+dict_rfc4006bis_avps
+dict_ts29212_avps
+dict_ts29061_avps
+dict_ts29272_avps
+dict_rfc5447_avps
+dict_rfc5778_avps
+dict_rfc5777_avps
+dict_ts29336_avps
+dict_etsi283034_avps
+dict_rfc4590_avps
+dict_rfc4004_avps
+dict_rfc7155_avps
+dict_ts29229_avps
+dict_rfc7683_avps
+dict_draftload_avps
+dict_rfc7944_avps
+dict_ts29329_avps
+dict_ts29368_avps
+dict_ts32299_avps
diff --git a/extensions/fdbuild_conf.sh b/extensions/fdbuild_conf.sh
new file mode 100644
index 0000000..6d09727
--- /dev/null
+++ b/extensions/fdbuild_conf.sh
@@ -0,0 +1,42 @@
+#Copyright (c) 2017 Sprint
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#    http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+#!/bin/sh
+
+usage () 
+{
+  echo "Scans the current directory and adds, as required, the "
+  echo "extensions to the specified config file intially disabled."
+  echo "Usage: $0 <config file>"
+}
+
+if [ "$#" -ne 1 ]; then
+  usage
+  exit 0
+fi
+
+if [ -e $1 ]; then
+  echo "Updating $1"
+  for D in *; do
+    if [ -d "${D}" ]; then
+      INDIR=`grep -c "${D}.fdx" $1`
+      if [ "$INDIR" -eq 0 ]; then
+	echo "Adding ${D} to file"
+	sed -i '$ i#LoadExtension = \"/usr/local/lib/freeDiameter/'"${D}"'.fdx\";' $1
+      fi
+    fi
+  done
+else
+  echo "File $1 does not exist. Please provide valid config file\n"
+fi
diff --git a/extensions/fdbuild_make.sh b/extensions/fdbuild_make.sh
new file mode 100644
index 0000000..8a13dfd
--- /dev/null
+++ b/extensions/fdbuild_make.sh
@@ -0,0 +1,43 @@
+#Copyright (c) 2017 Sprint
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#    http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+#!/bin/sh
+
+usage ()
+{
+  echo "Scans the current directory and adds, as required, the "
+  echo "subdirectories to the specified cmake file with their build ON (enabled)."
+  echo "Usage: $0 <make file>"
+}
+
+
+if [ "$#" -ne 1 ]; then
+  usage
+  exit 0
+fi
+
+if [ -e $1 ]; then
+  echo "Updating $1"
+  for D in *; do
+    if [ -d "${D}" ]; then
+      INDIR=`grep -c FD_EXTENSION_SUBDIR\(${D} $1`
+      if [ "$INDIR" -eq 0 ]; then
+	echo "Adding ${D} to file"
+	echo "FD_EXTENSION_SUBDIR(${D} \"${D} extension library\" ON)" >> $1
+      fi
+    fi
+  done
+else
+  echo "File $1 doesn't exist.Please provide valid make file\n"
+fi
diff --git a/extensions/fddict_conf.sh b/extensions/fddict_conf.sh
new file mode 100644
index 0000000..a5096e4
--- /dev/null
+++ b/extensions/fddict_conf.sh
@@ -0,0 +1,55 @@
+#Copyright (c) 2017 Sprint
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#    http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+#!/bin/sh
+
+usage () 
+{
+  echo "Usage: $0 <dictionary name> <ON|OFF> <config file>"
+}
+
+if [ "$#" -ne 3 ]; then
+  usage
+  exit 0
+fi
+
+if [ "$2" != "ON" ] && [ "$2" != "OFF" ]; then
+  usage
+  exit
+fi 
+
+DCTDIR=$1
+STATE=$2
+CFGFILE=$3
+
+if [ -e $3 ]; then
+  if [ -d "${DCTDIR}" ]; then
+    INDIR=`grep -c "${DCTDIR}.fdx" $3`
+    if [ "$INDIR" -eq 0 ]; then
+      echo "Adding ${DCTDIR} to file"
+      sed -i '$i#LoadExtension = "/usr/local/lib/freeDiameter/'"${DCTDIR}"'.fdx";' ${CFGFILE}
+    elif [ "${STATE}" = "ON" ]; then
+      echo "Turning On"
+      sed -i 's/\#LoadExtension = "\/usr\/local\/lib\/freeDiameter\/'"${DCTDIR}"'.fdx";/LoadExtension = "\/usr\/local\/lib\/freeDiameter\/'"${DCTDIR}"'.fdx";/g' ${CFGFILE}
+    else
+      echo "Turning Off"
+      sed -i.bak -e 's/LoadExtension = "\/usr\/local\/lib\/freeDiameter\/'"${DCTDIR}"'.fdx";/#LoadExtension = "\/usr\/local\/lib\/freeDiameter\/'"${DCTDIR}"'.fdx";/g' ${CFGFILE}
+    fi
+  else
+    echo "Directory $1 doesn't exist\n"
+  fi
+else
+  echo "File $3 doesn't exist. Please provide valid conf file\n"
+fi
+  
diff --git a/extensions/fddict_confall.sh b/extensions/fddict_confall.sh
new file mode 100644
index 0000000..e6bc48c
--- /dev/null
+++ b/extensions/fddict_confall.sh
@@ -0,0 +1,51 @@
+#Copyright (c) 2017 Sprint
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#    http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+#!/bin/sh
+
+usage () 
+{
+  echo "Usage: $0 <dictionary name> <ON|OFF> <config file>"
+}
+
+if [ "$#" -ne 3 ]; then
+  usage
+  exit 0
+fi
+
+if [ "$2" != "ON" ] && [ "$2" != "OFF" ]; then
+  usage
+  exit
+fi 
+
+DCTDIR=$1
+STATE=$2
+CFGFILE=$3
+
+if [ -e $3 ]; then
+  if [ -d "dict_${DCTDIR}" ]; then
+    if [ -e "dict_${DCTDIR}/${DCTDIR}.did" ]; then
+      while read p; do
+        echo "Turning $p $2"
+        ./fddict_conf.sh $p $2 $3 
+      done <dict_${DCTDIR}/${DCTDIR}.did  
+    else
+      echo "dict_${DCTDIR}.did was not present - skipping"
+    fi
+  else
+    echo "Directory dict_${DCTDIR} doesn't exist\n"
+  fi
+else
+  echo "File $3 doesn't exist. Please provide valid config file\n"
+fi
diff --git a/extensions/fddict_make.sh b/extensions/fddict_make.sh
new file mode 100644
index 0000000..607eef8
--- /dev/null
+++ b/extensions/fddict_make.sh
@@ -0,0 +1,55 @@
+#Copyright (c) 2017 Sprint
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#    http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+#!/bin/sh
+
+usage () 
+{
+  echo "Used to configure cmake files to turn on/off building a specific dictionary "
+  echo "Usage: $0 <dictionary name> <ON|OFF> <make file>"
+}
+
+if [ "$#" -ne 3 ]; then
+  usage
+  exit 0
+fi
+
+if [ "$2" != "ON" ] && [ "$2" != "OFF" ]; then
+  usage
+  exit
+fi 
+
+DCTDIR=$1
+STATE=$2
+CFGFILE=$3
+
+if [ -e $3 ]; then 
+  if [ -d "${DCTDIR}" ]; then
+    INDIR=`grep -c FD_EXTENSION_SUBDIR\(${DCTDIR} $3`
+    if [ "$INDIR" -eq 0 ]; then
+      echo "Adding ${DCTDIR} to file"
+      echo "FD_EXTENSION_SUBDIR(${DCTDIR} \"${DCTDIR} extension library\" $2)" >> ${CFGFILE}
+    elif [ "${STATE}" = "ON" ]; then
+      echo "Turning On"
+      sed -i.bak -e "s/FD_EXTENSION_SUBDIR(${DCTDIR}\\(.*\\)\"\\(.*\\)\"\\(.*\\)*OFF)/FD_EXTENSION_SUBDIR(${DCTDIR}\\1\"\\2\"\\3ON)/" ${CFGFILE}
+    else
+      echo "Turning Off"
+      sed -i.bak -e "s/FD_EXTENSION_SUBDIR(${DCTDIR}\\(.*\\)\"\\(.*\\)\"\\(.*\\)*ON)/FD_EXTENSION_SUBDIR(${DCTDIR}\\1\"\\2\"\\3OFF)/" ${CFGFILE}
+    fi
+  else
+    echo "Directory ${DCTDIR} doesn't exist\n"
+  fi
+else
+  echo "File $3 doesn't exist. Please provide valid make file\n"
+fi
diff --git a/extensions/fddict_makeall.sh b/extensions/fddict_makeall.sh
new file mode 100644
index 0000000..00274ca
--- /dev/null
+++ b/extensions/fddict_makeall.sh
@@ -0,0 +1,54 @@
+#Copyright (c) 2017 Sprint
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#    http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+#!/bin/sh
+
+usage () 
+{
+  echo "Turns on/off dictionary build in cmake for the specified"
+  echo "specific (no 'dict_' in front) and all items it depends upon"
+  echo "as defined in its associated .did file."
+  echo "Usage: $0 <dictionary name> <ON|OFF> <make file>"
+}
+
+if [ "$#" -ne 3 ]; then
+  usage
+  exit 0
+fi
+
+if [ "$2" != "ON" ] && [ "$2" != "OFF" ]; then
+  usage
+  exit
+fi 
+
+DCTDIR=$1
+STATE=$2
+CFGFILE=$3
+
+if [ -e $3 ]; then
+  if [ -d "dict_${DCTDIR}" ]; then
+    if [ -e "dict_${DCTDIR}/${DCTDIR}.did" ]; then
+      while read p; do
+        echo "Turning $p $2"
+        ./fddict_make.sh $p $2 $3 
+      done <dict_${DCTDIR}/${DCTDIR}.did  
+    else
+      echo "dict_${DCTDIR}.did was not present - skipping"
+    fi
+  else
+    echo "Directory dict_${DCTDIR} doesn't exist\n"
+  fi
+else
+  echo "File $3 doesn't exist. Please provide valid make file\n"
+fi
diff --git a/extensions/rt_busypeers/CMakeLists.txt b/extensions/rt_busypeers/CMakeLists.txt
new file mode 100644
index 0000000..af24d81
--- /dev/null
+++ b/extensions/rt_busypeers/CMakeLists.txt
@@ -0,0 +1,30 @@
+# The rt_busypeer extension
+PROJECT("Handling of TOO_BUSY messages and relay timeout capability routing extension" C)
+
+# Parser files
+BISON_FILE(rtbusy_conf.y)
+FLEX_FILE(rtbusy_conf.l)
+SET_SOURCE_FILES_PROPERTIES(lex.rtbusy_conf.c rtbusy_conf.tab.c PROPERTIES COMPILE_FLAGS "-I ${CMAKE_CURRENT_SOURCE_DIR}")
+
+# List of source files
+SET( RTBUSY_SRC
+	rtbusy.c
+	rtbusy.h
+	lex.rtbusy_conf.c
+	rtbusy_conf.tab.c
+	rtbusy_conf.tab.h
+)
+
+INCLUDE_DIRECTORIES(${CMAKE_CURRENT_BINARY_DIR})
+
+# Compile these files as a freeDiameter extension
+FD_ADD_EXTENSION(rt_busypeers ${RTBUSY_SRC})
+
+
+####
+## INSTALL section ##
+
+# We install with the daemon component because it is a base feature.
+INSTALL(TARGETS rt_busypeers
+	LIBRARY DESTINATION ${INSTALL_EXTENSIONS_SUFFIX}
+	COMPONENT freeDiameter-daemon)
diff --git a/extensions/rt_busypeers/rtbusy.c b/extensions/rt_busypeers/rtbusy.c
new file mode 100644
index 0000000..e554a44
--- /dev/null
+++ b/extensions/rt_busypeers/rtbusy.c
@@ -0,0 +1,281 @@
+/*********************************************************************************************************
+* Software License Agreement (BSD License)                                                               *
+* Author: Sebastien Decugis <sdecugis@freediameter.net>							 *
+*													 *
+* Copyright (c) 2015, WIDE Project and NICT								 *
+* All rights reserved.											 *
+* 													 *
+* Redistribution and use of this software in source and binary forms, with or without modification, are  *
+* permitted provided that the following conditions are met:						 *
+* 													 *
+* * Redistributions of source code must retain the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer.										 *
+*    													 *
+* * Redistributions in binary form must reproduce the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer in the documentation and/or other						 *
+*   materials provided with the distribution.								 *
+* 													 *
+* * Neither the name of the WIDE Project or NICT nor the 						 *
+*   names of its contributors may be used to endorse or 						 *
+*   promote products derived from this software without 						 *
+*   specific prior written permission of WIDE Project and 						 *
+*   NICT.												 *
+* 													 *
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED *
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
+* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR *
+* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 	 *
+* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 	 *
+* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR *
+* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF   *
+* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.								 *
+*********************************************************************************************************/
+
+/* See doc/rt_busypeers.conf.sample for more details about the features of this extension */
+#include "rtbusy.h"
+
+/* The configuration structure */
+struct rtbusy_conf rtbusy_conf;
+
+static struct fd_rt_fwd_hdl * rt_busy_hdl = NULL;
+
+static void rtbusy_expirecb(void * data, DiamId_t sentto, size_t senttolen, struct msg ** req);
+
+/* The function that does the actual work */
+int rt_busy_process_busy(struct msg ** pmsg, int is_req, DiamId_t sentto, size_t senttolen, union avp_value *oh)
+{
+	struct msg * qry = NULL;
+	struct rt_data * rtd = NULL;
+	struct fd_list * candidates = NULL;
+	int sendingattempts;
+	int resend = 1;
+	
+	
+	TRACE_ENTRY("%p(%p) %d %p %p", pmsg, pmsg?*pmsg:NULL, is_req, sentto, oh);
+	
+	if (is_req) {
+		qry = *pmsg;
+	} else {
+		CHECK_FCT( fd_msg_answ_getq( *pmsg, &qry ) );
+	}
+	
+	CHECK_FCT( fd_msg_rt_get ( qry, &rtd ) );
+	ASSERT(rtd);
+	
+	/* rtd is the routing data associated with the query that was sent */
+	
+	/* Store the error in this routing data, this avoids sending the message to the same peer again */
+	CHECK_FCT( fd_rtd_error_add(rtd, 
+				    sentto, senttolen, 
+				    (uint8_t *)(oh ? (DiamId_t)oh->os.data : fd_g_config->cnf_diamid), oh ? oh->os.len : fd_g_config->cnf_diamid_len , 
+	                            ER_DIAMETER_TOO_BUSY, 
+	                            &candidates, 
+	                            &sendingattempts) );
+	
+	/* Now we need to decide if we re-send this query to a different peer or return an error to upstream */
+	
+	/* First, are we exceeding the allowed attempts? */
+	if (rtbusy_conf.RetryMaxPeers != 0) {
+		if (sendingattempts >= rtbusy_conf.RetryMaxPeers) {
+			TRACE_DEBUG(FULL, "Maximum number of sending attempts reached for message %p, returning an error upstream", qry);
+			resend = 0;
+		}
+	}
+	
+	if (resend) {
+		/* Check if we have any valid candidate left for sending the message. This may not be 100% accurate but there should not be
+		any situation where this is actually an issue. */
+		if (FD_IS_LIST_EMPTY(candidates)) {
+			resend = 0;
+		} else {
+			struct rtd_candidate * first = candidates->next->o;
+			if (first->score < 0) /* No more candidate available */
+				resend = 0;
+		}
+	}
+	
+	/* Ok, now act on the message, we know what to do */
+	if (resend) {
+		if (!is_req) {
+			/* We must free the answer we received, and send the query again */
+			CHECK_FCT( fd_msg_answ_detach(*pmsg) );
+			CHECK_FCT( fd_msg_free(*pmsg) );
+			*pmsg = qry;
+		}
+		/* Send the query again. We  need to re-associate the expirecb which was cleaned, if it is used */
+		if (rtbusy_conf.RelayTimeout) {
+			char *buf = NULL;
+			size_t len;
+			struct timespec expire;
+			CHECK_SYS(  clock_gettime(CLOCK_REALTIME, &expire)  );
+			expire.tv_sec += rtbusy_conf.RelayTimeout/1000 + ((expire.tv_nsec + (1000000LL * (rtbusy_conf.RelayTimeout % 1000))) / 1000000000LL);
+			expire.tv_nsec = (expire.tv_nsec + (1000000LL * (rtbusy_conf.RelayTimeout % 1000))) % 1000000000LL;
+			CHECK_MALLOC_DO( fd_msg_dump_full(&buf, &len, NULL, *pmsg, fd_g_config->cnf_dict, 0, 1), /* nothing */);
+			TRACE_ERROR( "No answer received for message from peer '%.*s' before timeout (%dms), re-sending: %s", (int)senttolen, sentto,
+				     rtbusy_conf.RelayTimeout, buf);
+			free(buf);
+			CHECK_FCT( fd_msg_send_timeout( pmsg, NULL, NULL, rtbusy_expirecb, &expire ) );
+		} else {
+			CHECK_FCT( fd_msg_send(pmsg, NULL, NULL) );
+		}
+	
+	} else {
+		if (is_req) {
+			char *buf = NULL;
+			size_t len;
+
+			CHECK_MALLOC_DO( fd_msg_dump_full(&buf, &len, NULL, *pmsg, fd_g_config->cnf_dict, 0, 1), /* nothing */);
+			TRACE_ERROR( "No answer received for message from peer '%.*s' before timeout (%dms), giving up and sending error reply: %s", (int)senttolen, sentto,
+				     rtbusy_conf.RelayTimeout, buf);
+			free(buf);
+			/* We must create an answer */
+			CHECK_FCT( fd_msg_new_answer_from_req ( fd_g_config->cnf_dict, pmsg, MSGFL_ANSW_ERROR ) );
+			
+			CHECK_FCT( fd_msg_rescode_set(*pmsg, "DIAMETER_TOO_BUSY", "[rt_busypeers] Timeout reached while waiting for an answer", NULL, 1 ) );
+		
+			CHECK_FCT( fd_msg_send(pmsg, NULL, NULL) );
+		}
+		/* Otherwise, we have nothing to do at all, the answer will be forwarded upstream as part of the normal processing */
+	
+	}
+	
+	return 0;
+}
+
+/* Callback called on expiry of the timeout timer */
+static void rtbusy_expirecb(void * data, DiamId_t sentto, size_t senttolen, struct msg ** preq)
+{
+	CHECK_FCT_DO( rt_busy_process_busy(preq, 1, sentto, senttolen, NULL), /* continue */ );
+}
+
+/* the routing callback that handles all the tasks of this extension */
+static int rtbusy_fwd_cb(void * cbdata, struct msg ** pmsg)
+{
+	struct msg_hdr * hdr;
+	struct avp * avp;
+	union avp_value *a_rc = NULL, *a_oh = NULL;
+	DiamId_t sentto = NULL;
+	size_t senttolen;
+	
+	/* Get the header of the message */
+	CHECK_FCT( fd_msg_hdr(*pmsg, &hdr) );
+	
+	/* If the message is a request, we only associate the timeout */
+	if (hdr->msg_flags & CMD_FLAG_REQUEST) {
+		struct timespec expire;
+		CHECK_SYS(  clock_gettime(CLOCK_REALTIME, &expire)  );
+		expire.tv_sec += rtbusy_conf.RelayTimeout/1000 + ((expire.tv_nsec + (1000000LL * (rtbusy_conf.RelayTimeout % 1000))) / 1000000000LL);
+		expire.tv_nsec = (expire.tv_nsec + (1000000LL * (rtbusy_conf.RelayTimeout % 1000))) % 1000000000LL;
+		CHECK_FCT( fd_msg_anscb_associate( *pmsg, NULL, NULL, rtbusy_expirecb, &expire ) );
+		return 0;
+	}
+	
+	/* From this point, the message is an answer; we need to check if the E flag is set and if the Result-Code is DIAMETER_TOO_BUSY */
+	
+	if (!(hdr->msg_flags & CMD_FLAG_ERROR)) {
+		/* This answer does not have the E flag, no need to process further */
+		return 0;
+	}
+	
+	CHECK_FCT( fd_msg_source_get( *pmsg, &sentto, &senttolen ) );
+	
+	/* Now get the AVPs we are interested in */
+	CHECK_FCT(  fd_msg_browse(*pmsg, MSG_BRW_FIRST_CHILD, &avp, NULL)  );
+	while (avp) {
+		struct avp_hdr * ahdr;
+			
+		CHECK_FCT(  fd_msg_avp_hdr( avp, &ahdr )  );
+		if (! (ahdr->avp_flags & AVP_FLAG_VENDOR)) {
+			switch (ahdr->avp_code) {
+				case AC_ORIGIN_HOST:
+					/* Parse this AVP */
+					CHECK_FCT( fd_msg_parse_dict ( avp, fd_g_config->cnf_dict, NULL ) );
+					ASSERT( ahdr->avp_value );
+					a_oh = ahdr->avp_value;
+					break;
+					
+				case AC_RESULT_CODE:
+					/* Parse this AVP */
+					CHECK_FCT( fd_msg_parse_dict ( avp, fd_g_config->cnf_dict, NULL ) );
+					ASSERT( ahdr->avp_value );
+					a_rc = ahdr->avp_value;
+					
+					if (a_rc->u32 != ER_DIAMETER_TOO_BUSY) {
+						/* It is not a TOO_BUSY error, we don't do anything */
+						goto out;
+					}
+					break;
+			}
+			
+			if (a_rc && a_oh)
+				break;
+		}
+
+		/* Go to next AVP */
+		CHECK_FCT(  fd_msg_browse(avp, MSG_BRW_NEXT, &avp, NULL)  );
+	}
+	
+	/* Check we have received the necessary information */
+	if (!a_rc) {
+		TRACE_ERROR( "Invalid Diameter answer without a Result-Code AVP, rt_busypeer module gave up processing");
+		goto out;
+	}
+	
+	if (!a_oh) {
+		TRACE_ERROR( "Invalid Diameter answer without an Origin-Host AVP, rt_busypeer module gave up processing");
+		goto out;
+	}
+	
+	/* Pass this error to the function that processes BUSY status */
+	CHECK_FCT( rt_busy_process_busy(pmsg, 0, sentto, senttolen, a_oh) );
+	
+out:
+	return 0;
+}
+
+
+/* entry point */
+static int rtbusy_entry(char * conffile)
+{
+	enum fd_rt_fwd_dir dir = RT_FWD_ANS;
+	TRACE_ENTRY("%p", conffile);
+	
+	/* Initialize the configuration */
+	memset(&rtbusy_conf, 0, sizeof(rtbusy_conf));
+	
+	/* Parse the configuration file */
+	CHECK_FCT( rtbusy_conf_handle(conffile) );
+	
+	if (rtbusy_conf.SkipTooBusyErrors && !rtbusy_conf.RelayTimeout) {
+		TRACE_NOTICE("[rt_busypeers] Configuration file does not specify any behavior (no effect)!");
+		return 0;
+	}
+	
+	if (rtbusy_conf.SkipTooBusyErrors)
+		dir = RT_FWD_REQ; /* in this case, RelayTimeout is not 0 */
+	else if (rtbusy_conf.RelayTimeout)
+		dir = RT_FWD_ALL;
+	
+	/* Register the callback */
+	CHECK_FCT( fd_rt_fwd_register ( rtbusy_fwd_cb, NULL, dir, &rt_busy_hdl ) );
+	
+	/* We're done */
+	return 0;
+}
+
+/* Unload */
+void fd_ext_fini(void)
+{
+	TRACE_ENTRY();
+	
+	/* Unregister the cb */
+	if (rt_busy_hdl) 
+		CHECK_FCT_DO( fd_rt_fwd_unregister ( rt_busy_hdl, NULL), /* continue */);
+	
+	/* Done */
+	return ;
+}
+
+EXTENSION_ENTRY("rt_busypeers", rtbusy_entry);
diff --git a/extensions/rt_busypeers/rtbusy.h b/extensions/rt_busypeers/rtbusy.h
new file mode 100644
index 0000000..c6ce91c
--- /dev/null
+++ b/extensions/rt_busypeers/rtbusy.h
@@ -0,0 +1,54 @@
+/*********************************************************************************************************
+* Software License Agreement (BSD License)                                                               *
+* Author: Sebastien Decugis <sdecugis@freediameter.net>							 *
+*													 *
+* Copyright (c) 2013, WIDE Project and NICT								 *
+* All rights reserved.											 *
+* 													 *
+* Redistribution and use of this software in source and binary forms, with or without modification, are  *
+* permitted provided that the following conditions are met:						 *
+* 													 *
+* * Redistributions of source code must retain the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer.										 *
+*    													 *
+* * Redistributions in binary form must reproduce the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer in the documentation and/or other						 *
+*   materials provided with the distribution.								 *
+* 													 *
+* * Neither the name of the WIDE Project or NICT nor the 						 *
+*   names of its contributors may be used to endorse or 						 *
+*   promote products derived from this software without 						 *
+*   specific prior written permission of WIDE Project and 						 *
+*   NICT.												 *
+* 													 *
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED *
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
+* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR *
+* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 	 *
+* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 	 *
+* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR *
+* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF   *
+* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.								 *
+*********************************************************************************************************/
+
+/*
+ *  See the rt_busypeers.conf.sample file for the format of the configuration file.
+ */
+ 
+/* FreeDiameter's common include file */
+#include <freeDiameter/extension.h>
+
+
+/* Parse the configuration file */
+int rtbusy_conf_handle(char * conffile);
+
+/* The configuration structure */
+extern struct rtbusy_conf {
+	int	SkipTooBusyErrors;
+	int	RetryDistantPeers;
+	int	RetryMaxPeers;	
+	int	RelayTimeout;
+} rtbusy_conf;
+
diff --git a/extensions/rt_busypeers/rtbusy_conf.l b/extensions/rt_busypeers/rtbusy_conf.l
new file mode 100644
index 0000000..fe819bf
--- /dev/null
+++ b/extensions/rt_busypeers/rtbusy_conf.l
@@ -0,0 +1,107 @@
+/*********************************************************************************************************
+* Software License Agreement (BSD License)                                                               *
+* Author: Sebastien Decugis <sdecugis@freediameter.net>							 *
+*													 *
+* Copyright (c) 2013, WIDE Project and NICT								 *
+* All rights reserved.											 *
+* 													 *
+* Redistribution and use of this software in source and binary forms, with or without modification, are  *
+* permitted provided that the following conditions are met:						 *
+* 													 *
+* * Redistributions of source code must retain the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer.										 *
+*    													 *
+* * Redistributions in binary form must reproduce the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer in the documentation and/or other						 *
+*   materials provided with the distribution.								 *
+* 													 *
+* * Neither the name of the WIDE Project or NICT nor the 						 *
+*   names of its contributors may be used to endorse or 						 *
+*   promote products derived from this software without 						 *
+*   specific prior written permission of WIDE Project and 						 *
+*   NICT.												 *
+* 													 *
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED *
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
+* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR *
+* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 	 *
+* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 	 *
+* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR *
+* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF   *
+* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.								 *
+*********************************************************************************************************/
+
+/* Tokenizer
+ *
+ */
+
+%{
+#include "rtbusy.h"
+#include "rtbusy_conf.tab.h"
+
+/* Update the column information */
+#define YY_USER_ACTION { 						\
+	yylloc->first_column = yylloc->last_column + 1; 		\
+	yylloc->last_column = yylloc->first_column + yyleng - 1;	\
+}
+
+/* Avoid warning with newer flex */
+#define YY_NO_INPUT
+
+%}
+
+qstring		\"[^\"\n]*\"
+
+
+%option bison-bridge bison-locations
+%option noyywrap
+%option nounput
+
+%%
+
+	/* Update the line count */
+\n			{
+				yylloc->first_line++; 
+				yylloc->last_line++; 
+				yylloc->last_column=0; 
+			}
+	 
+	/* Eat all spaces but not new lines */
+([[:space:]]{-}[\n])+	;
+	/* Eat all comments */
+#.*$			;
+
+	/* Recognize any integer */
+[-]?[[:digit:]]+	{
+				/* Convert this to an integer value */
+				int ret=0;
+				ret = sscanf(yytext, "%i", &yylval->integer);
+				if (ret != 1) {
+					/* No matching: an error occurred */
+					TRACE_ERROR("Unable to convert the value '%s' to a valid number: %s", yytext, strerror(errno));
+					return LEX_ERROR; /* trig an error in yacc parser */
+					/* Maybe we could REJECT instead of failing here? */
+				}
+				return INTEGER;
+			}
+			
+	
+	
+	/* The key words */	
+(?i:"SkipTooBusyErrors")	 	{	return SKIPTOOBUSYERRORS;	}
+(?i:"RetryDistantPeers")	 	{	return RETRYDISTANTPEERS;	}
+(?i:"RetryMaxPeers")	 		{	return RETRYMAXPEERS;		}
+(?i:"RelayTimeout")	 		{	return RELAYTIMEOUT;		}
+			
+	/* Valid single characters for yyparse */
+[=;]			{ return yytext[0]; }
+
+	/* Unrecognized sequence, if it did not match any previous pattern */
+[^[:space:]=;\n]+	{ 
+				TRACE_ERROR("Unrecognized text on line %d col %d: '%s'.", yylloc->first_line, yylloc->first_column, yytext);
+			 	return LEX_ERROR; 
+			}
+
+%%
diff --git a/extensions/rt_busypeers/rtbusy_conf.y b/extensions/rt_busypeers/rtbusy_conf.y
new file mode 100644
index 0000000..96a5303
--- /dev/null
+++ b/extensions/rt_busypeers/rtbusy_conf.y
@@ -0,0 +1,168 @@
+/*********************************************************************************************************
+* Software License Agreement (BSD License)                                                               *
+* Author: Sebastien Decugis <sdecugis@freediameter.net>							 *
+*													 *
+* Copyright (c) 2013, WIDE Project and NICT								 *
+* All rights reserved.											 *
+* 													 *
+* Redistribution and use of this software in source and binary forms, with or without modification, are  *
+* permitted provided that the following conditions are met:						 *
+* 													 *
+* * Redistributions of source code must retain the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer.										 *
+*    													 *
+* * Redistributions in binary form must reproduce the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer in the documentation and/or other						 *
+*   materials provided with the distribution.								 *
+* 													 *
+* * Neither the name of the WIDE Project or NICT nor the 						 *
+*   names of its contributors may be used to endorse or 						 *
+*   promote products derived from this software without 						 *
+*   specific prior written permission of WIDE Project and 						 *
+*   NICT.												 *
+* 													 *
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED *
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
+* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR *
+* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 	 *
+* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 	 *
+* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR *
+* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF   *
+* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.								 *
+*********************************************************************************************************/
+
+/* Yacc extension's configuration parser.
+ */
+
+/* For development only : */
+%debug 
+%error-verbose
+
+/* The parser receives the configuration file filename as parameter */
+%parse-param {char * conffile}
+
+/* Keep track of location */
+%locations 
+%pure-parser
+
+%{
+#include "rtbusy.h"
+#include "rtbusy_conf.tab.h"
+
+/* Forward declaration */
+int yyparse(char * conffile);
+
+/* Parse the configuration file */
+int rtbusy_conf_handle(char * conffile)
+{
+	extern FILE * rtbusy_confin;
+	int ret;
+	
+	TRACE_ENTRY("%p", conffile);
+	
+	TRACE_DEBUG (FULL, "Parsing configuration file: %s...", conffile);
+	
+	rtbusy_confin = fopen(conffile, "r");
+	if (rtbusy_confin == NULL) {
+		ret = errno;
+		TRACE_ERROR("Unable to open extension configuration file %s for reading: %s", conffile, strerror(ret));
+		return ret;
+	}
+
+	ret = yyparse(conffile);
+
+	fclose(rtbusy_confin);
+
+	if (ret != 0) {
+		TRACE_ERROR( "Unable to parse the configuration file.");
+		return EINVAL;
+	} else {
+		TRACE_DEBUG(FULL, "[rt_busypeers] Configuration: %d-%d-%d-%d.", rtbusy_conf.SkipTooBusyErrors, rtbusy_conf.RetryDistantPeers, rtbusy_conf.RetryMaxPeers, rtbusy_conf.RelayTimeout);
+	}
+	
+	return 0;
+}
+
+/* The Lex parser prototype */
+int rtbusy_conflex(YYSTYPE *lvalp, YYLTYPE *llocp);
+
+/* Function to report the errors */
+void yyerror (YYLTYPE *ploc, char * conffile, char const *s)
+{
+	TRACE_DEBUG(INFO, "Error in configuration parsing");
+	
+	if (ploc->first_line != ploc->last_line)
+		fd_log_error("%s:%d.%d-%d.%d : %s", conffile, ploc->first_line, ploc->first_column, ploc->last_line, ploc->last_column, s);
+	else if (ploc->first_column != ploc->last_column)
+		fd_log_error("%s:%d.%d-%d : %s", conffile, ploc->first_line, ploc->first_column, ploc->last_column, s);
+	else
+		fd_log_error("%s:%d.%d : %s", conffile, ploc->first_line, ploc->first_column, s);
+}
+
+%}
+
+/* Values returned by lex for token */
+%union {
+	int		integer;
+}
+
+/* In case of error in the lexical analysis */
+%token 		LEX_ERROR
+
+/* A (de)quoted string (malloc'd in lex parser; it must be freed after use) */
+%token <integer> INTEGER
+
+/* Tokens */
+%token 		SKIPTOOBUSYERRORS
+%token 		RETRYDISTANTPEERS
+%token 		RETRYMAXPEERS
+%token 		RELAYTIMEOUT
+
+
+/* -------------------------------------- */
+%%
+
+	/* The grammar definition */
+conffile:		/* empty is OK */
+			| conffile toobusy
+			| conffile distant
+			| conffile maxretry
+			| conffile timeout
+			| conffile errors
+			{
+				yyerror(&yylloc, conffile, "An error occurred while parsing the configuration file");
+				return EINVAL;
+			}
+			;
+			
+			/* Lexical or syntax error */
+errors:			LEX_ERROR
+			| error
+			;
+
+toobusy:		SKIPTOOBUSYERRORS ';'
+			{
+				rtbusy_conf.SkipTooBusyErrors=1;
+			}
+			;
+			
+distant:		RETRYDISTANTPEERS ';'
+			{
+				rtbusy_conf.RetryDistantPeers=1;
+			}
+			;
+			
+maxretry:		RETRYMAXPEERS '=' INTEGER ';'
+			{
+				rtbusy_conf.RetryMaxPeers=$3;
+			}
+			;
+			
+timeout:		RELAYTIMEOUT '=' INTEGER ';'
+			{
+				rtbusy_conf.RelayTimeout=$3;
+			}
+			;
+			
diff --git a/extensions/rt_default/CMakeLists.txt b/extensions/rt_default/CMakeLists.txt
new file mode 100644
index 0000000..bdaa42c
--- /dev/null
+++ b/extensions/rt_default/CMakeLists.txt
@@ -0,0 +1,43 @@
+# The rt_default extension
+PROJECT("Configurable routing extension" C)
+
+# Check if REG_STARTEND is provided on the host
+SET(CHECK_REG_STARTEND_SOURCE_CODE "
+	#include <unistd.h>
+	#include <regex.h>
+	int main() {
+	   return regexec(NULL, NULL, 0, NULL, REG_STARTEND);
+	}
+	")
+CHECK_C_SOURCE_COMPILES("${CHECK_REG_STARTEND_SOURCE_CODE}" HAVE_REG_STARTEND)
+# Generate the host.h file
+CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/rt_default-host.h.in ${CMAKE_CURRENT_BINARY_DIR}/rt_default-host.h)
+
+# Parser files
+BISON_FILE(rtd_conf.y)
+FLEX_FILE(rtd_conf.l)
+SET_SOURCE_FILES_PROPERTIES(lex.rtd_conf.c rtd_conf.tab.c PROPERTIES COMPILE_FLAGS "-I ${CMAKE_CURRENT_SOURCE_DIR}")
+
+# List of source files
+SET( RT_DEFAULT_SRC
+	rt_default.c
+	rt_default.h
+	lex.rtd_conf.c
+	rtd_conf.tab.c
+	rtd_conf.tab.h
+	rtd_rules.c
+)
+
+INCLUDE_DIRECTORIES(${CMAKE_CURRENT_BINARY_DIR})
+
+# Compile these files as a freeDiameter extension
+FD_ADD_EXTENSION(rt_default ${RT_DEFAULT_SRC})
+
+
+####
+## INSTALL section ##
+
+# We install with the daemon component because it is a base feature.
+INSTALL(TARGETS rt_default
+	LIBRARY DESTINATION ${INSTALL_EXTENSIONS_SUFFIX}
+	COMPONENT freeDiameter-daemon)
diff --git a/extensions/rt_default/rt_default-host.h.in b/extensions/rt_default/rt_default-host.h.in
new file mode 100644
index 0000000..34e05a5
--- /dev/null
+++ b/extensions/rt_default/rt_default-host.h.in
@@ -0,0 +1,42 @@
+/*********************************************************************************************************
+* Software License Agreement (BSD License)                                                               *
+* Author: Sebastien Decugis <sdecugis@freediameter.net>							 *
+*													 *
+* Copyright (c) 2011, WIDE Project and NICT								 *
+* All rights reserved.											 *
+* 													 *
+* Redistribution and use of this software in source and binary forms, with or without modification, are  *
+* permitted provided that the following conditions are met:						 *
+* 													 *
+* * Redistributions of source code must retain the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer.										 *
+*    													 *
+* * Redistributions in binary form must reproduce the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer in the documentation and/or other						 *
+*   materials provided with the distribution.								 *
+* 													 *
+* * Neither the name of the WIDE Project or NICT nor the 						 *
+*   names of its contributors may be used to endorse or 						 *
+*   promote products derived from this software without 						 *
+*   specific prior written permission of WIDE Project and 						 *
+*   NICT.												 *
+* 													 *
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED *
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
+* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR *
+* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 	 *
+* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 	 *
+* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR *
+* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF   *
+* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.								 *
+*********************************************************************************************************/
+
+/* Configuration from compile-time */
+#ifndef RTD_IS_CONFIG
+#define RTD_IS_CONFIG
+
+#cmakedefine HAVE_REG_STARTEND
+
+#endif /* RTD_IS_CONFIG */
diff --git a/extensions/rt_default/rt_default.c b/extensions/rt_default/rt_default.c
new file mode 100644
index 0000000..dd4057a
--- /dev/null
+++ b/extensions/rt_default/rt_default.c
@@ -0,0 +1,99 @@
+/*********************************************************************************************************
+* Software License Agreement (BSD License)                                                               *
+* Author: Sebastien Decugis <sdecugis@freediameter.net>							 *
+*													 *
+* Copyright (c) 2013, WIDE Project and NICT								 *
+* All rights reserved.											 *
+* 													 *
+* Redistribution and use of this software in source and binary forms, with or without modification, are  *
+* permitted provided that the following conditions are met:						 *
+* 													 *
+* * Redistributions of source code must retain the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer.										 *
+*    													 *
+* * Redistributions in binary form must reproduce the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer in the documentation and/or other						 *
+*   materials provided with the distribution.								 *
+* 													 *
+* * Neither the name of the WIDE Project or NICT nor the 						 *
+*   names of its contributors may be used to endorse or 						 *
+*   promote products derived from this software without 						 *
+*   specific prior written permission of WIDE Project and 						 *
+*   NICT.												 *
+* 													 *
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED *
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
+* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR *
+* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 	 *
+* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 	 *
+* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR *
+* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF   *
+* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.								 *
+*********************************************************************************************************/
+
+/* 
+ * Configurable routing of messages for freeDiameter.
+ */
+
+#include "rt_default.h"
+
+/* The callback called on new messages */
+static int rtd_out(void * cbdata, struct msg ** pmsg, struct fd_list * candidates)
+{
+	struct msg * msg = *pmsg;
+	TRACE_ENTRY("%p %p %p", cbdata, msg, candidates);
+	
+	CHECK_PARAMS(msg && candidates);
+	
+	/* Simply pass it to the appropriate function */
+	if (FD_IS_LIST_EMPTY(candidates)) {
+		return 0;
+	} else {
+		return rtd_process( msg, candidates );
+	}
+}
+
+/* handler */
+static struct fd_rt_out_hdl * rtd_hdl = NULL;
+
+/* entry point */
+static int rtd_entry(char * conffile)
+{
+	TRACE_ENTRY("%p", conffile);
+	
+	/* Initialize the repo */
+	CHECK_FCT( rtd_init() );
+	
+	/* Parse the configuration file */
+	CHECK_FCT( rtd_conf_handle(conffile) );
+	
+#if 0
+	/* Dump the rules */
+	rtd_dump();
+#endif /* 0 */
+	
+	/* Register the callback */
+	CHECK_FCT( fd_rt_out_register( rtd_out, NULL, 5, &rtd_hdl ) );
+	
+	/* We're done */
+	return 0;
+}
+
+/* Unload */
+void fd_ext_fini(void)
+{
+	TRACE_ENTRY();
+	
+	/* Unregister the cb */
+	CHECK_FCT_DO( fd_rt_out_unregister ( rtd_hdl, NULL ), /* continue */ );
+	
+	/* Destroy the data */
+	rtd_fini();
+	
+	/* Done */
+	return ;
+}
+
+EXTENSION_ENTRY("rt_default", rtd_entry);
diff --git a/extensions/rt_default/rt_default.h b/extensions/rt_default/rt_default.h
new file mode 100644
index 0000000..8ecaa5e
--- /dev/null
+++ b/extensions/rt_default/rt_default.h
@@ -0,0 +1,86 @@
+/*********************************************************************************************************
+* Software License Agreement (BSD License)                                                               *
+* Author: Sebastien Decugis <sdecugis@freediameter.net>							 *
+*													 *
+* Copyright (c) 2011, WIDE Project and NICT								 *
+* All rights reserved.											 *
+* 													 *
+* Redistribution and use of this software in source and binary forms, with or without modification, are  *
+* permitted provided that the following conditions are met:						 *
+* 													 *
+* * Redistributions of source code must retain the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer.										 *
+*    													 *
+* * Redistributions in binary form must reproduce the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer in the documentation and/or other						 *
+*   materials provided with the distribution.								 *
+* 													 *
+* * Neither the name of the WIDE Project or NICT nor the 						 *
+*   names of its contributors may be used to endorse or 						 *
+*   promote products derived from this software without 						 *
+*   specific prior written permission of WIDE Project and 						 *
+*   NICT.												 *
+* 													 *
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED *
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
+* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR *
+* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 	 *
+* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 	 *
+* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR *
+* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF   *
+* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.								 *
+*********************************************************************************************************/
+
+/* Header file for the rt_default extension. 
+ *
+ *  See the rt_default.conf.sample file for the format of the configuration file.
+ */
+ 
+/* FreeDiameter's common include file */
+#include <freeDiameter/extension.h>
+
+/* Host configuration for this specific extension */
+#include <rt_default-host.h>
+
+/* Parse the configuration file */
+int rtd_conf_handle(char * conffile);
+
+/* Initialize the rules repository */
+int rtd_init(void);
+
+/* Destroy the rules repository */
+void rtd_fini(void);
+
+/* Some constants definitions */
+enum rtd_crit_type {
+	RTD_CRI_ALL	= 0,
+	RTD_CRI_OH,
+	RTD_CRI_OR,
+	RTD_CRI_DH,
+	RTD_CRI_DR,
+	RTD_CRI_UN,
+	RTD_CRI_SI,
+	
+	RTD_CRI_MAX
+};
+
+enum rtd_targ_type {
+	RTD_TAR_ID     = 0,
+	RTD_TAR_REALM,
+	
+	RTD_TAR_MAX
+};
+
+#define RTD_CRIT_REG	0x1
+#define RTD_TARG_REG	0x2
+
+/* Add a rule */
+int rtd_add(enum rtd_crit_type ct, char * criteria, enum rtd_targ_type tt, char * target, int score, int flags);
+
+/* Process a message & peer list through the rules repository, updating the scores */
+int rtd_process( struct msg * msg, struct fd_list * candidates );
+
+/* For debug: dump the rule repository */
+void rtd_dump(void);
diff --git a/extensions/rt_default/rtd_conf.l b/extensions/rt_default/rtd_conf.l
new file mode 100644
index 0000000..b256aa8
--- /dev/null
+++ b/extensions/rt_default/rtd_conf.l
@@ -0,0 +1,146 @@
+/*********************************************************************************************************
+* Software License Agreement (BSD License)                                                               *
+* Author: Sebastien Decugis <sdecugis@freediameter.net>							 *
+*													 *
+* Copyright (c) 2013, WIDE Project and NICT								 *
+* All rights reserved.											 *
+* 													 *
+* Redistribution and use of this software in source and binary forms, with or without modification, are  *
+* permitted provided that the following conditions are met:						 *
+* 													 *
+* * Redistributions of source code must retain the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer.										 *
+*    													 *
+* * Redistributions in binary form must reproduce the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer in the documentation and/or other						 *
+*   materials provided with the distribution.								 *
+* 													 *
+* * Neither the name of the WIDE Project or NICT nor the 						 *
+*   names of its contributors may be used to endorse or 						 *
+*   promote products derived from this software without 						 *
+*   specific prior written permission of WIDE Project and 						 *
+*   NICT.												 *
+* 													 *
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED *
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
+* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR *
+* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 	 *
+* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 	 *
+* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR *
+* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF   *
+* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.								 *
+*********************************************************************************************************/
+
+/* Tokenizer
+ *
+ */
+
+%{
+#include "rt_default.h"
+/* Include yacc tokens definitions */
+#include "rtd_conf.tab.h"
+
+/* Update the column information */
+#define YY_USER_ACTION { 						\
+	yylloc->first_column = yylloc->last_column + 1; 		\
+	yylloc->last_column = yylloc->first_column + yyleng - 1;	\
+}
+
+/* Avoid warning with newer flex */
+#define YY_NO_INPUT
+
+%}
+
+qstring		\"[^\"\n]*\"
+
+
+%option bison-bridge bison-locations
+%option noyywrap
+%option nounput
+
+%%
+
+	/* Update the line count */
+\n			{
+				yylloc->first_line++; 
+				yylloc->last_line++; 
+				yylloc->last_column=0; 
+			}
+	 
+	/* Eat all spaces but not new lines */
+([[:space:]]{-}[\n])+	;
+	/* Eat all comments */
+#.*$			;
+
+	/* Recognize any integer */
+[-]?[[:digit:]]+	{
+				/* Convert this to an integer value */
+				int ret=0;
+				ret = sscanf(yytext, "%i", &yylval->integer);
+				if (ret != 1) {
+					/* No matching: an error occurred */
+					fd_log_debug("Unable to convert the value '%s' to a valid number: %s", yytext, strerror(errno));
+					return LEX_ERROR; /* trig an error in yacc parser */
+					/* Maybe we could REJECT instead of failing here? */
+				}
+				return INTEGER;
+			}
+			
+	/* In addition, recognize some constant names as integers also */
+(?i:"NO_DELIVERY")	{	yylval->integer = FD_SCORE_NO_DELIVERY;		return INTEGER;		}
+(?i:"DEFAULT")		{	yylval->integer = FD_SCORE_DEFAULT; 		return INTEGER;		}
+(?i:"DEFAULT_REALM")	{	yylval->integer = FD_SCORE_DEFAULT_REALM; 	return INTEGER;		}
+(?i:"REALM")		{	yylval->integer = FD_SCORE_REALM; 		return INTEGER;		}
+(?i:"REDIR_HOST")	{	yylval->integer = FD_SCORE_REDIR_HOST; 		return INTEGER;		}
+(?i:"REDIR_APP")	{	yylval->integer = FD_SCORE_REDIR_APP; 		return INTEGER;		}
+(?i:"REDIR_REALM")	{	yylval->integer = FD_SCORE_REDIR_REALM; 	return INTEGER;		}
+(?i:"REDIR_REALM_APP")	{	yylval->integer = FD_SCORE_REDIR_REALM_APP; 	return INTEGER;		}
+(?i:"REDIR_USER")	{	yylval->integer = FD_SCORE_REDIR_USER; 		return INTEGER;		}
+(?i:"REDIR_SESSION")	{	yylval->integer = FD_SCORE_REDIR_SESSION; 	return INTEGER;		}
+(?i:"FINALDEST")	{	yylval->integer = FD_SCORE_FINALDEST; 		return INTEGER;		}
+
+	/* Recognize bracketed quoted strings */
+[[]{qstring}[]] 	{
+				/* Match a quoted string containing a regex */
+				CHECK_MALLOC_DO( yylval->string = strdup(yytext+2), 
+				{
+					TRACE_DEBUG(INFO, "Unable to copy the string '%s': %s", yytext, strerror(errno));
+					return LEX_ERROR; /* trig an error in yacc parser */
+				} );
+				yylval->string[strlen(yytext) - 4] = '\0';
+				return BQSTRING;
+			}
+			
+	/* Recognize quoted strings */
+{qstring}		{
+				/* Match a quoted string. */
+				CHECK_MALLOC_DO( yylval->string = strdup(yytext+1), 
+				{
+					TRACE_DEBUG(INFO, "Unable to copy the string '%s': %s", yytext, strerror(errno));
+					return LEX_ERROR; /* trig an error in yacc parser */
+				} );
+				yylval->string[strlen(yytext) - 2] = '\0';
+				return QSTRING;
+			}
+	
+	/* The key words */	
+(?i:"oh")	 	{	return OH;	}
+(?i:"or")	 	{	return OR;	}
+(?i:"dh")	 	{	return DH;	}
+(?i:"dr")	 	{	return DR;	}
+(?i:"un")	 	{	return UN;	}
+(?i:"si")	 	{	return SI;	}
+(?i:"rlm")	 	{	return REALM;	}
+			
+	/* Valid single characters for yyparse */
+[*:=+-;]		{ return yytext[0]; }
+
+	/* Unrecognized sequence, if it did not match any previous pattern */
+[^[:space:]\"*:=+;\n]+	{ 
+				fd_log_debug("Unrecognized text on line %d col %d: '%s'.", yylloc->first_line, yylloc->first_column, yytext);
+			 	return LEX_ERROR; 
+			}
+
+%%
diff --git a/extensions/rt_default/rtd_conf.y b/extensions/rt_default/rtd_conf.y
new file mode 100644
index 0000000..d6ed329
--- /dev/null
+++ b/extensions/rt_default/rtd_conf.y
@@ -0,0 +1,273 @@
+/*********************************************************************************************************
+* Software License Agreement (BSD License)                                                               *
+* Author: Sebastien Decugis <sdecugis@freediameter.net>							 *
+*													 *
+* Copyright (c) 2013, WIDE Project and NICT								 *
+* All rights reserved.											 *
+* 													 *
+* Redistribution and use of this software in source and binary forms, with or without modification, are  *
+* permitted provided that the following conditions are met:						 *
+* 													 *
+* * Redistributions of source code must retain the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer.										 *
+*    													 *
+* * Redistributions in binary form must reproduce the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer in the documentation and/or other						 *
+*   materials provided with the distribution.								 *
+* 													 *
+* * Neither the name of the WIDE Project or NICT nor the 						 *
+*   names of its contributors may be used to endorse or 						 *
+*   promote products derived from this software without 						 *
+*   specific prior written permission of WIDE Project and 						 *
+*   NICT.												 *
+* 													 *
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED *
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
+* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR *
+* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 	 *
+* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 	 *
+* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR *
+* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF   *
+* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.								 *
+*********************************************************************************************************/
+
+/* Yacc extension's configuration parser.
+ * See doc/rt_default.conf.sample for configuration file format
+ */
+
+/* For development only : */
+%debug 
+%error-verbose
+
+/* The parser receives the configuration file filename as parameter */
+%parse-param {char * conffile}
+
+/* Keep track of location */
+%locations 
+%pure-parser
+
+%{
+#include "rt_default.h"
+#include "rtd_conf.tab.h"	/* bison is not smart enough to define the YYLTYPE before including this code, so... */
+
+/* Forward declaration */
+int yyparse(char * conffile);
+
+static int rules_added = 0;
+
+/* Parse the configuration file */
+int rtd_conf_handle(char * conffile)
+{
+	extern FILE * rtd_confin;
+	int ret;
+	
+	TRACE_ENTRY("%p", conffile);
+	
+	TRACE_DEBUG (FULL, "Parsing configuration file: %s...", conffile);
+	
+	rtd_confin = fopen(conffile, "r");
+	if (rtd_confin == NULL) {
+		ret = errno;
+		fd_log_debug("Unable to open extension configuration file %s for reading: %s", conffile, strerror(ret));
+		TRACE_DEBUG (INFO, "Error occurred, message logged -- configuration file.");
+		return ret;
+	}
+
+	ret = yyparse(conffile);
+
+	fclose(rtd_confin);
+
+	if (ret != 0) {
+		TRACE_DEBUG (INFO, "Unable to parse the configuration file.");
+		return EINVAL;
+	} else {
+		TRACE_DEBUG(FULL, "Added %d RULES routing entries successfully.", rules_added);
+	}
+	
+	return 0;
+}
+
+/* The Lex parser prototype */
+int rtd_conflex(YYSTYPE *lvalp, YYLTYPE *llocp);
+
+/* Function to report the errors */
+void yyerror (YYLTYPE *ploc, char * conffile, char const *s)
+{
+	TRACE_DEBUG(INFO, "Error in configuration parsing");
+	
+	if (ploc->first_line != ploc->last_line)
+		fd_log_debug("%s:%d.%d-%d.%d : %s", conffile, ploc->first_line, ploc->first_column, ploc->last_line, ploc->last_column, s);
+	else if (ploc->first_column != ploc->last_column)
+		fd_log_debug("%s:%d.%d-%d : %s", conffile, ploc->first_line, ploc->first_column, ploc->last_column, s);
+	else
+		fd_log_debug("%s:%d.%d : %s", conffile, ploc->first_line, ploc->first_column, s);
+}
+
+%}
+
+/* Values returned by lex for token */
+%union {
+	int		 integer;	/* Store integer values */
+	char 		*string;	/* The string is allocated by strdup in lex.*/
+	struct {
+		char * str;
+		int regex;
+	}		 tstring;	/* typed string */
+	struct {
+		char * str;
+		int    regex;
+		enum rtd_crit_type type;
+	}		 criteria;
+	struct {
+		char * str;
+		int    regex;
+		enum rtd_targ_type type;
+	}		 target;
+}
+
+/* In case of error in the lexical analysis */
+%token 		LEX_ERROR
+
+/* A (de)quoted string (malloc'd in lex parser; it must be freed after use) */
+%token <string>	QSTRING
+/* A (de)bracket-quoted string (malloc'd in lex parser; it must be freed after use): ["blahblah"] */
+%token <string>	BQSTRING
+
+/* An integer value */
+%token <integer> INTEGER
+
+/* The types for this gramar */
+%type <tstring>  TSTRING
+%type <criteria> CRITERIA
+%type <target> 	 TARGET
+%type <integer>  EXPR_INT
+
+/* Tokens */
+%token 		OH
+%token 		OR
+%token 		DH
+%token 		DR
+%token 		UN
+%token 		SI
+
+%token 		REALM
+
+
+
+/* -------------------------------------- */
+%%
+
+	/* The grammar definition */
+conffile:		/* empty grammar is OK */
+			| conffile rule
+			;
+			
+	/* a RULE entry */
+rule:			CRITERIA ':' TARGET '+' '=' EXPR_INT ';'
+			{
+				int flag = 0;
+				if ($1.regex)
+					flag |= RTD_CRIT_REG;
+				if ($3.regex)
+					flag |= RTD_TARG_REG;
+					
+				/* Add this rule to the repository */
+				CHECK_FCT_DO( rtd_add($1.type, $1.str, $3.type, $3.str, $6, flag),
+					{
+						yyerror (&yylloc, conffile, "An error occurred while adding a rule, aborting...");
+						YYERROR;
+					} );
+				
+				rules_added++;
+			}
+			;
+	
+	/* QSTRING and BQSTRING are equivalent in the grammar */
+TSTRING:		QSTRING
+			{
+				$$.str = $1;
+				$$.regex = 0;
+			}
+			| BQSTRING
+			{
+				$$.str = $1;
+				$$.regex = 1;
+			}
+			;
+
+	/* Details of the CRITERIA type */
+CRITERIA:		'*'
+			{
+				$$.str = NULL;
+				$$.regex = 0;
+				$$.type = RTD_CRI_ALL;
+			}
+			| OH '=' TSTRING
+			{
+				$$.str = $3.str;
+				$$.regex =$3.regex;
+				$$.type = RTD_CRI_OH;
+			}
+			| OR '=' TSTRING
+			{
+				$$.str = $3.str;
+				$$.regex =$3.regex;
+				$$.type = RTD_CRI_OR;
+			}
+			| DH '=' TSTRING
+			{
+				$$.str = $3.str;
+				$$.regex =$3.regex;
+				$$.type = RTD_CRI_DH;
+			}
+			| DR '=' TSTRING
+			{
+				$$.str = $3.str;
+				$$.regex =$3.regex;
+				$$.type = RTD_CRI_DR;
+			}
+			| UN '=' TSTRING
+			{
+				$$.str = $3.str;
+				$$.regex =$3.regex;
+				$$.type = RTD_CRI_UN;
+			}
+			| SI '=' TSTRING
+			{
+				$$.str = $3.str;
+				$$.regex =$3.regex;
+				$$.type = RTD_CRI_SI;
+			}
+			;
+
+	/* Details of the TARGET type */
+TARGET:			TSTRING
+			{
+				$$.str = $1.str;
+				$$.regex =$1.regex;
+				$$.type = RTD_TAR_ID;
+			}
+			| REALM '=' TSTRING
+			{
+				$$.str = $3.str;
+				$$.regex =$3.regex;
+				$$.type = RTD_TAR_REALM;
+			}
+			;
+	
+	/* An expression that has an integer value; we allow + and - operators cause it is convenient */
+EXPR_INT:		INTEGER
+			{
+				$$ = $1;
+			}
+			| EXPR_INT '+' INTEGER
+			{
+				$$ = $1 + $3;
+			}
+			| EXPR_INT '-' INTEGER
+			{
+				$$ = $1 - $3;
+			}
+			;
diff --git a/extensions/rt_default/rtd_rules.c b/extensions/rt_default/rtd_rules.c
new file mode 100644
index 0000000..8d3a53c
--- /dev/null
+++ b/extensions/rt_default/rtd_rules.c
@@ -0,0 +1,608 @@
+/*********************************************************************************************************
+* Software License Agreement (BSD License)                                                               *
+* Author: Sebastien Decugis <sdecugis@freediameter.net>							 *
+*													 *
+* Copyright (c) 2013, WIDE Project and NICT								 *
+* All rights reserved.											 *
+* 													 *
+* Redistribution and use of this software in source and binary forms, with or without modification, are  *
+* permitted provided that the following conditions are met:						 *
+* 													 *
+* * Redistributions of source code must retain the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer.										 *
+*    													 *
+* * Redistributions in binary form must reproduce the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer in the documentation and/or other						 *
+*   materials provided with the distribution.								 *
+* 													 *
+* * Neither the name of the WIDE Project or NICT nor the 						 *
+*   names of its contributors may be used to endorse or 						 *
+*   promote products derived from this software without 						 *
+*   specific prior written permission of WIDE Project and 						 *
+*   NICT.												 *
+* 													 *
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED *
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
+* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR *
+* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 	 *
+* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 	 *
+* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR *
+* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF   *
+* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.								 *
+*********************************************************************************************************/
+
+#include "rt_default.h"
+
+/* The regular expressions header */
+#include <regex.h>
+
+/* We will search for each candidate peer all the rules that are defined, and check which one applies to the message
+ * Therefore our repository is organized hierarchicaly.
+ *  At the top level, we have two lists of TARGETS (one for IDENTITY, one for REALM), ordered as follow:
+ *   - first, the TARGETS defined with a regular expression. We will try matching all regexp to all candidates in the list.
+ *   - then, the TARGETS defined by a plain text. We don't have to compare the whole list to each candidate since the list is ordered.
+ *
+ *  Under each TARGET element, we have the list of RULES that are defined for this target, ordered by CRITERIA type, then is_regex, then string value.
+ *
+ * Note: Except during configuration parsing and module termination, the lists are only ever accessed read-only, so we do not need a lock.
+ */
+
+/* Structure to hold the data that is used for matching. */
+struct match_data {
+	int	 is_regex;	/* determines how the string is matched */
+	char 	*plain;		/* match this value with strcasecmp if is_regex is false. The string is allocated by the lex tokenizer, must be freed at the end. */
+	regex_t  preg;		/* match with regexec if is_regex is true. regfree must be called at the end. A copy of the original string is anyway saved in plain. */
+};
+
+/* The sentinels for the TARGET lists */
+static struct fd_list	TARGETS[RTD_TAR_MAX];
+
+/* Structure of a TARGET element */
+struct target {
+	struct fd_list		chain;			/* link in the top-level list */
+	struct match_data	md;			/* the data to determine if the current candidate matches this element */
+	struct fd_list		rules[RTD_CRI_MAX];	/* Sentinels for the lists of rules applying to this target. One list per rtd_crit_type */
+	/* note : we do not need the rtd_targ_type here, it is implied by the root of the list this target element is attached to */
+};
+
+/* Structure of a RULE element */
+struct rule {
+	struct fd_list		chain;	/* link in the parent target list */
+	struct match_data	md;	/* the data that the criteria must match, -- ignored for RTD_CRI_ALL */
+	int			score;	/* The score added to the candidate, if the message matches this criteria */
+	/* The type of rule depends on the sentinel */
+};
+
+/*********************************************************************/
+
+/* Compile a regular expression pattern */
+static int compile_regex( regex_t  * preg, char * str )
+{
+	int err;
+	
+	/* Compile the regular expression */
+	err = regcomp(preg, str, REG_EXTENDED | REG_NOSUB);
+	if (err != 0) {
+		char * buf;
+		size_t bl;
+		
+		/* Error while compiling the regex */
+		TRACE_DEBUG(INFO, "Error while compiling the regular expression '%s':", str);
+		
+		/* Get the error message size */
+		bl = regerror(err, preg, NULL, 0);
+		
+		/* Alloc the buffer for error message */
+		CHECK_MALLOC( buf = malloc(bl) );
+		
+		/* Get the error message content */
+		regerror(err, preg, buf, bl);
+		TRACE_DEBUG(INFO, "\t%s", buf);
+		
+		/* Free the buffer, return the error */
+		free(buf);
+		return EINVAL;
+	}
+
+	return 0;
+}
+
+/* Create a target item and initialize its content */
+static struct target * new_target(char * str, int regex)
+{
+	int i;
+	struct target *new = NULL;
+	CHECK_MALLOC_DO( new = malloc(sizeof(struct target)), return NULL );
+	memset(new, 0, sizeof(struct target));
+	
+	fd_list_init(&new->chain, new);
+	new->md.plain = str;
+	new->md.is_regex = regex;
+	if (regex) {
+		CHECK_FCT_DO( compile_regex(&new->md.preg, str),
+			{
+				free(new);
+				return NULL;
+			} );
+	}
+	for (i = 0; i < RTD_CRI_MAX; i++) {
+		fd_list_init(&new->rules[i], new);
+	}
+	return new;
+}
+
+/* Create a rule item and initialize its content; return NULL in case of error */
+static struct rule * new_rule(char * str, int regex, int score)
+{
+	struct rule *new = NULL;
+	CHECK_MALLOC_DO( new = malloc(sizeof(struct rule)), return NULL );
+	memset(new, 0, sizeof(struct rule));
+	
+	fd_list_init(&new->chain, new);
+	new->md.plain = str;
+	new->md.is_regex = regex;
+	if (regex) {
+		CHECK_FCT_DO( compile_regex(&new->md.preg, str),
+			{
+				free(new);
+				return NULL;
+			} );
+	}
+	new->score = score;
+	return new;
+}
+
+/* Debug functions */
+static void dump_rule(int indent, struct rule * rule)
+{
+	fd_log_debug("%*s%s%s%s += %d",
+		indent, "",
+		rule->md.is_regex ? "[" : "'",
+		rule->md.plain,
+		rule->md.is_regex ? "]" : "'",
+		rule->score);
+}
+static void dump_target(int indent, struct target * target)
+{
+	int i;
+	fd_log_debug("%*s%s%s%s :",
+		indent, "",
+		target->md.is_regex ? "[" : "'",
+		target->md.plain ?: "(empty)",
+		target->md.is_regex ? "]" : "'");
+	for (i = 0; i < RTD_CRI_MAX; i++) {
+		if (! FD_IS_LIST_EMPTY(&target->rules[i])) {
+			struct fd_list * li;
+			fd_log_debug("%*s  rules[%d]:",
+				indent, "", i);
+			for (li = target->rules[i].next; li != &target->rules[i]; li = li->next) {
+				dump_rule(indent + 3, (struct rule *)li);
+			}
+		}
+	}
+}
+
+static void clear_md(struct match_data * md)
+{
+	/* delete the string */
+	if (md->plain) {
+		free(md->plain);
+		md->plain = NULL;
+	}
+	
+	/* delete the preg if needed */
+	if (md->is_regex) {
+		regfree(&md->preg);
+		md->is_regex = 0;
+	}
+}
+
+/* Destroy a rule item */
+static void del_rule(struct rule * del)
+{
+	/* Unlink this rule */
+	fd_list_unlink(&del->chain);
+	
+	/* Delete the match data */
+	clear_md(&del->md);
+	
+	free(del);
+}
+
+/* Destroy a target item, and all its rules */
+static void del_target(struct target * del)
+{
+	int i;
+	
+	/* Unlink this target */
+	fd_list_unlink(&del->chain);
+	
+	/* Delete the match data */
+	clear_md(&del->md);
+	
+	/* Delete the children rules */
+	for (i = 0; i < RTD_CRI_MAX; i++) {
+		while (! FD_IS_LIST_EMPTY(&del->rules[i]) ) {
+			del_rule((struct rule *)(del->rules[i].next));
+		}
+	}
+	
+	free(del);
+}
+
+
+/* Compare a string with a match_data value. *res contains the result of the comparison (always >0 for regex non-match situations) */
+static int compare_match(char * str, size_t len, struct match_data * md, int * res)
+{
+	int err;
+	
+	CHECK_PARAMS( str && md && res );
+	
+	/* Plain strings: we compare with strncasecmp */
+	if (md->is_regex == 0) {
+		*res = strncasecmp(str, md->plain, len);
+		return 0;
+	}
+
+	/* Regexp */
+	*res = 1;
+	
+#ifdef HAVE_REG_STARTEND
+	{
+		regmatch_t pmatch[1];
+		memset(pmatch, 0, sizeof(pmatch));
+		pmatch[0].rm_so = 0;
+		pmatch[0].rm_eo = len;
+		err = regexec(&md->preg, str, 0, pmatch, REG_STARTEND);
+	}
+#else /* HAVE_REG_STARTEND */
+	{
+		/* We have to create a copy of the string in this case */
+		char *mystrcpy;
+		CHECK_MALLOC( mystrcpy = os0dup(str, len) );
+		err = regexec(&md->preg, mystrcpy, 0, NULL, 0);
+		free(mystrcpy);
+	}
+#endif /* HAVE_REG_STARTEND */
+	
+	/* Now check the result */
+	if (err == 0) {
+		/* We have a match */
+		*res = 0;
+		return 0;
+	}
+	
+	if (err == REG_NOMATCH) {
+		*res = 1;
+		return 0;
+	}
+	
+	/* In other cases, we have an error */
+	{
+		char * buf;
+		size_t bl;
+		
+		/* Error while compiling the regex */
+		TRACE_DEBUG(INFO, "Error while executing the regular expression '%s':", md->plain);
+		
+		/* Get the error message size */
+		bl = regerror(err, &md->preg, NULL, 0);
+		
+		/* Alloc the buffer for error message */
+		CHECK_MALLOC( buf = malloc(bl) );
+		
+		/* Get the error message content */
+		regerror(err, &md->preg, buf, bl);
+		TRACE_DEBUG(INFO, "\t%s", buf);
+		
+		/* Free the buffer, return the error */
+		free(buf);
+	}
+
+	return (err == REG_ESPACE) ? ENOMEM : EINVAL;
+}
+
+/* Search in list (targets or rules) the next matching item for octet string str(len). Returned in next_match, or *next_match == NULL if no more match. Re-enter with same next_match for the next one. */
+static int get_next_match(struct fd_list * list, char * str, size_t len, struct fd_list ** next_match)
+{
+	struct fd_list * li;
+	
+	TRACE_ENTRY("%p %p %zd %p", list, str, len, next_match);
+	CHECK_PARAMS(list && str && len && next_match);
+	
+	if (*next_match)
+		li = (*next_match)->next;
+	else
+		li = list->next;
+	
+	/* Initialize the return value */
+	*next_match = NULL;
+	
+	for ( ; li != list; li = li->next) {
+		int cmp;
+		struct {
+			struct fd_list 		chain;
+			struct match_data 	md;
+		} * next_item = (void *)li;
+		
+		/* Check if the string matches this next item */
+		CHECK_FCT( compare_match(str, len, &next_item->md, &cmp) );
+		
+		if (cmp == 0) {
+			/* matched! */
+			*next_match = li;
+			return 0;
+		}
+		
+		if (cmp < 0) /* we can stop searching */
+			break;
+	}
+	
+	/* We're done with the list */
+	return 0;
+}
+
+static struct dict_object * AVP_MODELS[RTD_CRI_MAX];
+
+/*********************************************************************/
+
+/* Prepare the module */
+int rtd_init(void)
+{
+	int i;
+	
+	TRACE_ENTRY();
+	
+	for (i = 0; i < RTD_TAR_MAX; i++) {
+		fd_list_init(&TARGETS[i], NULL);
+	}
+	
+	for (i = 1; i < RTD_CRI_MAX; i++) {
+		switch (i) {
+			case RTD_CRI_OH:
+				CHECK_FCT( fd_dict_search ( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Origin-Host", &AVP_MODELS[i], ENOENT ));
+				break;
+			case RTD_CRI_OR:
+				CHECK_FCT( fd_dict_search ( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Origin-Realm", &AVP_MODELS[i], ENOENT ));
+				break;
+			case RTD_CRI_DH:
+				CHECK_FCT( fd_dict_search ( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Destination-Host", &AVP_MODELS[i], ENOENT ));
+				break;
+			case RTD_CRI_DR:
+				CHECK_FCT( fd_dict_search ( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Destination-Realm", &AVP_MODELS[i], ENOENT ));
+				break;
+			case RTD_CRI_UN:
+				CHECK_FCT( fd_dict_search ( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "User-Name", &AVP_MODELS[i], ENOENT ));
+				break;
+			case RTD_CRI_SI:
+				CHECK_FCT( fd_dict_search ( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Session-Id", &AVP_MODELS[i], ENOENT ));
+				break;
+			default:
+				TRACE_DEBUG(INFO, "Missing definition in extension initializer");
+				ASSERT( 0 );
+				return EINVAL;
+		}
+	}
+	
+	return 0;
+}
+
+/* Destroy the module's data */
+void rtd_fini(void)
+{
+	int i;
+	
+	TRACE_ENTRY();
+
+	for (i = 0; i < RTD_TAR_MAX; i++) {
+		while (!FD_IS_LIST_EMPTY(&TARGETS[i])) {
+			del_target((struct target *) TARGETS[i].next);
+		}
+	}
+	
+}
+
+/* Add a new rule in the repository. this is called when the configuration file is being parsed */
+int rtd_add(enum rtd_crit_type ct, char * criteria, enum rtd_targ_type tt, char * target, int score, int flags)
+{
+	struct fd_list * target_suiv = NULL;
+	struct fd_list * rule_suiv = NULL;
+	struct target * trg = NULL;
+	struct rule * rul = NULL;
+	
+	TRACE_ENTRY("%d %p %d %p %d %x", ct, criteria, tt, target, score, flags);
+	CHECK_PARAMS((ct < RTD_CRI_MAX) && ((ct == RTD_CRI_ALL) || criteria) && (tt < RTD_TAR_MAX) && target);
+	
+	/* First, search in the TARGET list if we already have this target */
+	for (target_suiv = TARGETS[tt].next; target_suiv != &TARGETS[tt]; target_suiv = target_suiv->next) {
+		int cmp;
+		struct target * cur = (struct target *)target_suiv;
+		
+		if (flags & RTD_TARG_REG) {
+			/* We are adding a regexp, it is saved in the list before the plain expressions */
+			if (cur->md.is_regex == 0)
+				break;	
+		} else {
+			/* We are adding a plain expression, save it after all regexps */
+			if (cur->md.is_regex != 0)
+				continue;
+		}
+		
+		/* At this point, the type is the same, so compare the plain string value */
+		cmp = strcmp(cur->md.plain, target);
+		if (cmp < 0)
+			continue;
+		
+		if (cmp == 0) /* We already have a target with the same string */
+			trg = cur;
+		
+		break;
+	}
+	
+	if (trg) {
+		/* Ok, we can free the target string, we will use the previously allocated one */
+		free(target);
+	} else {
+		CHECK_MALLOC( trg = new_target(target, flags & RTD_TARG_REG) );
+		fd_list_insert_before( target_suiv, &trg->chain );
+	}
+	
+	/* Now, search for the rule position in this target's list */
+	if (ct == RTD_CRI_ALL) {
+		/* Special case: we don't have a criteria -- always create a rule element */
+		CHECK_MALLOC( rul = new_rule(NULL, 0, score) );
+		fd_list_insert_before( &trg->rules[RTD_CRI_ALL], &rul->chain );
+	} else {
+		for (rule_suiv = trg->rules[ct].next; rule_suiv != &trg->rules[ct]; rule_suiv = rule_suiv->next) {
+			int cmp;
+			struct rule * cur = (struct rule *)rule_suiv;
+
+			if (flags & RTD_CRIT_REG) {
+				/* We are adding a regexp, it is saved in the list before the plain expressions */
+				if (cur->md.is_regex == 0)
+					break;	
+			} else {
+				/* We are adding a plain expression, save it after all regexps */
+				if (cur->md.is_regex != 0)
+					continue;
+			}
+
+			/* At this point, the type is the same, so compare the plain string value */
+			cmp = strcmp(cur->md.plain, criteria);
+			if (cmp < 0)
+				continue;
+
+			if (cmp == 0) /* We already have a target with the same string */
+				rul = cur;
+
+			break;
+		}
+	
+		if (rul) {
+			/* Ok, we can free the target string, we will use the previously allocated one */
+			free(criteria);
+			TRACE_DEBUG(INFO, "Warning: duplicate rule (%s : %s) found, merging score...", rul->md.plain, trg->md.plain);
+			rul->score += score;
+		} else {
+			CHECK_MALLOC( rul = new_rule(criteria, flags & RTD_CRIT_REG, score) );
+			fd_list_insert_before( rule_suiv, &rul->chain );
+		}
+	}
+	
+	return 0;
+}
+
+/* Check if a message and list of eligible candidate match any of our rules, and update its score according to it. */
+int rtd_process( struct msg * msg, struct fd_list * candidates )
+{
+	struct fd_list * li;
+	struct {
+		enum { NOT_RESOLVED_YET = 0, NOT_FOUND, FOUND } status;
+		union avp_value * avp;
+	} parsed_msg_avp[RTD_CRI_MAX];
+	
+	TRACE_ENTRY("%p %p", msg, candidates);
+	CHECK_PARAMS(msg && candidates);
+	
+	/* We delay looking for the AVPs in the message until we really need them. Another approach would be to parse the message once and save all needed AVPs. */
+	memset(parsed_msg_avp, 0, sizeof(parsed_msg_avp));
+	
+	/* For each candidate in the list */
+	for (li = candidates->next; li != candidates; li = li->next) {
+		struct rtd_candidate * cand = (struct rtd_candidate *)li;
+		int i;
+		struct {
+			char * str;
+			size_t len;
+		} cand_data[RTD_TAR_MAX] = {
+			{ cand->diamid,  strlen(cand->diamid) },
+			{ cand->realm,   strlen(cand->realm)  }
+		};
+		
+		for (i = 0; i < RTD_TAR_MAX; i++) {
+			/* Search the next rule matching this candidate in the i-th target list */
+			struct target * target = NULL;
+			
+			do {
+				int j;
+				struct fd_list * l;
+				struct rule * r;
+				
+				CHECK_FCT ( get_next_match( &TARGETS[i], cand_data[i].str, cand_data[i].len, (void *)&target) );
+				if (!target)
+					break;
+				
+				/* First, apply all rules of criteria RTD_CRI_ALL */
+				for ( l = target->rules[RTD_CRI_ALL].next; l != &target->rules[RTD_CRI_ALL]; l = l->next ) {
+					r = (struct rule *)l;
+					cand->score += r->score;
+					TRACE_DEBUG(ANNOYING, "Applied rule {'*' : '%s' += %d} to candidate '%s'", target->md.plain, r->score, cand->diamid);
+				}
+				
+				/* The target is matching this candidate, check if there are additional rules criteria matching this message. */
+				for ( j = 1; j < RTD_CRI_MAX; j++ ) {
+					if ( ! FD_IS_LIST_EMPTY(&target->rules[j]) ) {
+						/* if needed, find the required data in the message */
+						if (parsed_msg_avp[j].status == NOT_RESOLVED_YET) {
+							struct avp * avp = NULL;
+							/* Search for the AVP in the message */
+							CHECK_FCT( fd_msg_search_avp ( msg, AVP_MODELS[j], &avp ) );
+							if (avp == NULL) {
+								parsed_msg_avp[j].status = NOT_FOUND;
+							} else {
+								struct avp_hdr * ahdr = NULL;
+								CHECK_FCT( fd_msg_avp_hdr ( avp, &ahdr ) );
+								if (ahdr->avp_value == NULL) {
+									/* This should not happen, but anyway let's just ignore it */
+									parsed_msg_avp[j].status = NOT_FOUND;
+								} else {
+									/* OK, we got the AVP */
+									parsed_msg_avp[j].status = FOUND;
+									parsed_msg_avp[j].avp = ahdr->avp_value;
+								}
+							}
+						}
+						
+						/* If we did not find the data for these rules in the message, just skip the series */
+						if (parsed_msg_avp[j].status == NOT_FOUND) {
+							TRACE_DEBUG(ANNOYING, "Skipping series of rules %d of target '%s', criteria absent from the message", j, target->md.plain);
+							continue;
+						}
+						
+						/* OK, we can now check if one of our rule's criteria match the message content */
+						r = NULL;
+						do {
+							CHECK_FCT ( get_next_match( &target->rules[j], (char *) /* is this cast safe? */ parsed_msg_avp[j].avp->os.data, parsed_msg_avp[j].avp->os.len, (void *)&r) );
+							if (!r)
+								break;
+							
+							cand->score += r->score;
+							TRACE_DEBUG(ANNOYING, "Applied rule {'%s' : '%s' += %d} to candidate '%s'", r->md.plain, target->md.plain, r->score, cand->diamid);
+						} while (1);
+					}
+				}
+			} while (1);
+		}
+	}
+	
+	return 0;
+}
+
+void rtd_dump(void)
+{
+	int i;
+	fd_log_debug("[rt_default] Dumping rules repository...");
+	for (i = 0; i < RTD_TAR_MAX; i++) {
+		if (!FD_IS_LIST_EMPTY( &TARGETS[i] )) {
+			struct fd_list * li;
+			fd_log_debug("  Targets list %d:", i);
+			for (li = TARGETS[i].next; li != &TARGETS[i]; li = li->next) {
+				dump_target(4, (struct target *)li);
+			}
+		}
+	}
+	
+	fd_log_debug("[rt_default] End of dump");
+}
diff --git a/extensions/rt_ereg/CMakeLists.txt b/extensions/rt_ereg/CMakeLists.txt
new file mode 100644
index 0000000..2b6ec2e
--- /dev/null
+++ b/extensions/rt_ereg/CMakeLists.txt
@@ -0,0 +1,44 @@
+# The rt_ereg extension
+PROJECT("Regular expression matching based routing extension" C)
+
+# Check if REG_STARTEND is provided on the host
+SET(CHECK_REG_STARTEND_SOURCE_CODE "
+	#include <unistd.h>
+	#include <regex.h>
+	int main() {
+	   return regexec(NULL, NULL, 0, NULL, REG_STARTEND);
+	}
+	")
+CHECK_C_SOURCE_COMPILES("${CHECK_REG_STARTEND_SOURCE_CODE}" HAVE_REG_STARTEND)
+IF (HAVE_REG_STARTEND)
+     ADD_DEFINITIONS(-DHAVE_REG_STARTEND)
+ENDIF (HAVE_REG_STARTEND)
+
+
+# Parser files
+BISON_FILE(rtereg_conf.y)
+FLEX_FILE(rtereg_conf.l)
+SET_SOURCE_FILES_PROPERTIES(lex.rtereg_conf.c rtereg_conf.tab.c PROPERTIES COMPILE_FLAGS "-I ${CMAKE_CURRENT_SOURCE_DIR}")
+
+# List of source files
+SET( RTEREG_SRC
+	rtereg.c
+	rtereg.h
+	lex.rtereg_conf.c
+	rtereg_conf.tab.c
+	rtereg_conf.tab.h
+)
+
+INCLUDE_DIRECTORIES(${CMAKE_CURRENT_BINARY_DIR})
+
+# Compile these files as a freeDiameter extension
+FD_ADD_EXTENSION(rt_ereg ${RTEREG_SRC})
+
+
+####
+## INSTALL section ##
+
+# We install with the daemon component because it is a base feature.
+INSTALL(TARGETS rt_ereg
+	LIBRARY DESTINATION ${INSTALL_EXTENSIONS_SUFFIX}
+	COMPONENT freeDiameter-daemon)
diff --git a/extensions/rt_ereg/rtereg.c b/extensions/rt_ereg/rtereg.c
new file mode 100644
index 0000000..be4db16
--- /dev/null
+++ b/extensions/rt_ereg/rtereg.c
@@ -0,0 +1,225 @@
+/*********************************************************************************************************
+* Software License Agreement (BSD License)                                                               *
+* Author: Sebastien Decugis <sdecugis@freediameter.net>							 *
+*													 *
+* Copyright (c) 2013, WIDE Project and NICT								 *
+* All rights reserved.											 *
+* 													 *
+* Redistribution and use of this software in source and binary forms, with or without modification, are  *
+* permitted provided that the following conditions are met:						 *
+* 													 *
+* * Redistributions of source code must retain the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer.										 *
+*    													 *
+* * Redistributions in binary form must reproduce the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer in the documentation and/or other						 *
+*   materials provided with the distribution.								 *
+* 													 *
+* * Neither the name of the WIDE Project or NICT nor the 						 *
+*   names of its contributors may be used to endorse or 						 *
+*   promote products derived from this software without 						 *
+*   specific prior written permission of WIDE Project and 						 *
+*   NICT.												 *
+* 													 *
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED *
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
+* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR *
+* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 	 *
+* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 	 *
+* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR *
+* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF   *
+* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.								 *
+*********************************************************************************************************/
+
+/* 
+ * This extension allows to perform some pattern-matching on an AVP
+ * and send the message to a server accordingly.
+ * See rt_ereg.conf.sample file for the format of the configuration file.
+ */
+
+#include "rtereg.h"
+
+/* The configuration structure */
+struct rtereg_conf rtereg_conf;
+
+#ifndef HAVE_REG_STARTEND
+static char * buf = NULL;
+static size_t bufsz;
+static pthread_mutex_t mtx = PTHREAD_MUTEX_INITIALIZER;
+#endif /* HAVE_REG_STARTEND */
+
+static int proceed(char * value, size_t len, struct fd_list * candidates)
+{
+	int i;
+	
+	for (i = 0; i < rtereg_conf.rules_nb; i++) {
+		/* Does this pattern match the value? */
+		struct rtereg_rule * r = &rtereg_conf.rules[i];
+		int err = 0;
+		struct fd_list * c;
+		
+		TRACE_DEBUG(ANNOYING, "Attempt pattern matching of '%.*s' with rule '%s'", (int)len, value, r->pattern);
+		
+		#ifdef HAVE_REG_STARTEND
+		{
+			regmatch_t pmatch[1];
+			memset(pmatch, 0, sizeof(pmatch));
+			pmatch[0].rm_so = 0;
+			pmatch[0].rm_eo = len;
+			err = regexec(&r->preg, value, 0, pmatch, REG_STARTEND);
+		}
+		#else /* HAVE_REG_STARTEND */
+		{
+			/* We have a 0-terminated string */
+			err = regexec(&r->preg, value, 0, NULL, 0);
+		}
+		#endif /* HAVE_REG_STARTEND */
+		
+		if (err == REG_NOMATCH)
+			continue;
+			
+		if (err != 0) {
+			char * errstr;
+			size_t bl;
+
+			/* Error while compiling the regex */
+			TRACE_DEBUG(INFO, "Error while executing the regular expression '%s':", r->pattern);
+
+			/* Get the error message size */
+			bl = regerror(err, &r->preg, NULL, 0);
+
+			/* Alloc the buffer for error message */
+			CHECK_MALLOC( errstr = malloc(bl) );
+
+			/* Get the error message content */
+			regerror(err, &r->preg, errstr, bl);
+			TRACE_DEBUG(INFO, "\t%s", errstr);
+
+			/* Free the buffer, return the error */
+			free(errstr);
+			
+			return (err == REG_ESPACE) ? ENOMEM : EINVAL;
+		}
+		
+		/* From this point, the expression matched the AVP value */
+		TRACE_DEBUG(FULL, "[rt_ereg] Match: '%s' to value '%.*s' => '%s' += %d",
+					r->pattern,
+					(int)len,
+					value,
+					r->server,
+					r->score);
+		
+		for (c = candidates->next; c != candidates; c = c->next) {
+			struct rtd_candidate * cand = (struct rtd_candidate *)c;
+
+			if (strcmp(r->server, cand->diamid) == 0) {
+				cand->score += r->score;
+				break;
+			}
+		}
+	};
+	
+	return 0;
+}
+
+/* The callback called on new messages */
+static int rtereg_out(void * cbdata, struct msg ** pmsg, struct fd_list * candidates)
+{
+	struct msg * msg = *pmsg;
+	struct avp * avp = NULL;
+	
+	TRACE_ENTRY("%p %p %p", cbdata, msg, candidates);
+	
+	CHECK_PARAMS(msg && candidates);
+	
+	/* Check if it is worth processing the message */
+	if (FD_IS_LIST_EMPTY(candidates)) {
+		return 0;
+	}
+	
+	/* Now search the AVP in the message */
+	CHECK_FCT( fd_msg_search_avp ( msg, rtereg_conf.avp, &avp ) );
+	if (avp != NULL) {
+		struct avp_hdr * ahdr = NULL;
+		CHECK_FCT( fd_msg_avp_hdr ( avp, &ahdr ) );
+		if (ahdr->avp_value != NULL) {
+#ifndef HAVE_REG_STARTEND
+			int ret;
+		
+			/* Lock the buffer */
+			CHECK_POSIX( pthread_mutex_lock(&mtx) );
+			
+			/* Augment the buffer if needed */
+			if (ahdr->avp_value->os.len >= bufsz) {
+				CHECK_MALLOC_DO( buf = realloc(buf, ahdr->avp_value->os.len + 1), 
+					{ pthread_mutex_unlock(&mtx); return ENOMEM; } );
+			}
+			
+			/* Copy the AVP value */
+			memcpy(buf, ahdr->avp_value->os.data, ahdr->avp_value->os.len);
+			buf[ahdr->avp_value->os.len] = '\0';
+			
+			/* Now apply the rules */
+			ret = proceed(buf, ahdr->avp_value->os.len, candidates);
+			
+			CHECK_POSIX(pthread_mutex_unlock(&mtx));
+			
+			CHECK_FCT(ret);
+#else /* HAVE_REG_STARTEND */
+			CHECK_FCT( proceed((char *) ahdr->avp_value->os.data, ahdr->avp_value->os.len, candidates) );
+#endif /* HAVE_REG_STARTEND */
+		}
+	}
+	
+	return 0;
+}
+
+/* handler */
+static struct fd_rt_out_hdl * rtereg_hdl = NULL;
+
+/* entry point */
+static int rtereg_entry(char * conffile)
+{
+	TRACE_ENTRY("%p", conffile);
+	
+	/* Initialize the configuration */
+	memset(&rtereg_conf, 0, sizeof(rtereg_conf));
+	
+	/* Parse the configuration file */
+	CHECK_FCT( rtereg_conf_handle(conffile) );
+	
+	/* Register the callback */
+	CHECK_FCT( fd_rt_out_register( rtereg_out, NULL, 1, &rtereg_hdl ) );
+	
+	/* We're done */
+	return 0;
+}
+
+/* Unload */
+void fd_ext_fini(void)
+{
+	int i;
+	TRACE_ENTRY();
+	
+	/* Unregister the cb */
+	CHECK_FCT_DO( fd_rt_out_unregister ( rtereg_hdl, NULL ), /* continue */ );
+	
+	/* Destroy the data */
+	if (rtereg_conf.rules) 
+		for (i = 0; i < rtereg_conf.rules_nb; i++) {
+			free(rtereg_conf.rules[i].pattern);
+			free(rtereg_conf.rules[i].server);
+			regfree(&rtereg_conf.rules[i].preg);
+		}
+	free(rtereg_conf.rules);
+#ifndef HAVE_REG_STARTEND
+	free(buf);
+#endif /* HAVE_REG_STARTEND */
+	
+	/* Done */
+	return ;
+}
+
+EXTENSION_ENTRY("rt_ereg", rtereg_entry);
diff --git a/extensions/rt_ereg/rtereg.h b/extensions/rt_ereg/rtereg.h
new file mode 100644
index 0000000..495c82f
--- /dev/null
+++ b/extensions/rt_ereg/rtereg.h
@@ -0,0 +1,64 @@
+/*********************************************************************************************************
+* Software License Agreement (BSD License)                                                               *
+* Author: Sebastien Decugis <sdecugis@freediameter.net>							 *
+*													 *
+* Copyright (c) 2011, WIDE Project and NICT								 *
+* All rights reserved.											 *
+* 													 *
+* Redistribution and use of this software in source and binary forms, with or without modification, are  *
+* permitted provided that the following conditions are met:						 *
+* 													 *
+* * Redistributions of source code must retain the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer.										 *
+*    													 *
+* * Redistributions in binary form must reproduce the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer in the documentation and/or other						 *
+*   materials provided with the distribution.								 *
+* 													 *
+* * Neither the name of the WIDE Project or NICT nor the 						 *
+*   names of its contributors may be used to endorse or 						 *
+*   promote products derived from this software without 						 *
+*   specific prior written permission of WIDE Project and 						 *
+*   NICT.												 *
+* 													 *
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED *
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
+* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR *
+* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 	 *
+* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 	 *
+* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR *
+* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF   *
+* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.								 *
+*********************************************************************************************************/
+
+/*
+ *  See the rt_ereg.conf.sample file for the format of the configuration file.
+ */
+ 
+/* FreeDiameter's common include file */
+#include <freeDiameter/extension.h>
+#include <regex.h>
+
+
+/* Parse the configuration file */
+int rtereg_conf_handle(char * conffile);
+
+struct rtereg_rule {
+	char *  pattern; /* The pattern we try to match the AVP value to */
+	regex_t preg;    /* compiled regex */
+	char *  server;  /* The peer that gets its score raised in case of match */
+	int     score;   /* The relative value that is added to the peer's score */
+};
+	
+
+/* The configuration structure */
+extern struct rtereg_conf {
+	int			rules_nb; /* Number of rules in the configuration */
+	struct rtereg_rule 	*rules;   /* The array of rules */
+	
+	struct dict_object * avp; /* cache the dictionary object that we are searching */
+	
+} rtereg_conf;
+
diff --git a/extensions/rt_ereg/rtereg_conf.l b/extensions/rt_ereg/rtereg_conf.l
new file mode 100644
index 0000000..8a281a5
--- /dev/null
+++ b/extensions/rt_ereg/rtereg_conf.l
@@ -0,0 +1,119 @@
+/*********************************************************************************************************
+* Software License Agreement (BSD License)                                                               *
+* Author: Sebastien Decugis <sdecugis@freediameter.net>							 *
+*													 *
+* Copyright (c) 2013, WIDE Project and NICT								 *
+* All rights reserved.											 *
+* 													 *
+* Redistribution and use of this software in source and binary forms, with or without modification, are  *
+* permitted provided that the following conditions are met:						 *
+* 													 *
+* * Redistributions of source code must retain the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer.										 *
+*    													 *
+* * Redistributions in binary form must reproduce the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer in the documentation and/or other						 *
+*   materials provided with the distribution.								 *
+* 													 *
+* * Neither the name of the WIDE Project or NICT nor the 						 *
+*   names of its contributors may be used to endorse or 						 *
+*   promote products derived from this software without 						 *
+*   specific prior written permission of WIDE Project and 						 *
+*   NICT.												 *
+* 													 *
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED *
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
+* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR *
+* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 	 *
+* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 	 *
+* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR *
+* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF   *
+* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.								 *
+*********************************************************************************************************/
+
+/* Tokenizer
+ *
+ */
+
+%{
+#include "rtereg.h"
+/* Include yacc tokens definitions */
+#include "rtereg_conf.tab.h"
+
+/* Update the column information */
+#define YY_USER_ACTION { 						\
+	yylloc->first_column = yylloc->last_column + 1; 		\
+	yylloc->last_column = yylloc->first_column + yyleng - 1;	\
+}
+
+/* Avoid warning with newer flex */
+#define YY_NO_INPUT
+
+%}
+
+qstring		\"[^\"\n]*\"
+
+
+%option bison-bridge bison-locations
+%option noyywrap
+%option nounput
+
+%%
+
+	/* Update the line count */
+\n			{
+				yylloc->first_line++; 
+				yylloc->last_line++; 
+				yylloc->last_column=0; 
+			}
+	 
+	/* Eat all spaces but not new lines */
+([[:space:]]{-}[\n])+	;
+	/* Eat all comments */
+#.*$			;
+
+
+	/* Recognize quoted strings */
+{qstring}		{
+				/* Match a quoted string. */
+				CHECK_MALLOC_DO( yylval->string = strdup(yytext+1), 
+				{
+					TRACE_DEBUG(INFO, "Unable to copy the string '%s': %s", yytext, strerror(errno));
+					return LEX_ERROR; /* trig an error in yacc parser */
+				} );
+				yylval->string[strlen(yytext) - 2] = '\0';
+				return QSTRING;
+			}
+	
+
+	/* Recognize any integer */
+[-]?[[:digit:]]+	{
+				/* Convert this to an integer value */
+				int ret=0;
+				ret = sscanf(yytext, "%i", &yylval->integer);
+				if (ret != 1) {
+					/* No matching: an error occurred */
+					fd_log_debug("Unable to convert the value '%s' to a valid number: %s", yytext, strerror(errno));
+					return LEX_ERROR; /* trig an error in yacc parser */
+					/* Maybe we could REJECT instead of failing here? */
+				}
+				return INTEGER;
+			}
+			
+	
+	
+	/* The key words */	
+(?i:"AVP")	 	{	return AVP;	}
+			
+	/* Valid single characters for yyparse */
+[=:;+-]			{ return yytext[0]; }
+
+	/* Unrecognized sequence, if it did not match any previous pattern */
+[^[:space:]\":=+;\n]+	{ 
+				fd_log_debug("Unrecognized text on line %d col %d: '%s'.", yylloc->first_line, yylloc->first_column, yytext);
+			 	return LEX_ERROR; 
+			}
+
+%%
diff --git a/extensions/rt_ereg/rtereg_conf.y b/extensions/rt_ereg/rtereg_conf.y
new file mode 100644
index 0000000..a213323
--- /dev/null
+++ b/extensions/rt_ereg/rtereg_conf.y
@@ -0,0 +1,209 @@
+/*********************************************************************************************************
+* Software License Agreement (BSD License)                                                               *
+* Author: Sebastien Decugis <sdecugis@freediameter.net>							 *
+*													 *
+* Copyright (c) 2013, WIDE Project and NICT								 *
+* All rights reserved.											 *
+* 													 *
+* Redistribution and use of this software in source and binary forms, with or without modification, are  *
+* permitted provided that the following conditions are met:						 *
+* 													 *
+* * Redistributions of source code must retain the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer.										 *
+*    													 *
+* * Redistributions in binary form must reproduce the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer in the documentation and/or other						 *
+*   materials provided with the distribution.								 *
+* 													 *
+* * Neither the name of the WIDE Project or NICT nor the 						 *
+*   names of its contributors may be used to endorse or 						 *
+*   promote products derived from this software without 						 *
+*   specific prior written permission of WIDE Project and 						 *
+*   NICT.												 *
+* 													 *
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED *
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
+* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR *
+* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 	 *
+* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 	 *
+* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR *
+* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF   *
+* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.								 *
+*********************************************************************************************************/
+
+/* Yacc extension's configuration parser.
+ */
+
+/* For development only : */
+%debug 
+%error-verbose
+
+/* The parser receives the configuration file filename as parameter */
+%parse-param {char * conffile}
+
+/* Keep track of location */
+%locations 
+%pure-parser
+
+%{
+#include "rtereg.h"
+#include "rtereg_conf.tab.h"	/* bison is not smart enough to define the YYLTYPE before including this code, so... */
+
+/* Forward declaration */
+int yyparse(char * conffile);
+
+/* Parse the configuration file */
+int rtereg_conf_handle(char * conffile)
+{
+	extern FILE * rtereg_confin;
+	int ret;
+	
+	TRACE_ENTRY("%p", conffile);
+	
+	TRACE_DEBUG (FULL, "Parsing configuration file: %s...", conffile);
+	
+	rtereg_confin = fopen(conffile, "r");
+	if (rtereg_confin == NULL) {
+		ret = errno;
+		fd_log_debug("Unable to open extension configuration file %s for reading: %s", conffile, strerror(ret));
+		TRACE_DEBUG (INFO, "Error occurred, message logged -- configuration file.");
+		return ret;
+	}
+
+	ret = yyparse(conffile);
+
+	fclose(rtereg_confin);
+
+	if (ret != 0) {
+		TRACE_DEBUG (INFO, "Unable to parse the configuration file.");
+		return EINVAL;
+	} else {
+		TRACE_DEBUG(FULL, "[rt-ereg] Added %d rules successfully.", rtereg_conf.rules_nb);
+	}
+	
+	return 0;
+}
+
+/* The Lex parser prototype */
+int rtereg_conflex(YYSTYPE *lvalp, YYLTYPE *llocp);
+
+/* Function to report the errors */
+void yyerror (YYLTYPE *ploc, char * conffile, char const *s)
+{
+	TRACE_DEBUG(INFO, "Error in configuration parsing");
+	
+	if (ploc->first_line != ploc->last_line)
+		fd_log_debug("%s:%d.%d-%d.%d : %s", conffile, ploc->first_line, ploc->first_column, ploc->last_line, ploc->last_column, s);
+	else if (ploc->first_column != ploc->last_column)
+		fd_log_debug("%s:%d.%d-%d : %s", conffile, ploc->first_line, ploc->first_column, ploc->last_column, s);
+	else
+		fd_log_debug("%s:%d.%d : %s", conffile, ploc->first_line, ploc->first_column, s);
+}
+
+%}
+
+/* Values returned by lex for token */
+%union {
+	char 		*string;	/* The string is allocated by strdup in lex.*/
+	int		integer;
+}
+
+/* In case of error in the lexical analysis */
+%token 		LEX_ERROR
+
+/* A (de)quoted string (malloc'd in lex parser; it must be freed after use) */
+%token <string>	 QSTRING
+%token <integer> INTEGER
+
+/* Tokens */
+%token 		AVP
+
+
+/* -------------------------------------- */
+%%
+
+	/* The grammar definition */
+conffile:		rules avp rules
+			;
+			
+	/* a server entry */
+avp:			AVP '=' QSTRING ';'
+			{
+				if (rtereg_conf.avp != NULL) {
+					yyerror(&yylloc, conffile, "Only one AVP can be specified");
+					YYERROR;
+				}
+				
+				CHECK_FCT_DO( fd_dict_search ( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, $3, &rtereg_conf.avp, ENOENT ),
+					{
+						TRACE_DEBUG(INFO, "Unable to find '%s' AVP in the loaded dictionaries.", $3);
+						yyerror (&yylloc, conffile, "Invalid AVP value.");
+						YYERROR;
+					} );
+				
+				/* Now check the type */
+				{
+					struct dict_avp_data data;
+					CHECK_FCT( fd_dict_getval( rtereg_conf.avp, &data) );
+					CHECK_PARAMS_DO (data.avp_basetype == AVP_TYPE_OCTETSTRING, 
+						{
+							TRACE_DEBUG(INFO, "'%s' AVP in not an OCTETSTRING AVP (%d).", $3, data.avp_basetype);
+							yyerror (&yylloc, conffile, "AVP in not an OCTETSTRING type.");
+							YYERROR;
+						} );
+				}
+			}
+			;
+			
+rules:			/* empty OK */
+			| rules rule
+			;
+			
+rule:			QSTRING ':' QSTRING '+' '=' INTEGER ';'
+			{
+				struct rtereg_rule * new;
+				int err;
+				
+				/* Add new rule in the array */
+				rtereg_conf.rules_nb += 1;
+				CHECK_MALLOC_DO(rtereg_conf.rules = realloc(rtereg_conf.rules, rtereg_conf.rules_nb * sizeof(struct rtereg_rule)),
+					{
+						yyerror (&yylloc, conffile, "Not enough memory to store the configuration...");
+						YYERROR;
+					} );
+				
+				new = &rtereg_conf.rules[rtereg_conf.rules_nb - 1];
+				
+				new->pattern = $1;
+				new->server  = $3;
+				new->score   = $6;
+				
+				/* Attempt to compile the regex */
+				CHECK_FCT_DO( err=regcomp(&new->preg, new->pattern, REG_EXTENDED | REG_NOSUB),
+					{
+						char * buf;
+						size_t bl;
+
+						/* Error while compiling the regex */
+						TRACE_DEBUG(INFO, "Error while compiling the regular expression '%s':", new->pattern);
+
+						/* Get the error message size */
+						bl = regerror(err, &new->preg, NULL, 0);
+
+						/* Alloc the buffer for error message */
+						CHECK_MALLOC( buf = malloc(bl) );
+
+						/* Get the error message content */
+						regerror(err, &new->preg, buf, bl);
+						TRACE_DEBUG(INFO, "\t%s", buf);
+						
+						/* Free the buffer, return the error */
+						free(buf);
+						
+						yyerror (&yylloc, conffile, "Invalid regular expression.");
+						YYERROR;
+					} );
+			}
+			;
diff --git a/extensions/rt_ignore_dh/CMakeLists.txt b/extensions/rt_ignore_dh/CMakeLists.txt
new file mode 100644
index 0000000..f0717b9
--- /dev/null
+++ b/extensions/rt_ignore_dh/CMakeLists.txt
@@ -0,0 +1,20 @@
+# The rt_ignore_dh extension
+PROJECT("Routing extension that removes Destination-Host from messages and restores from Proxy-Info for answers" C)
+
+# List of source files
+SET(RT_IGNORE_DH_SRC
+	rt_ignore_dh.c
+)
+
+INCLUDE_DIRECTORIES(${CMAKE_CURRENT_BINARY_DIR})
+
+# Compile these files as a freeDiameter extension
+FD_ADD_EXTENSION(rt_ignore_dh ${RT_IGNORE_DH_SRC})
+
+####
+## INSTALL section ##
+
+# We install with the daemon component because it is a base feature.
+INSTALL(TARGETS rt_ignore_dh
+	LIBRARY DESTINATION ${INSTALL_EXTENSIONS_SUFFIX}
+	COMPONENT freeDiameter-daemon)
diff --git a/extensions/rt_ignore_dh/rt_ignore_dh.c b/extensions/rt_ignore_dh/rt_ignore_dh.c
new file mode 100644
index 0000000..7385fef
--- /dev/null
+++ b/extensions/rt_ignore_dh/rt_ignore_dh.c
@@ -0,0 +1,217 @@
+/*********************************************************************************************************
+* Software License Agreement (BSD License)                                                               *
+* Author: Thomas Klausner <tk@giga.or.at>                                                                *
+*                                                                                                        *
+* Copyright (c) 2013, Thomas Klausner                                                                    *
+* All rights reserved.                                                                                   *
+*                                                                                                        *
+* Written under contract by nfotex IT GmbH, http://nfotex.com/                                           *
+*                                                                                                        *
+* Redistribution and use of this software in source and binary forms, with or without modification, are  *
+* permitted provided that the following conditions are met:                                              *
+*                                                                                                        *
+* * Redistributions of source code must retain the above                                                 *
+*   copyright notice, this list of conditions and the                                                    *
+*   following disclaimer.                                                                                *
+*                                                                                                        *
+* * Redistributions in binary form must reproduce the above                                              *
+*   copyright notice, this list of conditions and the                                                    *
+*   following disclaimer in the documentation and/or other                                               *
+*   materials provided with the distribution.                                                            *
+*                                                                                                        *
+* 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 <freeDiameter/extension.h>
+
+/* 
+ * Remove Destination-Hosts, putting it into Proxy-Info, and restore it to
+ * Origin-Host for answers.
+ */
+
+struct dict_object * dh_avp_do; /* cache the Destination-Host dictionary object */
+struct dict_object * oh_avp_do; /* cache the Origin-Host dictionary object */
+struct dict_object * ph_avp_do; /* cache the Proxy-Host dictionary object */
+struct dict_object * pi_avp_do; /* cache the Proxy-Info dictionary object */
+struct dict_object * ps_avp_do; /* cache the Proxy-State dictionary object */
+
+static int restore_origin_host(struct msg **msg) {
+	struct avp *avp, *child;
+	struct avp *oh_avp = NULL;
+	struct avp *pi_avp = NULL;
+	void *ps, *new_oh;
+	size_t ps_len, new_oh_len = 0;
+	union avp_value val;
+
+	ps = new_oh = NULL;
+
+	CHECK_FCT(fd_msg_browse(*msg, MSG_BRW_FIRST_CHILD, &avp, NULL));
+	/* look for Origin-Host and Proxy-Info matching this host */
+	while (avp && (!oh_avp || !pi_avp)) {
+		struct avp_hdr * ahdr;
+		int match = 0;
+		
+		CHECK_FCT(fd_msg_avp_hdr(avp, &ahdr));
+		if (!(ahdr->avp_flags & AVP_FLAG_VENDOR)) {
+			switch (ahdr->avp_code) {
+			case AC_ORIGIN_HOST:
+				oh_avp = avp;
+				CHECK_FCT(fd_msg_parse_dict(oh_avp, fd_g_config->cnf_dict, NULL));
+				break;
+			case AC_PROXY_INFO:
+				ps = NULL;
+				ps_len = 0;
+				CHECK_FCT(fd_msg_parse_dict(avp, fd_g_config->cnf_dict, NULL));
+				CHECK_FCT(fd_msg_browse(avp, MSG_BRW_FIRST_CHILD, &child, NULL));
+				while (child && (!match || !ps)) {
+					struct avp_hdr *chdr;
+					CHECK_FCT(fd_msg_avp_hdr(child, &chdr));
+					if (!(chdr->avp_flags & AVP_FLAG_VENDOR)) {
+						switch (chdr->avp_code) {
+						case AC_PROXY_HOST:
+							if (fd_os_cmp(chdr->avp_value->os.data, chdr->avp_value->os.len, 
+								      fd_g_config->cnf_diamid, fd_g_config->cnf_diamid_len) == 0) {
+								match = 1;
+							}
+							break;
+						case AC_PROXY_STATE:
+							ps = chdr->avp_value->os.data;
+							ps_len = chdr->avp_value->os.len;
+							break;
+						default:
+							break;
+						}
+					}
+					CHECK_FCT(fd_msg_browse(child, MSG_BRW_NEXT, &child, NULL));
+				}
+				if (match && ps) {
+					new_oh = ps;
+					new_oh_len = ps_len;
+					pi_avp = avp;
+				}
+				break;
+			default:
+				break;
+			}
+		}
+		CHECK_FCT(fd_msg_browse(avp, MSG_BRW_NEXT, &avp, NULL));
+	}
+	if (!pi_avp)
+		return 0;
+
+	memset(&val, 0, sizeof(val));
+	val.os.data = new_oh;
+	val.os.len = new_oh_len;
+	if (!oh_avp) {
+		TRACE_ERROR("Message contained no Origin-Host");
+	} else {
+		CHECK_FCT(fd_msg_avp_setvalue(oh_avp, &val));
+	}
+	fd_msg_free((msg_or_avp*)pi_avp);
+
+	fd_log_debug("Restored Origin-Host '%.*s' from Proxy-Info", (int)new_oh_len, (char *)new_oh);
+	return 0;
+}
+
+static int stow_destination_host(struct msg **msg) {
+	struct avp * avp = NULL;
+	struct avp * ph_avp = NULL;
+	struct avp * pi_avp = NULL;
+	struct avp * ps_avp = NULL;
+
+	/* Look for the Destination-Host AVP in the message */
+	CHECK_FCT(fd_msg_search_avp(*msg, dh_avp_do, &avp));
+	if (avp != NULL) {
+		struct avp_hdr * ahdr = NULL;
+		union avp_value val;
+
+		CHECK_FCT(fd_msg_avp_hdr(avp, &ahdr));
+		if (ahdr->avp_value != NULL) {
+			/* add Proxy-Info->{Proxy-Host, Proxy-State} using Destination-Host information */
+			CHECK_FCT(fd_msg_avp_new(ph_avp_do, 0, &ph_avp));
+			memset(&val, 0, sizeof(val));
+                        val.os.data = (uint8_t *)(fd_g_config->cnf_diamid);
+			val.os.len = fd_g_config->cnf_diamid_len;
+			CHECK_FCT(fd_msg_avp_setvalue(ph_avp, &val));
+
+			CHECK_FCT(fd_msg_avp_new(ps_avp_do, 0, &ps_avp));
+			memset(&val, 0, sizeof(val));
+			val.os.data = ahdr->avp_value->os.data;
+			val.os.len = ahdr->avp_value->os.len;
+			CHECK_FCT(fd_msg_avp_setvalue(ps_avp, &val));
+
+			CHECK_FCT(fd_msg_avp_new(pi_avp_do, 0, &pi_avp));
+			CHECK_FCT(fd_msg_avp_add(pi_avp, MSG_BRW_LAST_CHILD, ph_avp));
+			CHECK_FCT(fd_msg_avp_add(pi_avp, MSG_BRW_LAST_CHILD, ps_avp));
+
+			/* remove Destination-Host from message */
+			fd_msg_free((msg_or_avp*)avp);
+			/* add Proxy-Info */
+			CHECK_FCT(fd_msg_avp_add(*msg, MSG_BRW_LAST_CHILD, pi_avp));
+			fd_log_debug("Stowed Destination-Host '%.*s' into Proxy-Info", (int)val.os.len, (const char *)val.os.data);
+		}
+	}
+
+	return 0;
+}
+
+/* The callback for putting Destination-Host into Proxy-Info and restoring it on the way back */
+static int rt_ignore_destination_host(void * cbdata, struct msg **msg) {
+	struct msg_hdr * hdr;
+	int ret;
+
+	TRACE_ENTRY("%p %p", cbdata, msg);
+
+	CHECK_PARAMS(msg && *msg);
+
+	/* Read the message header */
+	CHECK_FCT(fd_msg_hdr(*msg, &hdr));
+	if (hdr->msg_flags & CMD_FLAG_REQUEST) {
+		ret = stow_destination_host(msg);
+	} else {
+		ret = restore_origin_host(msg);
+	}
+
+	return ret;
+}
+
+/* handler */
+static struct fd_rt_fwd_hdl * rt_ignore_destination_host_hdl = NULL;
+
+/* entry point */
+static int rt_ignore_destination_host_entry(char * conffile)
+{
+	CHECK_FCT_DO(fd_dict_search(fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Destination-Host", &dh_avp_do, ENOENT),
+		     { TRACE_ERROR("Unable to find 'Destination-Host' AVP in the loaded dictionaries."); });
+	CHECK_FCT_DO(fd_dict_search(fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Origin-Host", &oh_avp_do, ENOENT),
+		     { TRACE_ERROR("Unable to find 'Origin-Host' AVP in the loaded dictionaries."); });
+	CHECK_FCT_DO(fd_dict_search(fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Proxy-Host", &ph_avp_do, ENOENT),
+		     { TRACE_ERROR("Unable to find 'Proxy-Host' AVP in the loaded dictionaries."); });
+	CHECK_FCT_DO(fd_dict_search(fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Proxy-Info", &pi_avp_do, ENOENT),
+		     { TRACE_ERROR("Unable to find 'Proxy-Info' AVP in the loaded dictionaries."); });
+	CHECK_FCT_DO(fd_dict_search(fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Proxy-State", &ps_avp_do, ENOENT),
+		     { TRACE_ERROR("Unable to find 'Proxy-State' AVP in the loaded dictionaries."); });
+
+	/* Register the callback */
+	CHECK_FCT(fd_rt_fwd_register(rt_ignore_destination_host, NULL, RT_FWD_ALL, &rt_ignore_destination_host_hdl));
+
+	TRACE_DEBUG(INFO, "Extension 'Ignore Destination Host' initialized");
+	return 0;
+}
+
+/* Unload */
+void fd_ext_fini(void)
+{
+	/* Unregister the callbacks */
+	CHECK_FCT_DO(fd_rt_fwd_unregister(rt_ignore_destination_host_hdl, NULL), /* continue */);
+	return ;
+}
+
+EXTENSION_ENTRY("rt_ignore_destination_host", rt_ignore_destination_host_entry);
diff --git a/extensions/rt_load_balance/CMakeLists.txt b/extensions/rt_load_balance/CMakeLists.txt
new file mode 100644
index 0000000..d5c491e
--- /dev/null
+++ b/extensions/rt_load_balance/CMakeLists.txt
@@ -0,0 +1,20 @@
+# The rt_load_balance extension
+PROJECT("Routing extension splits requests evenly over multiple hosts, using current load as routing indicator" C)
+
+# List of source files
+SET(RT_LOAD_BALANCE_SRC
+	rt_load_balance.c
+)
+
+INCLUDE_DIRECTORIES(${CMAKE_CURRENT_BINARY_DIR})
+
+# Compile these files as a freeDiameter extension
+FD_ADD_EXTENSION(rt_load_balance ${RT_LOAD_BALANCE_SRC})
+
+####
+## INSTALL section ##
+
+# We install with the daemon component because it is a base feature.
+INSTALL(TARGETS rt_load_balance
+	LIBRARY DESTINATION ${INSTALL_EXTENSIONS_SUFFIX}
+	COMPONENT freeDiameter-daemon)
diff --git a/extensions/rt_load_balance/rt_load_balance.c b/extensions/rt_load_balance/rt_load_balance.c
new file mode 100644
index 0000000..9883a67
--- /dev/null
+++ b/extensions/rt_load_balance/rt_load_balance.c
@@ -0,0 +1,100 @@
+/*********************************************************************************************************
+* Software License Agreement (BSD License)                                                               *
+* Author: Thomas Klausner <tk@giga.or.at>                                                                *
+*                                                                                                        *
+* Copyright (c) 2013, 2014 Thomas Klausner                                                               *
+* All rights reserved.                                                                                   *
+*                                                                                                        *
+* Written under contract by nfotex IT GmbH, http://nfotex.com/                                           *
+*                                                                                                        *
+* Redistribution and use of this software in source and binary forms, with or without modification, are  *
+* permitted provided that the following conditions are met:                                              *
+*                                                                                                        *
+* * Redistributions of source code must retain the above                                                 *
+*   copyright notice, this list of conditions and the                                                    *
+*   following disclaimer.                                                                                *
+*                                                                                                        *
+* * Redistributions in binary form must reproduce the above                                              *
+*   copyright notice, this list of conditions and the                                                    *
+*   following disclaimer in the documentation and/or other                                               *
+*   materials provided with the distribution.                                                            *
+*                                                                                                        *
+* 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 <freeDiameter/extension.h>
+
+/*
+ * Load balancing extension. Send request to least-loaded node.
+ */
+
+/* The callback for load balancing the requests across the peers */
+static int rt_load_balancing(void * cbdata, struct msg ** pmsg, struct fd_list * candidates)
+{
+	struct fd_list *lic;
+	struct msg * msg = *pmsg;
+	
+	TRACE_ENTRY("%p %p %p", cbdata, msg, candidates);
+	
+	CHECK_PARAMS(msg && candidates);
+	
+	/* Check if it is worth processing the message */
+	if (FD_IS_LIST_EMPTY(candidates))
+		return 0;
+
+	/* load balancing */
+	for (lic = candidates->next; lic != candidates; lic = lic->next) {
+		struct rtd_candidate * cand = (struct rtd_candidate *) lic;
+		struct peer_hdr *peer;
+		long to_receive, to_send, load;
+		int score;
+		CHECK_FCT(fd_peer_getbyid(cand->diamid, cand->diamidlen, 0, &peer));
+		CHECK_FCT(fd_peer_get_load_pending(peer, &to_receive, &to_send));
+                load = to_receive + to_send;
+		/* other routing mechanisms need to add to the
+		 * appropriate entries so their base value is high
+		 * enough that they are considered */
+
+		/* logarithmic scaling */
+                int load_log = 0;
+                while (load > 0) {
+                    load_log++;
+                    load /= 2;
+                }
+		score = cand->score;
+		cand->score -= load_log;
+		TRACE_DEBUG(FULL, "evaluated peer `%.*s', score was %d, now %d", (int)cand->diamidlen, cand->diamid, score, cand->score);
+	}
+
+	return 0;
+}
+
+/* handler */
+static struct fd_rt_out_hdl * rt_load_balancing_hdl = NULL;
+
+/* entry point */
+static int rt_load_balance_entry(char * conffile)
+{
+	/* Register the callback */
+	CHECK_FCT(fd_rt_out_register(rt_load_balancing, NULL, 10, &rt_load_balancing_hdl));
+
+	TRACE_DEBUG(INFO, "Extension 'Load Balancing' initialized");
+	return 0;
+}
+
+/* Unload */
+void fd_ext_fini(void)
+{
+	/* Unregister the callbacks */
+	CHECK_FCT_DO(fd_rt_out_unregister(rt_load_balancing_hdl, NULL), /* continue */);
+	return ;
+}
+
+EXTENSION_ENTRY("rt_load_balance", rt_load_balance_entry);
diff --git a/extensions/rt_randomize/CMakeLists.txt b/extensions/rt_randomize/CMakeLists.txt
new file mode 100644
index 0000000..bcc7b84
--- /dev/null
+++ b/extensions/rt_randomize/CMakeLists.txt
@@ -0,0 +1,20 @@
+# The rt_randomize extension
+PROJECT("Routing extension randomly increases the routing count for one of the highest-rated hosts, if there are multiple ones" C)
+
+# List of source files
+SET(RT_RANDOMIZE_SRC
+	rt_randomize.c
+)
+
+INCLUDE_DIRECTORIES(${CMAKE_CURRENT_BINARY_DIR})
+
+# Compile these files as a freeDiameter extension
+FD_ADD_EXTENSION(rt_randomize ${RT_RANDOMIZE_SRC})
+
+####
+## INSTALL section ##
+
+# We install with the daemon component because it is a base feature.
+INSTALL(TARGETS rt_randomize
+	LIBRARY DESTINATION ${INSTALL_EXTENSIONS_SUFFIX}
+	COMPONENT freeDiameter-daemon)
diff --git a/extensions/rt_randomize/rt_randomize.c b/extensions/rt_randomize/rt_randomize.c
new file mode 100644
index 0000000..a606451
--- /dev/null
+++ b/extensions/rt_randomize/rt_randomize.c
@@ -0,0 +1,111 @@
+/*********************************************************************************************************
+* Software License Agreement (BSD License)                                                               *
+* Author: Thomas Klausner <tk@giga.or.at>                                                                *
+*                                                                                                        *
+* Copyright (c) 2014 Thomas Klausner                                                                     *
+* All rights reserved.                                                                                   *
+*                                                                                                        *
+* Written under contract by nfotex IT GmbH, http://nfotex.com/                                           *
+*                                                                                                        *
+* Redistribution and use of this software in source and binary forms, with or without modification, are  *
+* permitted provided that the following conditions are met:                                              *
+*                                                                                                        *
+* * Redistributions of source code must retain the above                                                 *
+*   copyright notice, this list of conditions and the                                                    *
+*   following disclaimer.                                                                                *
+*                                                                                                        *
+* * Redistributions in binary form must reproduce the above                                              *
+*   copyright notice, this list of conditions and the                                                    *
+*   following disclaimer in the documentation and/or other                                               *
+*   materials provided with the distribution.                                                            *
+*                                                                                                        *
+* 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 <freeDiameter/extension.h>
+
+/*
+ * Load balancing extension. If there are multiple highest-rated hosts with the same score,
+ * randomly increase the score of one of them.
+ */
+
+#include <stdlib.h>
+
+static unsigned int seed;
+
+static int rt_randomizing(void * cbdata, struct msg ** pmsg, struct fd_list * candidates)
+{
+	struct fd_list *lic;
+	struct msg * msg = *pmsg;
+	int max_score = -1;
+	int max_score_count = 0;
+	
+	TRACE_ENTRY("%p %p %p", cbdata, msg, candidates);
+	
+	CHECK_PARAMS(msg && candidates);
+	
+	/* Check if it is worth processing the message */
+	if (FD_IS_LIST_EMPTY(candidates))
+		return 0;
+
+	/* find out maximal score and how many candidates have it */
+	for (lic = candidates->next; lic != candidates; lic = lic->next) {
+		struct rtd_candidate * cand = (struct rtd_candidate *) lic;
+		if (max_score < cand->score) {
+			max_score = cand->score;
+			max_score_count = 1;
+		}
+		else if (cand->score == max_score) {
+			max_score_count++;
+		}
+	}
+
+	/* if there is more than one with positive score, randomly increase one of their scores by one */
+	if (max_score >= 0 && max_score_count > 1) {
+		int lucky_candidate = rand_r(&seed) % max_score_count;
+		int i = 0;
+
+		for (lic = candidates->next; lic != candidates; lic = lic->next) {
+			struct rtd_candidate * cand = (struct rtd_candidate *) lic;
+			if (cand->score == max_score) {
+				if (i == lucky_candidate) {
+					cand->score++;
+					break;
+				}
+				i++;
+			}
+		}
+	}
+
+	return 0;
+}
+
+/* handler */
+static struct fd_rt_out_hdl * rt_randomizing_hdl = NULL;
+
+/* entry point */
+static int rt_randomize_entry(char * conffile)
+{
+	/* Register the callback */
+	CHECK_FCT(fd_rt_out_register(rt_randomizing, NULL, 4, &rt_randomizing_hdl));
+	seed = (unsigned int)time(NULL);
+	TRACE_DEBUG(INFO, "Extension 'Randomizing' initialized");
+	return 0;
+}
+
+/* Unload */
+void fd_ext_fini(void)
+{
+	/* Unregister the callbacks */
+	CHECK_FCT_DO(fd_rt_out_unregister(rt_randomizing_hdl, NULL), /* continue */);
+	return ;
+}
+
+EXTENSION_ENTRY("rt_randomize", rt_randomize_entry);
diff --git a/extensions/rt_redirect/CMakeLists.txt b/extensions/rt_redirect/CMakeLists.txt
new file mode 100644
index 0000000..63e9f1b
--- /dev/null
+++ b/extensions/rt_redirect/CMakeLists.txt
@@ -0,0 +1,23 @@
+# The rt_redirect extension
+PROJECT("Diameter Redirect messages support" C)
+
+SET(RT_REDIR_SRC
+	rt_redir.h
+	rt_redir.c
+	redir_entries.c
+	redir_expiry.c
+	redir_fwd.c
+	redir_out.c
+	uthash.h
+	)
+
+# Compile as a module
+FD_ADD_EXTENSION(rt_redirect ${RT_REDIR_SRC})
+
+
+####
+## INSTALL section ##
+
+INSTALL(TARGETS rt_redirect
+	LIBRARY DESTINATION ${INSTALL_EXTENSIONS_SUFFIX}
+	COMPONENT freeDiameter-daemon)
diff --git a/extensions/rt_redirect/redir_entries.c b/extensions/rt_redirect/redir_entries.c
new file mode 100644
index 0000000..b0126d1
--- /dev/null
+++ b/extensions/rt_redirect/redir_entries.c
@@ -0,0 +1,410 @@
+/*********************************************************************************************************
+* Software License Agreement (BSD License)                                                               *
+* Authors: Sebastien Decugis <sdecugis@freediameter.net>						 *
+* and Thomas Klausner <tk@giga.or.at>									 *
+*													 *
+* Copyright (c) 2011, 2014, WIDE Project and NICT							 *
+* All rights reserved.											 *
+* 													 *
+* Redistribution and use of this software in source and binary forms, with or without modification, are  *
+* permitted provided that the following conditions are met:						 *
+* 													 *
+* * Redistributions of source code must retain the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer.										 *
+*    													 *
+* * Redistributions in binary form must reproduce the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer in the documentation and/or other						 *
+*   materials provided with the distribution.								 *
+* 													 *
+* * Neither the name of the WIDE Project or NICT nor the 						 *
+*   names of its contributors may be used to endorse or 						 *
+*   promote products derived from this software without 						 *
+*   specific prior written permission of WIDE Project and 						 *
+*   NICT.												 *
+* 													 *
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED *
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
+* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR *
+* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 	 *
+* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 	 *
+* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR *
+* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF   *
+* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.								 *
+*********************************************************************************************************/
+
+#include "rt_redir.h"
+#include "uthash.h"
+
+/* The array with all entries ordered by their data */
+struct redir_line redirects_usages[H_U_MAX + 1];
+
+/* for symmetry reasons, hash tables for all types exist, but only ALL_SESSION and ALL_USER will be used */
+struct redir_entry *redirect_hash_table[H_U_MAX+1];
+
+/* Initialize the array */
+int redir_entry_init()
+{
+	int i;
+
+	TRACE_ENTRY("");
+
+	/* redirects_usages */
+	memset(&redirects_usages, 0, sizeof(redirects_usages));
+
+	for (i = 0; i <= H_U_MAX; i++) {
+		/* only one of the two will be used for each type, but initialize both to be on the safe side */
+
+		/* initialize list */
+		CHECK_POSIX( pthread_rwlock_init( &redirects_usages[i].lock, NULL) );
+		fd_list_init( &redirects_usages[i].sentinel, &redirects_usages[i] );
+
+		/* initialize hash table */
+		redirect_hash_table[i] = NULL;
+	}
+
+	/* initialize the scores */
+	redirects_usages[ DONT_CACHE		].score = FD_SCORE_REDIR_ONCE;
+	redirects_usages[ ALL_SESSION		].score = FD_SCORE_REDIR_SESSION;
+	redirects_usages[ ALL_REALM		].score = FD_SCORE_REDIR_REALM;
+	redirects_usages[ REALM_AND_APPLICATION	].score = FD_SCORE_REDIR_REALM_APP;
+	redirects_usages[ ALL_APPLICATION	].score = FD_SCORE_REDIR_APP;
+	redirects_usages[ ALL_HOST		].score = FD_SCORE_REDIR_HOST;
+	redirects_usages[ ALL_USER		].score = FD_SCORE_REDIR_USER;
+
+	return 0;
+}
+
+int redir_entry_fini()
+{
+	int i;
+	struct redir_entry *current_entry, *tmp;
+
+	/* Empty all entries */
+	CHECK_POSIX_DO( pthread_mutex_lock(&redir_exp_peer_lock),   );
+	for (i = 0; i <= H_U_MAX; i++) {
+		CHECK_POSIX_DO( pthread_rwlock_wrlock( &redirects_usages[i].lock), );
+		switch(i) {
+		case ALL_SESSION:
+		case ALL_USER:
+			HASH_ITER(hh, redirect_hash_table[i], current_entry, tmp) {
+				HASH_DEL(redirect_hash_table[i], current_entry);
+				CHECK_FCT_DO( redir_entry_destroy(current_entry), );
+			}
+			break;
+		default:
+			while (!FD_IS_LIST_EMPTY(&redirects_usages[i].sentinel)) {
+				struct redir_entry * e = redirects_usages[i].sentinel.next->o;
+				fd_list_unlink(&e->redir_list);
+				CHECK_FCT_DO( redir_entry_destroy(e), );
+			}
+		}
+		CHECK_POSIX_DO( pthread_rwlock_unlock( &redirects_usages[i].lock), );
+		CHECK_POSIX_DO( pthread_rwlock_destroy( &redirects_usages[i].lock), );
+	}
+	CHECK_POSIX_DO( pthread_mutex_unlock(&redir_exp_peer_lock),   );
+
+	return 0;
+}
+
+/* Create a new redir_entry and add the correct data */
+int redir_entry_new(struct redir_entry ** e, struct fd_list * targets, uint32_t rhu, struct msg * qry, DiamId_t nh, size_t nhlen, os0_t oh, size_t ohlen)
+{
+	struct redir_entry * entry = NULL;
+	os0_t s;
+	size_t l;
+
+	TRACE_ENTRY("%p %p %d %p %p %zd %p %zd", e, targets, rhu, qry, nh, nhlen, oh, ohlen)
+	ASSERT(e && targets && (rhu <= H_U_MAX) && qry && nh && nhlen && oh && ohlen);
+
+	CHECK_MALLOC( entry = malloc(sizeof(struct redir_entry)) );
+	memset(entry, 0, sizeof(struct redir_entry));
+
+	entry->eyec = REDIR_ENTRY_EYEC;
+
+	CHECK_MALLOC( entry->from.s = os0dup(nh, nhlen) );
+	entry->from.l = nhlen;
+
+	fd_list_init(&entry->target_peers_list, entry);
+	fd_list_move_end(&entry->target_peers_list, targets);
+
+	fd_list_init(&entry->exp_list, entry);
+
+	entry->type = rhu;
+	/* list entry for putting into redirects_usage; also doubles as pointer into that list so it can be removed easily */
+	fd_list_init(&entry->redir_list, entry);
+	/* finally initialize the data */
+	switch (rhu) {
+		case DONT_CACHE:
+			entry->data.message.msg = qry;
+			break;
+
+		case ALL_SESSION:
+			{
+				/* There is a good chance that the session is already cached in the message, so retrieve it */
+				struct session * sess;
+				CHECK_FCT( fd_msg_sess_get(fd_g_config->cnf_dict, qry, &sess, NULL) );
+				if (!sess) {
+					TRACE_DEBUG(INFO, "Received a Redirect indication with usage ALL_SESSION but no Session-Id AVP in the message, defaulting to DONT_CACHE");
+					entry->type = DONT_CACHE;
+					entry->data.message.msg = qry;
+					break;
+				}
+				CHECK_FCT( fd_sess_getsid(sess, &s, &l) );
+				CHECK_MALLOC( entry->data.session.s = os0dup(s, l) );
+				entry->data.session.l = l;
+			}
+			break;
+
+		case ALL_REALM:
+			{
+				/* Search the Destination-Realm of the message */
+				struct avp * dr;
+				struct avp_hdr * ahdr;
+				CHECK_FCT( fd_msg_search_avp(qry, redir_dict_dr, &dr) );
+				if (!dr) {
+					TRACE_DEBUG(INFO, "Received a Redirect indication with usage ALL_REALM but no Destination-Realm AVP in the message, defaulting to DONT_CACHE");
+					entry->type = DONT_CACHE;
+					entry->data.message.msg = qry;
+					break;
+				}
+				CHECK_FCT(  fd_msg_avp_hdr( dr, &ahdr )  );
+				CHECK_MALLOC( entry->data.realm.s = os0dup(ahdr->avp_value->os.data, ahdr->avp_value->os.len) );
+				entry->data.realm.l = ahdr->avp_value->os.len;
+			}
+			break;
+
+		case REALM_AND_APPLICATION:
+			{
+				/* Search the Destination-Realm of the message */
+				struct avp * dr;
+				struct avp_hdr * ahdr;
+				CHECK_FCT( fd_msg_search_avp(qry, redir_dict_dr, &dr) );
+				if (!dr) {
+					TRACE_DEBUG(INFO, "Received a Redirect indication with usage REALM_AND_APPLICATION but no Destination-Realm AVP in the message, defaulting to DONT_CACHE");
+					entry->type = DONT_CACHE;
+					entry->data.message.msg = qry;
+					break;
+				}
+				CHECK_FCT(  fd_msg_avp_hdr( dr, &ahdr )  );
+				CHECK_MALLOC( entry->data.realm_app.s = os0dup(ahdr->avp_value->os.data, ahdr->avp_value->os.len) );
+				entry->data.realm_app.l = ahdr->avp_value->os.len;
+			}
+			/* and then the application */
+			{
+				struct msg_hdr * hdr;
+				CHECK_FCT( fd_msg_hdr(qry, &hdr) );
+				entry->data.realm_app.a = hdr->msg_appl;
+			}
+			break;
+
+		case ALL_APPLICATION:
+			{
+				struct msg_hdr * hdr;
+				CHECK_FCT( fd_msg_hdr(qry, &hdr) );
+				entry->data.app.a = hdr->msg_appl;
+			}
+			break;
+
+		case ALL_HOST:
+			CHECK_MALLOC( entry->data.host.s = os0dup(oh, ohlen) );
+			entry->data.host.l = ohlen;
+			break;
+
+		case ALL_USER:
+			{
+				/* Search the User-Name of the message */
+				struct avp * un;
+				struct avp_hdr * ahdr;
+				CHECK_FCT( fd_msg_search_avp(qry, redir_dict_un, &un) );
+				if (!un) {
+					TRACE_DEBUG(INFO, "Received a Redirect indication with usage ALL_USER but no User-Name AVP in the message, defaulting to DONT_CACHE");
+					entry->type = DONT_CACHE;
+					entry->data.message.msg = qry;
+					break;
+				}
+				CHECK_FCT(  fd_msg_avp_hdr( un, &ahdr )  );
+				CHECK_MALLOC( entry->data.user.s = os0dup(ahdr->avp_value->os.data, ahdr->avp_value->os.len) );
+				entry->data.user.l = ahdr->avp_value->os.len;
+			}
+			break;
+
+		default:
+			ASSERT(0);
+			return EINVAL;
+	}
+
+	/* We're done */
+	*e = entry;
+	return 0;
+}
+
+
+/* Compares two pointers (DONT_CACHE) */
+static int compare_entries_ptr(union matchdata * d1, union matchdata * d2) {
+	unsigned long v1 = (unsigned long) d1->message.msg;
+	unsigned long v2 = (unsigned long) d2->message.msg;
+	if (v1 > v2)
+		return 1;
+	if (v1 < v2)
+		return -1;
+	return 0;
+}
+/* Compare two applications (REALM_AND_APPLICATION and ALL_APPLICATION) */
+static int compare_entries_appl(union matchdata * d1, union matchdata * d2) {
+	if (d1->app.a > d2->app.a)
+		return 1;
+	if (d1->app.a < d2->app.a)
+		return -1;
+	return 0;
+}
+
+/* Compare two strings (ALL_SESSION, ALL_REALM, ALL_HOST, ALL_USER) */
+static int compare_entries_ostr(union matchdata * d1, union matchdata * d2) {
+	return fd_os_cmp(d1->session.s, d1->session.l, d2->session.s, d2->session.l);
+}
+
+/* The array of callbacks */
+int (*redir_entry_cmp_key[H_U_MAX +1])(union matchdata * , union matchdata * ) = {
+	compare_entries_ptr,  /* DONT_CACHE */
+	compare_entries_ostr, /* ALL_SESSION */
+	compare_entries_ostr, /* ALL_REALM */
+	compare_entries_appl, /* REALM_AND_APPLICATION */
+	compare_entries_appl, /* ALL_APPLICATION */
+	compare_entries_ostr, /* ALL_HOST */
+	compare_entries_ostr  /* ALL_USER */
+};
+
+/* Link the newly created entry into the correct redirects_usages list. The mutex must be held */
+int redir_entry_insert(struct redir_entry * e)
+{
+	struct fd_list * li;
+	struct redir_entry * r = NULL;
+
+	TRACE_ENTRY("%p", e);
+	CHECK_PARAMS(e && (e->eyec == REDIR_ENTRY_EYEC));
+
+	/* Write-Lock the line */
+	CHECK_POSIX( pthread_rwlock_wrlock( RWLOCK_REDIR(e) ) );
+
+	switch (e->type) {
+	case ALL_SESSION:
+		HASH_FIND(hh, redirect_hash_table[e->type], e->data.session.s, e->data.session.l, r);
+		if (r) {
+			/* previously existing entry, delete it from hash and free it */
+			HASH_DELETE(hh, redirect_hash_table[e->type], r);
+			CHECK_FCT_DO( redir_entry_destroy(r), );
+		}
+		HASH_ADD_KEYPTR(hh, redirect_hash_table[e->type], e->data.session.s, e->data.session.l, e);
+		break;
+	case ALL_USER:
+		HASH_FIND(hh, redirect_hash_table[e->type], e->data.user.s, e->data.user.l, r);
+		if (r) {
+			/* previously existing entry, delete it from hash and free it */
+			HASH_DELETE(hh, redirect_hash_table[e->type], r);
+			CHECK_FCT_DO( redir_entry_destroy(r), );
+		}
+		HASH_ADD_KEYPTR(hh, redirect_hash_table[e->type], e->data.user.s, e->data.user.l, e);
+		break;
+	default:
+		for (li = redirects_usages[e->type].sentinel.next; li != &redirects_usages[e->type].sentinel; li = li->next) {
+			struct redir_entry * n = li->o;
+			int cmp = redir_entry_cmp_key[e->type](&e->data, &n->data);
+			if (cmp <= 0)
+				break;
+		}
+
+		fd_list_insert_before(li, &e->redir_list);
+		break;
+	}
+
+	/* unLock the line */
+	CHECK_POSIX( pthread_rwlock_unlock( RWLOCK_REDIR(e) ) );
+
+	return 0;
+}
+
+/* Destroy -- the exp_peer_lock must be held when this function is called */
+int redir_entry_destroy(struct redir_entry * e)
+{
+	struct redir_entry *match;
+	TRACE_ENTRY("%p", e);
+	CHECK_PARAMS(e && (e->eyec == REDIR_ENTRY_EYEC));
+
+	switch (e->type) {
+	case ALL_SESSION:
+		/* If the entry is in the hash table, lock the rwlock also */
+		HASH_FIND(hh, redirect_hash_table[e->type], e->data.session.s, e->data.session.l, match);
+		if (match) {
+			/* TODO: check if e == match? */
+			CHECK_POSIX( pthread_rwlock_wrlock( RWLOCK_REDIR(e) ) );
+			HASH_DELETE(hh, redirect_hash_table[e->type], match);
+			CHECK_POSIX( pthread_rwlock_unlock( RWLOCK_REDIR(e) ) );
+		}
+		break;
+	case ALL_USER:
+		/* If the entry is in the hash table, lock the rwlock also */
+		HASH_FIND(hh, redirect_hash_table[e->type], e->data.user.s, e->data.user.l, match);
+		if (match) {
+			/* TODO: check if e == match? */
+			CHECK_POSIX( pthread_rwlock_wrlock( RWLOCK_REDIR(e) ) );
+			HASH_DELETE(hh, redirect_hash_table[e->type], match);
+			CHECK_POSIX( pthread_rwlock_unlock( RWLOCK_REDIR(e) ) );
+		}
+		break;
+	default:
+		/* If the entry is linked, lock the rwlock also */
+		if (!FD_IS_LIST_EMPTY(&e->redir_list)) {
+			CHECK_POSIX( pthread_rwlock_wrlock( RWLOCK_REDIR(e) ) );
+			fd_list_unlink(&e->redir_list);
+			CHECK_POSIX( pthread_rwlock_unlock( RWLOCK_REDIR(e) ) );
+		}
+		break;
+	}
+
+	/* Now unlink from other list */
+	fd_list_unlink(&e->exp_list);
+
+	/* Empty the targets list */
+	while (!FD_IS_LIST_EMPTY(&e->target_peers_list)) {
+		struct redir_host * h = (struct redir_host *)e->target_peers_list.next->o;
+
+		fd_list_unlink(&h->chain);
+		free(h->id);
+		free(h);
+	}
+
+	/* Now we can destroy the data safely */
+	switch (e->type) {
+		case DONT_CACHE:
+			/* nothing special */
+			break;
+		case ALL_SESSION:
+			free(e->data.session.s);
+			break;
+		case ALL_REALM:
+			free(e->data.realm.s);
+			break;
+		case REALM_AND_APPLICATION:
+			free(e->data.realm_app.s);
+			break;
+		case ALL_APPLICATION:
+			break;
+		case ALL_HOST:
+			free(e->data.host.s);
+			break;
+		case ALL_USER:
+			free(e->data.user.s);
+			break;
+		default:
+			TRACE_DEBUG(INFO, "Invalid redirect type was saved");
+			ASSERT(0);
+			return EINVAL;
+	}
+
+	free(e->from.s);
+
+	free(e);
+	return 0;
+}
diff --git a/extensions/rt_redirect/redir_expiry.c b/extensions/rt_redirect/redir_expiry.c
new file mode 100644
index 0000000..7274684
--- /dev/null
+++ b/extensions/rt_redirect/redir_expiry.c
@@ -0,0 +1,136 @@
+/*********************************************************************************************************
+* Software License Agreement (BSD License)                                                               *
+* Author: Sebastien Decugis <sdecugis@freediameter.net>							 *
+*													 *
+* Copyright (c) 2015, WIDE Project and NICT								 *
+* All rights reserved.											 *
+* 													 *
+* Redistribution and use of this software in source and binary forms, with or without modification, are  *
+* permitted provided that the following conditions are met:						 *
+* 													 *
+* * Redistributions of source code must retain the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer.										 *
+*    													 *
+* * Redistributions in binary form must reproduce the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer in the documentation and/or other						 *
+*   materials provided with the distribution.								 *
+* 													 *
+* * Neither the name of the WIDE Project or NICT nor the 						 *
+*   names of its contributors may be used to endorse or 						 *
+*   promote products derived from this software without 						 *
+*   specific prior written permission of WIDE Project and 						 *
+*   NICT.												 *
+* 													 *
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED *
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
+* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR *
+* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 	 *
+* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 	 *
+* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR *
+* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF   *
+* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.								 *
+*********************************************************************************************************/
+
+#include "rt_redir.h"
+
+/* Expiration management */
+
+
+/* Entries by their ascending expiration date, to accelerate the work of the expire thread */
+static struct fd_list  expire_list = FD_LIST_INITIALIZER(expire_list);
+static pthread_cond_t  exp_cnd  = PTHREAD_COND_INITIALIZER;
+
+pthread_mutex_t redir_exp_peer_lock = PTHREAD_MUTEX_INITIALIZER;
+
+/* The thread that handles expired entries cleanup. */
+void * redir_exp_thr_fct(void * arg)
+{
+	fd_log_threadname ( "Redirects/expire" );
+	TRACE_ENTRY( "" );
+
+	CHECK_POSIX_DO( pthread_mutex_lock(&redir_exp_peer_lock),  goto fatal_error );
+	pthread_cleanup_push( fd_cleanup_mutex, &redir_exp_peer_lock );
+
+	do {
+		struct timespec	now;
+		struct redir_entry * first;
+again:
+		/* Check if there are expiring entries available */
+		if (FD_IS_LIST_EMPTY(&expire_list)) {
+			/* Just wait for a change or cancelation */
+			CHECK_POSIX_DO( pthread_cond_wait( &exp_cnd, &redir_exp_peer_lock ), break /* this might not pop the cleanup handler, but since we ASSERT(0), it is not the big issue... */ );
+			/* Restart the loop on wakeup */
+			goto again;
+		}
+
+		/* Get the pointer to the entry that expires first */
+		first = (struct redir_entry *)(expire_list.next->o);
+
+		/* Get the current time */
+		CHECK_SYS_DO(  clock_gettime(CLOCK_REALTIME, &now),  break  );
+
+		/* If first session is not expired, we just wait until it happens */
+		if ( TS_IS_INFERIOR( &now, &first->timeout ) ) {
+
+			CHECK_POSIX_DO2(  pthread_cond_timedwait( &exp_cnd, &redir_exp_peer_lock, &first->timeout ),
+					ETIMEDOUT, /* ETIMEDOUT is a normal error, continue */,
+					/* on other error, */ break );
+
+			/* on wakeup, loop */
+			goto again;
+		}
+
+		/* Now, the first entry in the list is expired; destroy it */
+
+		CHECK_FCT_DO( redir_entry_destroy( first ), break );
+
+	} while (1);
+
+	pthread_cleanup_pop( 0 );
+	CHECK_POSIX_DO( pthread_mutex_unlock(&redir_exp_peer_lock),  );
+
+fatal_error:
+	TRACE_DEBUG(INFO, "A system error occurred in redirect module! Expiry thread is terminating...");
+	ASSERT(0);
+	return NULL;
+}
+
+/* Sets the timeout value & link in expiry list. The mutex must be held on calling */
+int redir_exp_set(struct redir_entry * e, uint32_t duration)
+{
+	struct fd_list * li;
+	TRACE_ENTRY("%p %d", e, duration);
+	CHECK_PARAMS(e && (e->eyec == REDIR_ENTRY_EYEC) && duration );
+
+	/* Unlink in case it was already set before */
+	fd_list_unlink(&e->exp_list);
+
+	/* Get current time */
+	CHECK_SYS(  clock_gettime(CLOCK_REALTIME, &e->timeout)  );
+
+	/* Add the duration */
+	e->timeout.tv_sec += duration;
+
+	/* now search the next element in the list */
+	for (li = expire_list.next; li != &expire_list; li = li->next) {
+		struct redir_entry * n = li->o;
+
+		if ( TS_IS_INFERIOR( &e->timeout, &n->timeout ) )
+			break;
+
+	}
+
+	/* Insert before this element */
+	fd_list_insert_before(li, &e->exp_list);
+
+	/* Signal the expiry thread if needed */
+	if (e->exp_list.prev == &expire_list) { /* it is the first element */
+		CHECK_POSIX( pthread_cond_signal(&exp_cnd) );
+	}
+
+	/* Done */
+	return 0;
+}
+
diff --git a/extensions/rt_redirect/redir_fwd.c b/extensions/rt_redirect/redir_fwd.c
new file mode 100644
index 0000000..aa3417e
--- /dev/null
+++ b/extensions/rt_redirect/redir_fwd.c
@@ -0,0 +1,272 @@
+/*********************************************************************************************************
+* Software License Agreement (BSD License)                                                               *
+* Author: Sebastien Decugis <sdecugis@freediameter.net>							 *
+*													 *
+* Copyright (c) 2015, WIDE Project and NICT								 *
+* All rights reserved.											 *
+* 													 *
+* Redistribution and use of this software in source and binary forms, with or without modification, are  *
+* permitted provided that the following conditions are met:						 *
+* 													 *
+* * Redistributions of source code must retain the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer.										 *
+*    													 *
+* * Redistributions in binary form must reproduce the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer in the documentation and/or other						 *
+*   materials provided with the distribution.								 *
+* 													 *
+* * Neither the name of the WIDE Project or NICT nor the 						 *
+*   names of its contributors may be used to endorse or 						 *
+*   promote products derived from this software without 						 *
+*   specific prior written permission of WIDE Project and 						 *
+*   NICT.												 *
+* 													 *
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED *
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
+* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR *
+* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 	 *
+* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 	 *
+* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR *
+* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF   *
+* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.								 *
+*********************************************************************************************************/
+
+#include "rt_redir.h"
+
+/* This structure contains the data to keep when a new peer's connection is attempted (for later) */
+struct redir_task {
+	struct msg * answer; /* the message that was being processed */
+	uint32_t     rhu;    /* Redirect-Host-Usage value */
+	uint32_t     rmct;   /* Redirect-Max-Cache-Time value */
+	struct fd_list rh;   /* the list of Redirect-Hosts */
+};
+
+/* Received answers FWD callback */
+int redir_fwd_cb(void * cbdata, struct msg ** msg)
+{
+	struct msg * m, * q;
+	struct rt_data *rtd;
+	struct msg_hdr * hdr;
+	union avp_value *a_rc = NULL, *a_rhu = NULL, *a_rmct = NULL, *a_oh = NULL;
+	int known = 0, actives = 0;
+	struct fd_list * li;
+	struct avp * avp;
+	struct redir_task task = { .answer = NULL, .rhu = 0, .rmct = 0, .rh = FD_LIST_INITIALIZER(task.rh) };
+	DiamId_t nh;
+	size_t   nhlen;
+	int nbrh = 0;
+	struct redir_entry * entry;
+
+	TRACE_ENTRY("%p %p", cbdata, msg);
+
+	CHECK_PARAMS(msg && *msg);
+
+	m = *msg;
+
+	/* First get the header */
+	CHECK_FCT( fd_msg_hdr(m, &hdr) );
+
+	/* Check if we have an error */
+	ASSERT(!(hdr->msg_flags & CMD_FLAG_REQUEST));
+	if (!(hdr->msg_flags & CMD_FLAG_ERROR)) {
+		/* This answer does not have the E flag, no need to process further */
+		return 0;
+	}
+
+	/* Now get the AVPs we are interested in */
+	CHECK_FCT(  fd_msg_browse(m, MSG_BRW_FIRST_CHILD, &avp, NULL)  );
+	while (avp) {
+		struct avp_hdr * ahdr;
+
+		CHECK_FCT(  fd_msg_avp_hdr( avp, &ahdr )  );
+		if (! (ahdr->avp_flags & AVP_FLAG_VENDOR)) {
+			switch (ahdr->avp_code) {
+				case AC_ORIGIN_HOST:
+					/* Parse this AVP */
+					CHECK_FCT( fd_msg_parse_dict ( avp, fd_g_config->cnf_dict, NULL ) );
+					ASSERT( ahdr->avp_value );
+					a_oh = ahdr->avp_value;
+					break;
+
+				case AC_RESULT_CODE:
+					/* Parse this AVP */
+					CHECK_FCT( fd_msg_parse_dict ( avp, fd_g_config->cnf_dict, NULL ) );
+					ASSERT( ahdr->avp_value );
+					a_rc = ahdr->avp_value;
+
+					if (a_rc->u32 != ER_DIAMETER_REDIRECT_INDICATION) {
+						/* It is not a REDIRECT error, we don't do anything */
+						goto out;
+					}
+					break;
+
+				case AC_REDIRECT_HOST:
+					{
+						struct redir_host * h = NULL;
+						DiamId_t id = NULL;
+						size_t	 len = 0;
+						int 	 secure = 0;
+						uint16_t port = 0;
+						int	 l4 = 0;
+						char	 proto = 0;
+
+						/* Parse this AVP */
+						CHECK_FCT( fd_msg_parse_dict ( avp, fd_g_config->cnf_dict, NULL ) );
+						ASSERT( ahdr->avp_value );
+
+						nbrh++;
+
+						CHECK_FCT_DO( fd_os_parse_DiameterURI(ahdr->avp_value->os.data, ahdr->avp_value->os.len,
+									&id, &len, &secure, &port, &l4, &proto),
+							{
+								TRACE_DEBUG(INFO, "Received an invalid Redirect-Host AVP value ('%.*s'), ignored", (int)ahdr->avp_value->os.len, ahdr->avp_value->os.data);
+								break;
+							} );
+
+						/* Now check if the transport & protocol are supported */
+						if (proto && (proto != 'd')) {
+							TRACE_DEBUG(FULL, "Ignored unsupported non-Diameter Redirect-Host AVP (%.*s)", (int)ahdr->avp_value->os.len, ahdr->avp_value->os.data);
+							free(id);
+							break;
+						}
+						if (l4 && (l4 == IPPROTO_UDP)) {
+							TRACE_DEBUG(FULL, "Ignored unsupported UDP Redirect-Host AVP (%.*s)", (int)ahdr->avp_value->os.len, ahdr->avp_value->os.data);
+							free(id);
+							break;
+						}
+
+						/* It looks OK, save this entry. */
+
+						CHECK_MALLOC( h = malloc(sizeof(struct redir_host)) );
+						memset(h, 0, sizeof(struct redir_host));
+						fd_list_init(&h->chain, h);
+						h->id = id;
+						h->len = len;
+						/* later: secure, port */
+
+						/* The list is kept ordered by id so that it is faster to compare to candidates later */
+						for (li = task.rh.next; li != &task.rh; li = li->next) {
+							struct redir_host * nhost = li->o;
+							if ( fd_os_cmp(id, len, nhost->id, nhost->len) <= 0 )
+								break;
+						}
+						fd_list_insert_before(li, &h->chain);
+					}
+					break;
+
+				case AC_REDIRECT_HOST_USAGE:
+					/* Parse this AVP */
+					CHECK_FCT( fd_msg_parse_dict ( avp, fd_g_config->cnf_dict, NULL ) );
+					ASSERT( ahdr->avp_value );
+					a_rhu = ahdr->avp_value;
+					if (a_rhu->u32 > H_U_MAX) {
+						TRACE_DEBUG(INFO, "Received unsupported Redirect-Host-Usage value (%d), defaulting to DONT_CACHE", a_rhu->u32);
+					} else {
+						task.rhu = a_rhu->u32;
+					}
+					break;
+
+				case AC_REDIRECT_MAX_CACHE_TIME:
+					/* Parse this AVP */
+					CHECK_FCT( fd_msg_parse_dict ( avp, fd_g_config->cnf_dict, NULL ) );
+					ASSERT( ahdr->avp_value );
+					a_rmct = ahdr->avp_value;
+					task.rmct = a_rmct->u32;
+					break;
+
+			}
+		}
+
+		/* Go to next AVP */
+		CHECK_FCT(  fd_msg_browse(avp, MSG_BRW_NEXT, &avp, NULL)  );
+	}
+
+	/* Check we have received the necessary information */
+	if (!a_rc) {
+		TRACE_DEBUG(FULL, "Invalid Diameter answer without a Result-Code AVP, Redirect module gave up");
+		goto out;
+	}
+
+	if (!a_oh) {
+		TRACE_DEBUG(FULL, "Invalid Diameter answer without an Origin-Host AVP, Redirect module gave up");
+		goto out;
+	}
+
+	if (FD_IS_LIST_EMPTY(&task.rh)) {
+		TRACE_DEBUG(FULL, "Diameter answer with a DIAMETER_REDIRECT_INDICATION Result-Code AVP but no valid/supported Redirect-Host AVP, Redirect module gave up");
+		goto out;
+	}
+
+	if (a_rhu && (task.rhu != DONT_CACHE) && !a_rmct) {
+		TRACE_DEBUG(FULL, "Invalid Diameter Redirect answer with a Redirect-Host-Usage AVP but no Redirect-Max-Cache-Time, Redirect module gave up");
+		goto out;
+	}
+
+	/* It looks like we can process the Redirect indication */
+
+	/* Search for the peers we already know */
+	for (li = task.rh.next; li != &task.rh; li = li->next) {
+		struct redir_host * h = li->o;
+		struct peer_hdr * peer;
+
+		CHECK_FCT( fd_peer_getbyid( h->id, h->len, 1, &peer ) );
+		if (peer) {
+			known ++;
+			memcpy(h->id, peer->info.pi_diamid, h->len); /* Overwrite the case so we can search case-sensitive from here on */
+			if (fd_peer_get_state(peer) == STATE_OPEN) {
+				actives ++;
+			}
+		}
+	}
+
+	TRACE_DEBUG(FULL, "Redirect module: received %d Redirect-Hosts, %d are known peers, %d have an OPEN connection", nbrh, known, actives);
+
+	/* in this version, we only redirect when there are known active peers. TODO: add new peers via fd_peer_add when no active peer is available */
+
+	if (!actives) {
+		TRACE_DEBUG(INFO, "Unable to comply to Redirect indication: none of the peers included is in OPEN state");
+		goto out;
+	}
+
+	/* From this point, we will re-send the query to a different peer, so stop forwarding the answer here */
+	*msg = NULL;
+
+	/* Get the query's routing data & add the new error */
+	CHECK_FCT( fd_msg_answ_getq(m, &q) );
+	CHECK_FCT( fd_msg_rt_get(q, &rtd) );
+	CHECK_FCT( fd_msg_source_get( m, &nh, &nhlen ) );
+	CHECK_FCT( fd_rtd_error_add(rtd, nh, nhlen, a_oh->os.data, a_oh->os.len, a_rc->u32, NULL, NULL) );
+
+	/* Create a redir_rule  */
+	CHECK_FCT( redir_entry_new(&entry, &task.rh, task.rhu, q, nh, nhlen, a_oh->os.data, a_oh->os.len) );
+
+	CHECK_POSIX(  pthread_mutex_lock(&redir_exp_peer_lock)  );
+	/* Insert in the split list */
+	CHECK_FCT( redir_entry_insert(entry) );
+	/* Set the expiry */
+	CHECK_FCT( redir_exp_set(entry, task.rmct ?: DEFAULT_EXPIRE_TIME) );
+	CHECK_POSIX(  pthread_mutex_unlock(&redir_exp_peer_lock)  );
+
+	/* Now we can get rid of the received answer and send again the query. */
+	CHECK_FCT( fd_msg_answ_detach(m) );
+	CHECK_FCT( fd_msg_free(m) );
+
+	/* Send it */
+	CHECK_FCT( fd_msg_send(&q, NULL, NULL) );
+
+	/* Done! */
+
+out:
+	while (!FD_IS_LIST_EMPTY(&task.rh)) {
+		struct redir_host * h = task.rh.next->o;
+		fd_list_unlink(&h->chain);
+		free(h->id);
+		free(h);
+	}
+
+	return 0;
+
+}
+
diff --git a/extensions/rt_redirect/redir_out.c b/extensions/rt_redirect/redir_out.c
new file mode 100644
index 0000000..9f80f52
--- /dev/null
+++ b/extensions/rt_redirect/redir_out.c
@@ -0,0 +1,323 @@
+/*********************************************************************************************************
+* Software License Agreement (BSD License)                                                               *
+* Authors: Sebastien Decugis <sdecugis@freediameter.net>						 *
+* and Thomas Klausner <tk@giga.or.at>									 *
+*													 *
+* Copyright (c) 2013, 2014, WIDE Project and NICT							 *
+* All rights reserved.											 *
+* 													 *
+* Redistribution and use of this software in source and binary forms, with or without modification, are  *
+* permitted provided that the following conditions are met:						 *
+* 													 *
+* * Redistributions of source code must retain the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer.										 *
+*    													 *
+* * Redistributions in binary form must reproduce the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer in the documentation and/or other						 *
+*   materials provided with the distribution.								 *
+* 													 *
+* * Neither the name of the WIDE Project or NICT nor the 						 *
+*   names of its contributors may be used to endorse or 						 *
+*   promote products derived from this software without 						 *
+*   specific prior written permission of WIDE Project and 						 *
+*   NICT.												 *
+* 													 *
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED *
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
+* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR *
+* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 	 *
+* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 	 *
+* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR *
+* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF   *
+* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.								 *
+*********************************************************************************************************/
+
+#include "rt_redir.h"
+
+
+/* Find the data pertinent to a type in the input data */
+static int get_data_to_match(enum redir_h_u type, struct msg *msg, union matchdata * data, int * nodata)
+{
+	TRACE_ENTRY("%d %p %p %p", type, msg, data, nodata);
+
+	/* Initialize the data area */
+	memset(data, 0, sizeof(union matchdata));
+	*nodata = 0;
+
+	/* Now, find the appropriate information, depending on type */
+	switch (type) {
+		case DONT_CACHE:
+			data->message.msg = msg;
+			break;
+
+		case ALL_SESSION:
+			{
+				/* Get the sid from the message */
+				struct session * sess;
+				CHECK_FCT( fd_msg_sess_get(fd_g_config->cnf_dict, msg, &sess, NULL) );
+				if (!sess) {
+					TRACE_DEBUG(ANNOYING, "Message %p cannot match any ALL_SESSION rule since it does not have a Session-Id", msg);
+					*nodata = 1;
+				} else {
+					CHECK_FCT( fd_sess_getsid(sess, &data->session.s, &data->session.l) );
+				}
+			}
+			break;
+
+		case ALL_REALM:
+			{
+				/* Search the Destination-Realm in the message */
+				struct avp * dr;
+				CHECK_FCT( fd_msg_search_avp(msg, redir_dict_dr, &dr) );
+				if (!dr) {
+					TRACE_DEBUG(ANNOYING, "Message %p cannot match any ALL_REALM rule since it does not have a Destination-Realm", msg);
+					*nodata = 1;
+				} else {
+					struct avp_hdr * ahdr;
+					CHECK_FCT(  fd_msg_avp_hdr( dr, &ahdr )  );
+					data->realm.s = ahdr->avp_value->os.data;
+					data->realm.l = ahdr->avp_value->os.len;
+				}
+			}
+			break;
+
+		case REALM_AND_APPLICATION:
+			{
+				/* Search the Destination-Realm of the message */
+				struct avp * dr;
+				CHECK_FCT( fd_msg_search_avp(msg, redir_dict_dr, &dr) );
+				if (!dr) {
+					TRACE_DEBUG(ANNOYING, "Message %p cannot match any REALM_AND_APPLICATION rule since it does not have a Destination-Realm", msg);
+					*nodata = 1;
+				} else {
+					struct avp_hdr * ahdr;
+					CHECK_FCT(  fd_msg_avp_hdr( dr, &ahdr )  );
+					data->realm_app.s = ahdr->avp_value->os.data;
+					data->realm_app.l = ahdr->avp_value->os.len;
+
+					/* and then the application */
+					{
+						struct msg_hdr * hdr;
+						CHECK_FCT( fd_msg_hdr(msg, &hdr) );
+						data->realm_app.a = hdr->msg_appl;
+						/* Should we forbid application 0? */
+					}
+				}
+			}
+			break;
+
+		case ALL_APPLICATION:
+			{
+				/* Retrieve the application from the message */
+				struct msg_hdr * hdr;
+				CHECK_FCT( fd_msg_hdr(msg, &hdr) );
+				data->app.a = hdr->msg_appl;
+			}
+			break;
+
+		case ALL_HOST:
+				/* This is more complex, we need to match with all candidates in each rule, it'll be done later */
+			break;
+
+		case ALL_USER:
+			{
+				/* Search the User-Name of the message */
+				struct avp * un;
+				CHECK_FCT( fd_msg_search_avp(msg, redir_dict_un, &un) );
+				if (!un) {
+					TRACE_DEBUG(ANNOYING, "Message %p cannot match any ALL_USER rule since it does not have a User-Name", msg);
+					*nodata = 1;
+				} else {
+					struct avp_hdr * ahdr;
+					CHECK_FCT(  fd_msg_avp_hdr( un, &ahdr )  );
+					data->user.s = ahdr->avp_value->os.data;
+					data->user.l = ahdr->avp_value->os.len;
+				}
+			}
+			break;
+
+		default:
+			ASSERT(0);
+			return EINVAL;
+	}
+
+	return 0;
+}
+
+
+/* Apply the score from a rule if the candidate list is appropriate */
+static int apply_rule(struct redir_entry * e, struct msg * msg, struct fd_list * candidates)
+{
+	struct fd_list * lic, *lirh;
+	struct rtd_candidate * c_oh = NULL;
+	int cmp;
+
+	TRACE_ENTRY("%p %p %p", e, msg, candidates);
+	ASSERT( e && msg && candidates );
+
+	if (FD_IS_LIST_EMPTY(candidates)) {
+		TRACE_DEBUG(ANNOYING, "Skip Redirect rule since candidates list is empty");
+		return 0;
+	}
+
+	/* Now search common peers between e->target_peers_list and candidates */
+	TRACE_DEBUG(ANNOYING, "Message %p matches a Redirect rule (t:%d, @%p), processing candidates list", msg, e->type, e);
+
+	/* First, decrease the score of the host that we received the previous Redirect from, in case it is in the list */
+	for (lic = candidates->next; lic != candidates; lic = lic->next) {
+		struct rtd_candidate * cand = (struct rtd_candidate *) lic;
+
+		/* Special case: ALL_HOST rules: we decrease the score of the Origin-Host if present */
+		if (e->type == ALL_HOST) {
+			cmp = fd_os_almostcasesrch(cand->diamid, cand->diamidlen, e->data.host.s, e->data.host.l, NULL);
+			if (!cmp) {
+				TRACE_DEBUG(FULL, "Redirect msg %p: peer '%.*s' += %d (previous ALL_HOST Redirect originated from this peer)", msg, (int)cand->diamidlen, cand->diamid, FD_SCORE_SENT_REDIRECT);
+				cand->score += FD_SCORE_SENT_REDIRECT;
+				c_oh = cand;
+				continue;
+			}
+		}
+
+		cmp = fd_os_cmp(cand->diamid, cand->diamidlen, e->from.s, e->from.l);
+		if (!cmp) {
+			TRACE_DEBUG(FULL, "Redirect msg %p: peer '%.*s' += %d (previous Redirect received from this peer)", msg, (int)cand->diamidlen, cand->diamid, FD_SCORE_SENT_REDIRECT);
+			cand->score += FD_SCORE_SENT_REDIRECT;
+		}
+
+	}
+
+	if ((e->type == ALL_HOST) && (c_oh == NULL)) {
+		/* The rule does not apply, we're done */
+		return 0;
+	}
+
+	/* for each candidate, if it is found in the target_peers list, we add the rule's score to this candidate */
+	for (lic = candidates->next; lic != candidates; lic = lic->next) {
+		/* the candidates list is not guaranteed to be ordered at this time, so we cannot avoid the two imbricated loops */
+		struct rtd_candidate * cand = (struct rtd_candidate *) lic;
+
+		/* Is this candidate in the "Redirect-Host" list ? We must search caseinsentive here. */
+		for (lirh = e->target_peers_list.next; lirh != &e->target_peers_list; lirh = lirh->next) {
+			struct redir_host * host = lirh->o;
+			int cont;
+
+			cmp = fd_os_almostcasesrch( cand->diamid, cand->diamidlen, host->id, host->len, &cont );
+
+			if (cmp == 0) {
+				TRACE_DEBUG(FULL, "Redirect msg %p: peer '%.*s' += %d (rule t:%d @%p)", msg, (int)cand->diamidlen, cand->diamid, redirects_usages[e->type].score, e->type, e);
+				cand->score += redirects_usages[e->type].score;
+				break;
+			}
+			if (!cont)
+				break;
+		}
+	}
+
+	return 0;
+}
+
+static int redir_exist_for_type(int rule_type)
+{
+	int ret;
+
+	switch(rule_type) {
+	case ALL_SESSION:
+	case ALL_USER:
+		ret = redirect_hash_table[rule_type] != NULL;
+		break;
+	default:
+		ret = !FD_IS_LIST_EMPTY(&redirects_usages[rule_type].sentinel);
+		break;
+	}
+	return ret;
+}
+
+static int match_message(int rule_type, struct msg *msg, union matchdata *data, struct fd_list * candidates)
+{
+	struct fd_list * li;
+	struct redir_entry * e = NULL;
+	int ret = 0;
+
+	switch(rule_type) {
+	case ALL_SESSION:
+		HASH_FIND(hh, redirect_hash_table[rule_type], data->session.s, data->session.l, e);
+		if (e) {
+			/* This message matches a rule, apply */
+			CHECK_FCT_DO( ret = apply_rule(e, msg, candidates), break );
+		}
+		break;
+	case ALL_USER:
+		HASH_FIND(hh, redirect_hash_table[rule_type], data->user.s, data->user.l, e);
+		if (e) {
+			/* This message matches a rule, apply */
+			CHECK_FCT_DO( ret = apply_rule(e, msg, candidates), break );
+		}
+		break;
+	default:
+		/* Attempt each rule we have stored */
+		for (li = redirects_usages[rule_type].sentinel.next; li != &redirects_usages[rule_type].sentinel; li = li->next) {
+			e = li->o;
+
+			/* Does it match ? */
+			if (rule_type != ALL_HOST) { /* this one is an exception, we handle it separately */
+				int cmp = redir_entry_cmp_key[rule_type](data, &e->data);
+				if (cmp > 0)
+					continue;
+				if (cmp < 0)
+					break;
+			}
+
+			/* This rule matches (or we are in ALL_HOST), apply */
+			CHECK_FCT_DO( ret = apply_rule(e, msg, candidates), break );
+
+			/* If this was a DONT_CACHE rule, we unlink it, so that it will not be used again */
+			if (rule_type == DONT_CACHE) {
+				li = li->prev;
+				fd_list_unlink( li->next );
+				/* We cannot delete here without taking the mutex, which would mean we have first to release the lock...
+				   just let expiry garbage collect the rule */
+			}
+		}
+	}
+
+	return ret;
+}
+
+/* OUT callback */
+int redir_out_cb(void * cbdata, struct msg ** pmsg, struct fd_list * candidates)
+{
+	int i, ret = 0;
+	struct msg * msg = *pmsg;
+
+	TRACE_ENTRY("%p %p %p", cbdata, msg, candidates);
+
+	for (i = 0; i <= H_U_MAX; i++) {
+		/* Lock the line. We write lock in case of DONT_CACHE so we can directly unlink the entry. read in other cases is sufficient */
+		if (i == DONT_CACHE) {
+			CHECK_POSIX( pthread_rwlock_wrlock( &redirects_usages[i].lock ) );
+		} else {
+			CHECK_POSIX( pthread_rwlock_rdlock( &redirects_usages[i].lock ) );
+		}
+
+		if (redir_exist_for_type(i)) {
+			union matchdata data;
+			int nodata; /* The message does not allow to apply this rule, skip */
+
+			/* Retrieve the data that may match in the message */
+			CHECK_FCT_DO( ret = get_data_to_match(i, msg, &data, &nodata), goto out );
+
+			/* If data found for this type of rule, then try matching it */
+			if (!nodata)
+				ret = match_message(i, msg, &data, candidates);
+		}
+out:
+		CHECK_POSIX( pthread_rwlock_unlock( &redirects_usages[i].lock ) );
+		if (ret)
+			return ret;
+	}
+
+	return 0;
+}
+
diff --git a/extensions/rt_redirect/rt_redir.c b/extensions/rt_redirect/rt_redir.c
new file mode 100644
index 0000000..21b5a93
--- /dev/null
+++ b/extensions/rt_redirect/rt_redir.c
@@ -0,0 +1,90 @@
+/*********************************************************************************************************
+* Software License Agreement (BSD License)                                                               *
+* Authors: Sebastien Decugis <sdecugis@freediameter.net>						 *
+* and Thomas Klausner <tk@giga.or.at>									 *
+*													 *
+* Copyright (c) 2011, 2014, WIDE Project and NICT							 *
+* All rights reserved.											 *
+* 													 *
+* Redistribution and use of this software in source and binary forms, with or without modification, are  *
+* permitted provided that the following conditions are met:						 *
+* 													 *
+* * Redistributions of source code must retain the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer.										 *
+*    													 *
+* * Redistributions in binary form must reproduce the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer in the documentation and/or other						 *
+*   materials provided with the distribution.								 *
+* 													 *
+* * Neither the name of the WIDE Project or NICT nor the 						 *
+*   names of its contributors may be used to endorse or 						 *
+*   promote products derived from this software without 						 *
+*   specific prior written permission of WIDE Project and 						 *
+*   NICT.												 *
+* 													 *
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED *
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
+* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR *
+* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 	 *
+* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 	 *
+* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR *
+* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF   *
+* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.								 *
+*********************************************************************************************************/
+
+#include "rt_redir.h"
+
+struct dict_object * redir_dict_dr = NULL;
+struct dict_object * redir_dict_un = NULL;
+
+static struct fd_rt_fwd_hdl * fwd_hdl = NULL;
+static struct fd_rt_out_hdl * out_hdl = NULL;
+static pthread_t exp_thr  = (pthread_t)NULL;
+
+/* Initialize the module */
+static int redir_entry(char * conffile)
+{
+	TRACE_ENTRY("");
+
+	/* Dictionary objects */
+	CHECK_FCT(  fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Destination-Realm", &redir_dict_dr, ENOENT)  );
+	CHECK_FCT(  fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "User-Name", &redir_dict_un, ENOENT)  );
+
+	/* Initialize the entries array */
+	CHECK_FCT( redir_entry_init() );
+
+	/* Start the expire thread */
+	CHECK_POSIX( pthread_create( &exp_thr, NULL, redir_exp_thr_fct, NULL ) );
+
+	/* Register the callback that receives the answers and processes when it contains a Redirect indication. */
+	CHECK_FCT( fd_rt_fwd_register ( redir_fwd_cb, NULL, RT_FWD_ANS, &fwd_hdl ) );
+
+	/* Register the callback that applies the saved Redirect rules to outgoing messages. */
+	CHECK_FCT( fd_rt_out_register ( redir_out_cb, NULL, 10, &out_hdl ) );
+
+	return 0;
+}
+
+EXTENSION_ENTRY("rt_redirect", redir_entry);
+
+/* And terminate it */
+void fd_ext_fini(void)
+{
+	/* Unregister the callbacks */
+	if (fwd_hdl) {
+		CHECK_FCT_DO( fd_rt_fwd_unregister(fwd_hdl, NULL), );
+	}
+	if (out_hdl) {
+		CHECK_FCT_DO( fd_rt_out_unregister(out_hdl, NULL), );
+	}
+
+	/* Stop the expiry thread */
+	CHECK_FCT_DO( fd_thr_term(&exp_thr), );
+
+	/* Empty all entries */
+	redir_entry_fini();
+
+	return;
+}
diff --git a/extensions/rt_redirect/rt_redir.h b/extensions/rt_redirect/rt_redir.h
new file mode 100644
index 0000000..980d26f
--- /dev/null
+++ b/extensions/rt_redirect/rt_redir.h
@@ -0,0 +1,180 @@
+/*********************************************************************************************************
+* Software License Agreement (BSD License)                                                               *
+* Author: Sebastien Decugis <sdecugis@freediameter.net> and						 *
+* Thomas Klausner <tk@giga.or.at>									 *
+* 													 *
+* Copyright (c) 2013, 2014, WIDE Project and NICT							 *
+* All rights reserved.											 *
+* 													 *
+* Redistribution and use of this software in source and binary forms, with or without modification, are  *
+* permitted provided that the following conditions are met:						 *
+* 													 *
+* * Redistributions of source code must retain the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer.										 *
+*    													 *
+* * Redistributions in binary form must reproduce the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer in the documentation and/or other						 *
+*   materials provided with the distribution.								 *
+* 													 *
+* * Neither the name of the WIDE Project or NICT nor the 						 *
+*   names of its contributors may be used to endorse or 						 *
+*   promote products derived from this software without 						 *
+*   specific prior written permission of WIDE Project and 						 *
+*   NICT.												 *
+* 													 *
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED *
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
+* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR *
+* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 	 *
+* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 	 *
+* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR *
+* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF   *
+* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.								 *
+*********************************************************************************************************/
+
+/* Diameter Redirect management */
+#include <freeDiameter/extension.h>
+
+#include "uthash.h"
+
+/* There are 2 locks in this module. The priority is established as follow to avoid deadlocks:
+exp_peer mutex > usages rwlock.
+(e.g., the rwlock can be taken while holding the mutex, but not the other way)
+*/
+
+/* The types of redirects (from Redirect-Host-Usage AVP value) */
+enum redir_h_u {
+	DONT_CACHE = 0,
+	ALL_SESSION,
+	ALL_REALM,
+	REALM_AND_APPLICATION,
+	ALL_APPLICATION,
+	ALL_HOST,
+	ALL_USER
+};
+#define H_U_MAX	ALL_USER
+
+/* Eye catcher */
+#define REDIR_ENTRY_EYEC  0x43D14E74
+
+/* Expiration time set for DONT_CACHE tasks, so that the entry is found when the code is called back */
+#define DEFAULT_EXPIRE_TIME 10 /* seconds */
+
+/* Structure to store a parsed Redirect-Host */
+struct redir_host {
+	struct fd_list chain;
+
+	DiamId_t id;	/* malloc'd */
+	size_t	 len;
+	/* We don't use the following yet because we don't support dynamic new connections
+	int 	 secure;
+	uint16_t port;
+	int	 l4;
+	char	 proto;
+	*/
+};
+
+/* Rule data that is stored depending on Redirect-Host-Usage value */
+union matchdata {
+	/* DONT_CACHE */
+	struct {
+		struct msg * msg; /* The query message for which this rule was created */
+	} message;
+
+	/* ALL_SESSION */
+	struct {
+		os0_t s;  /* sid */
+		size_t l;
+	} session;
+
+	/* ALL_REALM */
+	struct {
+		os0_t s;  /* Destination-Realm AVP data */
+		size_t l;
+	} realm;
+
+	/* REALM_AND_APPLICATION */
+	struct {
+		application_id_t a; /* message's application */
+		os0_t s;  /* Destination-Realm AVP data */
+		size_t l;
+	} realm_app;
+
+	/* ALL_APPLICATION */
+	struct {
+		application_id_t a; /* message's application */
+	} app;
+
+	/* ALL_HOST */
+	struct {
+		os0_t s;  /* the Origin-Host of the Redirect message (which may be the next hop or not) */
+		size_t l;
+	} host;
+
+	/* ALL_USER */
+	struct {
+		os0_t s;  /* User-Name AVP data */
+		size_t l;
+	} user;
+};
+
+
+/* Structure to store a Redirect indication */
+struct redir_entry {
+	uint32_t eyec; /* must be REDIR_ENTRY_EYEC, used for debug only */
+
+	struct {
+		os0_t s; /* alloc'd, must be freed */
+		size_t l;
+	} from; /* whom this rule was received from (next hop) ? */
+
+	struct fd_list	 target_peers_list; /* The list of Redirect-Hosts for this entry */
+
+	struct timespec  timeout;  /* When does this entry expire? */
+	struct fd_list   exp_list; /* chain in the expire_list list, ordered by expiration date, protected by exp_peer_lock */
+
+	enum redir_h_u type;       /* Type of this entry */
+	struct fd_list redir_list; /* link in redirects_usages lists. Lists are ordered by the data value. Protected by rw locks */
+	union matchdata	data;	   /* The strings are duplicated & must be freed in this structure */
+	UT_hash_handle hh;         /* magic entry for hash table */
+};
+
+/* The array where the redir_entries are stored */
+struct redir_line {
+	enum fd_rt_out_score 	score;
+	pthread_rwlock_t	lock; /* protect the list */
+	struct fd_list		sentinel; /* list of redir_entry, the "o" field of the sentinel points to the redir_line entry */
+};
+extern struct redir_line redirects_usages[];
+/* the hash table where entries are stored for ALL_SESSION and ALL_USER */
+extern struct redir_entry *redirect_hash_table[];
+
+/* Accelerator to the line lock */
+#define RWLOCK_REDIR( _entry ) ( &(redirects_usages[(_entry)->type].lock) )
+
+/* Lock that must be owned before calling some functions */
+extern pthread_mutex_t redir_exp_peer_lock;
+
+/* Dictionary cached objects */
+extern struct dict_object * redir_dict_dr;
+extern struct dict_object * redir_dict_un;
+
+/* Functions on redir_entry */
+int redir_entry_init();
+int redir_entry_fini();
+int redir_entry_new(struct redir_entry ** e, struct fd_list * targets, uint32_t rhu, struct msg * qry, DiamId_t nh, size_t nhlen, os0_t oh, size_t ohlen);
+extern int (*redir_entry_cmp_key[])(union matchdata * , union matchdata *); /* compare functions */
+int redir_entry_insert(struct redir_entry * e);
+int redir_entry_destroy(struct redir_entry * e);
+
+/* Functions for expiry */
+void * redir_exp_thr_fct(void * arg);
+int redir_exp_set(struct redir_entry * e, uint32_t duration);
+
+/* Forward cb */
+int redir_fwd_cb(void * cbdata, struct msg ** msg);
+
+/* Out callback */
+int redir_out_cb(void * cbdata, struct msg ** pmsg, struct fd_list * candidates);
diff --git a/extensions/rt_redirect/uthash.h b/extensions/rt_redirect/uthash.h
new file mode 100644
index 0000000..f1c3032
--- /dev/null
+++ b/extensions/rt_redirect/uthash.h
@@ -0,0 +1,940 @@
+/*
+Copyright (c) 2003-2013, Troy D. Hanson     http://troydhanson.github.com/uthash/
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+
+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 UTHASH_H
+#define UTHASH_H
+
+#include <string.h>   /* memcmp,strlen */
+#include <stddef.h>   /* ptrdiff_t */
+#include <stdlib.h>   /* exit() */
+
+/* These macros use decltype or the earlier __typeof GNU extension.
+   As decltype is only available in newer compilers (VS2010 or gcc 4.3+
+   when compiling c++ source) this code uses whatever method is needed
+   or, for VS2008 where neither is available, uses casting workarounds. */
+#ifdef _MSC_VER         /* MS compiler */
+#if _MSC_VER >= 1600 && defined(__cplusplus)  /* VS2010 or newer in C++ mode */
+#define DECLTYPE(x) (decltype(x))
+#else                   /* VS2008 or older (or VS2010 in C mode) */
+#define NO_DECLTYPE
+#define DECLTYPE(x)
+#endif
+#else                   /* GNU, Sun and other compilers */
+#define DECLTYPE(x) (__typeof(x))
+#endif
+
+#ifdef NO_DECLTYPE
+#define DECLTYPE_ASSIGN(dst,src)                                                 \
+do {                                                                             \
+  char **_da_dst = (char**)(&(dst));                                             \
+  *_da_dst = (char*)(src);                                                       \
+} while(0)
+#else
+#define DECLTYPE_ASSIGN(dst,src)                                                 \
+do {                                                                             \
+  (dst) = DECLTYPE(dst)(src);                                                    \
+} while(0)
+#endif
+
+/* a number of the hash function use uint32_t which isn't defined on win32 */
+#ifdef _MSC_VER
+typedef unsigned int uint32_t;
+typedef unsigned char uint8_t;
+#else
+#include <inttypes.h>   /* uint32_t */
+#endif
+
+#define UTHASH_VERSION 1.9.8
+
+#ifndef uthash_fatal
+#define uthash_fatal(msg) exit(-1)        /* fatal error (out of memory,etc) */
+#endif
+#ifndef uthash_malloc
+#define uthash_malloc(sz) malloc(sz)      /* malloc fcn                      */
+#endif
+#ifndef uthash_free
+#define uthash_free(ptr,sz) free(ptr)     /* free fcn                        */
+#endif
+
+#ifndef uthash_noexpand_fyi
+#define uthash_noexpand_fyi(tbl)          /* can be defined to log noexpand  */
+#endif
+#ifndef uthash_expand_fyi
+#define uthash_expand_fyi(tbl)            /* can be defined to log expands   */
+#endif
+
+/* initial number of buckets */
+#define HASH_INITIAL_NUM_BUCKETS 32      /* initial number of buckets        */
+#define HASH_INITIAL_NUM_BUCKETS_LOG2 5  /* lg2 of initial number of buckets */
+#define HASH_BKT_CAPACITY_THRESH 10      /* expand when bucket count reaches */
+
+/* calculate the element whose hash handle address is hhe */
+#define ELMT_FROM_HH(tbl,hhp) ((void*)(((char*)(hhp)) - ((tbl)->hho)))
+
+#define HASH_FIND(hh,head,keyptr,keylen,out)                                     \
+do {                                                                             \
+  unsigned _hf_bkt,_hf_hashv;                                                    \
+  out=NULL;                                                                      \
+  if (head) {                                                                    \
+     HASH_FCN(keyptr,keylen, (head)->hh.tbl->num_buckets, _hf_hashv, _hf_bkt);   \
+     if (HASH_BLOOM_TEST((head)->hh.tbl, _hf_hashv)) {                           \
+       HASH_FIND_IN_BKT((head)->hh.tbl, hh, (head)->hh.tbl->buckets[ _hf_bkt ],  \
+                        keyptr,keylen,out);                                      \
+     }                                                                           \
+  }                                                                              \
+} while (0)
+
+#ifdef HASH_BLOOM
+#define HASH_BLOOM_BITLEN (1ULL << HASH_BLOOM)
+#define HASH_BLOOM_BYTELEN (HASH_BLOOM_BITLEN/8) + ((HASH_BLOOM_BITLEN%8) ? 1:0)
+#define HASH_BLOOM_MAKE(tbl)                                                     \
+do {                                                                             \
+  (tbl)->bloom_nbits = HASH_BLOOM;                                               \
+  (tbl)->bloom_bv = (uint8_t*)uthash_malloc(HASH_BLOOM_BYTELEN);                 \
+  if (!((tbl)->bloom_bv))  { uthash_fatal( "out of memory"); }                   \
+  memset((tbl)->bloom_bv, 0, HASH_BLOOM_BYTELEN);                                \
+  (tbl)->bloom_sig = HASH_BLOOM_SIGNATURE;                                       \
+} while (0)
+
+#define HASH_BLOOM_FREE(tbl)                                                     \
+do {                                                                             \
+  uthash_free((tbl)->bloom_bv, HASH_BLOOM_BYTELEN);                              \
+} while (0)
+
+#define HASH_BLOOM_BITSET(bv,idx) (bv[(idx)/8] |= (1U << ((idx)%8)))
+#define HASH_BLOOM_BITTEST(bv,idx) (bv[(idx)/8] & (1U << ((idx)%8)))
+
+#define HASH_BLOOM_ADD(tbl,hashv)                                                \
+  HASH_BLOOM_BITSET((tbl)->bloom_bv, (hashv & (uint32_t)((1ULL << (tbl)->bloom_nbits) - 1)))
+
+#define HASH_BLOOM_TEST(tbl,hashv)                                               \
+  HASH_BLOOM_BITTEST((tbl)->bloom_bv, (hashv & (uint32_t)((1ULL << (tbl)->bloom_nbits) - 1)))
+
+#else
+#define HASH_BLOOM_MAKE(tbl)
+#define HASH_BLOOM_FREE(tbl)
+#define HASH_BLOOM_ADD(tbl,hashv)
+#define HASH_BLOOM_TEST(tbl,hashv) (1)
+#define HASH_BLOOM_BYTELEN 0
+#endif
+
+#define HASH_MAKE_TABLE(hh,head)                                                 \
+do {                                                                             \
+  (head)->hh.tbl = (UT_hash_table*)uthash_malloc(                                \
+                  sizeof(UT_hash_table));                                        \
+  if (!((head)->hh.tbl))  { uthash_fatal( "out of memory"); }                    \
+  memset((head)->hh.tbl, 0, sizeof(UT_hash_table));                              \
+  (head)->hh.tbl->tail = &((head)->hh);                                          \
+  (head)->hh.tbl->num_buckets = HASH_INITIAL_NUM_BUCKETS;                        \
+  (head)->hh.tbl->log2_num_buckets = HASH_INITIAL_NUM_BUCKETS_LOG2;              \
+  (head)->hh.tbl->hho = (char*)(&(head)->hh) - (char*)(head);                    \
+  (head)->hh.tbl->buckets = (UT_hash_bucket*)uthash_malloc(                      \
+          HASH_INITIAL_NUM_BUCKETS*sizeof(struct UT_hash_bucket));               \
+  if (! (head)->hh.tbl->buckets) { uthash_fatal( "out of memory"); }             \
+  memset((head)->hh.tbl->buckets, 0,                                             \
+          HASH_INITIAL_NUM_BUCKETS*sizeof(struct UT_hash_bucket));               \
+  HASH_BLOOM_MAKE((head)->hh.tbl);                                               \
+  (head)->hh.tbl->signature = HASH_SIGNATURE;                                    \
+} while(0)
+
+#define HASH_ADD(hh,head,fieldname,keylen_in,add)                                \
+        HASH_ADD_KEYPTR(hh,head,&((add)->fieldname),keylen_in,add)
+
+#define HASH_REPLACE(hh,head,fieldname,keylen_in,add,replaced)                   \
+do {                                                                             \
+  replaced=NULL;                                                                 \
+  HASH_FIND(hh,head,&((add)->fieldname),keylen_in,replaced);                     \
+  if (replaced!=NULL) {                                                          \
+     HASH_DELETE(hh,head,replaced);                                              \
+  };                                                                             \
+  HASH_ADD(hh,head,fieldname,keylen_in,add);                                     \
+} while(0)
+
+#define HASH_ADD_KEYPTR(hh,head,keyptr,keylen_in,add)                            \
+do {                                                                             \
+ unsigned _ha_bkt;                                                               \
+ (add)->hh.next = NULL;                                                          \
+ (add)->hh.key = (char*)keyptr;                                                  \
+ (add)->hh.keylen = (unsigned)keylen_in;                                                   \
+ if (!(head)) {                                                                  \
+    head = (add);                                                                \
+    (head)->hh.prev = NULL;                                                      \
+    HASH_MAKE_TABLE(hh,head);                                                    \
+ } else {                                                                        \
+    (head)->hh.tbl->tail->next = (add);                                          \
+    (add)->hh.prev = ELMT_FROM_HH((head)->hh.tbl, (head)->hh.tbl->tail);         \
+    (head)->hh.tbl->tail = &((add)->hh);                                         \
+ }                                                                               \
+ (head)->hh.tbl->num_items++;                                                    \
+ (add)->hh.tbl = (head)->hh.tbl;                                                 \
+ HASH_FCN(keyptr,keylen_in, (head)->hh.tbl->num_buckets,                         \
+         (add)->hh.hashv, _ha_bkt);                                              \
+ HASH_ADD_TO_BKT((head)->hh.tbl->buckets[_ha_bkt],&(add)->hh);                   \
+ HASH_BLOOM_ADD((head)->hh.tbl,(add)->hh.hashv);                                 \
+ HASH_EMIT_KEY(hh,head,keyptr,keylen_in);                                        \
+ HASH_FSCK(hh,head);                                                             \
+} while(0)
+
+#define HASH_TO_BKT( hashv, num_bkts, bkt )                                      \
+do {                                                                             \
+  bkt = ((hashv) & ((num_bkts) - 1));                                            \
+} while(0)
+
+/* delete "delptr" from the hash table.
+ * "the usual" patch-up process for the app-order doubly-linked-list.
+ * The use of _hd_hh_del below deserves special explanation.
+ * These used to be expressed using (delptr) but that led to a bug
+ * if someone used the same symbol for the head and deletee, like
+ *  HASH_DELETE(hh,users,users);
+ * We want that to work, but by changing the head (users) below
+ * we were forfeiting our ability to further refer to the deletee (users)
+ * in the patch-up process. Solution: use scratch space to
+ * copy the deletee pointer, then the latter references are via that
+ * scratch pointer rather than through the repointed (users) symbol.
+ */
+#define HASH_DELETE(hh,head,delptr)                                              \
+do {                                                                             \
+    unsigned _hd_bkt;                                                            \
+    struct UT_hash_handle *_hd_hh_del;                                           \
+    if ( ((delptr)->hh.prev == NULL) && ((delptr)->hh.next == NULL) )  {         \
+        uthash_free((head)->hh.tbl->buckets,                                     \
+                    (head)->hh.tbl->num_buckets*sizeof(struct UT_hash_bucket) ); \
+        HASH_BLOOM_FREE((head)->hh.tbl);                                         \
+        uthash_free((head)->hh.tbl, sizeof(UT_hash_table));                      \
+        head = NULL;                                                             \
+    } else {                                                                     \
+        _hd_hh_del = &((delptr)->hh);                                            \
+        if ((delptr) == ELMT_FROM_HH((head)->hh.tbl,(head)->hh.tbl->tail)) {     \
+            (head)->hh.tbl->tail =                                               \
+                (UT_hash_handle*)((ptrdiff_t)((delptr)->hh.prev) +               \
+                (head)->hh.tbl->hho);                                            \
+        }                                                                        \
+        if ((delptr)->hh.prev) {                                                 \
+            ((UT_hash_handle*)((ptrdiff_t)((delptr)->hh.prev) +                  \
+                    (head)->hh.tbl->hho))->next = (delptr)->hh.next;             \
+        } else {                                                                 \
+            DECLTYPE_ASSIGN(head,(delptr)->hh.next);                             \
+        }                                                                        \
+        if (_hd_hh_del->next) {                                                  \
+            ((UT_hash_handle*)((ptrdiff_t)_hd_hh_del->next +                     \
+                    (head)->hh.tbl->hho))->prev =                                \
+                    _hd_hh_del->prev;                                            \
+        }                                                                        \
+        HASH_TO_BKT( _hd_hh_del->hashv, (head)->hh.tbl->num_buckets, _hd_bkt);   \
+        HASH_DEL_IN_BKT(hh,(head)->hh.tbl->buckets[_hd_bkt], _hd_hh_del);        \
+        (head)->hh.tbl->num_items--;                                             \
+    }                                                                            \
+    HASH_FSCK(hh,head);                                                          \
+} while (0)
+
+
+/* convenience forms of HASH_FIND/HASH_ADD/HASH_DEL */
+#define HASH_FIND_STR(head,findstr,out)                                          \
+    HASH_FIND(hh,head,findstr,strlen(findstr),out)
+#define HASH_ADD_STR(head,strfield,add)                                          \
+    HASH_ADD(hh,head,strfield,strlen(add->strfield),add)
+#define HASH_REPLACE_STR(head,strfield,add,replaced)                             \
+  HASH_REPLACE(hh,head,strfield,strlen(add->strfield),add,replaced)
+#define HASH_FIND_INT(head,findint,out)                                          \
+    HASH_FIND(hh,head,findint,sizeof(int),out)
+#define HASH_ADD_INT(head,intfield,add)                                          \
+    HASH_ADD(hh,head,intfield,sizeof(int),add)
+#define HASH_REPLACE_INT(head,intfield,add,replaced)                             \
+    HASH_REPLACE(hh,head,intfield,sizeof(int),add,replaced)
+#define HASH_FIND_PTR(head,findptr,out)                                          \
+    HASH_FIND(hh,head,findptr,sizeof(void *),out)
+#define HASH_ADD_PTR(head,ptrfield,add)                                          \
+    HASH_ADD(hh,head,ptrfield,sizeof(void *),add)
+#define HASH_REPLACE_PTR(head,ptrfield,add)                                      \
+    HASH_REPLACE(hh,head,ptrfield,sizeof(void *),add,replaced)
+#define HASH_DEL(head,delptr)                                                    \
+    HASH_DELETE(hh,head,delptr)
+
+/* HASH_FSCK checks hash integrity on every add/delete when HASH_DEBUG is defined.
+ * This is for uthash developer only; it compiles away if HASH_DEBUG isn't defined.
+ */
+#ifdef HASH_DEBUG
+#define HASH_OOPS(...) do { fprintf(stderr,__VA_ARGS__); exit(-1); } while (0)
+#define HASH_FSCK(hh,head)                                                       \
+do {                                                                             \
+    unsigned _bkt_i;                                                             \
+    unsigned _count, _bkt_count;                                                 \
+    char *_prev;                                                                 \
+    struct UT_hash_handle *_thh;                                                 \
+    if (head) {                                                                  \
+        _count = 0;                                                              \
+        for( _bkt_i = 0; _bkt_i < (head)->hh.tbl->num_buckets; _bkt_i++) {       \
+            _bkt_count = 0;                                                      \
+            _thh = (head)->hh.tbl->buckets[_bkt_i].hh_head;                      \
+            _prev = NULL;                                                        \
+            while (_thh) {                                                       \
+               if (_prev != (char*)(_thh->hh_prev)) {                            \
+                   HASH_OOPS("invalid hh_prev %p, actual %p\n",                  \
+                    _thh->hh_prev, _prev );                                      \
+               }                                                                 \
+               _bkt_count++;                                                     \
+               _prev = (char*)(_thh);                                            \
+               _thh = _thh->hh_next;                                             \
+            }                                                                    \
+            _count += _bkt_count;                                                \
+            if ((head)->hh.tbl->buckets[_bkt_i].count !=  _bkt_count) {          \
+               HASH_OOPS("invalid bucket count %d, actual %d\n",                 \
+                (head)->hh.tbl->buckets[_bkt_i].count, _bkt_count);              \
+            }                                                                    \
+        }                                                                        \
+        if (_count != (head)->hh.tbl->num_items) {                               \
+            HASH_OOPS("invalid hh item count %d, actual %d\n",                   \
+                (head)->hh.tbl->num_items, _count );                             \
+        }                                                                        \
+        /* traverse hh in app order; check next/prev integrity, count */         \
+        _count = 0;                                                              \
+        _prev = NULL;                                                            \
+        _thh =  &(head)->hh;                                                     \
+        while (_thh) {                                                           \
+           _count++;                                                             \
+           if (_prev !=(char*)(_thh->prev)) {                                    \
+              HASH_OOPS("invalid prev %p, actual %p\n",                          \
+                    _thh->prev, _prev );                                         \
+           }                                                                     \
+           _prev = (char*)ELMT_FROM_HH((head)->hh.tbl, _thh);                    \
+           _thh = ( _thh->next ?  (UT_hash_handle*)((char*)(_thh->next) +        \
+                                  (head)->hh.tbl->hho) : NULL );                 \
+        }                                                                        \
+        if (_count != (head)->hh.tbl->num_items) {                               \
+            HASH_OOPS("invalid app item count %d, actual %d\n",                  \
+                (head)->hh.tbl->num_items, _count );                             \
+        }                                                                        \
+    }                                                                            \
+} while (0)
+#else
+#define HASH_FSCK(hh,head)
+#endif
+
+/* When compiled with -DHASH_EMIT_KEYS, length-prefixed keys are emitted to
+ * the descriptor to which this macro is defined for tuning the hash function.
+ * The app can #include <unistd.h> to get the prototype for write(2). */
+#ifdef HASH_EMIT_KEYS
+#define HASH_EMIT_KEY(hh,head,keyptr,fieldlen)                                   \
+do {                                                                             \
+    unsigned _klen = fieldlen;                                                   \
+    write(HASH_EMIT_KEYS, &_klen, sizeof(_klen));                                \
+    write(HASH_EMIT_KEYS, keyptr, fieldlen);                                     \
+} while (0)
+#else
+#define HASH_EMIT_KEY(hh,head,keyptr,fieldlen)
+#endif
+
+/* default to Jenkin's hash unless overridden e.g. DHASH_FUNCTION=HASH_SAX */
+#ifdef HASH_FUNCTION
+#define HASH_FCN HASH_FUNCTION
+#else
+#define HASH_FCN HASH_JEN
+#endif
+
+/* The Bernstein hash function, used in Perl prior to v5.6 */
+#define HASH_BER(key,keylen,num_bkts,hashv,bkt)                                  \
+do {                                                                             \
+  unsigned _hb_keylen=keylen;                                                    \
+  char *_hb_key=(char*)(key);                                                    \
+  (hashv) = 0;                                                                   \
+  while (_hb_keylen--)  { (hashv) = ((hashv) * 33) + *_hb_key++; }               \
+  bkt = (hashv) & (num_bkts-1);                                                  \
+} while (0)
+
+
+/* SAX/FNV/OAT/JEN hash functions are macro variants of those listed at
+ * http://eternallyconfuzzled.com/tuts/algorithms/jsw_tut_hashing.aspx */
+#define HASH_SAX(key,keylen,num_bkts,hashv,bkt)                                  \
+do {                                                                             \
+  unsigned _sx_i;                                                                \
+  char *_hs_key=(char*)(key);                                                    \
+  hashv = 0;                                                                     \
+  for(_sx_i=0; _sx_i < keylen; _sx_i++)                                          \
+      hashv ^= (hashv << 5) + (hashv >> 2) + _hs_key[_sx_i];                     \
+  bkt = hashv & (num_bkts-1);                                                    \
+} while (0)
+
+#define HASH_FNV(key,keylen,num_bkts,hashv,bkt)                                  \
+do {                                                                             \
+  unsigned _fn_i;                                                                \
+  char *_hf_key=(char*)(key);                                                    \
+  hashv = 2166136261UL;                                                          \
+  for(_fn_i=0; _fn_i < keylen; _fn_i++)                                          \
+      hashv = (hashv * 16777619) ^ _hf_key[_fn_i];                               \
+  bkt = hashv & (num_bkts-1);                                                    \
+} while(0)
+
+#define HASH_OAT(key,keylen,num_bkts,hashv,bkt)                                  \
+do {                                                                             \
+  unsigned _ho_i;                                                                \
+  char *_ho_key=(char*)(key);                                                    \
+  hashv = 0;                                                                     \
+  for(_ho_i=0; _ho_i < keylen; _ho_i++) {                                        \
+      hashv += _ho_key[_ho_i];                                                   \
+      hashv += (hashv << 10);                                                    \
+      hashv ^= (hashv >> 6);                                                     \
+  }                                                                              \
+  hashv += (hashv << 3);                                                         \
+  hashv ^= (hashv >> 11);                                                        \
+  hashv += (hashv << 15);                                                        \
+  bkt = hashv & (num_bkts-1);                                                    \
+} while(0)
+
+#define HASH_JEN_MIX(a,b,c)                                                      \
+do {                                                                             \
+  a -= b; a -= c; a ^= ( c >> 13 );                                              \
+  b -= c; b -= a; b ^= ( a << 8 );                                               \
+  c -= a; c -= b; c ^= ( b >> 13 );                                              \
+  a -= b; a -= c; a ^= ( c >> 12 );                                              \
+  b -= c; b -= a; b ^= ( a << 16 );                                              \
+  c -= a; c -= b; c ^= ( b >> 5 );                                               \
+  a -= b; a -= c; a ^= ( c >> 3 );                                               \
+  b -= c; b -= a; b ^= ( a << 10 );                                              \
+  c -= a; c -= b; c ^= ( b >> 15 );                                              \
+} while (0)
+
+#define HASH_JEN(key,keylen,num_bkts,hashv,bkt)                                  \
+do {                                                                             \
+  unsigned _hj_i,_hj_j,_hj_k;                                                    \
+  unsigned char *_hj_key=(unsigned char*)(key);                                  \
+  hashv = 0xfeedbeef;                                                            \
+  _hj_i = _hj_j = 0x9e3779b9;                                                    \
+  _hj_k = (unsigned)keylen;                                                      \
+  while (_hj_k >= 12) {                                                          \
+    _hj_i +=    (_hj_key[0] + ( (unsigned)_hj_key[1] << 8 )                      \
+        + ( (unsigned)_hj_key[2] << 16 )                                         \
+        + ( (unsigned)_hj_key[3] << 24 ) );                                      \
+    _hj_j +=    (_hj_key[4] + ( (unsigned)_hj_key[5] << 8 )                      \
+        + ( (unsigned)_hj_key[6] << 16 )                                         \
+        + ( (unsigned)_hj_key[7] << 24 ) );                                      \
+    hashv += (_hj_key[8] + ( (unsigned)_hj_key[9] << 8 )                         \
+        + ( (unsigned)_hj_key[10] << 16 )                                        \
+        + ( (unsigned)_hj_key[11] << 24 ) );                                     \
+                                                                                 \
+     HASH_JEN_MIX(_hj_i, _hj_j, hashv);                                          \
+                                                                                 \
+     _hj_key += 12;                                                              \
+     _hj_k -= 12;                                                                \
+  }                                                                              \
+  hashv += keylen;                                                               \
+  switch ( _hj_k ) {                                                             \
+     case 11: hashv += ( (unsigned)_hj_key[10] << 24 );                          \
+     case 10: hashv += ( (unsigned)_hj_key[9] << 16 );                           \
+     case 9:  hashv += ( (unsigned)_hj_key[8] << 8 );                            \
+     case 8:  _hj_j += ( (unsigned)_hj_key[7] << 24 );                           \
+     case 7:  _hj_j += ( (unsigned)_hj_key[6] << 16 );                           \
+     case 6:  _hj_j += ( (unsigned)_hj_key[5] << 8 );                            \
+     case 5:  _hj_j += _hj_key[4];                                               \
+     case 4:  _hj_i += ( (unsigned)_hj_key[3] << 24 );                           \
+     case 3:  _hj_i += ( (unsigned)_hj_key[2] << 16 );                           \
+     case 2:  _hj_i += ( (unsigned)_hj_key[1] << 8 );                            \
+     case 1:  _hj_i += _hj_key[0];                                               \
+  }                                                                              \
+  HASH_JEN_MIX(_hj_i, _hj_j, hashv);                                             \
+  bkt = hashv & (num_bkts-1);                                                    \
+} while(0)
+
+/* The Paul Hsieh hash function */
+#undef get16bits
+#if (defined(__GNUC__) && defined(__i386__)) || defined(__WATCOMC__)             \
+  || defined(_MSC_VER) || defined (__BORLANDC__) || defined (__TURBOC__)
+#define get16bits(d) (*((const uint16_t *) (d)))
+#endif
+
+#if !defined (get16bits)
+#define get16bits(d) ((((uint32_t)(((const uint8_t *)(d))[1])) << 8)             \
+                       +(uint32_t)(((const uint8_t *)(d))[0]) )
+#endif
+#define HASH_SFH(key,keylen,num_bkts,hashv,bkt)                                  \
+do {                                                                             \
+  unsigned char *_sfh_key=(unsigned char*)(key);                                 \
+  uint32_t _sfh_tmp, _sfh_len = keylen;                                          \
+                                                                                 \
+  int _sfh_rem = _sfh_len & 3;                                                   \
+  _sfh_len >>= 2;                                                                \
+  hashv = 0xcafebabe;                                                            \
+                                                                                 \
+  /* Main loop */                                                                \
+  for (;_sfh_len > 0; _sfh_len--) {                                              \
+    hashv    += get16bits (_sfh_key);                                            \
+    _sfh_tmp       = (uint32_t)(get16bits (_sfh_key+2)) << 11  ^ hashv;          \
+    hashv     = (hashv << 16) ^ _sfh_tmp;                                        \
+    _sfh_key += 2*sizeof (uint16_t);                                             \
+    hashv    += hashv >> 11;                                                     \
+  }                                                                              \
+                                                                                 \
+  /* Handle end cases */                                                         \
+  switch (_sfh_rem) {                                                            \
+    case 3: hashv += get16bits (_sfh_key);                                       \
+            hashv ^= hashv << 16;                                                \
+            hashv ^= (uint32_t)(_sfh_key[sizeof (uint16_t)] << 18);              \
+            hashv += hashv >> 11;                                                \
+            break;                                                               \
+    case 2: hashv += get16bits (_sfh_key);                                       \
+            hashv ^= hashv << 11;                                                \
+            hashv += hashv >> 17;                                                \
+            break;                                                               \
+    case 1: hashv += *_sfh_key;                                                  \
+            hashv ^= hashv << 10;                                                \
+            hashv += hashv >> 1;                                                 \
+  }                                                                              \
+                                                                                 \
+    /* Force "avalanching" of final 127 bits */                                  \
+    hashv ^= hashv << 3;                                                         \
+    hashv += hashv >> 5;                                                         \
+    hashv ^= hashv << 4;                                                         \
+    hashv += hashv >> 17;                                                        \
+    hashv ^= hashv << 25;                                                        \
+    hashv += hashv >> 6;                                                         \
+    bkt = hashv & (num_bkts-1);                                                  \
+} while(0)
+
+#ifdef HASH_USING_NO_STRICT_ALIASING
+/* The MurmurHash exploits some CPU's (x86,x86_64) tolerance for unaligned reads.
+ * For other types of CPU's (e.g. Sparc) an unaligned read causes a bus error.
+ * MurmurHash uses the faster approach only on CPU's where we know it's safe.
+ *
+ * Note the preprocessor built-in defines can be emitted using:
+ *
+ *   gcc -m64 -dM -E - < /dev/null                  (on gcc)
+ *   cc -## a.c (where a.c is a simple test file)   (Sun Studio)
+ */
+#if (defined(__i386__) || defined(__x86_64__)  || defined(_M_IX86))
+#define MUR_GETBLOCK(p,i) p[i]
+#else /* non intel */
+#define MUR_PLUS0_ALIGNED(p) (((unsigned long)p & 0x3) == 0)
+#define MUR_PLUS1_ALIGNED(p) (((unsigned long)p & 0x3) == 1)
+#define MUR_PLUS2_ALIGNED(p) (((unsigned long)p & 0x3) == 2)
+#define MUR_PLUS3_ALIGNED(p) (((unsigned long)p & 0x3) == 3)
+#define WP(p) ((uint32_t*)((unsigned long)(p) & ~3UL))
+#if (defined(__BIG_ENDIAN__) || defined(SPARC) || defined(__ppc__) || defined(__ppc64__))
+#define MUR_THREE_ONE(p) ((((*WP(p))&0x00ffffff) << 8) | (((*(WP(p)+1))&0xff000000) >> 24))
+#define MUR_TWO_TWO(p)   ((((*WP(p))&0x0000ffff) <<16) | (((*(WP(p)+1))&0xffff0000) >> 16))
+#define MUR_ONE_THREE(p) ((((*WP(p))&0x000000ff) <<24) | (((*(WP(p)+1))&0xffffff00) >>  8))
+#else /* assume little endian non-intel */
+#define MUR_THREE_ONE(p) ((((*WP(p))&0xffffff00) >> 8) | (((*(WP(p)+1))&0x000000ff) << 24))
+#define MUR_TWO_TWO(p)   ((((*WP(p))&0xffff0000) >>16) | (((*(WP(p)+1))&0x0000ffff) << 16))
+#define MUR_ONE_THREE(p) ((((*WP(p))&0xff000000) >>24) | (((*(WP(p)+1))&0x00ffffff) <<  8))
+#endif
+#define MUR_GETBLOCK(p,i) (MUR_PLUS0_ALIGNED(p) ? ((p)[i]) :           \
+                            (MUR_PLUS1_ALIGNED(p) ? MUR_THREE_ONE(p) : \
+                             (MUR_PLUS2_ALIGNED(p) ? MUR_TWO_TWO(p) :  \
+                                                      MUR_ONE_THREE(p))))
+#endif
+#define MUR_ROTL32(x,r) (((x) << (r)) | ((x) >> (32 - (r))))
+#define MUR_FMIX(_h) \
+do {                 \
+  _h ^= _h >> 16;    \
+  _h *= 0x85ebca6b;  \
+  _h ^= _h >> 13;    \
+  _h *= 0xc2b2ae35l; \
+  _h ^= _h >> 16;    \
+} while(0)
+
+#define HASH_MUR(key,keylen,num_bkts,hashv,bkt)                        \
+do {                                                                   \
+  const uint8_t *_mur_data = (const uint8_t*)(key);                    \
+  const int _mur_nblocks = (keylen) / 4;                               \
+  uint32_t _mur_h1 = 0xf88D5353;                                       \
+  uint32_t _mur_c1 = 0xcc9e2d51;                                       \
+  uint32_t _mur_c2 = 0x1b873593;                                       \
+  uint32_t _mur_k1 = 0;                                                \
+  const uint8_t *_mur_tail;                                            \
+  const uint32_t *_mur_blocks = (const uint32_t*)(_mur_data+_mur_nblocks*4); \
+  int _mur_i;                                                          \
+  for(_mur_i = -_mur_nblocks; _mur_i; _mur_i++) {                      \
+    _mur_k1 = MUR_GETBLOCK(_mur_blocks,_mur_i);                        \
+    _mur_k1 *= _mur_c1;                                                \
+    _mur_k1 = MUR_ROTL32(_mur_k1,15);                                  \
+    _mur_k1 *= _mur_c2;                                                \
+                                                                       \
+    _mur_h1 ^= _mur_k1;                                                \
+    _mur_h1 = MUR_ROTL32(_mur_h1,13);                                  \
+    _mur_h1 = _mur_h1*5+0xe6546b64;                                    \
+  }                                                                    \
+  _mur_tail = (const uint8_t*)(_mur_data + _mur_nblocks*4);            \
+  _mur_k1=0;                                                           \
+  switch((keylen) & 3) {                                               \
+    case 3: _mur_k1 ^= _mur_tail[2] << 16;                             \
+    case 2: _mur_k1 ^= _mur_tail[1] << 8;                              \
+    case 1: _mur_k1 ^= _mur_tail[0];                                   \
+    _mur_k1 *= _mur_c1;                                                \
+    _mur_k1 = MUR_ROTL32(_mur_k1,15);                                  \
+    _mur_k1 *= _mur_c2;                                                \
+    _mur_h1 ^= _mur_k1;                                                \
+  }                                                                    \
+  _mur_h1 ^= (keylen);                                                 \
+  MUR_FMIX(_mur_h1);                                                   \
+  hashv = _mur_h1;                                                     \
+  bkt = hashv & (num_bkts-1);                                          \
+} while(0)
+#endif  /* HASH_USING_NO_STRICT_ALIASING */
+
+/* key comparison function; return 0 if keys equal */
+#define HASH_KEYCMP(a,b,len) memcmp(a,b,len)
+
+/* iterate over items in a known bucket to find desired item */
+#define HASH_FIND_IN_BKT(tbl,hh,head,keyptr,keylen_in,out)                       \
+do {                                                                             \
+ if (head.hh_head) DECLTYPE_ASSIGN(out,ELMT_FROM_HH(tbl,head.hh_head));          \
+ else out=NULL;                                                                  \
+ while (out) {                                                                   \
+    if ((out)->hh.keylen == keylen_in) {                                           \
+        if ((HASH_KEYCMP((out)->hh.key,keyptr,keylen_in)) == 0) break;             \
+    }                                                                            \
+    if ((out)->hh.hh_next) DECLTYPE_ASSIGN(out,ELMT_FROM_HH(tbl,(out)->hh.hh_next)); \
+    else out = NULL;                                                             \
+ }                                                                               \
+} while(0)
+
+/* add an item to a bucket  */
+#define HASH_ADD_TO_BKT(head,addhh)                                              \
+do {                                                                             \
+ head.count++;                                                                   \
+ (addhh)->hh_next = head.hh_head;                                                \
+ (addhh)->hh_prev = NULL;                                                        \
+ if (head.hh_head) { (head).hh_head->hh_prev = (addhh); }                        \
+ (head).hh_head=addhh;                                                           \
+ if (head.count >= ((head.expand_mult+1) * HASH_BKT_CAPACITY_THRESH)             \
+     && (addhh)->tbl->noexpand != 1) {                                           \
+       HASH_EXPAND_BUCKETS((addhh)->tbl);                                        \
+ }                                                                               \
+} while(0)
+
+/* remove an item from a given bucket */
+#define HASH_DEL_IN_BKT(hh,head,hh_del)                                          \
+    (head).count--;                                                              \
+    if ((head).hh_head == hh_del) {                                              \
+      (head).hh_head = hh_del->hh_next;                                          \
+    }                                                                            \
+    if (hh_del->hh_prev) {                                                       \
+        hh_del->hh_prev->hh_next = hh_del->hh_next;                              \
+    }                                                                            \
+    if (hh_del->hh_next) {                                                       \
+        hh_del->hh_next->hh_prev = hh_del->hh_prev;                              \
+    }
+
+/* Bucket expansion has the effect of doubling the number of buckets
+ * and redistributing the items into the new buckets. Ideally the
+ * items will distribute more or less evenly into the new buckets
+ * (the extent to which this is true is a measure of the quality of
+ * the hash function as it applies to the key domain).
+ *
+ * With the items distributed into more buckets, the chain length
+ * (item count) in each bucket is reduced. Thus by expanding buckets
+ * the hash keeps a bound on the chain length. This bounded chain
+ * length is the essence of how a hash provides constant time lookup.
+ *
+ * The calculation of tbl->ideal_chain_maxlen below deserves some
+ * explanation. First, keep in mind that we're calculating the ideal
+ * maximum chain length based on the *new* (doubled) bucket count.
+ * In fractions this is just n/b (n=number of items,b=new num buckets).
+ * Since the ideal chain length is an integer, we want to calculate
+ * ceil(n/b). We don't depend on floating point arithmetic in this
+ * hash, so to calculate ceil(n/b) with integers we could write
+ *
+ *      ceil(n/b) = (n/b) + ((n%b)?1:0)
+ *
+ * and in fact a previous version of this hash did just that.
+ * But now we have improved things a bit by recognizing that b is
+ * always a power of two. We keep its base 2 log handy (call it lb),
+ * so now we can write this with a bit shift and logical AND:
+ *
+ *      ceil(n/b) = (n>>lb) + ( (n & (b-1)) ? 1:0)
+ *
+ */
+#define HASH_EXPAND_BUCKETS(tbl)                                                 \
+do {                                                                             \
+    unsigned _he_bkt;                                                            \
+    unsigned _he_bkt_i;                                                          \
+    struct UT_hash_handle *_he_thh, *_he_hh_nxt;                                 \
+    UT_hash_bucket *_he_new_buckets, *_he_newbkt;                                \
+    _he_new_buckets = (UT_hash_bucket*)uthash_malloc(                            \
+             2 * tbl->num_buckets * sizeof(struct UT_hash_bucket));              \
+    if (!_he_new_buckets) { uthash_fatal( "out of memory"); }                    \
+    memset(_he_new_buckets, 0,                                                   \
+            2 * tbl->num_buckets * sizeof(struct UT_hash_bucket));               \
+    tbl->ideal_chain_maxlen =                                                    \
+       (tbl->num_items >> (tbl->log2_num_buckets+1)) +                           \
+       ((tbl->num_items & ((tbl->num_buckets*2)-1)) ? 1 : 0);                    \
+    tbl->nonideal_items = 0;                                                     \
+    for(_he_bkt_i = 0; _he_bkt_i < tbl->num_buckets; _he_bkt_i++)                \
+    {                                                                            \
+        _he_thh = tbl->buckets[ _he_bkt_i ].hh_head;                             \
+        while (_he_thh) {                                                        \
+           _he_hh_nxt = _he_thh->hh_next;                                        \
+           HASH_TO_BKT( _he_thh->hashv, tbl->num_buckets*2, _he_bkt);            \
+           _he_newbkt = &(_he_new_buckets[ _he_bkt ]);                           \
+           if (++(_he_newbkt->count) > tbl->ideal_chain_maxlen) {                \
+             tbl->nonideal_items++;                                              \
+             _he_newbkt->expand_mult = _he_newbkt->count /                       \
+                                        tbl->ideal_chain_maxlen;                 \
+           }                                                                     \
+           _he_thh->hh_prev = NULL;                                              \
+           _he_thh->hh_next = _he_newbkt->hh_head;                               \
+           if (_he_newbkt->hh_head) _he_newbkt->hh_head->hh_prev =               \
+                _he_thh;                                                         \
+           _he_newbkt->hh_head = _he_thh;                                        \
+           _he_thh = _he_hh_nxt;                                                 \
+        }                                                                        \
+    }                                                                            \
+    uthash_free( tbl->buckets, tbl->num_buckets*sizeof(struct UT_hash_bucket) ); \
+    tbl->num_buckets *= 2;                                                       \
+    tbl->log2_num_buckets++;                                                     \
+    tbl->buckets = _he_new_buckets;                                              \
+    tbl->ineff_expands = (tbl->nonideal_items > (tbl->num_items >> 1)) ?         \
+        (tbl->ineff_expands+1) : 0;                                              \
+    if (tbl->ineff_expands > 1) {                                                \
+        tbl->noexpand=1;                                                         \
+        uthash_noexpand_fyi(tbl);                                                \
+    }                                                                            \
+    uthash_expand_fyi(tbl);                                                      \
+} while(0)
+
+
+/* This is an adaptation of Simon Tatham's O(n log(n)) mergesort */
+/* Note that HASH_SORT assumes the hash handle name to be hh.
+ * HASH_SRT was added to allow the hash handle name to be passed in. */
+#define HASH_SORT(head,cmpfcn) HASH_SRT(hh,head,cmpfcn)
+#define HASH_SRT(hh,head,cmpfcn)                                                 \
+do {                                                                             \
+  unsigned _hs_i;                                                                \
+  unsigned _hs_looping,_hs_nmerges,_hs_insize,_hs_psize,_hs_qsize;               \
+  struct UT_hash_handle *_hs_p, *_hs_q, *_hs_e, *_hs_list, *_hs_tail;            \
+  if (head) {                                                                    \
+      _hs_insize = 1;                                                            \
+      _hs_looping = 1;                                                           \
+      _hs_list = &((head)->hh);                                                  \
+      while (_hs_looping) {                                                      \
+          _hs_p = _hs_list;                                                      \
+          _hs_list = NULL;                                                       \
+          _hs_tail = NULL;                                                       \
+          _hs_nmerges = 0;                                                       \
+          while (_hs_p) {                                                        \
+              _hs_nmerges++;                                                     \
+              _hs_q = _hs_p;                                                     \
+              _hs_psize = 0;                                                     \
+              for ( _hs_i = 0; _hs_i  < _hs_insize; _hs_i++ ) {                  \
+                  _hs_psize++;                                                   \
+                  _hs_q = (UT_hash_handle*)((_hs_q->next) ?                      \
+                          ((void*)((char*)(_hs_q->next) +                        \
+                          (head)->hh.tbl->hho)) : NULL);                         \
+                  if (! (_hs_q) ) break;                                         \
+              }                                                                  \
+              _hs_qsize = _hs_insize;                                            \
+              while ((_hs_psize > 0) || ((_hs_qsize > 0) && _hs_q )) {           \
+                  if (_hs_psize == 0) {                                          \
+                      _hs_e = _hs_q;                                             \
+                      _hs_q = (UT_hash_handle*)((_hs_q->next) ?                  \
+                              ((void*)((char*)(_hs_q->next) +                    \
+                              (head)->hh.tbl->hho)) : NULL);                     \
+                      _hs_qsize--;                                               \
+                  } else if ( (_hs_qsize == 0) || !(_hs_q) ) {                   \
+                      _hs_e = _hs_p;                                             \
+                      _hs_p = (UT_hash_handle*)((_hs_p->next) ?                  \
+                              ((void*)((char*)(_hs_p->next) +                    \
+                              (head)->hh.tbl->hho)) : NULL);                     \
+                      _hs_psize--;                                               \
+                  } else if ((                                                   \
+                      cmpfcn(DECLTYPE(head)(ELMT_FROM_HH((head)->hh.tbl,_hs_p)), \
+                             DECLTYPE(head)(ELMT_FROM_HH((head)->hh.tbl,_hs_q))) \
+                             ) <= 0) {                                           \
+                      _hs_e = _hs_p;                                             \
+                      _hs_p = (UT_hash_handle*)((_hs_p->next) ?                  \
+                              ((void*)((char*)(_hs_p->next) +                    \
+                              (head)->hh.tbl->hho)) : NULL);                     \
+                      _hs_psize--;                                               \
+                  } else {                                                       \
+                      _hs_e = _hs_q;                                             \
+                      _hs_q = (UT_hash_handle*)((_hs_q->next) ?                  \
+                              ((void*)((char*)(_hs_q->next) +                    \
+                              (head)->hh.tbl->hho)) : NULL);                     \
+                      _hs_qsize--;                                               \
+                  }                                                              \
+                  if ( _hs_tail ) {                                              \
+                      _hs_tail->next = ((_hs_e) ?                                \
+                            ELMT_FROM_HH((head)->hh.tbl,_hs_e) : NULL);          \
+                  } else {                                                       \
+                      _hs_list = _hs_e;                                          \
+                  }                                                              \
+                  _hs_e->prev = ((_hs_tail) ?                                    \
+                     ELMT_FROM_HH((head)->hh.tbl,_hs_tail) : NULL);              \
+                  _hs_tail = _hs_e;                                              \
+              }                                                                  \
+              _hs_p = _hs_q;                                                     \
+          }                                                                      \
+          _hs_tail->next = NULL;                                                 \
+          if ( _hs_nmerges <= 1 ) {                                              \
+              _hs_looping=0;                                                     \
+              (head)->hh.tbl->tail = _hs_tail;                                   \
+              DECLTYPE_ASSIGN(head,ELMT_FROM_HH((head)->hh.tbl, _hs_list));      \
+          }                                                                      \
+          _hs_insize *= 2;                                                       \
+      }                                                                          \
+      HASH_FSCK(hh,head);                                                        \
+ }                                                                               \
+} while (0)
+
+/* This function selects items from one hash into another hash.
+ * The end result is that the selected items have dual presence
+ * in both hashes. There is no copy of the items made; rather
+ * they are added into the new hash through a secondary hash
+ * hash handle that must be present in the structure. */
+#define HASH_SELECT(hh_dst, dst, hh_src, src, cond)                              \
+do {                                                                             \
+  unsigned _src_bkt, _dst_bkt;                                                   \
+  void *_last_elt=NULL, *_elt;                                                   \
+  UT_hash_handle *_src_hh, *_dst_hh, *_last_elt_hh=NULL;                         \
+  ptrdiff_t _dst_hho = ((char*)(&(dst)->hh_dst) - (char*)(dst));                 \
+  if (src) {                                                                     \
+    for(_src_bkt=0; _src_bkt < (src)->hh_src.tbl->num_buckets; _src_bkt++) {     \
+      for(_src_hh = (src)->hh_src.tbl->buckets[_src_bkt].hh_head;                \
+          _src_hh;                                                               \
+          _src_hh = _src_hh->hh_next) {                                          \
+          _elt = ELMT_FROM_HH((src)->hh_src.tbl, _src_hh);                       \
+          if (cond(_elt)) {                                                      \
+            _dst_hh = (UT_hash_handle*)(((char*)_elt) + _dst_hho);               \
+            _dst_hh->key = _src_hh->key;                                         \
+            _dst_hh->keylen = _src_hh->keylen;                                   \
+            _dst_hh->hashv = _src_hh->hashv;                                     \
+            _dst_hh->prev = _last_elt;                                           \
+            _dst_hh->next = NULL;                                                \
+            if (_last_elt_hh) { _last_elt_hh->next = _elt; }                     \
+            if (!dst) {                                                          \
+              DECLTYPE_ASSIGN(dst,_elt);                                         \
+              HASH_MAKE_TABLE(hh_dst,dst);                                       \
+            } else {                                                             \
+              _dst_hh->tbl = (dst)->hh_dst.tbl;                                  \
+            }                                                                    \
+            HASH_TO_BKT(_dst_hh->hashv, _dst_hh->tbl->num_buckets, _dst_bkt);    \
+            HASH_ADD_TO_BKT(_dst_hh->tbl->buckets[_dst_bkt],_dst_hh);            \
+            (dst)->hh_dst.tbl->num_items++;                                      \
+            _last_elt = _elt;                                                    \
+            _last_elt_hh = _dst_hh;                                              \
+          }                                                                      \
+      }                                                                          \
+    }                                                                            \
+  }                                                                              \
+  HASH_FSCK(hh_dst,dst);                                                         \
+} while (0)
+
+#define HASH_CLEAR(hh,head)                                                      \
+do {                                                                             \
+  if (head) {                                                                    \
+    uthash_free((head)->hh.tbl->buckets,                                         \
+                (head)->hh.tbl->num_buckets*sizeof(struct UT_hash_bucket));      \
+    HASH_BLOOM_FREE((head)->hh.tbl);                                             \
+    uthash_free((head)->hh.tbl, sizeof(UT_hash_table));                          \
+    (head)=NULL;                                                                 \
+  }                                                                              \
+} while(0)
+
+#define HASH_OVERHEAD(hh,head)                                                   \
+ (size_t)((((head)->hh.tbl->num_items   * sizeof(UT_hash_handle))   +            \
+           ((head)->hh.tbl->num_buckets * sizeof(UT_hash_bucket))   +            \
+            (sizeof(UT_hash_table))                                 +            \
+            (HASH_BLOOM_BYTELEN)))
+
+#ifdef NO_DECLTYPE
+#define HASH_ITER(hh,head,el,tmp)                                                \
+for((el)=(head), (*(char**)(&(tmp)))=(char*)((head)?(head)->hh.next:NULL);       \
+  el; (el)=(tmp),(*(char**)(&(tmp)))=(char*)((tmp)?(tmp)->hh.next:NULL))
+#else
+#define HASH_ITER(hh,head,el,tmp)                                                \
+for((el)=(head),(tmp)=DECLTYPE(el)((head)?(head)->hh.next:NULL);                 \
+  el; (el)=(tmp),(tmp)=DECLTYPE(el)((tmp)?(tmp)->hh.next:NULL))
+#endif
+
+/* obtain a count of items in the hash */
+#define HASH_COUNT(head) HASH_CNT(hh,head)
+#define HASH_CNT(hh,head) ((head)?((head)->hh.tbl->num_items):0)
+
+typedef struct UT_hash_bucket {
+   struct UT_hash_handle *hh_head;
+   unsigned count;
+
+   /* expand_mult is normally set to 0. In this situation, the max chain length
+    * threshold is enforced at its default value, HASH_BKT_CAPACITY_THRESH. (If
+    * the bucket's chain exceeds this length, bucket expansion is triggered).
+    * However, setting expand_mult to a non-zero value delays bucket expansion
+    * (that would be triggered by additions to this particular bucket)
+    * until its chain length reaches a *multiple* of HASH_BKT_CAPACITY_THRESH.
+    * (The multiplier is simply expand_mult+1). The whole idea of this
+    * multiplier is to reduce bucket expansions, since they are expensive, in
+    * situations where we know that a particular bucket tends to be overused.
+    * It is better to let its chain length grow to a longer yet-still-bounded
+    * value, than to do an O(n) bucket expansion too often.
+    */
+   unsigned expand_mult;
+
+} UT_hash_bucket;
+
+/* random signature used only to find hash tables in external analysis */
+#define HASH_SIGNATURE 0xa0111fe1
+#define HASH_BLOOM_SIGNATURE 0xb12220f2
+
+typedef struct UT_hash_table {
+   UT_hash_bucket *buckets;
+   unsigned num_buckets, log2_num_buckets;
+   unsigned num_items;
+   struct UT_hash_handle *tail; /* tail hh in app order, for fast append    */
+   ptrdiff_t hho; /* hash handle offset (byte pos of hash handle in element */
+
+   /* in an ideal situation (all buckets used equally), no bucket would have
+    * more than ceil(#items/#buckets) items. that's the ideal chain length. */
+   unsigned ideal_chain_maxlen;
+
+   /* nonideal_items is the number of items in the hash whose chain position
+    * exceeds the ideal chain maxlen. these items pay the penalty for an uneven
+    * hash distribution; reaching them in a chain traversal takes >ideal steps */
+   unsigned nonideal_items;
+
+   /* ineffective expands occur when a bucket doubling was performed, but
+    * afterward, more than half the items in the hash had nonideal chain
+    * positions. If this happens on two consecutive expansions we inhibit any
+    * further expansion, as it's not helping; this happens when the hash
+    * function isn't a good fit for the key domain. When expansion is inhibited
+    * the hash will still work, albeit no longer in constant time. */
+   unsigned ineff_expands, noexpand;
+
+   uint32_t signature; /* used only to find hash tables in external analysis */
+#ifdef HASH_BLOOM
+   uint32_t bloom_sig; /* used only to test bloom exists in external analysis */
+   uint8_t *bloom_bv;
+   char bloom_nbits;
+#endif
+
+} UT_hash_table;
+
+typedef struct UT_hash_handle {
+   struct UT_hash_table *tbl;
+   void *prev;                       /* prev element in app order      */
+   void *next;                       /* next element in app order      */
+   struct UT_hash_handle *hh_prev;   /* previous hh in bucket order    */
+   struct UT_hash_handle *hh_next;   /* next hh in bucket order        */
+   void *key;                        /* ptr to enclosing struct's key  */
+   unsigned keylen;                  /* enclosing struct's key len     */
+   unsigned hashv;                   /* result of hash-fcn(key)        */
+} UT_hash_handle;
+
+#endif /* UTHASH_H */
diff --git a/extensions/test_acct/CMakeLists.txt b/extensions/test_acct/CMakeLists.txt
new file mode 100644
index 0000000..848255e
--- /dev/null
+++ b/extensions/test_acct/CMakeLists.txt
@@ -0,0 +1,13 @@
+# The test_acct extension
+PROJECT("Accounting dummy server" C)
+
+FD_ADD_EXTENSION(test_acct test_acct.c)
+
+
+####
+## INSTALL section ##
+
+INSTALL(TARGETS test_acct
+	LIBRARY DESTINATION ${INSTALL_EXTENSIONS_SUFFIX}
+	COMPONENT freeDiameter-debug-tools)
+
diff --git a/extensions/test_acct/test_acct.c b/extensions/test_acct/test_acct.c
new file mode 100644
index 0000000..7b648e5
--- /dev/null
+++ b/extensions/test_acct/test_acct.c
@@ -0,0 +1,145 @@
+/*********************************************************************************************************
+* Software License Agreement (BSD License)                                                               *
+* Author: Sebastien Decugis <sdecugis@freediameter.net>							 *
+*													 *
+* Copyright (c) 2013, WIDE Project and NICT								 *
+* All rights reserved.											 *
+* 													 *
+* Redistribution and use of this software in source and binary forms, with or without modification, are  *
+* permitted provided that the following conditions are met:						 *
+* 													 *
+* * Redistributions of source code must retain the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer.										 *
+*    													 *
+* * Redistributions in binary form must reproduce the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer in the documentation and/or other						 *
+*   materials provided with the distribution.								 *
+* 													 *
+* * Neither the name of the WIDE Project or NICT nor the 						 *
+*   names of its contributors may be used to endorse or 						 *
+*   promote products derived from this software without 						 *
+*   specific prior written permission of WIDE Project and 						 *
+*   NICT.												 *
+* 													 *
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED *
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
+* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR *
+* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 	 *
+* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 	 *
+* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR *
+* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF   *
+* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.								 *
+*********************************************************************************************************/
+
+/* This extension simply receives ACR and sends positive ACA after displaying the content, 
+but does not commit the data to any storage */
+
+#include <freeDiameter/extension.h>
+
+static struct {
+	struct dict_object * Accounting_Record_Number;
+	struct dict_object * Accounting_Record_Type;
+} tac_dict;
+	
+/* Callback for incoming Base Accounting application messages */
+static int tac_cb( struct msg ** msg, struct avp * avp, struct session * sess, void * data, enum disp_action * act)
+{
+	struct msg_hdr *hdr = NULL;
+	
+	TRACE_ENTRY("%p %p %p %p", msg, avp, sess, act);
+	
+	if (msg == NULL)
+		return EINVAL;
+	
+	/* Check what we received */
+	CHECK_FCT( fd_msg_hdr(*msg, &hdr) );
+	
+	if (hdr->msg_flags & CMD_FLAG_REQUEST) {
+		/* It was a request, create an answer */
+		struct msg *ans, *qry;
+		struct avp * a = NULL;
+		struct avp_hdr * h = NULL;
+		os0_t s;
+		size_t sl;
+	
+		qry = *msg;
+		/* Create the answer message, including the Session-Id AVP */
+		CHECK_FCT( fd_msg_new_answer_from_req ( fd_g_config->cnf_dict, msg, 0 ) );
+		ans = *msg;
+
+		/* Set the Origin-Host, Origin-Realm, Result-Code AVPs */
+		CHECK_FCT( fd_msg_rescode_set( ans, "DIAMETER_SUCCESS", NULL, NULL, 1 ) );
+		
+		fd_log_debug("--------------Received the following Accounting message:--------------");
+		
+		CHECK_FCT( fd_sess_getsid ( sess, &s, &sl ) );
+		fd_log_debug("Session: %.*s", (int)sl, s);
+		
+		/* The AVPs that we copy in the answer */
+		CHECK_FCT( fd_msg_search_avp ( qry, tac_dict.Accounting_Record_Type, &a) );
+		if (a) {
+			CHECK_FCT( fd_msg_avp_hdr( a, &h )  );
+			fd_log_debug("Accounting-Record-Type: %d (%s)", h->avp_value->u32, 
+						/* it would be better to search this in the dictionary, but it is only for debug, so ok */
+						(h->avp_value->u32 == 1) ? "EVENT_RECORD" : 
+						(h->avp_value->u32 == 2) ? "START_RECORD" : 
+						(h->avp_value->u32 == 3) ? "INTERIM_RECORD" : 
+						(h->avp_value->u32 == 4) ? "STOP_RECORD" : 
+						"<unknown value>"
+					);
+			CHECK_FCT( fd_msg_avp_new ( tac_dict.Accounting_Record_Type, 0, &a ) );
+			CHECK_FCT( fd_msg_avp_setvalue( a, h->avp_value ) );
+			CHECK_FCT( fd_msg_avp_add( ans, MSG_BRW_LAST_CHILD, a ) );
+		}
+		CHECK_FCT( fd_msg_search_avp ( qry, tac_dict.Accounting_Record_Number, &a) );
+		if (a) {
+			CHECK_FCT( fd_msg_avp_hdr( a, &h )  );
+			fd_log_debug("Accounting-Record-Number: %d", h->avp_value->u32);
+			CHECK_FCT( fd_msg_avp_new ( tac_dict.Accounting_Record_Number, 0, &a ) );
+			CHECK_FCT( fd_msg_avp_setvalue( a, h->avp_value ) );
+			CHECK_FCT( fd_msg_avp_add( ans, MSG_BRW_LAST_CHILD, a ) );
+		}
+		
+		/* We may also dump other data from the message, such as Accounting session Id, number of packets, ...  */
+
+		fd_log_debug("----------------------------------------------------------------------");
+		
+		/* Send the answer */
+		CHECK_FCT( fd_msg_send( msg, NULL, NULL ) );
+		
+	} else {
+		/* We received an answer message, just discard it */
+		CHECK_FCT( fd_msg_free( *msg ) );
+		*msg = NULL;
+	}
+	
+	return 0;
+}
+
+/* entry point: register handler for Base Accounting messages in the daemon */
+static int tac_entry(char * conffile)
+{
+	struct disp_when data;
+	
+	TRACE_ENTRY("%p", conffile);
+	
+	memset(&tac_dict, 0, sizeof(tac_dict));
+	memset(&data, 0, sizeof(data));
+	
+	/* Initialize the dictionary objects we use */
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_APPLICATION, APPLICATION_BY_NAME, "Diameter Base Accounting", &data.app, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Accounting-Record-Number", &tac_dict.Accounting_Record_Number, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Accounting-Record-Type", &tac_dict.Accounting_Record_Type, ENOENT) );
+	
+	/* Register the dispatch callback */
+	CHECK_FCT( fd_disp_register( tac_cb, DISP_HOW_APPID, &data, NULL, NULL ) );
+	
+	/* Advertise the support for the Diameter Base Accounting application in the peer */
+	CHECK_FCT( fd_disp_app_support ( data.app, NULL, 0, 1 ) );
+	
+	return 0;
+}
+
+EXTENSION_ENTRY("test_acct", tac_entry);
diff --git a/extensions/test_app/CMakeLists.txt b/extensions/test_app/CMakeLists.txt
new file mode 100644
index 0000000..7557445
--- /dev/null
+++ b/extensions/test_app/CMakeLists.txt
@@ -0,0 +1,31 @@
+# The test_app extension
+PROJECT("Test Diameter Application" C)
+
+# Parser files
+BISON_FILE(ta_conf.y)
+FLEX_FILE(ta_conf.l)
+SET_SOURCE_FILES_PROPERTIES(lex.ta_conf.c ta_conf.tab.c PROPERTIES COMPILE_FLAGS "-I ${CMAKE_CURRENT_SOURCE_DIR}")
+
+# List of source files
+SET( APP_TEST_SRC
+	test_app.h
+	test_app.c
+	lex.ta_conf.c
+	ta_conf.tab.c
+	ta_conf.tab.h
+	ta_dict.c
+	ta_cli.c
+	ta_bench.c
+	ta_serv.c
+)
+
+# Compile as a module
+FD_ADD_EXTENSION(test_app ${APP_TEST_SRC})
+
+
+####
+## INSTALL section ##
+
+INSTALL(TARGETS test_app
+	LIBRARY DESTINATION ${INSTALL_EXTENSIONS_SUFFIX}
+	COMPONENT freeDiameter-debug-tools)
diff --git a/extensions/test_app/ta_bench.c b/extensions/test_app/ta_bench.c
new file mode 100644
index 0000000..95aa246
--- /dev/null
+++ b/extensions/test_app/ta_bench.c
@@ -0,0 +1,336 @@
+/*********************************************************************************************************
+* Software License Agreement (BSD License)                                                               *
+* Author: Sebastien Decugis <sdecugis@freediameter.net>							 *
+*													 *
+* Copyright (c) 2015, WIDE Project and NICT								 *
+* All rights reserved.											 *
+* 													 *
+* Redistribution and use of this software in source and binary forms, with or without modification, are  *
+* permitted provided that the following conditions are met:						 *
+* 													 *
+* * Redistributions of source code must retain the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer.										 *
+*    													 *
+* * Redistributions in binary form must reproduce the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer in the documentation and/or other						 *
+*   materials provided with the distribution.								 *
+* 													 *
+* * Neither the name of the WIDE Project or NICT nor the 						 *
+*   names of its contributors may be used to endorse or 						 *
+*   promote products derived from this software without 						 *
+*   specific prior written permission of WIDE Project and 						 *
+*   NICT.												 *
+* 													 *
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED *
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
+* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR *
+* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 	 *
+* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 	 *
+* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR *
+* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF   *
+* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.								 *
+*********************************************************************************************************/
+
+/* Create and send a message, and receive it */
+
+#include "test_app.h"
+#include <stdio.h>
+
+#ifndef __APPLE__ /* they deprecated the semaphore there... */
+#include <semaphore.h>
+
+#define my_sem_t sem_t
+#define my_sem_init sem_init
+#define my_sem_destroy sem_destroy
+#define my_sem_timedwait sem_timedwait
+#define my_sem_post sem_post
+
+#else // on APPLE
+#include <sched.h>
+#include <dispatch/dispatch.h>
+
+#define my_sem_t dispatch_semaphore_t
+
+static int my_sem_init(my_sem_t * s, int pshared, unsigned int value ) {
+	*s = dispatch_semaphore_create(value);
+	if (*s == NULL)
+		return ENOMEM;
+	return 0;
+}
+
+static int my_sem_destroy(my_sem_t *s) {
+	dispatch_release(*s);
+	*s = NULL;
+	return 0;
+}
+
+static int my_sem_timedwait(my_sem_t * s, struct timespec *ts) {
+	struct timespec tsn;
+	int64_t nsec;
+	dispatch_time_t when;
+	
+	CHECK_SYS( clock_gettime(CLOCK_REALTIME, &tsn) );
+	
+	nsec = (ts->tv_sec * 1000000000) + ts->tv_nsec
+		- (tsn.tv_sec * 1000000000) - tsn.tv_nsec;
+	
+	when = dispatch_time (  DISPATCH_TIME_NOW, nsec );
+	
+	return dispatch_semaphore_wait ( *s, when ) ? ETIMEDOUT : 0;
+}
+
+static int my_sem_post(my_sem_t *s) {
+	dispatch_semaphore_signal(*s);
+	return 0;
+}
+
+#endif // APPLE
+
+
+
+struct ta_mess_info {
+	int32_t		randval;	/* a random value to store in Test-AVP */
+	struct timespec ts;		/* Time of sending the message */
+};
+
+static my_sem_t ta_sem; /* To handle the concurrency */
+
+/* Cb called when an answer is received */
+static void ta_cb_ans(void * data, struct msg ** msg)
+{
+	struct ta_mess_info * mi = (struct ta_mess_info *)data;
+	struct timespec ts;
+	struct avp * avp;
+	struct avp_hdr * hdr;
+	unsigned long dur;
+	
+	CHECK_SYS_DO( clock_gettime(CLOCK_REALTIME, &ts), return );
+
+	/* Value of Result Code */
+	CHECK_FCT_DO( fd_msg_search_avp ( *msg, ta_res_code, &avp), return );
+	if (avp) {
+		CHECK_FCT_DO( fd_msg_avp_hdr( avp, &hdr ), return );
+	}
+	if (!avp || !hdr || hdr->avp_value->i32 != 2001) {
+		/* error */
+		CHECK_POSIX_DO( pthread_mutex_lock(&ta_conf->stats_lock), );
+		ta_conf->stats.nb_errs++;
+		CHECK_POSIX_DO( pthread_mutex_unlock(&ta_conf->stats_lock), );
+		goto end;
+	}
+	
+	/* Check value of Test-AVP */
+	CHECK_FCT_DO( fd_msg_search_avp ( *msg, ta_avp, &avp), return );
+	if (avp) {
+		CHECK_FCT_DO( fd_msg_avp_hdr( avp, &hdr ), return );
+		ASSERT(hdr->avp_value->i32 == mi->randval);
+	}
+	
+	/* Compute how long it took */
+	dur = ((ts.tv_sec - mi->ts.tv_sec) * 1000000) + ((ts.tv_nsec - mi->ts.tv_nsec) / 1000);
+	
+	/* Add this value to the stats */
+	CHECK_POSIX_DO( pthread_mutex_lock(&ta_conf->stats_lock), );
+	
+	if (ta_conf->stats.nb_recv) {
+		/* Ponderate in the avg */
+		ta_conf->stats.avg = (ta_conf->stats.avg * ta_conf->stats.nb_recv + dur) / (ta_conf->stats.nb_recv + 1);
+		/* Min, max */
+		if (dur < ta_conf->stats.shortest)
+			ta_conf->stats.shortest = dur;
+		if (dur > ta_conf->stats.longest)
+			ta_conf->stats.longest = dur;
+	} else {
+		ta_conf->stats.shortest = dur;
+		ta_conf->stats.longest = dur;
+		ta_conf->stats.avg = dur;
+	}
+	ta_conf->stats.nb_recv++;
+	
+	CHECK_POSIX_DO( pthread_mutex_unlock(&ta_conf->stats_lock), );
+	
+end:	
+	/* Free the message */
+	CHECK_FCT_DO(fd_msg_free(*msg), );
+	*msg = NULL;
+	
+	free(mi);
+	
+	/* Post the semaphore */
+	CHECK_SYS_DO( my_sem_post(&ta_sem), );
+	
+	return;
+}
+
+/* Create a test message */
+static void ta_bench_test_message()
+{
+	struct msg * req = NULL;
+	struct avp * avp;
+	union avp_value val;
+	struct ta_mess_info * mi = NULL;
+	
+	TRACE_DEBUG(FULL, "Creating a new message for sending.");
+	
+	/* Create the request */
+	CHECK_FCT_DO( fd_msg_new( ta_cmd_r, MSGFL_ALLOC_ETEID, &req ), goto out );
+	
+	/* Create a new session */
+	#define TEST_APP_SID_OPT  "app_testb"
+	CHECK_FCT_DO( fd_msg_new_session( req, (os0_t)TEST_APP_SID_OPT, CONSTSTRLEN(TEST_APP_SID_OPT) ), goto out );
+	
+	/* Create the random value to store with the session */
+	mi = malloc(sizeof(struct ta_mess_info));
+	if (mi == NULL) {
+		fd_log_debug("malloc failed: %s", strerror(errno));
+		goto out;
+	}
+	
+	mi->randval = (int32_t)random();
+	
+	/* Now set all AVPs values */
+	
+	/* Set the Destination-Realm AVP */
+	{
+		CHECK_FCT_DO( fd_msg_avp_new ( ta_dest_realm, 0, &avp ), goto out  );
+		val.os.data = (unsigned char *)(ta_conf->dest_realm);
+		val.os.len  = strlen(ta_conf->dest_realm);
+		CHECK_FCT_DO( fd_msg_avp_setvalue( avp, &val ), goto out  );
+		CHECK_FCT_DO( fd_msg_avp_add( req, MSG_BRW_LAST_CHILD, avp ), goto out  );
+	}
+	
+	/* Set the Destination-Host AVP if needed*/
+	if (ta_conf->dest_host) {
+		CHECK_FCT_DO( fd_msg_avp_new ( ta_dest_host, 0, &avp ), goto out  );
+		val.os.data = (unsigned char *)(ta_conf->dest_host);
+		val.os.len  = strlen(ta_conf->dest_host);
+		CHECK_FCT_DO( fd_msg_avp_setvalue( avp, &val ), goto out  );
+		CHECK_FCT_DO( fd_msg_avp_add( req, MSG_BRW_LAST_CHILD, avp ), goto out  );
+	}
+	
+	/* Set Origin-Host & Origin-Realm */
+	CHECK_FCT_DO( fd_msg_add_origin ( req, 0 ), goto out  );
+	
+	/* Set the User-Name AVP if needed*/
+	if (ta_conf->user_name) {
+		CHECK_FCT_DO( fd_msg_avp_new ( ta_user_name, 0, &avp ), goto out  );
+		val.os.data = (unsigned char *)(ta_conf->user_name);
+		val.os.len  = strlen(ta_conf->user_name);
+		CHECK_FCT_DO( fd_msg_avp_setvalue( avp, &val ), goto out  );
+		CHECK_FCT_DO( fd_msg_avp_add( req, MSG_BRW_LAST_CHILD, avp ), goto out  );
+	}
+	
+	/* Set the Test-AVP AVP */
+	{
+		CHECK_FCT_DO( fd_msg_avp_new ( ta_avp, 0, &avp ), goto out  );
+		val.i32 = mi->randval;
+		CHECK_FCT_DO( fd_msg_avp_setvalue( avp, &val ), goto out  );
+		CHECK_FCT_DO( fd_msg_avp_add( req, MSG_BRW_LAST_CHILD, avp ), goto out  );
+	}
+	
+	CHECK_SYS_DO( clock_gettime(CLOCK_REALTIME, &mi->ts), goto out );
+	
+	/* Send the request */
+	CHECK_FCT_DO( fd_msg_send( &req, ta_cb_ans, mi ), goto out );
+	
+	/* Increment the counter */
+	CHECK_POSIX_DO( pthread_mutex_lock(&ta_conf->stats_lock), );
+	ta_conf->stats.nb_sent++;
+	CHECK_POSIX_DO( pthread_mutex_unlock(&ta_conf->stats_lock), );
+
+out:
+	return;
+}
+
+/* The function called when the signal is received */
+static void ta_bench_start() {
+	struct timespec end_time, now;
+	struct ta_stats start, end;
+	int nsec = 0;
+	
+	/* Save the initial stats */
+	CHECK_POSIX_DO( pthread_mutex_lock(&ta_conf->stats_lock), );
+	memcpy(&start, &ta_conf->stats, sizeof(struct ta_stats));
+	CHECK_POSIX_DO( pthread_mutex_unlock(&ta_conf->stats_lock), );
+	
+	/* We will run for ta_conf->bench_duration seconds */
+	LOG_N("Starting benchmark client, %ds", ta_conf->bench_duration);
+	CHECK_SYS_DO( clock_gettime(CLOCK_REALTIME, &end_time), );
+	end_time.tv_sec += ta_conf->bench_duration;
+	
+	/* Now loop until timeout is reached */
+	do {
+		/* Do not create more that NB_CONCURRENT_MESSAGES in paralel */
+		int ret = my_sem_timedwait(&ta_sem, &end_time);
+		if (ret == -1) {
+			ret = errno;
+			if (ret != ETIMEDOUT) {
+				CHECK_POSIX_DO(ret, ); /* Just to log it */
+			}
+			break;
+		}
+		
+		/* Update the current time */
+		CHECK_SYS_DO( clock_gettime(CLOCK_REALTIME, &now), );
+		
+		if (!TS_IS_INFERIOR(&now, &end_time))
+			break;
+		
+		/* Create and send a new test message */
+		ta_bench_test_message();
+	} while (1);
+	
+	do {
+		CHECK_POSIX_DO( pthread_mutex_lock(&ta_conf->stats_lock), );
+		CHECK_SYS_DO( clock_gettime(CLOCK_REALTIME, &now), ); /* Re-read the time because we might have spent some time wiating for the mutex */
+		memcpy(&end, &ta_conf->stats, sizeof(struct ta_stats));
+		CHECK_POSIX_DO( pthread_mutex_unlock(&ta_conf->stats_lock), );
+		
+		/* Now, display the statistics */
+		LOG_N( "------- app_test Benchmark results, end sending +%ds ---------", nsec);
+		if (now.tv_nsec >= end_time.tv_nsec) {
+			LOG_N( " Executing for: %d.%06ld sec",
+					(int)(now.tv_sec + ta_conf->bench_duration - end_time.tv_sec),
+					(long)(now.tv_nsec - end_time.tv_nsec) / 1000);
+		} else {
+			LOG_N( " Executing for: %d.%06ld sec",
+					(int)(now.tv_sec + ta_conf->bench_duration - 1 - end_time.tv_sec),
+					(long)(now.tv_nsec + 1000000000 - end_time.tv_nsec) / 1000);
+		}
+		LOG_N( "   %llu messages sent", end.nb_sent - start.nb_sent);
+		LOG_N( "   %llu error(s) received", end.nb_errs - start.nb_errs);
+		LOG_N( "   %llu answer(s) received", end.nb_recv - start.nb_recv);
+		LOG_N( "   Overall:");
+		LOG_N( "     fastest: %ld.%06ld sec.", end.shortest / 1000000, end.shortest % 1000000);
+		LOG_N( "     slowest: %ld.%06ld sec.", end.longest / 1000000, end.longest % 1000000);
+		LOG_N( "     Average: %ld.%06ld sec.", end.avg / 1000000, end.avg % 1000000);
+		LOG_N( "   Throughput: %llu messages / sec", (end.nb_recv - start.nb_recv) / (( now.tv_sec + ta_conf->bench_duration - end_time.tv_sec ) + ((now.tv_nsec - end_time.tv_nsec) / 1000000000)));
+		LOG_N( "-------------------------------------");
+		
+		nsec ++;
+		sleep(1);
+	} while ( (end.nb_sent - start.nb_sent) > (end.nb_errs - start.nb_errs) + (end.nb_recv - start.nb_recv) );
+	LOG_N( "--------------- Test Complete --------------");
+
+}
+
+
+int ta_bench_init(void)
+{
+	CHECK_SYS( my_sem_init( &ta_sem, 0, ta_conf->bench_concur) );
+
+	CHECK_FCT( fd_event_trig_regcb(ta_conf->signal, "test_app.bench", ta_bench_start ) );
+	
+	return 0;
+}
+
+void ta_bench_fini(void)
+{
+	// CHECK_FCT_DO( fd_sig_unregister(ta_conf->signal), /* continue */ );
+	
+	CHECK_SYS_DO( my_sem_destroy(&ta_sem), );
+	
+	return;
+};
diff --git a/extensions/test_app/ta_cli.c b/extensions/test_app/ta_cli.c
new file mode 100644
index 0000000..686338a
--- /dev/null
+++ b/extensions/test_app/ta_cli.c
@@ -0,0 +1,293 @@
+/*********************************************************************************************************
+* Software License Agreement (BSD License)                                                               *
+* Author: Sebastien Decugis <sdecugis@freediameter.net>							 *
+*													 *
+* Copyright (c) 2015, WIDE Project and NICT								 *
+* All rights reserved.											 *
+* 													 *
+* Redistribution and use of this software in source and binary forms, with or without modification, are  *
+* permitted provided that the following conditions are met:						 *
+* 													 *
+* * Redistributions of source code must retain the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer.										 *
+*    													 *
+* * Redistributions in binary form must reproduce the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer in the documentation and/or other						 *
+*   materials provided with the distribution.								 *
+* 													 *
+* * Neither the name of the WIDE Project or NICT nor the 						 *
+*   names of its contributors may be used to endorse or 						 *
+*   promote products derived from this software without 						 *
+*   specific prior written permission of WIDE Project and 						 *
+*   NICT.												 *
+* 													 *
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED *
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
+* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR *
+* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 	 *
+* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 	 *
+* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR *
+* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF   *
+* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.								 *
+*********************************************************************************************************/
+
+/* Create and send a message, and receive it */
+
+/* Note that we use both sessions and the argument to answer callback to pass the same value.
+ * This is just for the purpose of checking everything went OK.
+ */
+
+#include "test_app.h"
+
+#include <stdio.h>
+
+static struct session_handler * ta_cli_reg = NULL;
+
+struct sess_state {
+	int32_t		randval;	/* a random value to store in Test-AVP */
+	struct timespec ts;		/* Time of sending the message */
+} ;
+
+/* Cb called when an answer is received */
+static void ta_cb_ans(void * data, struct msg ** msg)
+{
+	struct sess_state * mi = NULL;
+	struct timespec ts;
+	struct session * sess;
+	struct avp * avp;
+	struct avp_hdr * hdr;
+	unsigned long dur;
+	int error = 0;
+	
+	CHECK_SYS_DO( clock_gettime(CLOCK_REALTIME, &ts), return );
+
+	/* Search the session, retrieve its data */
+	{
+		int new;
+		CHECK_FCT_DO( fd_msg_sess_get(fd_g_config->cnf_dict, *msg, &sess, &new), return );
+		ASSERT( new == 0 );
+		
+		CHECK_FCT_DO( fd_sess_state_retrieve( ta_cli_reg, sess, &mi ), return );
+		ASSERT( (void *)mi == data );
+	}
+	
+	/* Now log content of the answer */
+	fprintf(stderr, "RECV ");
+	
+	/* Value of Test-AVP */
+	CHECK_FCT_DO( fd_msg_search_avp ( *msg, ta_avp, &avp), return );
+	if (avp) {
+		CHECK_FCT_DO( fd_msg_avp_hdr( avp, &hdr ), return );
+		if (hdr->avp_value->i32 == mi->randval) {
+			fprintf(stderr, "%x (%s) ", hdr->avp_value->i32, "Ok");
+		} else {
+			fprintf(stderr, "%x (%s) ", hdr->avp_value->i32, "PROBLEM");
+			error++;
+		}
+	} else {
+		fprintf(stderr, "no_Test-AVP ");
+		error++;
+	}
+	
+	/* Value of Result Code */
+	CHECK_FCT_DO( fd_msg_search_avp ( *msg, ta_res_code, &avp), return );
+	if (avp) {
+		CHECK_FCT_DO( fd_msg_avp_hdr( avp, &hdr ), return );
+		fprintf(stderr, "Status: %d ", hdr->avp_value->i32);
+		if (hdr->avp_value->i32 != 2001)
+			error++;
+	} else {
+		fprintf(stderr, "no_Result-Code ");
+		error++;
+	}
+	
+	/* Value of Origin-Host */
+	CHECK_FCT_DO( fd_msg_search_avp ( *msg, ta_origin_host, &avp), return );
+	if (avp) {
+		CHECK_FCT_DO( fd_msg_avp_hdr( avp, &hdr ), return );
+		fprintf(stderr, "From '%.*s' ", (int)hdr->avp_value->os.len, hdr->avp_value->os.data);
+	} else {
+		fprintf(stderr, "no_Origin-Host ");
+		error++;
+	}
+	
+	/* Value of Origin-Realm */
+	CHECK_FCT_DO( fd_msg_search_avp ( *msg, ta_origin_realm, &avp), return );
+	if (avp) {
+		CHECK_FCT_DO( fd_msg_avp_hdr( avp, &hdr ), return );
+		fprintf(stderr, "('%.*s') ", (int)hdr->avp_value->os.len, hdr->avp_value->os.data);
+	} else {
+		fprintf(stderr, "no_Origin-Realm ");
+		error++;
+	}
+	
+	CHECK_POSIX_DO( pthread_mutex_lock(&ta_conf->stats_lock), );
+	dur = ((ts.tv_sec - mi->ts.tv_sec) * 1000000) + ((ts.tv_nsec - mi->ts.tv_nsec) / 1000);
+	if (ta_conf->stats.nb_recv) {
+		/* Ponderate in the avg */
+		ta_conf->stats.avg = (ta_conf->stats.avg * ta_conf->stats.nb_recv + dur) / (ta_conf->stats.nb_recv + 1);
+		/* Min, max */
+		if (dur < ta_conf->stats.shortest)
+			ta_conf->stats.shortest = dur;
+		if (dur > ta_conf->stats.longest)
+			ta_conf->stats.longest = dur;
+	} else {
+		ta_conf->stats.shortest = dur;
+		ta_conf->stats.longest = dur;
+		ta_conf->stats.avg = dur;
+	}
+	
+	if (error)
+		ta_conf->stats.nb_errs++;
+	else 
+		ta_conf->stats.nb_recv++;
+	
+	
+	CHECK_POSIX_DO( pthread_mutex_unlock(&ta_conf->stats_lock), );
+	
+	/* Display how long it took */
+	if (ts.tv_nsec > mi->ts.tv_nsec) {
+		fprintf(stderr, "in %d.%06ld sec", 
+				(int)(ts.tv_sec - mi->ts.tv_sec),
+				(long)(ts.tv_nsec - mi->ts.tv_nsec) / 1000);
+	} else {
+		fprintf(stderr, "in %d.%06ld sec", 
+				(int)(ts.tv_sec + 1 - mi->ts.tv_sec),
+				(long)(1000000000 + ts.tv_nsec - mi->ts.tv_nsec) / 1000);
+	}
+	fprintf(stderr, "\n");
+	fflush(stderr);
+	
+	/* Free the message */
+	CHECK_FCT_DO(fd_msg_free(*msg), return);
+	*msg = NULL;
+	
+	free(mi);
+	
+	return;
+}
+
+/* Create a test message */
+static void ta_cli_test_message()
+{
+	struct msg * req = NULL;
+	struct avp * avp;
+	union avp_value val;
+	struct sess_state * mi = NULL, *svg;
+	struct session *sess = NULL;
+	
+	TRACE_DEBUG(FULL, "Creating a new message for sending.");
+	
+	/* Create the request */
+	CHECK_FCT_DO( fd_msg_new( ta_cmd_r, MSGFL_ALLOC_ETEID, &req ), goto out );
+	
+	/* Create a new session */
+	#define TEST_APP_SID_OPT  "app_test"
+	CHECK_FCT_DO( fd_msg_new_session( req, (os0_t)TEST_APP_SID_OPT, CONSTSTRLEN(TEST_APP_SID_OPT) ), goto out );
+	CHECK_FCT_DO( fd_msg_sess_get(fd_g_config->cnf_dict, req, &sess, NULL), goto out );
+	
+	/* Create the random value to store with the session */
+	mi = malloc(sizeof(struct sess_state));
+	if (mi == NULL) {
+		fd_log_debug("malloc failed: %s", strerror(errno));
+		goto out;
+	}
+	
+	mi->randval = (int32_t)random();
+	
+	/* Now set all AVPs values */
+	
+	/* Set the Destination-Realm AVP */
+	{
+		CHECK_FCT_DO( fd_msg_avp_new ( ta_dest_realm, 0, &avp ), goto out  );
+		val.os.data = (unsigned char *)(ta_conf->dest_realm);
+		val.os.len  = strlen(ta_conf->dest_realm);
+		CHECK_FCT_DO( fd_msg_avp_setvalue( avp, &val ), goto out  );
+		CHECK_FCT_DO( fd_msg_avp_add( req, MSG_BRW_LAST_CHILD, avp ), goto out  );
+	}
+	
+	/* Set the Destination-Host AVP if needed*/
+	if (ta_conf->dest_host) {
+		CHECK_FCT_DO( fd_msg_avp_new ( ta_dest_host, 0, &avp ), goto out  );
+		val.os.data = (unsigned char *)(ta_conf->dest_host);
+		val.os.len  = strlen(ta_conf->dest_host);
+		CHECK_FCT_DO( fd_msg_avp_setvalue( avp, &val ), goto out  );
+		CHECK_FCT_DO( fd_msg_avp_add( req, MSG_BRW_LAST_CHILD, avp ), goto out  );
+	}
+	
+	/* Set Origin-Host & Origin-Realm */
+	CHECK_FCT_DO( fd_msg_add_origin ( req, 0 ), goto out  );
+	
+	/* Set the User-Name AVP if needed*/
+	if (ta_conf->user_name) {
+		CHECK_FCT_DO( fd_msg_avp_new ( ta_user_name, 0, &avp ), goto out  );
+		val.os.data = (unsigned char *)(ta_conf->user_name);
+		val.os.len  = strlen(ta_conf->user_name);
+		CHECK_FCT_DO( fd_msg_avp_setvalue( avp, &val ), goto out  );
+		CHECK_FCT_DO( fd_msg_avp_add( req, MSG_BRW_LAST_CHILD, avp ), goto out  );
+	}
+	
+	/* Set the Test-AVP AVP */
+	{
+		CHECK_FCT_DO( fd_msg_avp_new ( ta_avp, 0, &avp ), goto out  );
+		val.i32 = mi->randval;
+		CHECK_FCT_DO( fd_msg_avp_setvalue( avp, &val ), goto out  );
+		CHECK_FCT_DO( fd_msg_avp_add( req, MSG_BRW_LAST_CHILD, avp ), goto out  );
+	}
+	
+	/* Set the Test-Payload-AVP AVP */
+	if (ta_conf->long_avp_id) {
+		int l;
+		CHECK_FCT_DO( fd_msg_avp_new ( ta_avp_long, 0, &avp ), goto out  );
+		CHECK_MALLOC_DO( val.os.data = malloc(ta_conf->long_avp_len), goto out);
+		val.os.len = ta_conf->long_avp_len;
+		for (l=0; l < ta_conf->long_avp_len; l++)
+			val.os.data[l]=l;
+		CHECK_FCT_DO( fd_msg_avp_setvalue( avp, &val ), goto out  );
+		free(val.os.data);
+		CHECK_FCT_DO( fd_msg_avp_add( req, MSG_BRW_LAST_CHILD, avp ), goto out  );
+	}
+	
+	CHECK_SYS_DO( clock_gettime(CLOCK_REALTIME, &mi->ts), goto out );
+	
+	/* Keep a pointer to the session data for debug purpose, in real life we would not need it */
+	svg = mi;
+	
+	/* Store this value in the session */
+	CHECK_FCT_DO( fd_sess_state_store ( ta_cli_reg, sess, &mi ), goto out ); 
+	
+	/* Log sending the message */
+	fprintf(stderr, "SEND %x to '%s' (%s)\n", svg->randval, ta_conf->dest_realm, ta_conf->dest_host?:"-" );
+	fflush(stderr);
+	
+	/* Send the request */
+	CHECK_FCT_DO( fd_msg_send( &req, ta_cb_ans, svg ), goto out );
+
+	/* Increment the counter */
+	CHECK_POSIX_DO( pthread_mutex_lock(&ta_conf->stats_lock), );
+	ta_conf->stats.nb_sent++;
+	CHECK_POSIX_DO( pthread_mutex_unlock(&ta_conf->stats_lock), );
+
+out:
+	return;
+}
+
+int ta_cli_init(void)
+{
+	CHECK_FCT( fd_sess_handler_create(&ta_cli_reg, (void *)free, NULL, NULL) );
+	
+	CHECK_FCT( fd_event_trig_regcb(ta_conf->signal, "test_app.cli", ta_cli_test_message ) );
+	
+	return 0;
+}
+
+void ta_cli_fini(void)
+{
+	// CHECK_FCT_DO( fd_sig_unregister(ta_conf->signal), /* continue */ );
+	
+	CHECK_FCT_DO( fd_sess_handler_destroy(&ta_cli_reg, NULL), /* continue */ );
+	
+	return;
+};
diff --git a/extensions/test_app/ta_conf.l b/extensions/test_app/ta_conf.l
new file mode 100644
index 0000000..1bae950
--- /dev/null
+++ b/extensions/test_app/ta_conf.l
@@ -0,0 +1,177 @@
+/*********************************************************************************************************
+* Software License Agreement (BSD License)                                                               *
+* Author: Sebastien Decugis <sdecugis@freediameter.net>							 *
+*													 *
+* Copyright (c) 2013, WIDE Project and NICT								 *
+* All rights reserved.											 *
+* 													 *
+* Redistribution and use of this software in source and binary forms, with or without modification, are  *
+* permitted provided that the following conditions are met:						 *
+* 													 *
+* * Redistributions of source code must retain the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer.										 *
+*    													 *
+* * Redistributions in binary form must reproduce the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer in the documentation and/or other						 *
+*   materials provided with the distribution.								 *
+* 													 *
+* * Neither the name of the WIDE Project or NICT nor the 						 *
+*   names of its contributors may be used to endorse or 						 *
+*   promote products derived from this software without 						 *
+*   specific prior written permission of WIDE Project and 						 *
+*   NICT.												 *
+* 													 *
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED *
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
+* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR *
+* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 	 *
+* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 	 *
+* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR *
+* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF   *
+* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.								 *
+*********************************************************************************************************/
+
+/* Lex extension's configuration parser.
+ *
+ * The configuration file contains a default priority, and a list of peers with optional overwite priority.
+ * -- see the app_test.conf.sample file for more detail.
+ */
+
+%{
+#include "test_app.h"
+/* Include yacc tokens definitions */
+#include "ta_conf.tab.h"
+
+/* Update the column information */
+#define YY_USER_ACTION { 						\
+	yylloc->first_column = yylloc->last_column + 1; 		\
+	yylloc->last_column = yylloc->first_column + yyleng - 1;	\
+}
+
+/* Avoid warning with newer flex */
+#define YY_NO_INPUT
+
+%}
+
+%option bison-bridge bison-locations
+%option noyywrap
+%option nounput
+
+%%
+
+	/* Update the line count */
+\n			{
+				yylloc->first_line++; 
+				yylloc->last_line++; 
+				yylloc->last_column=0; 
+			}
+	 
+	/* Eat all spaces but not new lines */
+([[:space:]]{-}[\n])+	;
+	/* Eat all comments */
+#.*$			;
+
+	/* Recognize any integer */
+[-]?[[:digit:]]+		{
+				/* Convert this to an integer value */
+				int ret=0;
+				ret = sscanf(yytext, "%i", &yylval->integer);
+				if (ret != 1) {
+					/* No matching: an error occurred */
+					fd_log_debug("Unable to convert the value '%s' to a valid number: %s", yytext, strerror(errno));
+					return LEX_ERROR; /* trig an error in yacc parser */
+					/* Maybe we could REJECT instead of failing here? */
+				}
+				return INTEGER;
+			}
+
+	/* Recognize quoted strings -- we do not support escaped \" in the string currently. */
+\"[^\"]+\"		{
+				/* Match a quoted string. Let's be very permissive. */
+				yylval->string = strdup(yytext+1);
+				if (!yylval->string) {
+					fd_log_debug("Unable to copy the string '%s': %s", yytext, strerror(errno));
+					TRACE_DEBUG(INFO, "strdup failed");
+					return LEX_ERROR; /* trig an error in yacc parser */
+				}
+				yylval->string[strlen(yytext) - 2] = '\0';
+				return QSTRING;
+			}
+			
+	/* Recognize the tokens */	
+(?i:"vendor-id")	{
+				return VENDOR_ID;
+			}
+
+(?i:"appli-id")		{
+				return APPLI_ID;
+			}
+
+(?i:"cmd-id")		{
+				return CMD_ID;
+			}
+
+(?i:"avp-id")		{
+				return AVP_ID;
+			}
+
+(?i:"long-avp-id")	{
+				return LONG_AVP_ID;
+			}
+
+(?i:"long-avp-len")	{
+				return LONG_AVP_LEN;
+			}
+
+(?i:"mode")		{
+				return MODE;
+			}
+
+(?i:"server")		{
+				yylval->integer = MODE_SERV;
+				return INTEGER;
+			}
+
+(?i:"client")		{
+				yylval->integer = MODE_CLI;
+				return INTEGER;
+			}
+
+(?i:"both")		{
+				yylval->integer = MODE_SERV | MODE_CLI;
+				return INTEGER;
+			}
+
+(?i:"dest-realm")	{
+				return DEST_REALM;
+			}
+
+(?i:"dest-host")	{
+				return DEST_HOST;
+			}
+
+(?i:"user-name")	{
+				return USER_NAME;
+			}
+
+(?i:"Signal")		{
+				return SIGNAL;
+			}
+
+(?i:"Benchmark")	{
+				return BENCH;
+			}
+
+			
+	/* Valid single characters for yyparse */
+[=;]			{ return yytext[0]; }
+
+	/* Unrecognized sequence, if it did not match any previous pattern */
+[^[:space:]"*=>;\n]+	{ 
+				fd_log_debug("Unrecognized text on line %d col %d: '%s'.", yylloc->first_line, yylloc->first_column, yytext);
+			 	return LEX_ERROR; 
+			}
+
+%%
diff --git a/extensions/test_app/ta_conf.y b/extensions/test_app/ta_conf.y
new file mode 100644
index 0000000..52e3648
--- /dev/null
+++ b/extensions/test_app/ta_conf.y
@@ -0,0 +1,239 @@
+/*********************************************************************************************************
+* Software License Agreement (BSD License)                                                               *
+* Author: Sebastien Decugis <sdecugis@freediameter.net>							 *
+*													 *
+* Copyright (c) 2013, WIDE Project and NICT								 *
+* All rights reserved.											 *
+* 													 *
+* Redistribution and use of this software in source and binary forms, with or without modification, are  *
+* permitted provided that the following conditions are met:						 *
+* 													 *
+* * Redistributions of source code must retain the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer.										 *
+*    													 *
+* * Redistributions in binary form must reproduce the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer in the documentation and/or other						 *
+*   materials provided with the distribution.								 *
+* 													 *
+* * Neither the name of the WIDE Project or NICT nor the 						 *
+*   names of its contributors may be used to endorse or 						 *
+*   promote products derived from this software without 						 *
+*   specific prior written permission of WIDE Project and 						 *
+*   NICT.												 *
+* 													 *
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED *
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
+* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR *
+* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 	 *
+* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 	 *
+* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR *
+* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF   *
+* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.								 *
+*********************************************************************************************************/
+
+/* Yacc extension's configuration parser.
+ * See doc/app_test.conf.sample for configuration file format
+ */
+
+/* For development only : */
+%debug 
+%error-verbose
+
+/* The parser receives the configuration file filename as parameter */
+%parse-param {char * conffile}
+
+/* Keep track of location */
+%locations 
+%pure-parser
+
+%{
+#include "test_app.h"
+#include "ta_conf.tab.h"	/* bison is not smart enough to define the YYLTYPE before including this code, so... */
+
+#include <string.h>
+#include <errno.h>
+
+/* Forward declaration */
+int yyparse(char * conffile);
+
+/* Parse the configuration file */
+int ta_conf_handle(char * conffile)
+{
+	extern FILE * ta_confin;
+	int ret;
+	
+	TRACE_ENTRY("%p", conffile);
+	
+	TRACE_DEBUG (FULL, "Parsing configuration file: %s...", conffile);
+	
+	ta_confin = fopen(conffile, "r");
+	if (ta_confin == NULL) {
+		ret = errno;
+		fd_log_debug("Unable to open extension configuration file %s for reading: %s", conffile, strerror(ret));
+		TRACE_DEBUG (INFO, "Error occurred, message logged -- configuration file.");
+		return ret;
+	}
+
+	ret = yyparse(conffile);
+
+	fclose(ta_confin);
+
+	if (ret != 0) {
+		TRACE_DEBUG (INFO, "Unable to parse the configuration file.");
+		return EINVAL;
+	}
+	
+	return 0;
+}
+
+/* The Lex parser prototype */
+int ta_conflex(YYSTYPE *lvalp, YYLTYPE *llocp);
+
+/* Function to report the errors */
+void yyerror (YYLTYPE *ploc, char * conffile, char const *s)
+{
+	TRACE_DEBUG(INFO, "Error in configuration parsing");
+	
+	if (ploc->first_line != ploc->last_line)
+		fd_log_debug("%s:%d.%d-%d.%d : %s", conffile, ploc->first_line, ploc->first_column, ploc->last_line, ploc->last_column, s);
+	else if (ploc->first_column != ploc->last_column)
+		fd_log_debug("%s:%d.%d-%d : %s", conffile, ploc->first_line, ploc->first_column, ploc->last_column, s);
+	else
+		fd_log_debug("%s:%d.%d : %s", conffile, ploc->first_line, ploc->first_column, s);
+}
+
+%}
+
+/* Values returned by lex for token */
+%union {
+	char 		*string;	/* The string is allocated by strdup in lex.*/
+	int		 integer;	/* Store integer values */
+}
+
+/* In case of error in the lexical analysis */
+%token 		LEX_ERROR
+
+/* Key words */
+%token 		VENDOR_ID
+%token 		APPLI_ID
+%token 		CMD_ID
+%token 		AVP_ID
+%token 		LONG_AVP_ID
+%token 		LONG_AVP_LEN
+%token 		MODE
+%token 		DEST_REALM
+%token 		DEST_HOST
+%token 		USER_NAME
+%token 		SIGNAL
+%token		BENCH
+
+/* Tokens and types for routing table definition */
+/* A (de)quoted string (malloc'd in lex parser; it must be freed after use) */
+%token <string>	QSTRING
+
+/* An integer value */
+%token <integer> INTEGER
+
+
+
+/* -------------------------------------- */
+%%
+
+	/* The grammar definition */
+conffile:		/* empty grammar is OK */
+			| conffile vendor
+			| conffile appli
+			| conffile cmd
+			| conffile avp
+			| conffile long_avp_id
+			| conffile long_avp_len
+			| conffile mode
+			| conffile dstrealm
+			| conffile dsthost
+			| conffile usrname
+			| conffile signal
+			| conffile bench
+			;
+
+vendor:			VENDOR_ID '=' INTEGER ';'
+			{
+				ta_conf->vendor_id = $3;
+			}
+			;
+
+appli:			APPLI_ID '=' INTEGER ';'
+			{
+				ta_conf->appli_id = $3;
+			}
+			;
+
+cmd:			CMD_ID '=' INTEGER ';'
+			{
+				ta_conf->cmd_id = $3;
+			}
+			;
+
+avp:			AVP_ID '=' INTEGER ';'
+			{
+				ta_conf->avp_id = $3;
+			}
+			;
+
+long_avp_id:		LONG_AVP_ID '=' INTEGER ';'
+			{
+				ta_conf->long_avp_id = $3;
+			}
+			;
+
+long_avp_len:		LONG_AVP_LEN '=' INTEGER ';'
+			{
+				ta_conf->long_avp_len = $3;
+			}
+			;
+
+mode:			MODE '=' INTEGER ';'
+			{
+				ta_conf->mode = $3 | (ta_conf->mode & ~3); /* overwrite the 2 lsb */
+			}
+			;
+
+bench:			BENCH ';'
+			{
+				ta_conf->mode |= MODE_BENCH;
+			}
+			| BENCH INTEGER INTEGER ';'
+			{
+				ta_conf->mode |= MODE_BENCH;
+				ta_conf->bench_duration = $2;
+				ta_conf->bench_concur   = $3;
+			}
+			;
+
+dstrealm:		DEST_REALM '=' QSTRING ';'
+			{
+				free(ta_conf->dest_realm);
+				ta_conf->dest_realm = $3;
+			}
+			;
+
+dsthost:		DEST_HOST '=' QSTRING ';'
+			{
+				free(ta_conf->dest_host);
+				ta_conf->dest_host = $3;
+			}
+			;
+
+usrname:		USER_NAME '=' QSTRING ';'
+			{
+				free(ta_conf->user_name);
+				ta_conf->user_name = $3;
+			}
+			;
+
+signal:			SIGNAL '=' INTEGER ';'
+			{
+				ta_conf->signal = $3;
+			}
+			;
diff --git a/extensions/test_app/ta_dict.c b/extensions/test_app/ta_dict.c
new file mode 100644
index 0000000..2b9c6b3
--- /dev/null
+++ b/extensions/test_app/ta_dict.c
@@ -0,0 +1,166 @@
+/*********************************************************************************************************
+* Software License Agreement (BSD License)                                                               *
+* Author: Sebastien Decugis <sdecugis@freediameter.net>							 *
+*													 *
+* Copyright (c) 2013, WIDE Project and NICT								 *
+* All rights reserved.											 *
+* 													 *
+* Redistribution and use of this software in source and binary forms, with or without modification, are  *
+* permitted provided that the following conditions are met:						 *
+* 													 *
+* * Redistributions of source code must retain the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer.										 *
+*    													 *
+* * Redistributions in binary form must reproduce the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer in the documentation and/or other						 *
+*   materials provided with the distribution.								 *
+* 													 *
+* * Neither the name of the WIDE Project or NICT nor the 						 *
+*   names of its contributors may be used to endorse or 						 *
+*   promote products derived from this software without 						 *
+*   specific prior written permission of WIDE Project and 						 *
+*   NICT.												 *
+* 													 *
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED *
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
+* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR *
+* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 	 *
+* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 	 *
+* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR *
+* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF   *
+* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.								 *
+*********************************************************************************************************/
+
+/* Install the dictionary objects */
+
+#include "test_app.h"
+
+struct dict_object * ta_vendor = NULL;
+struct dict_object * ta_appli = NULL;
+struct dict_object * ta_cmd_r = NULL;
+struct dict_object * ta_cmd_a = NULL;
+struct dict_object * ta_avp = NULL;
+struct dict_object * ta_avp_long = NULL;
+
+struct dict_object * ta_sess_id = NULL;
+struct dict_object * ta_origin_host = NULL;
+struct dict_object * ta_origin_realm = NULL;
+struct dict_object * ta_dest_host = NULL;
+struct dict_object * ta_dest_realm = NULL;
+struct dict_object * ta_user_name = NULL;
+struct dict_object * ta_res_code = NULL;
+
+int ta_dict_init(void)
+{
+	TRACE_DEBUG(FULL, "Initializing the dictionary for test");
+	
+	/* Create the Test Vendor */
+	{
+		struct dict_vendor_data data;
+		data.vendor_id = ta_conf->vendor_id;
+		data.vendor_name = "app_test vendor";
+		CHECK_FCT(fd_dict_new( fd_g_config->cnf_dict, DICT_VENDOR, &data, NULL, &ta_vendor));
+	}
+	
+	/* Create the Test Application */
+	{
+		struct dict_application_data data;
+		data.application_id = ta_conf->appli_id;
+		data.application_name = "app_test application";
+		CHECK_FCT(fd_dict_new( fd_g_config->cnf_dict, DICT_APPLICATION, &data, ta_vendor, &ta_appli));
+	}
+	
+	/* Create the Test-Request & Test-Answer commands */
+	{
+		struct dict_cmd_data data;
+		data.cmd_code = ta_conf->cmd_id;
+		data.cmd_name = "Test-Request";
+		data.cmd_flag_mask = CMD_FLAG_PROXIABLE | CMD_FLAG_REQUEST;
+		data.cmd_flag_val  = CMD_FLAG_PROXIABLE | CMD_FLAG_REQUEST;
+		CHECK_FCT(fd_dict_new( fd_g_config->cnf_dict, DICT_COMMAND, &data, ta_appli, &ta_cmd_r));
+		data.cmd_name = "Test-Answer";
+		data.cmd_flag_val  = CMD_FLAG_PROXIABLE;
+		CHECK_FCT(fd_dict_new( fd_g_config->cnf_dict, DICT_COMMAND, &data, ta_appli, &ta_cmd_a));
+	}
+	
+	/* Create the Test AVP */
+	{
+		struct dict_avp_data data;
+		data.avp_code = ta_conf->avp_id;
+		data.avp_vendor = ta_conf->vendor_id;
+		data.avp_name = "Test-AVP";
+		data.avp_flag_mask = AVP_FLAG_VENDOR;
+		data.avp_flag_val = AVP_FLAG_VENDOR;
+		data.avp_basetype = AVP_TYPE_INTEGER32;
+		CHECK_FCT(fd_dict_new( fd_g_config->cnf_dict, DICT_AVP, &data, NULL, &ta_avp));
+	}
+	
+	/* Create the Test Payload AVP */
+	if (ta_conf->long_avp_id) {
+		struct dict_avp_data data;
+		data.avp_code = ta_conf->long_avp_id;
+		data.avp_vendor = ta_conf->vendor_id;
+		data.avp_name = "Test-Payload-AVP";
+		data.avp_flag_mask = AVP_FLAG_VENDOR;
+		data.avp_flag_val = AVP_FLAG_VENDOR;
+		data.avp_basetype = AVP_TYPE_OCTETSTRING;
+		CHECK_FCT(fd_dict_new( fd_g_config->cnf_dict, DICT_AVP, &data, NULL, &ta_avp_long));
+	}
+	
+	/* Now resolve some other useful AVPs */
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Session-Id", &ta_sess_id, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Origin-Host", &ta_origin_host, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Origin-Realm", &ta_origin_realm, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Destination-Host", &ta_dest_host, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Destination-Realm", &ta_dest_realm, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "User-Name", &ta_user_name, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Result-Code", &ta_res_code, ENOENT) );
+	
+	/* Create the rules for Test-Request and Test-Answer */
+	{
+		struct dict_rule_data data;
+		data.rule_min = 1;
+		data.rule_max = 1;
+		
+		/* Session-Id is in first position */
+		data.rule_avp = ta_sess_id;
+		data.rule_position = RULE_FIXED_HEAD;
+		data.rule_order = 1;
+		CHECK_FCT(fd_dict_new( fd_g_config->cnf_dict, DICT_RULE, &data, ta_cmd_r, NULL));
+		CHECK_FCT(fd_dict_new( fd_g_config->cnf_dict, DICT_RULE, &data, ta_cmd_a, NULL));
+		
+		data.rule_position = RULE_REQUIRED;
+		/* Test-AVP is mandatory */
+		data.rule_avp = ta_avp;
+		CHECK_FCT(fd_dict_new( fd_g_config->cnf_dict, DICT_RULE, &data, ta_cmd_r, NULL));
+		CHECK_FCT(fd_dict_new( fd_g_config->cnf_dict, DICT_RULE, &data, ta_cmd_a, NULL));
+		
+		/* idem for Origin Host and Realm */
+		data.rule_avp = ta_origin_host;
+		CHECK_FCT(fd_dict_new( fd_g_config->cnf_dict, DICT_RULE, &data, ta_cmd_r, NULL));
+		CHECK_FCT(fd_dict_new( fd_g_config->cnf_dict, DICT_RULE, &data, ta_cmd_a, NULL));
+		
+		data.rule_avp = ta_origin_realm;
+		CHECK_FCT(fd_dict_new( fd_g_config->cnf_dict, DICT_RULE, &data, ta_cmd_r, NULL));
+		CHECK_FCT(fd_dict_new( fd_g_config->cnf_dict, DICT_RULE, &data, ta_cmd_a, NULL));
+		
+		/* And Result-Code is mandatory for answers only */
+		data.rule_avp = ta_res_code;
+		CHECK_FCT(fd_dict_new( fd_g_config->cnf_dict, DICT_RULE, &data, ta_cmd_a, NULL));
+		
+		/* And Destination-Realm for requests only */
+		data.rule_avp = ta_dest_realm;
+		CHECK_FCT(fd_dict_new( fd_g_config->cnf_dict, DICT_RULE, &data, ta_cmd_r, NULL));
+		
+		/* And Destination-Host optional for requests only */
+		data.rule_position = RULE_OPTIONAL;
+		data.rule_min = 0;
+		data.rule_avp = ta_dest_host;
+		CHECK_FCT(fd_dict_new( fd_g_config->cnf_dict, DICT_RULE, &data, ta_cmd_r, NULL));
+		
+	}
+	
+	return 0;
+}
diff --git a/extensions/test_app/ta_serv.c b/extensions/test_app/ta_serv.c
new file mode 100644
index 0000000..848c9de
--- /dev/null
+++ b/extensions/test_app/ta_serv.c
@@ -0,0 +1,154 @@
+/*********************************************************************************************************
+* Software License Agreement (BSD License)                                                               *
+* Author: Sebastien Decugis <sdecugis@freediameter.net>							 *
+*													 *
+* Copyright (c) 2013, WIDE Project and NICT								 *
+* All rights reserved.											 *
+* 													 *
+* Redistribution and use of this software in source and binary forms, with or without modification, are  *
+* permitted provided that the following conditions are met:						 *
+* 													 *
+* * Redistributions of source code must retain the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer.										 *
+*    													 *
+* * Redistributions in binary form must reproduce the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer in the documentation and/or other						 *
+*   materials provided with the distribution.								 *
+* 													 *
+* * Neither the name of the WIDE Project or NICT nor the 						 *
+*   names of its contributors may be used to endorse or 						 *
+*   promote products derived from this software without 						 *
+*   specific prior written permission of WIDE Project and 						 *
+*   NICT.												 *
+* 													 *
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED *
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
+* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR *
+* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 	 *
+* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 	 *
+* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR *
+* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF   *
+* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.								 *
+*********************************************************************************************************/
+
+/* Install the dispatch callbacks */
+
+#include "test_app.h"
+
+static struct disp_hdl * ta_hdl_fb = NULL; /* handler for fallback cb */
+static struct disp_hdl * ta_hdl_tr = NULL; /* handler for Test-Request req cb */
+
+/* Default callback for the application. */
+static int ta_fb_cb( struct msg ** msg, struct avp * avp, struct session * sess, void * opaque, enum disp_action * act)
+{
+	/* This CB should never be called */
+	TRACE_ENTRY("%p %p %p %p", msg, avp, sess, act);
+	
+	fd_log_debug("Unexpected message received!");
+	
+	return ENOTSUP;
+}
+
+/* Callback for incoming Test-Request messages */
+static int ta_tr_cb( struct msg ** msg, struct avp * avp, struct session * sess, void * opaque, enum disp_action * act)
+{
+	struct msg *ans, *qry;
+	struct avp * a;
+	
+	TRACE_ENTRY("%p %p %p %p", msg, avp, sess, act);
+	
+	if (msg == NULL)
+		return EINVAL;
+	
+	/* Value of Origin-Host */
+	if (! (ta_conf->mode & MODE_BENCH)) {
+		fprintf(stderr, "ECHO Test-Request received from ");
+		CHECK_FCT( fd_msg_search_avp ( *msg, ta_origin_host, &a) );
+		if (a) {
+			struct avp_hdr * hdr;
+			CHECK_FCT( fd_msg_avp_hdr( a, &hdr ) );
+			fprintf(stderr, "'%.*s'", (int)hdr->avp_value->os.len, hdr->avp_value->os.data);
+		} else {
+			fprintf(stderr, "no_Origin-Host");
+		}
+		fprintf(stderr, ", replying...\n");
+	}
+	
+	/* Create answer header */
+	qry = *msg;
+	CHECK_FCT( fd_msg_new_answer_from_req ( fd_g_config->cnf_dict, msg, 0 ) );
+	ans = *msg;
+	
+	/* Set the Test-AVP AVP */
+	{
+		struct avp * src = NULL;
+		struct avp_hdr * hdr = NULL;
+		
+		CHECK_FCT( fd_msg_search_avp ( qry, ta_avp, &src) );
+		CHECK_FCT( fd_msg_avp_hdr( src, &hdr )  );
+		
+		CHECK_FCT( fd_msg_avp_new ( ta_avp, 0, &avp ) );
+		CHECK_FCT( fd_msg_avp_setvalue( avp, hdr->avp_value ) );
+		CHECK_FCT( fd_msg_avp_add( ans, MSG_BRW_LAST_CHILD, avp ) );
+	}
+	
+	/* Set the Test-Payload-AVP AVP */
+	if (ta_conf->long_avp_id) {
+		struct avp * src = NULL;
+		struct avp_hdr * hdr = NULL;
+		
+		CHECK_FCT( fd_msg_search_avp ( qry, ta_avp_long, &src) );
+		CHECK_FCT( fd_msg_avp_hdr( src, &hdr )  );
+		
+		CHECK_FCT( fd_msg_avp_new ( ta_avp_long, 0, &avp ) );
+		CHECK_FCT( fd_msg_avp_setvalue( avp, hdr->avp_value ) );
+		CHECK_FCT( fd_msg_avp_add( ans, MSG_BRW_LAST_CHILD, avp ) );
+	}
+	
+	
+	/* Set the Origin-Host, Origin-Realm, Result-Code AVPs */
+	CHECK_FCT( fd_msg_rescode_set( ans, "DIAMETER_SUCCESS", NULL, NULL, 1 ) );
+	
+	/* Send the answer */
+	CHECK_FCT( fd_msg_send( msg, NULL, NULL ) );
+	
+	/* Add this value to the stats */
+	CHECK_POSIX_DO( pthread_mutex_lock(&ta_conf->stats_lock), );
+	ta_conf->stats.nb_echoed++;
+	CHECK_POSIX_DO( pthread_mutex_unlock(&ta_conf->stats_lock), );
+	
+	return 0;
+}
+
+int ta_serv_init(void)
+{
+	struct disp_when data;
+	
+	TRACE_DEBUG(FULL, "Initializing dispatch callbacks for test");
+	
+	memset(&data, 0, sizeof(data));
+	data.app = ta_appli;
+	data.command = ta_cmd_r;
+	
+	/* fallback CB if command != Test-Request received */
+	CHECK_FCT( fd_disp_register( ta_fb_cb, DISP_HOW_APPID, &data, NULL, &ta_hdl_fb ) );
+	
+	/* Now specific handler for Test-Request */
+	CHECK_FCT( fd_disp_register( ta_tr_cb, DISP_HOW_CC, &data, NULL, &ta_hdl_tr ) );
+	
+	return 0;
+}
+
+void ta_serv_fini(void)
+{
+	if (ta_hdl_fb) {
+		(void) fd_disp_unregister(&ta_hdl_fb, NULL);
+	}
+	if (ta_hdl_tr) {
+		(void) fd_disp_unregister(&ta_hdl_tr, NULL);
+	}
+	
+	return;
+}
diff --git a/extensions/test_app/test_app.c b/extensions/test_app/test_app.c
new file mode 100644
index 0000000..a89f281
--- /dev/null
+++ b/extensions/test_app/test_app.c
@@ -0,0 +1,223 @@
+/*********************************************************************************************************
+* Software License Agreement (BSD License)                                                               *
+* Author: Sebastien Decugis <sdecugis@freediameter.net>							 *
+*													 *
+* Copyright (c) 2013, WIDE Project and NICT								 *
+* All rights reserved.											 *
+* 													 *
+* Redistribution and use of this software in source and binary forms, with or without modification, are  *
+* permitted provided that the following conditions are met:						 *
+* 													 *
+* * Redistributions of source code must retain the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer.										 *
+*    													 *
+* * Redistributions in binary form must reproduce the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer in the documentation and/or other						 *
+*   materials provided with the distribution.								 *
+* 													 *
+* * Neither the name of the WIDE Project or NICT nor the 						 *
+*   names of its contributors may be used to endorse or 						 *
+*   promote products derived from this software without 						 *
+*   specific prior written permission of WIDE Project and 						 *
+*   NICT.												 *
+* 													 *
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED *
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
+* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR *
+* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 	 *
+* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 	 *
+* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR *
+* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF   *
+* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.								 *
+*********************************************************************************************************/
+
+/* 
+ * Test application for freeDiameter.
+ */
+
+#include "test_app.h"
+
+/* Initialize the configuration */
+struct ta_conf * ta_conf = NULL;
+static struct ta_conf _conf;
+static pthread_t ta_stats_th = (pthread_t)NULL;
+
+static int ta_conf_init(void)
+{
+	ta_conf = &_conf;
+	memset(ta_conf, 0, sizeof(struct ta_conf));
+	
+	/* Set the default values */
+	ta_conf->vendor_id  = 999999;		/* Dummy value */
+	ta_conf->appli_id   = 0xffffff;	/* dummy value */
+	ta_conf->cmd_id     = 0xfffffe;	/* Experimental */
+	ta_conf->avp_id     = 0xffffff;	/* dummy value */
+	ta_conf->long_avp_len = 5000;
+	ta_conf->mode       = MODE_SERV | MODE_CLI;
+	ta_conf->dest_realm = strdup(fd_g_config->cnf_diamrlm);
+	ta_conf->dest_host  = NULL;
+	ta_conf->signal     = TEST_APP_DEFAULT_SIGNAL;
+	ta_conf->bench_concur   = 100;
+	ta_conf->bench_duration = 10;
+	
+	/* Initialize the mutex */
+	CHECK_POSIX( pthread_mutex_init(&ta_conf->stats_lock, NULL) );
+	
+	return 0;
+}
+
+static void ta_conf_dump(void)
+{
+	if (!TRACE_BOOL(INFO))
+		return;
+	fd_log_debug( "------- app_test configuration dump: ---------");
+	fd_log_debug( " Vendor Id .......... : %u", ta_conf->vendor_id);
+	fd_log_debug( " Application Id ..... : %u", ta_conf->appli_id);
+	fd_log_debug( " Command Id ......... : %u", ta_conf->cmd_id);
+	fd_log_debug( " AVP Id ............. : %u", ta_conf->avp_id);
+	fd_log_debug( " Long AVP Id ........ : %u", ta_conf->long_avp_id);
+	fd_log_debug( " Long AVP len ....... : %zu", ta_conf->long_avp_len);
+	fd_log_debug( " Mode ............... : %s%s%s", ta_conf->mode & MODE_SERV ? "Serv" : "", ta_conf->mode & MODE_CLI ? "Cli" : "",  ta_conf->mode & MODE_BENCH ? " (Benchmark)" : "");
+	fd_log_debug( " Destination Realm .. : %s", ta_conf->dest_realm ?: "- none -");
+	fd_log_debug( " Destination Host ... : %s", ta_conf->dest_host ?: "- none -");
+	fd_log_debug( " Signal ............. : %i", ta_conf->signal);
+	fd_log_debug( "------- /app_test configuration dump ---------");
+}
+
+/* Function to display statistics periodically */
+static void * ta_stats(void * arg) {
+
+	struct timespec start, now;
+	struct ta_stats copy;
+	
+	/* Get the start time */
+	CHECK_SYS_DO( clock_gettime(CLOCK_REALTIME, &start), );
+	
+	/* Now, loop until canceled */
+	while (1) {
+		/* Display statistics every XX seconds */
+		sleep(ta_conf->bench_duration + 3);
+		
+		/* Now, get the current stats */
+		CHECK_POSIX_DO( pthread_mutex_lock(&ta_conf->stats_lock), );
+		memcpy(&copy, &ta_conf->stats, sizeof(struct ta_stats));
+		CHECK_POSIX_DO( pthread_mutex_unlock(&ta_conf->stats_lock), );
+		
+		/* Get the current execution time */
+		CHECK_SYS_DO( clock_gettime(CLOCK_REALTIME, &now), );
+		
+		/* Now, display everything */
+		fd_log_debug( "------- app_test statistics ---------");
+		if (now.tv_nsec >= start.tv_nsec) {
+			fd_log_debug( " Executing for: %d.%06ld sec",
+					(int)(now.tv_sec - start.tv_sec),
+					(long)(now.tv_nsec - start.tv_nsec) / 1000);
+		} else {
+			fd_log_debug( " Executing for: %d.%06ld sec",
+					(int)(now.tv_sec - 1 - start.tv_sec),
+					(long)(now.tv_nsec + 1000000000 - start.tv_nsec) / 1000);
+		}
+		
+		if (ta_conf->mode & MODE_SERV) {
+			fd_log_debug( " Server: %llu message(s) echoed", copy.nb_echoed);
+		}
+		if (ta_conf->mode & MODE_CLI) {
+			fd_log_debug( " Client:");
+			fd_log_debug( "   %llu message(s) sent", copy.nb_sent);
+			fd_log_debug( "   %llu error(s) received", copy.nb_errs);
+			fd_log_debug( "   %llu answer(s) received", copy.nb_recv);
+			fd_log_debug( "     fastest: %ld.%06ld sec.", copy.shortest / 1000000, copy.shortest % 1000000);
+			fd_log_debug( "     slowest: %ld.%06ld sec.", copy.longest / 1000000, copy.longest % 1000000);
+			fd_log_debug( "     Average: %ld.%06ld sec.", copy.avg / 1000000, copy.avg % 1000000);
+		}
+		fd_log_debug( "-------------------------------------");
+	}
+	
+	return NULL; /* never called */
+}
+
+static struct fd_hook_hdl * hookhdl[2] = { NULL, NULL };
+static void ta_hook_cb_silent(enum fd_hook_type type, struct msg * msg, struct peer_hdr * peer, void * other, struct fd_hook_permsgdata *pmd, void * regdata) {
+}
+static void ta_hook_cb_oneline(enum fd_hook_type type, struct msg * msg, struct peer_hdr * peer, void * other, struct fd_hook_permsgdata *pmd, void * regdata) {
+	char * buf = NULL;
+	size_t len;
+	
+	CHECK_MALLOC_DO( fd_msg_dump_summary(&buf, &len, NULL, msg, NULL, 0, 0), 
+		{ LOG_E("Error while dumping a message"); return; } );
+	
+	LOG_N("{%d} %s: %s", type, (char *)other ?:"<nil>", buf ?:"<nil>");
+
+	free(buf);
+}
+
+
+/* entry point */
+static int ta_entry(char * conffile)
+{
+	TRACE_ENTRY("%p", conffile);
+	
+	/* Initialize configuration */
+	CHECK_FCT( ta_conf_init() );
+	
+	/* Parse configuration file */
+	if (conffile != NULL) {
+		CHECK_FCT( ta_conf_handle(conffile) );
+	}
+	
+	TRACE_DEBUG(INFO, "Extension Test_App initialized with configuration: '%s'", conffile);
+	ta_conf_dump();
+	
+	/* Install objects definitions for this test application */
+	CHECK_FCT( ta_dict_init() );
+	
+	/* Install the handlers for incoming messages */
+	if (ta_conf->mode & MODE_SERV) {
+		CHECK_FCT( ta_serv_init() );
+	}
+	
+	/* Start the signal handler thread */
+	if (ta_conf->mode & MODE_CLI) {
+		if (ta_conf->mode & MODE_BENCH) {
+			CHECK_FCT( ta_bench_init() );
+		} else {
+			CHECK_FCT( ta_cli_init() );
+		}
+	}
+	
+	/* Advertise the support for the test application in the peer */
+	CHECK_FCT( fd_disp_app_support ( ta_appli, ta_vendor, 1, 0 ) );
+	
+	if (ta_conf->mode & MODE_BENCH) {
+		/* Register an empty hook to disable the default handling */
+		CHECK_FCT( fd_hook_register( HOOK_MASK( HOOK_DATA_RECEIVED, HOOK_MESSAGE_RECEIVED, HOOK_MESSAGE_LOCAL, HOOK_MESSAGE_SENT, HOOK_MESSAGE_ROUTING_FORWARD, HOOK_MESSAGE_ROUTING_LOCAL ), 
+					ta_hook_cb_silent, NULL, NULL, &hookhdl[0]) );
+		CHECK_FCT( fd_hook_register( HOOK_MASK( HOOK_MESSAGE_ROUTING_ERROR, HOOK_MESSAGE_DROPPED ), 
+					ta_hook_cb_oneline, NULL, NULL, &hookhdl[1]) );
+		
+	}
+	
+	/* Start the statistics thread */
+	CHECK_POSIX( pthread_create(&ta_stats_th, NULL, ta_stats, NULL) );
+	
+	return 0;
+}
+
+/* Unload */
+void fd_ext_fini(void)
+{
+	if (ta_conf->mode & MODE_CLI)
+		ta_cli_fini();
+	if (ta_conf->mode & MODE_SERV)
+		ta_serv_fini();
+	if (hookhdl[0])
+		fd_hook_unregister( hookhdl[0] );
+	if (hookhdl[1])
+		fd_hook_unregister( hookhdl[1] );
+	CHECK_FCT_DO( fd_thr_term(&ta_stats_th), );
+	CHECK_POSIX_DO( pthread_mutex_destroy(&ta_conf->stats_lock), );
+}
+
+EXTENSION_ENTRY("test_app", ta_entry);
diff --git a/extensions/test_app/test_app.h b/extensions/test_app/test_app.h
new file mode 100644
index 0000000..8d01a45
--- /dev/null
+++ b/extensions/test_app/test_app.h
@@ -0,0 +1,117 @@
+/*********************************************************************************************************
+* Software License Agreement (BSD License)                                                               *
+* Author: Sebastien Decugis <sdecugis@freediameter.net>							 *
+*													 *
+* Copyright (c) 2013, WIDE Project and NICT								 *
+* All rights reserved.											 *
+* 													 *
+* Redistribution and use of this software in source and binary forms, with or without modification, are  *
+* permitted provided that the following conditions are met:						 *
+* 													 *
+* * Redistributions of source code must retain the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer.										 *
+*    													 *
+* * Redistributions in binary form must reproduce the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer in the documentation and/or other						 *
+*   materials provided with the distribution.								 *
+* 													 *
+* * Neither the name of the WIDE Project or NICT nor the 						 *
+*   names of its contributors may be used to endorse or 						 *
+*   promote products derived from this software without 						 *
+*   specific prior written permission of WIDE Project and 						 *
+*   NICT.												 *
+* 													 *
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED *
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
+* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR *
+* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 	 *
+* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 	 *
+* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR *
+* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF   *
+* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.								 *
+*********************************************************************************************************/
+
+/* Header file for the app_test extension. 
+ *
+ *  This extension provides a way to send configurable messages on the network
+ *
+ *  See the app_test.conf.sample file for the format of the configuration file.
+ */
+ 
+#include <freeDiameter/extension.h>
+#include <signal.h>
+
+#ifndef TEST_APP_DEFAULT_SIGNAL
+#define TEST_APP_DEFAULT_SIGNAL	SIGUSR1
+#endif /* TEST_APP_DEFAULT_SIGNAL */
+
+
+/* Mode for the extension */
+#define MODE_SERV	0x1
+#define	MODE_CLI	0x2
+#define	MODE_BENCH	0x4
+
+/* The module configuration */
+struct ta_conf {
+	uint32_t	vendor_id;	/* default 999999 */
+	uint32_t	appli_id;	/* default 123456 */
+	uint32_t	cmd_id;		/* default 234567 */
+	uint32_t	avp_id;		/* default 345678 */
+	uint32_t	long_avp_id;	/* default 0 */
+	size_t		long_avp_len;	/* default 5000 */
+	int		mode;		/* default MODE_SERV | MODE_CLI */
+	char 	*	dest_realm;	/* default local realm */
+	char 	*	dest_host;	/* default NULL */
+	char 	*	user_name;	/* default NULL */
+	int 		signal;		/* default TEST_APP_DEFAULT_SIGNAL */
+	int		bench_concur;	/* default 100 */
+	int		bench_duration; /* default 10 */
+	struct ta_stats {
+		unsigned long long	nb_echoed; /* server */
+		unsigned long long	nb_sent;   /* client */
+		unsigned long long	nb_recv;   /* client */
+		unsigned long long	nb_errs;   /* client */
+		unsigned long		shortest;  /* fastest answer, in microseconds */
+		unsigned long		longest;   /* slowest answer, in microseconds */
+		unsigned long		avg;       /* average answer time, in microseconds */
+	} stats;
+	pthread_mutex_t		stats_lock;
+};
+extern struct ta_conf * ta_conf;
+
+/* Parse the configuration file */
+int ta_conf_handle(char * conffile);
+
+/* Handle incoming messages (server) */
+int ta_serv_init(void);
+void ta_serv_fini(void);
+
+/* Create outgoing message (client) */
+int ta_cli_init(void);
+void ta_cli_fini(void);
+
+/* Benchmark flavour */
+int ta_bench_init(void);
+void ta_bench_fini(void);
+
+/* Initialize dictionary definitions */
+int ta_dict_init(void);
+
+
+/* Some global variables for dictionary */
+extern struct dict_object * ta_vendor;
+extern struct dict_object * ta_appli;
+extern struct dict_object * ta_cmd_r;
+extern struct dict_object * ta_cmd_a;
+extern struct dict_object * ta_avp;
+extern struct dict_object * ta_avp_long;
+
+extern struct dict_object * ta_sess_id;
+extern struct dict_object * ta_origin_host;
+extern struct dict_object * ta_origin_realm;
+extern struct dict_object * ta_dest_host;
+extern struct dict_object * ta_dest_realm;
+extern struct dict_object * ta_user_name;
+extern struct dict_object * ta_res_code;
diff --git a/extensions/test_netemul/CMakeLists.txt b/extensions/test_netemul/CMakeLists.txt
new file mode 100644
index 0000000..507e96a
--- /dev/null
+++ b/extensions/test_netemul/CMakeLists.txt
@@ -0,0 +1,43 @@
+# The test_netemul extension
+PROJECT("Simple Diameter network emulator proxy extension (latency, PDV, duplicates)" C)
+
+# Parser files
+BISON_FILE(test_netemul.y)
+FLEX_FILE(test_netemul.l)
+SET_SOURCE_FILES_PROPERTIES(lex.test_netemul.c test_netemul.tab.c PROPERTIES COMPILE_FLAGS "-I ${CMAKE_CURRENT_SOURCE_DIR}")
+
+# List of source files
+SET( TNEMUL_SRC
+	test_netemul.c
+	test_netemul.h
+	lex.test_netemul.c
+	test_netemul.tab.c
+	test_netemul.tab.h
+	tne_process.c
+)
+
+INCLUDE_DIRECTORIES(${CMAKE_CURRENT_BINARY_DIR})
+
+# Compile these files as a freeDiameter extension
+FD_ADD_EXTENSION(test_netemul ${TNEMUL_SRC})
+
+
+# math functions
+CHECK_FUNCTION_EXISTS (sqrt HAVE_SQRT)
+IF (HAVE_SQRT)
+   SET(MATH_LIBS "")
+ELSE (HAVE_SQRT)
+   CHECK_LIBRARY_EXISTS (m sqrt "" HAVE_LIBM)
+   IF (HAVE_LIBM)
+     SET(MATH_LIBS "-lm")
+   ENDIF (HAVE_LIBM)
+ENDIF (HAVE_SQRT)
+
+TARGET_LINK_LIBRARIES(test_netemul ${MATH_LIBS})
+
+####
+## INSTALL section ##
+
+INSTALL(TARGETS test_netemul
+	LIBRARY DESTINATION ${INSTALL_EXTENSIONS_SUFFIX}
+	COMPONENT freeDiameter-debug-tools)
diff --git a/extensions/test_netemul/test_netemul.c b/extensions/test_netemul/test_netemul.c
new file mode 100644
index 0000000..66fe610
--- /dev/null
+++ b/extensions/test_netemul/test_netemul.c
@@ -0,0 +1,106 @@
+/*********************************************************************************************************
+* Software License Agreement (BSD License)                                                               *
+* Author: Sebastien Decugis <sdecugis@freediameter.net>							 *
+*													 *
+* Copyright (c) 2011, WIDE Project and NICT								 *
+* All rights reserved.											 *
+* 													 *
+* Redistribution and use of this software in source and binary forms, with or without modification, are  *
+* permitted provided that the following conditions are met:						 *
+* 													 *
+* * Redistributions of source code must retain the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer.										 *
+*    													 *
+* * Redistributions in binary form must reproduce the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer in the documentation and/or other						 *
+*   materials provided with the distribution.								 *
+* 													 *
+* * Neither the name of the WIDE Project or NICT nor the 						 *
+*   names of its contributors may be used to endorse or 						 *
+*   promote products derived from this software without 						 *
+*   specific prior written permission of WIDE Project and 						 *
+*   NICT.												 *
+* 													 *
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED *
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
+* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR *
+* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 	 *
+* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 	 *
+* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR *
+* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF   *
+* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.								 *
+*********************************************************************************************************/
+
+/* 
+ * This extension provides a simple Diameter network emulator mechanism.
+ * It allows the introduction of delays and duplicates of Diameter messages.
+ * See test_netemul.conf.sample file for the format of the configuration file.
+ */
+
+#include "test_netemul.h"
+
+/* The configuration structure */
+struct tne_conf tne_conf;
+
+
+
+/* Proxying callback */
+static int tne_fwd_cb(void * cbdata, struct msg ** msg)
+{
+	struct msg * m;
+	
+	TRACE_ENTRY("%p %p", cbdata, msg);
+	
+	m = *msg;
+	*msg = NULL;
+	
+	TRACE_DEBUG(FULL, "[tne] Processing message %p", m);
+	CHECK_FCT( tne_process_message(m) );
+	
+	return 0;
+}
+
+
+static struct fd_rt_fwd_hdl * fwd_hdl = NULL;
+
+/* Register the callbacks to the daemon */
+static int tne_main(char * conffile)
+{
+	TRACE_ENTRY("%p", conffile);
+	
+	/* Initialize the configuration */
+	memset(&tne_conf, 0, sizeof(tne_conf));
+	tne_conf.lat_avg = 500;
+	tne_conf.lat_dev = 20;
+	tne_conf.dupl_proba = 1E-2;
+	
+	/* Parse the configuration file */
+	CHECK_FCT( tne_conf_handle(conffile) );
+	
+	/* Initialize the process module */
+	CHECK_FCT( tne_process_init() );
+	
+	/* Now, register the proxying callback */
+	CHECK_FCT( fd_rt_fwd_register ( tne_fwd_cb, NULL, RT_FWD_REQ, &fwd_hdl ) );
+
+	return 0;
+}
+
+/* Cleanup the callbacks */
+void fd_ext_fini(void)
+{
+	TRACE_ENTRY();
+	
+	/* Unregister the module */
+	CHECK_FCT_DO( fd_rt_fwd_unregister ( fwd_hdl, NULL ), /* continue */ );
+	
+	/* Destroy the process thread */
+	CHECK_FCT_DO( tne_process_fini (  ), /* continue */ );
+	
+	return ;
+}
+
+/* Define the entry point function */
+EXTENSION_ENTRY("test_netemul", tne_main);
diff --git a/extensions/test_netemul/test_netemul.h b/extensions/test_netemul/test_netemul.h
new file mode 100644
index 0000000..0d9d40b
--- /dev/null
+++ b/extensions/test_netemul/test_netemul.h
@@ -0,0 +1,56 @@
+/*********************************************************************************************************
+* Software License Agreement (BSD License)                                                               *
+* Author: Sebastien Decugis <sdecugis@freediameter.net>							 *
+*													 *
+* Copyright (c) 2011, WIDE Project and NICT								 *
+* All rights reserved.											 *
+* 													 *
+* Redistribution and use of this software in source and binary forms, with or without modification, are  *
+* permitted provided that the following conditions are met:						 *
+* 													 *
+* * Redistributions of source code must retain the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer.										 *
+*    													 *
+* * Redistributions in binary form must reproduce the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer in the documentation and/or other						 *
+*   materials provided with the distribution.								 *
+* 													 *
+* * Neither the name of the WIDE Project or NICT nor the 						 *
+*   names of its contributors may be used to endorse or 						 *
+*   promote products derived from this software without 						 *
+*   specific prior written permission of WIDE Project and 						 *
+*   NICT.												 *
+* 													 *
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED *
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
+* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR *
+* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 	 *
+* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 	 *
+* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR *
+* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF   *
+* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.								 *
+*********************************************************************************************************/
+
+/*
+ *  See the test_netemul.conf.sample file for the format of the configuration file.
+ */
+ 
+/* FreeDiameter's common include file */
+#include <freeDiameter/extension.h>
+
+/* Parse the configuration file */
+int tne_conf_handle(char * conffile);
+
+/* The configuration structure */
+extern struct tne_conf {
+	unsigned long  lat_avg; /* in milliseconds */
+	unsigned int   lat_dev; /* between 0 and 100 */
+	float          dupl_proba; 
+} tne_conf;
+
+/* Apply the configured process to the message, then send it. */
+int tne_process_message(struct msg * msg);
+int tne_process_init();
+int tne_process_fini();
diff --git a/extensions/test_netemul/test_netemul.l b/extensions/test_netemul/test_netemul.l
new file mode 100644
index 0000000..430e785
--- /dev/null
+++ b/extensions/test_netemul/test_netemul.l
@@ -0,0 +1,119 @@
+/*********************************************************************************************************
+* Software License Agreement (BSD License)                                                               *
+* Author: Sebastien Decugis <sdecugis@freediameter.net>							 *
+*													 *
+* Copyright (c) 2013, WIDE Project and NICT								 *
+* All rights reserved.											 *
+* 													 *
+* Redistribution and use of this software in source and binary forms, with or without modification, are  *
+* permitted provided that the following conditions are met:						 *
+* 													 *
+* * Redistributions of source code must retain the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer.										 *
+*    													 *
+* * Redistributions in binary form must reproduce the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer in the documentation and/or other						 *
+*   materials provided with the distribution.								 *
+* 													 *
+* * Neither the name of the WIDE Project or NICT nor the 						 *
+*   names of its contributors may be used to endorse or 						 *
+*   promote products derived from this software without 						 *
+*   specific prior written permission of WIDE Project and 						 *
+*   NICT.												 *
+* 													 *
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED *
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
+* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR *
+* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 	 *
+* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 	 *
+* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR *
+* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF   *
+* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.								 *
+*********************************************************************************************************/
+
+/* Tokenizer */
+
+%{
+#include "test_netemul.h"
+/* Include yacc tokens definitions */
+#include "test_netemul.tab.h"
+
+/* Update the column information */
+#define YY_USER_ACTION { 						\
+	yylloc->first_column = yylloc->last_column + 1; 		\
+	yylloc->last_column = yylloc->first_column + yyleng - 1;	\
+}
+
+/* Avoid warning with newer flex */
+#define YY_NO_INPUT
+
+%}
+
+%option bison-bridge bison-locations
+%option noyywrap
+%option nounput
+
+%%
+
+	/* Update the line count */
+\n			{
+				yylloc->first_line++; 
+				yylloc->last_line++; 
+				yylloc->last_column=0; 
+			}
+	 
+	/* Eat all spaces but not new lines */
+([[:space:]]{-}[\n])+	;
+	/* Eat all comments */
+#.*$			;
+
+
+	/* Recognize floats */
+[[:digit:]]+"."[[:digit:]]*	{
+				/* Convert this to an integer value */
+				int ret=0;
+				ret = sscanf(yytext, "%f", &yylval->decimal);
+				if (ret != 1) {
+					/* No matching: an error occurred */
+					fd_log_debug("Unable to convert the value '%s' to a valid float: %s", yytext, strerror(errno));
+					return LEX_ERROR; /* trig an error in yacc parser */
+					/* Maybe we could REJECT instead of failing here? */
+				}
+				return FLOAT;
+			}
+			
+	/* Recognize simple integers */
+[[:digit:]]+		{
+				/* Convert this to an integer value */
+				int ret=0;
+				ret = sscanf(yytext, "%lu", &yylval->ulong);
+				if (ret != 1) {
+					/* No matching: an error occurred */
+					fd_log_debug("Unable to convert the value '%s' to a valid long: %s", yytext, strerror(errno));
+					return LEX_ERROR; /* trig an error in yacc parser */
+					/* Maybe we could REJECT instead of failing here? */
+				}
+				return ULONG;
+			}
+			
+	
+	
+	/* The key words */	
+(?i:"latency_average")	 	{	return LATENCY_AVERAGE;		}
+(?i:"latency_deviation")	{	return LATENCY_DEVIATION;	}
+(?i:"dupl_proba")	 	{	return DUPL_PROBA;		}
+(?i:"ms")	 		{	return UNIT_MSEC;		}
+(?i:"s")	 		{	return UNIT_SEC;		}
+			
+	/* Valid single characters for yyparse */
+[=;%/]			{ return yytext[0]; }
+
+	/* Unrecognized sequence, if it did not match any previous pattern */
+[^[:space:][:digit:]=;%/\n]+	{ 
+				fd_log_debug("Unrecognized text on line %d col %d: '%s'.", yylloc->first_line, yylloc->first_column, yytext);
+			 	return LEX_ERROR; 
+			}
+
+%%
diff --git a/extensions/test_netemul/test_netemul.y b/extensions/test_netemul/test_netemul.y
new file mode 100644
index 0000000..222cf2e
--- /dev/null
+++ b/extensions/test_netemul/test_netemul.y
@@ -0,0 +1,171 @@
+/*********************************************************************************************************
+* Software License Agreement (BSD License)                                                               *
+* Author: Sebastien Decugis <sdecugis@freediameter.net>							 *
+*													 *
+* Copyright (c) 2013, WIDE Project and NICT								 *
+* All rights reserved.											 *
+* 													 *
+* Redistribution and use of this software in source and binary forms, with or without modification, are  *
+* permitted provided that the following conditions are met:						 *
+* 													 *
+* * Redistributions of source code must retain the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer.										 *
+*    													 *
+* * Redistributions in binary form must reproduce the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer in the documentation and/or other						 *
+*   materials provided with the distribution.								 *
+* 													 *
+* * Neither the name of the WIDE Project or NICT nor the 						 *
+*   names of its contributors may be used to endorse or 						 *
+*   promote products derived from this software without 						 *
+*   specific prior written permission of WIDE Project and 						 *
+*   NICT.												 *
+* 													 *
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED *
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
+* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR *
+* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 	 *
+* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 	 *
+* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR *
+* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF   *
+* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.								 *
+*********************************************************************************************************/
+
+/* Yacc extension's configuration parser.
+ */
+
+/* For development only : */
+%debug 
+%error-verbose
+
+/* The parser receives the configuration file filename as parameter */
+%parse-param {char * conffile}
+
+/* Keep track of location */
+%locations 
+%pure-parser
+
+%{
+#include "test_netemul.h"
+#include "test_netemul.tab.h"	/* YYLTYPE */
+
+/* Forward declaration */
+int yyparse(char * conffile);
+
+/* Parse the configuration file */
+int tne_conf_handle(char * conffile)
+{
+	extern FILE * test_netemulin;
+	int ret;
+	
+	TRACE_ENTRY("%p", conffile);
+	
+	TRACE_DEBUG (FULL, "Parsing configuration file: %s...", conffile);
+	
+	test_netemulin = fopen(conffile, "r");
+	if (test_netemulin == NULL) {
+		ret = errno;
+		fd_log_debug("Unable to open extension configuration file %s for reading: %s", conffile, strerror(ret));
+		TRACE_DEBUG (INFO, "Error occurred, message logged -- configuration file.");
+		return ret;
+	}
+
+	ret = yyparse(conffile);
+
+	fclose(test_netemulin);
+
+	if (ret != 0) {
+		TRACE_DEBUG (INFO, "Unable to parse the configuration file.");
+		return EINVAL;
+	} else {
+		TRACE_DEBUG(FULL, "[test_netemul]  latency: %lu ms (var:%u%%)  duplicates: %G probability.", tne_conf.lat_avg, tne_conf.lat_dev, tne_conf.dupl_proba);
+	}
+	
+	return 0;
+}
+
+/* The Lex parser prototype */
+int test_netemullex(YYSTYPE *lvalp, YYLTYPE *llocp);
+
+/* Function to report the errors */
+void yyerror (YYLTYPE *ploc, char * conffile, char const *s)
+{
+	TRACE_DEBUG(INFO, "Error in configuration parsing");
+	
+	if (ploc->first_line != ploc->last_line)
+		fd_log_debug("%s:%d.%d-%d.%d : %s", conffile, ploc->first_line, ploc->first_column, ploc->last_line, ploc->last_column, s);
+	else if (ploc->first_column != ploc->last_column)
+		fd_log_debug("%s:%d.%d-%d : %s", conffile, ploc->first_line, ploc->first_column, ploc->last_column, s);
+	else
+		fd_log_debug("%s:%d.%d : %s", conffile, ploc->first_line, ploc->first_column, s);
+}
+
+%}
+
+/* Values returned by lex for token */
+%union {
+	unsigned long	ulong;
+	float	decimal;
+}
+
+/* In case of error in the lexical analysis */
+%token 		LEX_ERROR
+
+%token <ulong>   ULONG
+%token <decimal> FLOAT
+
+/* Tokens */
+%token 		LATENCY_AVERAGE
+%token 		LATENCY_DEVIATION
+%token 		DUPL_PROBA
+%token 		UNIT_SEC
+%token 		UNIT_MSEC
+
+
+/* -------------------------------------- */
+%%
+
+	/* The grammar definition */
+conffile:		/* empty */
+			| conffile latency_average
+			| conffile latency_deviation
+			| conffile dupl_proba
+			;
+			
+	/* a server entry */
+latency_average:	LATENCY_AVERAGE '=' ULONG UNIT_SEC ';'
+			{
+				tne_conf.lat_avg = $3 * 1000;
+			}
+			|
+			LATENCY_AVERAGE '=' ULONG UNIT_MSEC ';'
+			{
+				tne_conf.lat_avg = $3;
+			}
+			;
+
+latency_deviation:	LATENCY_DEVIATION '=' ULONG '%' ';'
+			{
+				tne_conf.lat_dev = (int)$3;
+				if ((tne_conf.lat_dev < 0) || (tne_conf.lat_dev > 100)) {
+					yyerror (&yylloc, conffile, "Latency_Deviation must be comprised between 0 and 100.");
+					YYERROR;
+				}
+			}
+			;
+
+dupl_proba:		DUPL_PROBA '=' ULONG ';'
+			{
+				tne_conf.dupl_proba = (float) $3;
+			}
+			| DUPL_PROBA '=' FLOAT ';'
+			{
+				tne_conf.dupl_proba = $3;
+			}
+			| DUPL_PROBA '=' ULONG '/' ULONG ';'
+			{
+				tne_conf.dupl_proba = ((float)$3) / ((float)$5) ;
+			}
+			;
diff --git a/extensions/test_netemul/tne_process.c b/extensions/test_netemul/tne_process.c
new file mode 100644
index 0000000..1bff64c
--- /dev/null
+++ b/extensions/test_netemul/tne_process.c
@@ -0,0 +1,333 @@
+/*********************************************************************************************************
+* Software License Agreement (BSD License)                                                               *
+* Author: Sebastien Decugis <sdecugis@freediameter.net>							 *
+*													 *
+* Copyright (c) 2013, WIDE Project and NICT								 *
+* All rights reserved.											 *
+* 													 *
+* Redistribution and use of this software in source and binary forms, with or without modification, are  *
+* permitted provided that the following conditions are met:						 *
+* 													 *
+* * Redistributions of source code must retain the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer.										 *
+*    													 *
+* * Redistributions in binary form must reproduce the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer in the documentation and/or other						 *
+*   materials provided with the distribution.								 *
+* 													 *
+* * Neither the name of the WIDE Project or NICT nor the 						 *
+*   names of its contributors may be used to endorse or 						 *
+*   promote products derived from this software without 						 *
+*   specific prior written permission of WIDE Project and 						 *
+*   NICT.												 *
+* 													 *
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED *
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
+* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR *
+* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 	 *
+* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 	 *
+* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR *
+* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF   *
+* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.								 *
+*********************************************************************************************************/
+
+#include "test_netemul.h"
+#include <math.h>
+
+/* This file implements the real processing of the message.
+ The entry point is tne_process_message().
+ 
+ First, the duplicate filter is applied: with the configured
+ probability, a copy of the message is created. Then, with 
+ the tenth probability, a second copy is created, and so on,
+ until the random value tells not to create a copy.
+ 
+ The original message + all copies are stored in a list, for next step.
+ 
+ Second step is the latency filter. For each message in the list, a
+ latency value is randomly generated (with a lognormal shape of the 
+ random distribution) and stored in the list.
+ 
+ Finally, when the latency time is over, the message is sent.
+ */
+
+static pthread_mutex_t mtx = PTHREAD_MUTEX_INITIALIZER;
+static pthread_cond_t  cnd = PTHREAD_COND_INITIALIZER;
+static pthread_t       thr = (pthread_t)NULL;
+
+/* The lists below are all protected by the same mutex mtx */
+static struct fd_list input = FD_LIST_INITIALIZER(input); /* messages received from network */
+static struct fd_list forlat = FD_LIST_INITIALIZER(forlat); /* messages after duplicate filter */
+static struct fd_list waitlist = FD_LIST_INITIALIZER(waitlist); /* messages waiting for sending */
+
+struct process_item {
+	struct fd_list chain; /* link into one of the lists. "o" points to the message. */
+	struct timespec ts; /* when the message must be sent */
+};
+
+/******************************************************************/
+/* helper functions */
+
+/* Process all pi in input list and queue in forlat, duplicating when needed */
+static int do_duplicates()
+{
+	TRACE_ENTRY("");
+	
+	while (!FD_IS_LIST_EMPTY(&input)) {
+		struct msg * m;
+		struct process_item * pi = (struct process_item *)(input.next);
+		
+		/* Take out this pi from input */
+		fd_list_unlink(&pi->chain);
+		
+		/* store it in forlat */
+		fd_list_insert_before(&forlat, &pi->chain);
+		
+		/* Duplicate eventually, unless deactivated */
+		if (tne_conf.dupl_proba != 0.0) {
+			DiamId_t src;
+			size_t srclen;
+			/* Pick a random value in [0, 1] */
+			double my_rand = drand48();
+			m = pi->chain.o;
+			CHECK_FCT( fd_msg_source_get(m, &src, &srclen) );
+			
+			while (my_rand < (double) tne_conf.dupl_proba) {
+				/* create the duplicate */
+				struct process_item * npi;
+				struct msg * nm;
+				struct msg_hdr * nh;
+				unsigned char * buf;
+				size_t len;
+				
+				/* Duplicate the message */
+				CHECK_FCT( fd_msg_bufferize(m, &buf, &len) );
+				CHECK_FCT( fd_msg_parse_buffer(&buf, len, &nm) );
+				CHECK_FCT( fd_msg_source_set(nm, src, srclen) );
+				CHECK_FCT( fd_msg_hdr(nm, &nh) );
+				nh->msg_flags |= CMD_FLAG_RETRANSMIT; /* Add the 'T' flag */
+				TRACE_DEBUG(FULL, "[tne] Duplicated message %p as %p", m, nm);
+				
+				/* Duplicate the pi */
+				CHECK_MALLOC( npi = malloc(sizeof(struct process_item)) );
+				memset(npi, 0, sizeof(struct process_item));
+				fd_list_init(&npi->chain, nm);
+				memcpy(&npi->ts, &pi->ts, sizeof(struct timespec));
+				
+				/* Enqueue the candidate in forlat */
+				fd_list_insert_before(&forlat, &npi->chain);
+				
+				/* loop for another duplicate */
+				if (!my_rand)
+					break; /* otherwise, infinite loop */
+				my_rand *= 10.0;
+			}
+		}
+	}
+	
+	/* Done */
+	return 0;
+}
+
+/* Generate a random value with a normal distribution, mean 0, variance 1 */
+/* Using Box-Muller algo from Numerical Recipes in C++, 2nd Ed. */
+static double get_rand_norm()
+{
+	double ru1, ru2; /* two random uniform values in -1..1 */
+	double rsq;      /* ru1^2 + ru2^2, to ensure we are in the circle */
+	
+	/* Get our appropriate 2 random uniform values */
+	do {
+		ru1 = 2.0 * drand48() - 1.0;
+		ru2 = 2.0 * drand48() - 1.0;
+		rsq = ru1 * ru1 + ru2 * ru2;
+	} while ((rsq >= 1.0) || (rsq == 0.0));
+	
+	/* Do the Box-Muller transform -- we don't use the 2nd value generated */
+	return ru1 * sqrt( -2.0 * log(rsq) / rsq );
+}
+
+/* Return the latency to add, in ms. */
+static __inline__ unsigned long get_latency()
+{
+	unsigned long lat = tne_conf.lat_avg;
+
+	if (tne_conf.lat_dev) {
+		/* We randomize the value to add */
+		double rn;
+
+		rn = get_rand_norm(); /* this is normal random value with mean = 0 and variance = 1 */
+		rn = rn * ((double)tne_conf.lat_dev) / 100.0; /* now the variance is lat_dev */
+		rn = exp(rn); /* and now, we have a lognormal random value, with geometric mean = 1 */
+
+		lat = (unsigned long)(rn * (double)lat); /* Apply to our mean latency */
+	}
+	
+	return lat;
+}
+			
+/* Process all pi in forlat and add a random latency, then requeue in order into waitlist */
+static int do_latency()
+{
+	TRACE_ENTRY("");
+	
+	while (!FD_IS_LIST_EMPTY(&forlat)) {
+		struct process_item * pi = (struct process_item *)(forlat.next);
+		struct fd_list * li;
+		
+		/* Take out this pi from forlat */
+		fd_list_unlink(&pi->chain);
+		
+		/* If there is a latency to add */
+		if (tne_conf.lat_avg) {
+			unsigned long l = get_latency();
+			TRACE_DEBUG(FULL, "[tne] Set %lu ms latency for %p", l, pi->chain.o);
+			pi->ts.tv_sec += l / 1000;
+			l %= 1000;
+			pi->ts.tv_nsec += l * 1000000;
+			if (pi->ts.tv_nsec >= 1000000000) {
+				pi->ts.tv_sec += 1;
+				pi->ts.tv_nsec -= 1000000000;
+			}
+		}
+
+		for (li = waitlist.prev; li != &waitlist; li=li->prev) {
+			struct process_item * p = (struct process_item *)li;
+			if (TS_IS_INFERIOR( &p->ts, &pi->ts ))
+				break; /* we must insert after this one */
+		}
+		
+		/* store it */
+		fd_list_insert_after(li, &pi->chain);
+	}
+	
+	/* Done */
+	return 0;
+}
+
+/* Send all messages in waitlist that have passed their latency period */
+static int send_all_ready()
+{
+	struct timespec now;
+	
+	TRACE_ENTRY("");
+	
+	CHECK_SYS( clock_gettime(CLOCK_REALTIME, &now) );
+	
+	while (!FD_IS_LIST_EMPTY(&waitlist)) {
+		struct msg * m;
+		struct process_item * pi = (struct process_item *)(waitlist.next);
+		
+		if (!TS_IS_INFERIOR( &pi->ts, &now))
+			break; /* We sent already all we could */
+		
+		/* Take out this pi and send the message */
+		fd_list_unlink(&pi->chain);
+		m = pi->chain.o;
+		free(pi);
+		
+		TRACE_DEBUG(FULL, "[tne] Sending now %p", m);
+		CHECK_FCT( fd_msg_send(&m, NULL, NULL) );
+	}
+	
+	return 0;
+
+}
+
+
+/******************************************************************/
+/* the processing thread */
+static void * tne_process_th(void * arg) 
+{
+	TRACE_ENTRY("%p", arg);
+	
+	/* Name the thread */
+	fd_log_threadname ( "test_netemul/process" );
+	
+	CHECK_POSIX_DO( pthread_mutex_lock(&mtx), goto error );
+	pthread_cleanup_push( fd_cleanup_mutex, &mtx );
+	
+	/* The loop */
+	while (1) {
+		/* First, test if we are canceled */
+		pthread_testcancel();
+		
+		/* Send all messages that are ready (free resources before using new ones) */
+		CHECK_FCT_DO( send_all_ready(), break );
+		
+		/* Now process the new messages in input list for duplicate filter */
+		CHECK_FCT_DO( do_duplicates(), break );
+		
+		/* Now compute the latency for each new item */
+		CHECK_FCT_DO( do_latency(), break );
+		
+		/* Now, wait then loop */
+		if (FD_IS_LIST_EMPTY(&waitlist)) {
+			CHECK_POSIX_DO( pthread_cond_wait(&cnd, &mtx), break );
+		} else {
+			CHECK_POSIX_DO2( pthread_cond_timedwait(&cnd, &mtx, &((struct process_item *)(waitlist.next))->ts), 
+				ETIMEDOUT, /* ETIMEDOUT is a normal return value, continue */,
+					/* on other error, */ break );
+		}
+		
+		/* loop */
+	}
+
+	pthread_cleanup_pop( 0 );
+	CHECK_POSIX_DO( pthread_mutex_unlock(&mtx),  );
+error:
+	TRACE_DEBUG(INFO, "A fatal error occurred in test_netemul/process thread!");
+	ASSERT(0);
+	CHECK_FCT_DO(fd_core_shutdown(), );
+	return NULL;
+}
+
+/******************************************************************/
+/* functions visible from outside this file */
+int tne_process_init() 
+{
+	CHECK_POSIX( pthread_create(&thr, NULL, tne_process_th, NULL) );
+	
+	#if 0 /* debug */
+	int i;
+	for (i=0; i< 20; i++) {
+		printf("LAT: %lu\n", get_latency()); 
+	}
+	#endif /* 0 */
+	
+	return 0;
+}
+
+
+int tne_process_fini() 
+{
+	CHECK_FCT( fd_thr_term(&thr) );
+	return 0;
+}
+
+
+int tne_process_message(struct msg * msg) 
+{
+	struct process_item * pi;
+	
+	TRACE_ENTRY("%p", msg);
+	
+	/* Create a new pi for this message */
+	CHECK_MALLOC( pi = malloc(sizeof(struct process_item)) );
+	memset(pi, 0, sizeof(struct process_item));
+	fd_list_init(&pi->chain, msg);
+	CHECK_SYS(clock_gettime(CLOCK_REALTIME, &pi->ts));
+	
+	/* Store it in the input list */
+	CHECK_POSIX( pthread_mutex_lock(&mtx) );
+	fd_list_insert_before(&input, &pi->chain);
+	CHECK_POSIX( pthread_mutex_unlock(&mtx) );
+	
+	/* Wake up the process thread so that it processes the message */
+	CHECK_POSIX( pthread_cond_signal(&cnd) );
+	
+	/* done */
+	return 0;
+}
diff --git a/extensions/test_rt_any/CMakeLists.txt b/extensions/test_rt_any/CMakeLists.txt
new file mode 100644
index 0000000..f6b494c
--- /dev/null
+++ b/extensions/test_rt_any/CMakeLists.txt
@@ -0,0 +1,13 @@
+# The test_rt_any extension
+PROJECT("Random routing extension (for tests)" C)
+
+# Compile as a module
+FD_ADD_EXTENSION(test_rt_any test_rt_any.c)
+
+
+####
+## INSTALL section ##
+
+INSTALL(TARGETS test_rt_any
+	LIBRARY DESTINATION ${INSTALL_EXTENSIONS_SUFFIX}
+	COMPONENT freeDiameter-debug-tools)
diff --git a/extensions/test_rt_any/test_rt_any.c b/extensions/test_rt_any/test_rt_any.c
new file mode 100644
index 0000000..fd2c3c8
--- /dev/null
+++ b/extensions/test_rt_any/test_rt_any.c
@@ -0,0 +1,77 @@
+/*********************************************************************************************************
+* Software License Agreement (BSD License)                                                               *
+* Author: Sebastien Decugis <sdecugis@freediameter.net>							 *
+*													 *
+* Copyright (c) 2013, WIDE Project and NICT								 *
+* All rights reserved.											 *
+* 													 *
+* Redistribution and use of this software in source and binary forms, with or without modification, are  *
+* permitted provided that the following conditions are met:						 *
+* 													 *
+* * Redistributions of source code must retain the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer.										 *
+*    													 *
+* * Redistributions in binary form must reproduce the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer in the documentation and/or other						 *
+*   materials provided with the distribution.								 *
+* 													 *
+* * Neither the name of the WIDE Project or NICT nor the 						 *
+*   names of its contributors may be used to endorse or 						 *
+*   promote products derived from this software without 						 *
+*   specific prior written permission of WIDE Project and 						 *
+*   NICT.												 *
+* 													 *
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED *
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
+* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR *
+* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 	 *
+* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 	 *
+* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR *
+* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF   *
+* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.								 *
+*********************************************************************************************************/
+
+/* 
+ * Test-only extension for routing: gives a random positive score to any candidate peer.
+ */
+#include <freeDiameter/extension.h>
+#include <stdlib.h>
+
+/* The callback */
+static int tra_out_cb(void * cbdata, struct msg ** pmsg, struct fd_list * candidates)
+{
+	struct msg * msg = *pmsg;
+	struct fd_list * li;
+	
+	TRACE_ENTRY("%p %p %p", cbdata, msg, candidates);
+	
+	for (li = candidates->next; li != candidates; li = li->next) {
+		struct rtd_candidate *c = (struct rtd_candidate *) li;
+		c->score = (int)lrand48();
+	}
+	
+	return 0;
+}
+
+static struct fd_rt_out_hdl * out_hdl = NULL;
+
+/* Register the callbacks to the daemon */
+static int tra_main(char * conffile)
+{
+	TRACE_ENTRY("%p", conffile);
+	CHECK_FCT( fd_rt_out_register ( tra_out_cb, NULL, 0 /* we call it late so that it replaces previous scores */, &out_hdl ) );
+	return 0;
+}
+
+/* Cleanup the callbacks */
+void fd_ext_fini(void)
+{
+	TRACE_ENTRY();
+	CHECK_FCT_DO( fd_rt_out_unregister ( out_hdl, NULL ), /* continue */ );
+	return ;
+}
+
+/* Define the entry point function */
+EXTENSION_ENTRY("test_rt_any", tra_main);
diff --git a/extensions/test_sip/CMakeLists.txt b/extensions/test_sip/CMakeLists.txt
new file mode 100644
index 0000000..2b2c9e9
--- /dev/null
+++ b/extensions/test_sip/CMakeLists.txt
@@ -0,0 +1,30 @@
+# The test_sip extension
+PROJECT("Diameter-SIP client Test Application (RFC4740)" C)
+
+FIND_PACKAGE(MySQL REQUIRED)
+INCLUDE_DIRECTORIES(${MySQL_INCLUDE_DIR}) 
+
+# List of source files
+SET( TEST_SIP_SRC
+	test_sip.c
+	test_sip.h
+	multimediaauth.c
+	locationinfo.c
+	locationinfosl.c
+	registrationtermination.c
+	userauthorization.c
+	serverassignment.c
+)
+
+# Compile as a module
+FD_ADD_EXTENSION(test_sip ${TEST_SIP_SRC})
+
+TARGET_LINK_LIBRARIES(test_sip ${MySQL_LIBRARIES})
+
+
+####
+## INSTALL section ##
+
+INSTALL(TARGETS test_sip
+	LIBRARY DESTINATION ${INSTALL_EXTENSIONS_SUFFIX}
+	COMPONENT freeDiameter-debug-tools)
diff --git a/extensions/test_sip/locationinfo.c b/extensions/test_sip/locationinfo.c
new file mode 100644
index 0000000..98e89f9
--- /dev/null
+++ b/extensions/test_sip/locationinfo.c
@@ -0,0 +1,122 @@
+/*********************************************************************************************************
+* Software License Agreement (BSD License)                                                               *
+* Author: Alexandre Westfahl <awestfahl@freediameter.net>						 *
+*													 *
+* Copyright (c) 2010, Alexandre Westfahl, Teraoka Laboratory (Keio University), and the WIDE Project. 	 *		
+*													 *
+* All rights reserved.											 *
+* 													 *
+* Redistribution and use of this software in source and binary forms, with or without modification, are  *
+* permitted provided that the following conditions are met:						 *
+* 													 *
+* * Redistributions of source code must retain the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer.										 *
+*    													 *
+* * Redistributions in binary form must reproduce the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer in the documentation and/or other						 *
+*   materials provided with the distribution.								 *
+* 													 *
+* * Neither the name of the Teraoka Laboratory nor the 							 *
+*   names of its contributors may be used to endorse or 						 *
+*   promote products derived from this software without 						 *
+*   specific prior written permission of Teraoka Laboratory 						 *
+*   													 *
+* 													 *
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED *
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
+* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR *
+* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 	 *
+* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 	 *
+* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR *
+* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF   *
+* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.								 *
+*********************************************************************************************************/
+#include "test_sip.h"
+
+//Called to send a LIR
+int test_sip_LIR_cb()
+{
+	struct dict_object * lir_model=NULL;
+	struct msg * message=NULL;
+	struct avp *avp=NULL;
+	union avp_value value;
+	
+	//Fake values START
+	char *sip_aor="sip:aw-lappy@tera.ics.keio.ac.jp";
+	size_t aor_len=strlen(sip_aor); 
+	char *destination_realm="tera.ics.keio.ac.jp";
+	size_t destination_realmlen=strlen(destination_realm);
+	char *destination_host="suika.tera.ics.keio.ac.jp";
+	size_t destination_hostlen=strlen(destination_host);
+	//Fake values STOP
+	
+	//Create the base message for an RTR
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_COMMAND, CMD_BY_NAME, "Location-Info-Request", &lir_model, ENOENT) );
+	CHECK_FCT( fd_msg_new (lir_model, 0, &message));
+	
+	
+		
+	// Create a new session 
+	{
+		CHECK_FCT( fd_msg_new_session( message, (os0_t)"appsip", CONSTSTRLEN("appsip") ) );
+	}
+	
+	//Add the Auth-Application-Id 
+	{
+		CHECK_FCT( fd_msg_avp_new ( sip_dict.Auth_Application_Id, 0, &avp ) );
+		value.i32 = 6;
+		CHECK_FCT( fd_msg_avp_setvalue ( avp, &value ) );
+		CHECK_FCT( fd_msg_avp_add ( message, MSG_BRW_LAST_CHILD, avp) );
+	}
+	
+	//Auth_Session_State
+	{
+		CHECK_FCT( fd_msg_avp_new ( sip_dict.Auth_Session_State, 0, &avp ) );
+		value.i32=1;
+		CHECK_FCT( fd_msg_avp_setvalue( avp, &value ) );
+		CHECK_FCT( fd_msg_avp_add( message, MSG_BRW_LAST_CHILD, avp ) );
+	}
+	
+	//Origin_Host & Origin_Realm
+	CHECK_FCT( fd_msg_add_origin ( message, 0 ));
+	
+	//Destination_Host
+	{
+		CHECK_FCT( fd_msg_avp_new ( sip_dict.Destination_Host, 0, &avp ) );
+		value.os.data=(unsigned char *)destination_host;
+		value.os.len=destination_hostlen;
+		CHECK_FCT( fd_msg_avp_setvalue( avp, &value ) );
+		CHECK_FCT( fd_msg_avp_add( message, MSG_BRW_LAST_CHILD, avp ) );
+	}
+	//Destination_Realm
+	{
+		CHECK_FCT( fd_msg_avp_new ( sip_dict.Destination_Realm, 0, &avp ) );
+		value.os.data=(unsigned char *)destination_realm;
+		value.os.len=destination_realmlen;
+		CHECK_FCT( fd_msg_avp_setvalue( avp, &value ) );
+		CHECK_FCT( fd_msg_avp_add( message, MSG_BRW_LAST_CHILD, avp ) );
+	}
+	
+	//SIP_AOR
+	{
+		
+		CHECK_FCT( fd_msg_avp_new ( sip_dict.SIP_AOR, 0, &avp ) );
+		value.os.data=(unsigned char *)sip_aor;
+		value.os.len=aor_len;
+		CHECK_FCT( fd_msg_avp_setvalue( avp, &value ) );
+		CHECK_FCT( fd_msg_avp_add( message, MSG_BRW_LAST_CHILD, avp ) );
+			
+	}
+	
+	CHECK_FCT( fd_msg_send( &message, NULL, NULL ));
+	
+	return 0;
+}
+
+int test_sip_LIA_cb( struct msg ** msg, struct avp * paramavp, struct session * sess, void * opaque, enum disp_action * act)
+{
+	
+	return 0;
+}
diff --git a/extensions/test_sip/locationinfosl.c b/extensions/test_sip/locationinfosl.c
new file mode 100644
index 0000000..53c8494
--- /dev/null
+++ b/extensions/test_sip/locationinfosl.c
@@ -0,0 +1,124 @@
+/*********************************************************************************************************
+* Software License Agreement (BSD License)                                                               *
+* Author: Alexandre Westfahl <awestfahl@freediameter.net>						 *
+*													 *
+* Copyright (c) 2010, Alexandre Westfahl, Teraoka Laboratory (Keio University), and the WIDE Project. 	 *		
+*													 *
+* All rights reserved.											 *
+* 													 *
+* Redistribution and use of this software in source and binary forms, with or without modification, are  *
+* permitted provided that the following conditions are met:						 *
+* 													 *
+* * Redistributions of source code must retain the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer.										 *
+*    													 *
+* * Redistributions in binary form must reproduce the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer in the documentation and/or other						 *
+*   materials provided with the distribution.								 *
+* 													 *
+* * Neither the name of the Teraoka Laboratory nor the 							 *
+*   names of its contributors may be used to endorse or 						 *
+*   promote products derived from this software without 						 *
+*   specific prior written permission of Teraoka Laboratory 						 *
+*   													 *
+* 													 *
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED *
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
+* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR *
+* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 	 *
+* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 	 *
+* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR *
+* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF   *
+* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.								 *
+*********************************************************************************************************/
+#include "test_sip.h"
+
+//Called to send a LIR
+int test_sipSL_LIR_cb()
+{
+	struct dict_object * lir_model=NULL;
+	struct msg * message=NULL;
+	struct avp *avp=NULL;
+	union avp_value value;
+	
+	//Fake values START
+	char *sip_aor="sip:aw-lappy@tera.ics.keio.ac.jp";
+	size_t aor_len=strlen(sip_aor); 
+	char *destination_realm="tera.ics.keio.ac.jp";
+	size_t destination_realmlen=strlen(destination_realm);
+	char *destination_host="biwa.tera.ics.keio.ac.jp";
+	size_t destination_hostlen=strlen(destination_host);
+	//Fake values STOP
+	
+	//Create the base message for an RTR
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_COMMAND, CMD_BY_NAME, "Location-Info-Request", &lir_model, ENOENT) );
+	CHECK_FCT( fd_msg_new (lir_model, 0, &message));
+	
+	
+		
+	// Create a new session 
+	{
+		CHECK_FCT( fd_msg_new_session( message, (os0_t)"appsip", CONSTSTRLEN("appsip") ) );
+	}
+	
+	//Add the Auth-Application-Id 
+	{
+		CHECK_FCT( fd_msg_avp_new ( sip_dict.Auth_Application_Id, 0, &avp ) );
+		value.i32 = 6;
+		CHECK_FCT( fd_msg_avp_setvalue ( avp, &value ) );
+		CHECK_FCT( fd_msg_avp_add ( message, MSG_BRW_LAST_CHILD, avp) );
+	}
+	
+	//Auth_Session_State
+	{
+		CHECK_FCT( fd_msg_avp_new ( sip_dict.Auth_Session_State, 0, &avp ) );
+		value.i32=1;
+		CHECK_FCT( fd_msg_avp_setvalue( avp, &value ) );
+		CHECK_FCT( fd_msg_avp_add( message, MSG_BRW_LAST_CHILD, avp ) );
+	}
+	
+	//Origin_Host & Origin_Realm
+	CHECK_FCT( fd_msg_add_origin ( message, 0 ));
+	
+	//Destination_Host
+	{
+		CHECK_FCT( fd_msg_avp_new ( sip_dict.Destination_Host, 0, &avp ) );
+		value.os.data=(unsigned char *)destination_host;
+		value.os.len=destination_hostlen;
+		CHECK_FCT( fd_msg_avp_setvalue( avp, &value ) );
+		CHECK_FCT( fd_msg_avp_add( message, MSG_BRW_LAST_CHILD, avp ) );
+	}
+	//Destination_Realm
+	{
+		CHECK_FCT( fd_msg_avp_new ( sip_dict.Destination_Realm, 0, &avp ) );
+		value.os.data=(unsigned char *)destination_realm;
+		value.os.len=destination_realmlen;
+		CHECK_FCT( fd_msg_avp_setvalue( avp, &value ) );
+		CHECK_FCT( fd_msg_avp_add( message, MSG_BRW_LAST_CHILD, avp ) );
+	}
+	
+	
+	
+	//SIP_AOR
+	{
+		
+		CHECK_FCT( fd_msg_avp_new ( sip_dict.SIP_AOR, 0, &avp ) );
+		value.os.data=(unsigned char *)sip_aor;
+		value.os.len=aor_len;
+		CHECK_FCT( fd_msg_avp_setvalue( avp, &value ) );
+		CHECK_FCT( fd_msg_avp_add( message, MSG_BRW_LAST_CHILD, avp ) );
+			
+	}
+	
+	CHECK_FCT( fd_msg_send( &message, NULL, NULL ));
+	
+	return 0;
+}
+
+int test_sipSL_LIA_cb( struct msg ** msg, struct avp * paramavp, struct session * sess, void * opaque, enum disp_action * act)
+{
+	
+	return 0;
+}
diff --git a/extensions/test_sip/multimediaauth.c b/extensions/test_sip/multimediaauth.c
new file mode 100644
index 0000000..b1edb8d
--- /dev/null
+++ b/extensions/test_sip/multimediaauth.c
@@ -0,0 +1,786 @@
+/********************************************************************************************************
+* Software License Agreement (BSD License)                                                               *
+* Author: Alexandre Westfahl <awestfahl@freediameter.net>						 *
+*													 *
+* Copyright (c) 2010, Alexandre Westfahl, Teraoka Laboratory (Keio University), and the WIDE Project. 	 *		
+*													 *
+* All rights reserved.											 *
+* 													 *
+* Redistribution and use of this software in source and binary forms, with or without modification, are  *
+* permitted provided that the following conditions are met:						 *
+* 													 *
+* * Redistributions of source code must retain the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer.										 *
+*    													 *
+* * Redistributions in binary form must reproduce the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer in the documentation and/or other						 *
+*   materials provided with the distribution.								 *
+* 													 *
+* * Neither the name of the Teraoka Laboratory nor the 							 *
+*   names of its contributors may be used to endorse or 						 *
+*   promote products derived from this software without 						 *
+*   specific prior written permission of Teraoka Laboratory 						 *
+*   													 *
+* 													 *
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED *
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
+* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR *
+* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 	 *
+* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 	 *
+* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR *
+* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF   *
+* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.								 *
+********************************************************************************************************/
+#include "test_sip.h"
+
+
+int test_sip_MAA_cb( struct msg ** msg, struct avp * paramavp, struct session * sess, void * opaque, enum disp_action * act)
+{
+/*
+	struct msg *ans, *qry;
+	struct avp *avp, *a2, *authdataitem;
+	struct msg_hdr * header = NULL;
+	struct avp_hdr * avphdr=NULL, *avpheader=NULL, *avpheader_auth=NULL,*digestheader=NULL;
+	union avp_value val;
+	int found_cnonce=0;
+	struct avp * tempavp=NULL,*sipAuthentication=NULL,*sipAuthenticate=NULL;
+	char * result;
+	char password[51];
+	int idx=0, idx2=0, number_of_auth_items=0,i=0;
+	//Flags and variables for Database
+	int sipurinotstored=0, authenticationpending=0, querylen=0, usernamelen=0;
+	char *query=NULL,*username=NULL;
+	
+	//The nonce we will store and retrieve in session
+	struct ds_nonce *storednonce=NULL;
+	
+	
+	TRACE_ENTRY("%p %p %p %p", msg, avp, sess, act);
+	
+	if (msg == NULL)
+		return EINVAL;
+
+	
+	// Create answer header 
+	qry = *msg;
+	CHECK_FCT( fd_msg_new_answer_from_req ( fd_g_config->cnf_dict, msg, 0 ) );
+	ans = *msg;
+	
+
+
+	// Add the appropriate command code & Auth-Application-Id 
+	{
+		
+		CHECK_FCT( fd_msg_hdr ( *msg, &header ) );
+		header->msg_flags = CMD_FLAG_PROXIABLE;
+		header->msg_code = 286;
+		header->msg_appl = 6;
+		
+		
+		// Add the Auth-Application-Id 
+		{
+			CHECK_FCT( fd_msg_avp_new ( sip_dict.Auth_Application_Id, 0, &avp ) );
+			ASSERT(avp);
+			val.i32 = header->msg_appl;
+			CHECK_FCT( fd_msg_avp_setvalue ( avp, &val ) );
+			CHECK_FCT( fd_msg_avp_add ( ans, MSG_BRW_LAST_CHILD, avp) );
+		}
+	}
+	
+	
+	// Add the Auth-Session-State AVP 
+	{
+		
+		CHECK_FCT( fd_msg_search_avp ( qry, sip_dict.Auth_Session_State, &avp) );
+		CHECK_FCT( fd_msg_avp_hdr( avp, &avphdr )  );
+		
+		CHECK_FCT( fd_msg_avp_new ( sip_dict.Auth_Session_State, 0, &avp ) );
+		CHECK_FCT( fd_msg_avp_setvalue( avp, avphdr->avp_value ) );
+		CHECK_FCT( fd_msg_avp_add( ans, MSG_BRW_LAST_CHILD, avp ) );
+	}
+
+	
+	
+	// Check if method is REGISTER then User-Name must be present 
+	{
+		
+		CHECK_FCT( fd_msg_search_avp ( qry, sip_dict.SIP_Method, &avp) );
+		CHECK_FCT( fd_msg_avp_hdr( avp, &avpheader ));
+		
+
+		char *method=NULL;
+		
+		CHECK_FCT( fd_msg_search_avp ( qry, sip_dict.User_Name, &avp) );
+		if(avp!=NULL)
+		{
+			
+			int not_found=1;
+			MYSQL_RES *res=NULL;
+			MYSQL_ROW row;
+			
+			CHECK_FCT( fd_msg_avp_hdr( avp, &avphdr )  );
+			
+			//We allocate the double size of username because at worst it can be all quotes
+			username=malloc(avphdr->avp_value->os.len*2+1);
+			//We purify username not to have forbidden characters
+			usernamelen=mysql_real_escape_string(conn, username, avphdr->avp_value->os.data, avphdr->avp_value->os.len);
+			
+			
+			if((strncmp(avpheader->avp_value->os.data,"REGISTER",avpheader->avp_value->os.len)==0))
+			{
+				not_found=1;
+				
+				//We copy username in query
+				querylen=SQL_GETPASSWORD_LEN + usernamelen;
+				query = malloc(querylen+2);
+				snprintf(query, querylen+1, SQL_GETPASSWORD, username);
+				
+				
+				
+				//We make the query	
+				request_mysql(query);
+				res=mysql_use_result(conn);
+				if(res==NULL)
+				{
+					//We couldn't make the request
+					result="DIAMETER_UNABLE_TO_COMPLY";
+					goto out;
+				}
+			
+			
+			
+				while ((row = mysql_fetch_row(res)) != NULL)
+      				{
+      					if(row[0]!="")
+      					{
+      						strcpy(password,row[0]);
+      						not_found=0;
+      						break;
+      					}
+      				}
+      				mysql_free_result(res);
+      				free(query);
+      				
+      				if(not_found)
+				{
+					TRACE_DEBUG(FULL,"The user %s doesn't exist!",username);
+					result="DIAMETER_ERROR_USER_UNKNOWN";
+					free(username);	
+					goto out;
+				}
+			
+			
+			
+				//Now that we know the user exist, we get the list of AOR owned by this user
+				querylen=SQL_GETSIPAOR_LEN + usernamelen;
+				query = malloc(querylen+2);
+				snprintf(query, querylen+1, SQL_GETSIPAOR, username);
+			
+				//We make the query
+				request_mysql(query);
+				res=mysql_use_result(conn);
+				if(res==NULL)
+				{
+					//We couldn't make the request
+					result="DIAMETER_UNABLE_TO_COMPLY";
+					goto out;
+				}
+			
+				//We retrieve the SIP-AOR from AVP to check if the user can us it
+				CHECK_FCT( fd_msg_search_avp ( qry, sip_dict.SIP_AOR, &avp) );
+				CHECK_FCT( fd_msg_avp_hdr( avp, &avphdr )  );
+			
+				not_found=1;
+				while ((row = mysql_fetch_row(res)) != NULL)
+      				{
+      					if(strncmp(avphdr->avp_value->os.data,row[0],avphdr->avp_value->os.len)==0)
+      					{
+      						not_found=0;
+      						break;
+      					}
+      				}
+      				mysql_free_result(res);
+      				free(query);
+      				
+      				if(not_found)
+				{
+					TRACE_DEBUG(FULL,"The user %s can't use this SIP-AOR!",username);
+					result="DIAMETER_ERROR_IDENTITIES_DONT_MATCH";
+					free(username);	
+					goto out;
+				}
+				
+			}
+
+			CHECK_FCT( fd_msg_search_avp ( qry, sip_dict.SIP_Server_URI, &avp) );
+			CHECK_FCT( fd_msg_avp_hdr( avp, &avphdr ));
+			
+			if(avphdr!=NULL)
+			{
+				char *sipuri=NULL;
+				int sipurilen=0;
+
+				//We allocate the double size of SIP-URI because at worst it can be all quotes
+				sipuri=malloc(avphdr->avp_value->os.len*2+1);
+				//We purify SIP-URI not to have forbidden characters
+				sipurilen=mysql_real_escape_string(conn, sipuri, avphdr->avp_value->os.data, avphdr->avp_value->os.len);
+				
+				
+				//We get the SIP-URI assignated to the user
+				querylen=SQL_GETSIPURI_LEN + usernamelen;
+				query = malloc(querylen+2);
+				snprintf(query, querylen+1, SQL_GETSIPURI, username);
+
+				//We make the query
+				request_mysql(query);
+				res=mysql_use_result(conn);
+				if(res==NULL)
+				{
+					//We couldn't make the request
+					result="DIAMETER_UNABLE_TO_COMPLY";
+					goto out;
+				}
+				not_found=1;
+				while ((row = mysql_fetch_row(res)) != NULL)
+      				{
+      					if(strncmp(avphdr->avp_value->os.data,row[0],avphdr->avp_value->os.len)==0)
+      					{
+      						not_found=0;
+      						break;
+      					}
+      				}
+      				mysql_free_result(res);
+      				free(query);
+
+      				if(not_found)
+				{
+					//We update the SIP_URI for the user and we flag "authentication in progress"
+					querylen=SQL_SETSIPURI_LEN + usernamelen + sipurilen;
+					query = malloc(querylen+2);
+					snprintf(query, querylen+1, SQL_SETSIPURI, sipuri, username);
+			
+					//We make the query
+					request_mysql(query);
+					
+	      				free(query);
+	      				authenticationpending=1;
+				}
+      				free(sipuri);
+				
+			}
+			else
+				sipurinotstored=1;
+
+		}
+		else
+		{
+			result="DIAMETER_USER_NAME_REQUIRED";
+			goto out;
+		}
+
+			
+		free(method);
+
+	}
+
+	
+	//TODO: remove loop for authdataitem because RFC say only one (wait for answer from Garcia)
+	// How many Auth Data Items?
+	CHECK_FCT( fd_msg_search_avp ( qry, sip_dict.SIP_Number_Auth_Items, &avp) );
+	CHECK_FCT( fd_msg_avp_hdr( avp, &avpheader )  );
+	
+	
+	if(avp!=NULL)
+	{
+		CHECK_FCT(fd_msg_search_avp ( qry, sip_dict.SIP_Auth_Data_Item, &avp));
+		CHECK_FCT( fd_msg_avp_hdr( avp, &avphdr )  );
+		
+		if(avp!=NULL)
+		{
+			//First is Authentication Scheme
+			CHECK_FCT(fd_msg_browse ( avp, MSG_BRW_FIRST_CHILD, &avp, NULL) );
+			CHECK_FCT( fd_msg_avp_hdr( avp, &avphdr )  );
+			
+			//Digest-Authentication?
+			if(avphdr->avp_value->i32==0)
+			{
+				
+				for(idx=0;idx<avpheader->avp_value->i32;idx++)
+				{
+					//We look for SIP Auth items
+					CHECK_FCT(fd_msg_browse ( avp, MSG_BRW_WALK, &avp, NULL) );
+					
+					if(avp!=NULL)
+					{
+						
+						CHECK_FCT( fd_msg_avp_hdr( avp,&avphdr ));
+		
+						if(avphdr->avp_code==380) //We only create Auth-Data-Item to answer Auth-Data-Item
+						{
+							// Add the Auth-Data-Item AVP 
+							CHECK_FCT( fd_msg_avp_new ( sip_dict.SIP_Auth_Data_Item, 0, &authdataitem ) );
+					
+							// Add the Authentication Scheme AVP 
+							{
+								CHECK_FCT( fd_msg_avp_new ( sip_dict.SIP_Authentication_Scheme, 0, &a2 ) );
+								val.i32=0; //We only know Digest Authentication
+								CHECK_FCT( fd_msg_avp_setvalue( a2, &val ) );
+								CHECK_FCT( fd_msg_avp_add( authdataitem, MSG_BRW_LAST_CHILD, a2 ) );
+							}
+							
+							//We need to know if there is a Cnonce attribute (only in the second MAR request)
+							
+							//CHECK_FCT(fd_msg_browse ( avp, MSG_BRW_WALK, &avp, NULL) );
+							
+							
+							CHECK_FCT(fd_avp_search_avp (avp, sip_dict.Digest_CNonce, &a2 ));
+							
+							if(a2!=NULL)
+								found_cnonce=1;
+							else
+								found_cnonce=0;
+								
+							if(!found_cnonce)
+							{
+								//
+								We are in the case of first access request so we need to challenge the user.
+								
+								TRACE_DEBUG(FULL,"First Authorization in progress...");
+
+								// Create a new session  //this create a new session Id !!!
+								//CHECK_FCT_DO( fd_sess_new( &sess, fd_g_config->cnf_diamid, "test_sip", 7), goto out );
+								
+
+								// Create the SIP-Authenticate AVP 
+								{
+									CHECK_FCT( fd_msg_avp_new ( sip_dict.SIP_Authenticate, 0, &sipAuthenticate ) );
+								}						
+
+								// Add the Digest QOP AVP 
+								{
+									CHECK_FCT( fd_msg_avp_new ( sip_dict.Digest_QOP, 0, &a2 ) );
+									val.os.data="auth";
+									val.os.len=strlen(val.os.data);
+									CHECK_FCT( fd_msg_avp_setvalue( a2, &val ) );
+									CHECK_FCT( fd_msg_avp_add( sipAuthenticate, MSG_BRW_LAST_CHILD, a2 ) );
+								}
+								// Add the Digest Nonce AVP 
+								{
+									uint8_t buffer[NONCE_SIZE];
+									char nonce[NONCE_SIZE * 2 + 1];
+							
+								
+									gcry_create_nonce ((uint8_t *)buffer, sizeof(buffer));
+							
+									for(i=0;i<NONCE_SIZE;i++)
+										sprintf(&nonce[2 * i], "%2.2hhx", buffer[i]);
+								
+									CHECK_FCT( fd_msg_avp_new ( sip_dict.Digest_Nonce, 0, &a2 ) );
+									
+									
+									//We store the nonce (storednonce structure) inside the session
+									storednonce=malloc(sizeof(struct ds_nonce));
+									memset(storednonce,0,sizeof(struct ds_nonce));
+									CHECK_MALLOC(storednonce->nonce=malloc(NONCE_SIZE*2+1));
+									memcpy(storednonce->nonce,(char *)nonce,NONCE_SIZE*2+1);
+									CHECK_FCT( fd_sess_state_store ( ds_sess_hdl, sess, &storednonce ));  
+									
+									val.os.data=nonce;
+									val.os.len=NONCE_SIZE * 2;
+									
+									CHECK_FCT( fd_msg_avp_setvalue( a2, &val ) );
+									CHECK_FCT( fd_msg_avp_add( sipAuthenticate, MSG_BRW_LAST_CHILD, a2 ) );
+								}
+								// Add the Digest Algorithm AVP 
+								{
+									CHECK_FCT( fd_msg_avp_new ( sip_dict.Digest_Algorithm, 0, &a2 ) );
+									val.os.data="MD5";
+									val.os.len=strlen(val.os.data);
+									CHECK_FCT( fd_msg_avp_setvalue( a2, &val ) );
+									CHECK_FCT( fd_msg_avp_add( sipAuthenticate, MSG_BRW_LAST_CHILD, a2 ) );
+							
+								}
+								// Add the Digest Realm AVP 
+								{
+									tempavp=avp;
+								
+									avpheader_auth=walk_digest(tempavp, 104);
+									if(avpheader_auth!=NULL)
+									{
+										CHECK_FCT( fd_msg_avp_new ( sip_dict.Digest_Realm, 0, &a2 ) );
+										CHECK_FCT( fd_msg_avp_setvalue( a2, avpheader_auth->avp_value ) );
+										CHECK_FCT( fd_msg_avp_add( sipAuthenticate, MSG_BRW_LAST_CHILD, a2 ) );
+								
+									}
+								}
+						
+						
+								//We add SIP Authenticate to Auth Data Item
+								CHECK_FCT( fd_msg_avp_add( authdataitem, MSG_BRW_LAST_CHILD, sipAuthenticate ) );
+								//We add Auth Data Item to Answer
+								CHECK_FCT( fd_msg_avp_add( ans, MSG_BRW_LAST_CHILD, authdataitem ) );
+						
+								number_of_auth_items++;
+								if(sipurinotstored)
+									result="DIAMETER_SUCCESS_AUTH_SENT_SERVER_NOT_STORED";
+								else
+									result="DIAMETER_MULTI_ROUND_AUTH";
+								found_cnonce=0;
+							}
+							else
+							{
+								//
+								We are in the case of access request after challenge so we need to check credentials.
+								
+								TRACE_DEBUG(FULL,"Authentication after challenge");
+								
+								// Search the session, retrieve its data 
+								{
+									//int new=0;
+									
+									//TRACE_DEBUG(FULL,"new: *%d*",new);
+									//ASSERT( new == 0 );
+									CHECK_FCT( fd_sess_state_retrieve( ds_sess_hdl, sess, &storednonce ));
+									if(storednonce ==NULL)
+									{
+										result="DIAMETER_UNABLE_TO_COMPLY";
+												
+										if(username!=NULL)
+											free(username);
+										goto out;
+									}
+								}
+								
+								// Create the SIP-Authentication-Info AVP 
+								{
+									CHECK_FCT( fd_msg_avp_new ( sip_dict.SIP_Authentication_Info, 0, &sipAuthentication ) );
+								}
+								
+								
+							
+								// Add the Digest response Auth AVP 
+								{
+									//uint8_t bufferresp[DIGEST_LEN];
+									//char response[DIGEST_LEN*2+1];
+									int i=0;
+									
+									//We extract all the data we need
+									tempavp=avp;
+									
+									char * digest_username=NULL, *digest_uri=NULL, *digest_response=NULL, *digest_realm=NULL, *digest_nonce=NULL, *digest_method=NULL, *digest_qop=NULL, *digest_algorithm=NULL, *digest_cnonce=NULL, *digest_noncecount=NULL;
+									
+									
+									CHECK_FCT(fd_avp_search_avp (avp, sip_dict.Digest_Nonce, &a2 ));
+									if(a2!=NULL)
+									{
+										CHECK_FCT( fd_msg_avp_hdr( a2, &digestheader )  );
+										if(digestheader!=NULL)
+										{
+											
+											digest_nonce = malloc(digestheader->avp_value->os.len + 1);
+											memcpy(digest_nonce, digestheader->avp_value->os.data,
+											digestheader->avp_value->os.len);
+											digest_nonce[digestheader->avp_value->os.len]='\0';
+											TRACE_DEBUG(FULL,"Element:*%s*",digest_nonce);	
+											TRACE_DEBUG(FULL,"Stored Nonce:*%s*",storednonce->nonce);
+											
+											if(strcmp(digest_nonce,storednonce->nonce)!=0)
+											{
+												free(digest_nonce);
+												free(storednonce->nonce);
+												free(storednonce);
+												result="DIAMETER_UNABLE_TO_COMPLY";
+												
+												if(username!=NULL)
+													free(username);
+												goto out;
+											}
+											
+										}
+											
+									}
+									CHECK_FCT(fd_avp_search_avp (avp, sip_dict.Digest_Response, &a2 ));
+									if(a2!=NULL)
+									{
+										CHECK_FCT( fd_msg_avp_hdr( a2, &digestheader )  );
+										if(digestheader!=NULL)
+										{
+											digest_response = malloc(digestheader->avp_value->os.len + 1);
+											memcpy(digest_response, digestheader->avp_value->os.data,
+											digestheader->avp_value->os.len);
+											digest_response[digestheader->avp_value->os.len]='\0';
+											TRACE_DEBUG(FULL,"Element:*%s*",digest_response);	
+										}
+										
+									}
+									CHECK_FCT(fd_avp_search_avp (avp, sip_dict.Digest_Realm, &a2 ));
+									if(a2!=NULL)
+									{
+										CHECK_FCT( fd_msg_avp_hdr( a2, &digestheader )  );
+										if(digestheader!=NULL)
+										{
+											digest_realm = malloc(digestheader->avp_value->os.len + 1);
+											memcpy(digest_realm, digestheader->avp_value->os.data,
+											digestheader->avp_value->os.len);
+											digest_realm[digestheader->avp_value->os.len]='\0';
+											TRACE_DEBUG(FULL,"Element:*%s*",digest_realm);	
+										}
+									}
+									
+									CHECK_FCT(fd_avp_search_avp (avp, sip_dict.Digest_Method, &a2 ));
+									if(a2!=NULL)
+									{
+										CHECK_FCT( fd_msg_avp_hdr( a2, &digestheader )  );
+										if(digestheader!=NULL)
+										{
+											digest_method = malloc(digestheader->avp_value->os.len + 1);
+											memcpy(digest_method, digestheader->avp_value->os.data,
+											digestheader->avp_value->os.len);
+											digest_method[digestheader->avp_value->os.len]='\0';
+											TRACE_DEBUG(FULL,"Element:*%s*",digest_method);	
+										}
+									}
+									else
+										digest_method="";
+									
+									CHECK_FCT(fd_avp_search_avp (avp, sip_dict.Digest_URI, &a2 ));
+									if(a2!=NULL)
+									{
+										CHECK_FCT( fd_msg_avp_hdr( a2, &digestheader )  );
+										if(digestheader!=NULL)
+										{
+											digest_uri = malloc(digestheader->avp_value->os.len + 1);
+											memcpy(digest_uri, digestheader->avp_value->os.data,
+											digestheader->avp_value->os.len);
+											digest_uri[digestheader->avp_value->os.len]='\0';
+											TRACE_DEBUG(FULL,"Element:*%s*",digest_uri);	
+										}
+									}
+									
+									CHECK_FCT(fd_avp_search_avp (avp, sip_dict.Digest_QOP, &a2 ));
+									if(a2!=NULL)
+									{
+										CHECK_FCT( fd_msg_avp_hdr( a2, &digestheader )  );
+										if(digestheader!=NULL)
+										{
+											digest_qop = malloc(digestheader->avp_value->os.len + 1);
+											memcpy(digest_qop, digestheader->avp_value->os.data,
+											digestheader->avp_value->os.len);
+											digest_qop[digestheader->avp_value->os.len]='\0';
+											TRACE_DEBUG(FULL,"Element:*%s*",digest_qop);	
+										}
+									}
+									else
+										digest_qop=NULL;
+									CHECK_FCT(fd_avp_search_avp (avp, sip_dict.Digest_Algorithm, &a2 ));
+									if(a2!=NULL)
+									{
+										CHECK_FCT( fd_msg_avp_hdr( a2, &digestheader )  );
+										if(digestheader!=NULL)
+										{
+											digest_algorithm = malloc(digestheader->avp_value->os.len + 1);
+											memcpy(digest_algorithm, digestheader->avp_value->os.data,
+											digestheader->avp_value->os.len);
+											digest_algorithm[digestheader->avp_value->os.len]='\0';
+											TRACE_DEBUG(FULL,"Element:*%s*",digest_algorithm);	
+										}
+									}
+									else
+										digest_algorithm=NULL;
+									CHECK_FCT(fd_avp_search_avp (avp, sip_dict.Digest_CNonce, &a2 ));
+									if(a2!=NULL)
+									{
+										CHECK_FCT( fd_msg_avp_hdr( a2, &digestheader )  );
+										if(digestheader!=NULL)
+										{
+											digest_cnonce = malloc(digestheader->avp_value->os.len + 1);
+											memcpy(digest_cnonce, digestheader->avp_value->os.data,
+											digestheader->avp_value->os.len);
+											digest_cnonce[digestheader->avp_value->os.len]='\0';
+											TRACE_DEBUG(FULL,"Element:*%s*",digest_cnonce);	
+										}
+									}
+									else
+										digest_cnonce="";
+									CHECK_FCT(fd_avp_search_avp (avp, sip_dict.Digest_Nonce_Count, &a2 ));
+									if(a2!=NULL)
+									{
+										CHECK_FCT( fd_msg_avp_hdr( a2, &digestheader )  );
+										if(digestheader!=NULL)
+										{
+											digest_noncecount = malloc(digestheader->avp_value->os.len + 1);
+											memcpy(digest_noncecount, digestheader->avp_value->os.data,
+											digestheader->avp_value->os.len);
+											digest_noncecount[digestheader->avp_value->os.len]='\0';
+											TRACE_DEBUG(FULL,"Element:*%s*",digest_noncecount);	
+										}
+									}
+									else
+										digest_noncecount="";
+									CHECK_FCT(fd_avp_search_avp (avp, sip_dict.Digest_Username, &a2 ));
+									if(a2!=NULL)
+									{
+										CHECK_FCT( fd_msg_avp_hdr( a2, &digestheader )  );
+										if(digestheader!=NULL)
+										{
+											digest_username = malloc(digestheader->avp_value->os.len + 1);
+											memcpy(digest_username, digestheader->avp_value->os.data,
+											digestheader->avp_value->os.len);
+											digest_username[digestheader->avp_value->os.len]='\0';
+											TRACE_DEBUG(FULL,"Element:*%s*",digest_username);	
+										}
+									}
+									//TODO: replace by authentication function
+									
+									HASHHEX HA1;
+									HASHHEX HA2 = "";
+									HASHHEX response, responseauth;
+
+									
+									DigestCalcHA1(digest_algorithm, digest_username, digest_realm, password, digest_nonce,digest_cnonce, HA1);
+									
+      							DigestCalcResponse(HA1, digest_nonce, digest_noncecount, digest_cnonce, digest_qop,digest_method, digest_uri, HA2, response);
+      									
+		
+									// We check that the Digest-Response is the same (UA, Diameter)
+									if(strcmp(response,digest_response)!=0)
+									{
+										TRACE_DEBUG(FULL,"Response calculated by Diameter server:%s",response);
+										TRACE_DEBUG(FULL,"Response calculated by UA:%s",digest_response);
+										TRACE_DEBUG(INFO,"Digest-Response does not match!");
+										result="DIAMETER_UNABLE_TO_COMPLY";
+										free(digest_algorithm);
+										free(digest_cnonce);
+										free(digest_nonce);
+										free(digest_noncecount);
+										free(digest_method);
+										free(digest_username);
+										free(digest_uri);
+										free(digest_qop);
+										free(digest_response);
+										free(digest_realm);
+										free(storednonce->nonce);
+										free(storednonce);
+										if(username!=NULL)
+											free(username);
+										goto out;
+										
+									}
+									//We calculate Digest_Response_Auth
+									DigestCalcResponseAuth(HA1, digest_nonce, digest_noncecount, digest_cnonce, digest_qop,digest_method, digest_uri, HA2, responseauth);
+									
+									TRACE_DEBUG(FULL,"Response calculated by Diameter server:%s",response);
+										TRACE_DEBUG(FULL,"Response calculated by UA:%s",digest_response);
+									if(strcmp(digest_qop,"auth-int")==0)
+									{
+										//Digest-HA1 MUST be used instead of Digest-Response-Auth if Digest-Qop is 'auth-int'.
+										CHECK_FCT( fd_msg_avp_new ( sip_dict.Digest_HA1, 0, &a2 ) );
+										val.os.data=HA1;
+										val.os.len=HASHHEXLEN+1;
+										CHECK_FCT( fd_msg_avp_setvalue( a2, &val ) );
+										CHECK_FCT( fd_msg_avp_add( sipAuthentication, MSG_BRW_LAST_CHILD, a2 ) );
+									}
+									else
+									{
+										//Digest-Response-Auth MUST be used instead of Digest-HA1 if Digest-Qop is 'auth'.
+										CHECK_FCT( fd_msg_avp_new ( sip_dict.Digest_Response_Auth, 0, &a2 ) );
+										val.os.data=responseauth;
+										val.os.len=DIGEST_LEN*2;
+										CHECK_FCT( fd_msg_avp_setvalue( a2, &val ) );
+										CHECK_FCT( fd_msg_avp_add( sipAuthentication, MSG_BRW_LAST_CHILD, a2 ) );
+									}
+									free(digest_algorithm);
+									free(digest_cnonce);
+									free(digest_nonce);
+									free(digest_noncecount);
+									free(digest_method);
+									free(digest_username);
+									free(digest_uri);
+									free(digest_qop);
+									free(digest_response);
+									free(digest_realm);
+									free(storednonce->nonce);
+									free(storednonce);
+								
+									number_of_auth_items++;
+								}	
+								
+								
+								//We add SIP Authentication-Info to Auth Data Item
+								CHECK_FCT( fd_msg_avp_add( authdataitem, MSG_BRW_LAST_CHILD, sipAuthentication ) );
+								//We add Auth Data Item to Answer
+								CHECK_FCT( fd_msg_avp_add( ans, MSG_BRW_LAST_CHILD, authdataitem ) );
+								
+								
+								if(username!=NULL && authenticationpending)
+								{
+									//We clear the flag "authentication pending"
+									querylen=SQL_CLEARFLAG_LEN + usernamelen;
+									query = malloc(querylen+2);
+									snprintf(query, querylen+1, SQL_CLEARFLAG, username);
+		
+									//We make the query
+									request_mysql(query);
+				
+					      				free(query);
+								}
+								
+								if(sipurinotstored)
+									result="DIAMETER_SUCCESS_SERVER_NAME_NOT_STORED";
+								else
+									result="DIAMETER_SUCCESS";
+								found_cnonce=0;
+							}
+						}
+					}
+					else
+						TRACE_DEBUG(INFO,"No auth data items!");
+				}
+				//Add SIP_Number_Auth_Items  AVP 
+				{
+					CHECK_FCT( fd_msg_avp_new ( sip_dict.SIP_Number_Auth_Items, 0, &avp ) );
+					val.i32 = number_of_auth_items;
+					CHECK_FCT( fd_msg_avp_setvalue ( avp, &val ) );
+					CHECK_FCT( fd_msg_avp_add ( ans, MSG_BRW_LAST_CHILD, avp) );
+				}
+				
+				
+			}
+			else
+			{
+				TRACE_DEBUG(INFO,"We only support DIGEST for now, unable to comply");
+				result="DIAMETER_ERROR_AUTH_SCHEME_NOT_SUPPORTED";
+				if(username!=NULL)
+					free(username);
+				goto out;
+			}
+		}
+	}
+	else
+	{
+		//TODO: remove this because Number_Auth_Items is not compulsory
+		TRACE_DEBUG(FULL,"Number-Auth-Items is not included.");
+		result="DIAMETER_UNABLE_TO_COMPLY";
+		if(username!=NULL)
+			free(username);
+		goto out;
+	}
+	
+	if(username!=NULL)
+		free(username);
+	
+
+out:
+	// Set the Origin-Host, Origin-Realm, Result-Code AVPs 
+	CHECK_FCT( fd_msg_rescode_set( ans, result, NULL, NULL, 1 ) );
+	
+	
+	// Send the answer 
+	CHECK_FCT( fd_msg_send( msg, NULL, NULL ) );
+	
+*/	
+	return 0;
+}
+
diff --git a/extensions/test_sip/registrationtermination.c b/extensions/test_sip/registrationtermination.c
new file mode 100644
index 0000000..5286e73
--- /dev/null
+++ b/extensions/test_sip/registrationtermination.c
@@ -0,0 +1,43 @@
+/*********************************************************************************************************
+* Software License Agreement (BSD License)                                                               *
+* Author: Alexandre Westfahl <awestfahl@freediameter.net>						 *
+*													 *
+* Copyright (c) 2010, Alexandre Westfahl, Teraoka Laboratory (Keio University), and the WIDE Project. 	 *		
+*													 *
+* All rights reserved.											 *
+* 													 *
+* Redistribution and use of this software in source and binary forms, with or without modification, are  *
+* permitted provided that the following conditions are met:						 *
+* 													 *
+* * Redistributions of source code must retain the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer.										 *
+*    													 *
+* * Redistributions in binary form must reproduce the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer in the documentation and/or other						 *
+*   materials provided with the distribution.								 *
+* 													 *
+* * Neither the name of the Teraoka Laboratory nor the 							 *
+*   names of its contributors may be used to endorse or 						 *
+*   promote products derived from this software without 						 *
+*   specific prior written permission of Teraoka Laboratory 						 *
+*   													 *
+* 													 *
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED *
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
+* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR *
+* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 	 *
+* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 	 *
+* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR *
+* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF   *
+* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.								 *
+*********************************************************************************************************/
+#include "test_sip.h"
+
+
+int test_sip_RTR_cb( struct msg ** msg, struct avp * paramavp, struct session * sess, void * opaque, enum disp_action * act)
+{
+	
+	return 0;
+}
diff --git a/extensions/test_sip/serverassignment.c b/extensions/test_sip/serverassignment.c
new file mode 100644
index 0000000..887ed28
--- /dev/null
+++ b/extensions/test_sip/serverassignment.c
@@ -0,0 +1,165 @@
+/*********************************************************************************************************
+* Software License Agreement (BSD License)                                                               *
+* Author: Alexandre Westfahl <awestfahl@freediameter.net>						 *
+*													 *
+* Copyright (c) 2010, Alexandre Westfahl, Teraoka Laboratory (Keio University), and the WIDE Project. 	 *		
+*													 *
+* All rights reserved.											 *
+* 													 *
+* Redistribution and use of this software in source and binary forms, with or without modification, are  *
+* permitted provided that the following conditions are met:						 *
+* 													 *
+* * Redistributions of source code must retain the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer.										 *
+*    													 *
+* * Redistributions in binary form must reproduce the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer in the documentation and/or other						 *
+*   materials provided with the distribution.								 *
+* 													 *
+* * Neither the name of the Teraoka Laboratory nor the 							 *
+*   names of its contributors may be used to endorse or 						 *
+*   promote products derived from this software without 						 *
+*   specific prior written permission of Teraoka Laboratory 						 *
+*   													 *
+* 													 *
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED *
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
+* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR *
+* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 	 *
+* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 	 *
+* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR *
+* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF   *
+* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.								 *
+*********************************************************************************************************/
+#include "test_sip.h"
+
+//Called to send a UAR
+int test_sip_SAR_cb()
+{
+	struct dict_object * sar_model=NULL;
+	struct msg * message=NULL;
+	struct avp *avp=NULL;
+	union avp_value value;
+	
+	//Fake values START
+	char *sip_aor="sip:aw-lappy@tera.ics.keio.ac.jp";
+	size_t aor_len=strlen(sip_aor); 
+	char *destination_realm="tera.ics.keio.ac.jp";
+	size_t destination_realmlen=strlen(destination_realm);
+	char *destination_host="suika.tera.ics.keio.ac.jp";
+	size_t destination_hostlen=strlen(destination_host);
+	char *username="aw-lappy";
+	size_t usernamelen=strlen(username);
+	char *sipserveruri="sip:ichigo@tera.ics.keio.ac.jp";
+	size_t sipserverurilen=strlen(sipserveruri);
+	// char *visitednetwork="Pink";
+	//size_t visitednetworklen=strlen(visitednetwork);
+	//int registrationtype = 2;
+	int data_already_available=0;
+	int assignment_type=0;
+	//Fake values STOP
+	
+	//Create the base message for an RTR
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_COMMAND, CMD_BY_NAME, "Server-Assignment-Request", &sar_model, ENOENT) );
+	CHECK_FCT( fd_msg_new (sar_model, 0, &message));
+	
+	
+	
+	// Create a new session 
+	{
+		CHECK_FCT( fd_msg_new_session( message, (os0_t)"appsip", CONSTSTRLEN("appsip") ) );
+	}
+	
+	//Add the Auth-Application-Id 
+	{
+		CHECK_FCT( fd_msg_avp_new ( sip_dict.Auth_Application_Id, 0, &avp ) );
+		value.i32 = 6;
+		CHECK_FCT( fd_msg_avp_setvalue ( avp, &value ) );
+		CHECK_FCT( fd_msg_avp_add ( message, MSG_BRW_LAST_CHILD, avp) );
+	}	
+	//Auth_Session_State
+	{
+		CHECK_FCT( fd_msg_avp_new ( sip_dict.Auth_Session_State, 0, &avp ) );
+		value.i32=1;
+		CHECK_FCT( fd_msg_avp_setvalue( avp, &value ) );
+		CHECK_FCT( fd_msg_avp_add( message, MSG_BRW_LAST_CHILD, avp ) );
+	}
+	
+	//Origin_Host & Origin_Realm
+	CHECK_FCT( fd_msg_add_origin ( message, 0 ));
+	
+	//Destination_Host
+	{
+		CHECK_FCT( fd_msg_avp_new ( sip_dict.Destination_Host, 0, &avp ) );
+		value.os.data=(unsigned char *)destination_host;
+		value.os.len=destination_hostlen;
+		CHECK_FCT( fd_msg_avp_setvalue( avp, &value ) );
+		CHECK_FCT( fd_msg_avp_add( message, MSG_BRW_LAST_CHILD, avp ) );
+	}
+	//Destination_Realm
+	{
+		CHECK_FCT( fd_msg_avp_new ( sip_dict.Destination_Realm, 0, &avp ) );
+		value.os.data=(unsigned char *)destination_realm;
+		value.os.len=destination_realmlen;
+		CHECK_FCT( fd_msg_avp_setvalue( avp, &value ) );
+		CHECK_FCT( fd_msg_avp_add( message, MSG_BRW_LAST_CHILD, avp ) );
+	}
+	
+	//SIP_AOR
+	{
+		
+		CHECK_FCT( fd_msg_avp_new ( sip_dict.SIP_AOR, 0, &avp ) );
+		value.os.data=(unsigned char *)sip_aor;
+		value.os.len=aor_len;
+		CHECK_FCT( fd_msg_avp_setvalue( avp, &value ) );
+		CHECK_FCT( fd_msg_avp_add( message, MSG_BRW_LAST_CHILD, avp ) );
+		
+	}
+	//Username
+	{
+		
+		CHECK_FCT( fd_msg_avp_new ( sip_dict.User_Name, 0, &avp ) );
+		value.os.data=(unsigned char *)username;
+		value.os.len=usernamelen;
+		CHECK_FCT( fd_msg_avp_setvalue( avp, &value ) );
+		CHECK_FCT( fd_msg_avp_add( message, MSG_BRW_LAST_CHILD, avp ) );
+		
+	}
+	//SIP_User_Data_Already_Available
+	{
+		CHECK_FCT( fd_msg_avp_new ( sip_dict.SIP_User_Data_Already_Available, 0, &avp ) );
+		value.i32=data_already_available;
+		CHECK_FCT( fd_msg_avp_setvalue( avp, &value ) );
+		CHECK_FCT( fd_msg_avp_add( message, MSG_BRW_LAST_CHILD, avp ) );
+	}
+	
+	//SIP_Server_Assignment_Type;
+	{
+		CHECK_FCT( fd_msg_avp_new ( sip_dict.SIP_Server_Assignment_Type, 0, &avp ) );
+		value.i32=assignment_type;
+		CHECK_FCT( fd_msg_avp_setvalue( avp, &value ) );
+		CHECK_FCT( fd_msg_avp_add( message, MSG_BRW_LAST_CHILD, avp ) );
+	}
+	//SIP_server_uri
+	{
+		
+		CHECK_FCT( fd_msg_avp_new ( sip_dict.SIP_Server_URI, 0, &avp ) );
+		value.os.data=(unsigned char *)sipserveruri;
+		value.os.len=sipserverurilen;
+		CHECK_FCT( fd_msg_avp_setvalue( avp, &value ) );
+		CHECK_FCT( fd_msg_avp_add( message, MSG_BRW_LAST_CHILD, avp ) );
+		
+	}
+	
+	CHECK_FCT( fd_msg_send( &message, NULL, NULL ));
+	
+	return 0;
+}
+
+int test_sip_SAA_cb( struct msg ** msg, struct avp * paramavp, struct session * sess, void * opaque, enum disp_action * act)
+{
+	
+	return 0;
+}
diff --git a/extensions/test_sip/test_sip.c b/extensions/test_sip/test_sip.c
new file mode 100644
index 0000000..463fcd9
--- /dev/null
+++ b/extensions/test_sip/test_sip.c
@@ -0,0 +1,241 @@
+/*********************************************************************************************************
+* Software License Agreement (BSD License)                                                               *
+* Author: Alexandre Westfahl <awestfahl@freediameter.net>						 *
+*													 *
+* Copyright (c) 2010, Alexandre Westfahl, Teraoka Laboratory (Keio University), and the WIDE Project. 	 *		
+*													 *
+* All rights reserved.											 *
+* 													 *
+* Redistribution and use of this software in source and binary forms, with or without modification, are  *
+* permitted provided that the following conditions are met:						 *
+* 													 *
+* * Redistributions of source code must retain the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer.										 *
+*    													 *
+* * Redistributions in binary form must reproduce the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer in the documentation and/or other						 *
+*   materials provided with the distribution.								 *
+* 													 *
+* * Neither the name of the Teraoka Laboratory nor the 							 *
+*   names of its contributors may be used to endorse or 						 *
+*   promote products derived from this software without 						 *
+*   specific prior written permission of Teraoka Laboratory 						 *
+*   													 *
+* 													 *
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED *
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
+* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR *
+* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 	 *
+* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 	 *
+* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR *
+* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF   *
+* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.								 *
+*********************************************************************************************************/
+
+
+#include"test_sip.h"
+
+struct disp_hdl * test_sip_MAR_hdl=NULL;
+struct disp_hdl * test_sip_LIR_hdl=NULL;
+struct disp_hdl * test_sip_UAR_hdl=NULL;
+struct disp_hdl * test_sip_SAR_hdl=NULL;
+struct disp_hdl * test_sip_PPA_hdl=NULL;
+struct disp_hdl * test_sip_RTA_hdl=NULL;
+
+struct disp_hdl * test_sip_MAA_hdl=NULL;
+struct disp_hdl * test_sip_LIA_hdl=NULL;
+struct disp_hdl * test_sip_UAA_hdl=NULL;
+struct disp_hdl * test_sip_SAA_hdl=NULL;
+struct disp_hdl * test_sip_PPR_hdl=NULL;
+struct disp_hdl * test_sip_RTR_hdl=NULL;
+
+
+struct disp_hdl * test_sip_default_hdl=NULL;
+
+//configuration stucture
+struct ts_conf * ts_conf=NULL;
+static struct ts_conf test_sip_conf;
+
+
+//dictionary of SIP
+struct sip_dict sip_dict;
+
+int test_sip_default_cb( struct msg ** msg, struct avp * avp, struct session * sess, void * opaque, enum disp_action * act)
+{
+	TRACE_ENTRY("%p %p %p %p", msg, avp, sess, act);
+	
+	return 0;
+}
+
+
+/*
+void dump_config()
+{
+	TRACE_DEBUG(FULL,"***Configuration of TEST Diameter-SIP extension***");
+	TRACE_DEBUG(FULL,"# username: *%s*",ts_conf->username);
+	TRACE_DEBUG(FULL,"# password: *%s*",ts_conf->password);
+	TRACE_DEBUG(FULL,"# sip_aor: *%s*",ts_conf->sip_aor);
+	TRACE_DEBUG(FULL,"# destination_realm: *%s*",ts_conf->destination_realm);
+	TRACE_DEBUG(FULL,"# destination_sip: *%s*",ts_conf->destination_sip);
+	TRACE_DEBUG(FULL,"***End of TEST Diameter-SIP configuration extension***");
+}
+*/
+static int ts_conf_init(void)
+{
+	ts_conf=&test_sip_conf;
+	//memset(app_sip_conf, 0, sizeof(struct ts_conf));
+	
+
+	return 0;
+}
+
+/* entry point */
+int ts_entry(char * conffile)
+{
+	TRACE_ENTRY("%p", conffile);
+	
+	struct dict_object * app=NULL;
+	struct disp_when data;
+	
+	
+	//TODO: activate again configuration file
+	CHECK_FCT( ts_conf_init() );
+	/* Initialize configuration 
+	//CHECK_FCT( ts_conf_init() );
+	
+	
+	//We parse the configuration file
+	if (conffile != NULL) {
+		CHECK_FCT( ts_conf_handle(conffile) );
+	}
+	else
+	{
+		TRACE_DEBUG(INFO, "We need a configuration file for Diameter-SIP extension. See doc/ for an example.");
+	}
+	
+	//We can dump the configuration extracted from app_sip.conf
+	dump_config();
+	*/
+	
+	
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_APPLICATION, APPLICATION_BY_NAME, "Diameter Session Initiation Protocol (SIP) Application", &app, ENOENT) );
+	CHECK_FCT( fd_disp_app_support ( app, NULL, 1, 0 ) );
+	
+	
+	
+	//We set useful AVPs 
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Auth-Session-State", &sip_dict.Auth_Session_State, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Auth-Application-Id", &sip_dict.Auth_Application_Id, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Destination-Host", &sip_dict.Destination_Host, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Destination-Realm", &sip_dict.Destination_Realm, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Session-Id", &sip_dict.Session_Id, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Redirect-Host", &sip_dict.Redirect_Host, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Redirect-Host-Usage", &sip_dict.Redirect_Host_Usage, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "SIP-Auth-Data-Item", &sip_dict.SIP_Auth_Data_Item, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "SIP-Authorization", &sip_dict.SIP_Authorization, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "SIP-Authenticate", &sip_dict.SIP_Authenticate, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "SIP-Number-Auth-Items", &sip_dict.SIP_Number_Auth_Items, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "SIP-Authentication-Scheme", &sip_dict.SIP_Authentication_Scheme, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "SIP-Authentication-Info", &sip_dict.SIP_Authentication_Info, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "SIP-Server-URI", &sip_dict.SIP_Server_URI, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "SIP-Server-Capabilities", &sip_dict.SIP_Server_Capabilities, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "SIP-Mandatory-Capability", &sip_dict.SIP_Mandatory_Capability, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "SIP-Optional-Capability", &sip_dict.SIP_Optional_Capability, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "SIP-Method", &sip_dict.SIP_Method, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "SIP-AOR", &sip_dict.SIP_AOR, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "SIP-Deregistration-Reason", &sip_dict.SIP_Deregistration_Reason, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "SIP-Reason-Code", &sip_dict.SIP_Reason_Code, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "SIP-Reason-Info", &sip_dict.SIP_Reason_Info, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "SIP-Accounting-Information", &sip_dict.SIP_Accounting_Information, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "SIP-Accounting-Server-URI", &sip_dict.SIP_Accounting_Server_URI, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "SIP-Credit-Control-Server-URI", &sip_dict.SIP_Credit_Control_Server_URI, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "SIP-Server-Assignment-Type", &sip_dict.SIP_Server_Assignment_Type, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "SIP-Item-Number", &sip_dict.SIP_Item_Number, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "SIP-User-Authorization-Type", &sip_dict.SIP_User_Authorization_Type, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "SIP-Supported-User-Data-Type", &sip_dict.SIP_Supported_User_Data_Type, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "SIP-User-Data", &sip_dict.SIP_User_Data, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "SIP-User-Data-Type", &sip_dict.SIP_User_Data_Type, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "SIP-User-Data-Contents", &sip_dict.SIP_User_Data_Contents, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "SIP-User-Data-Already-Available", &sip_dict.SIP_User_Data_Already_Available, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "SIP-Visited-Network-Id", &sip_dict.SIP_Visited_Network_Id, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Digest-Realm", &sip_dict.Digest_Realm, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Digest-URI", &sip_dict.Digest_URI, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Digest-Nonce", &sip_dict.Digest_Nonce, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Digest-CNonce", &sip_dict.Digest_CNonce, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Digest-Method", &sip_dict.Digest_Method, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Digest-Nonce-Count", &sip_dict.Digest_Nonce_Count, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Digest-Realm", &sip_dict.Digest_Realm, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Digest-Response", &sip_dict.Digest_Response, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Digest-Response-Auth", &sip_dict.Digest_Response_Auth, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Digest-Username", &sip_dict.Digest_Username, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Digest-Algorithm", &sip_dict.Digest_Algorithm, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Digest-QoP", &sip_dict.Digest_QOP, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "User-Name", &sip_dict.User_Name, ENOENT) );
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Digest-HA1", &sip_dict.Digest_HA1, ENOENT) );
+	
+	
+	//Register Application
+	memset(&data, 0, sizeof(data));
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_APPLICATION, APPLICATION_BY_NAME, "Diameter Session Initiation Protocol (SIP) Application", &data.app, ENOENT) );
+	
+	
+	//**Command Codes
+	/**/
+	//MAA
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_COMMAND, CMD_BY_NAME, "Multimedia-Auth-Answer", &data.command, ENOENT) );
+	CHECK_FCT( fd_disp_register( test_sip_MAA_cb, DISP_HOW_CC, &data, NULL, &test_sip_MAA_hdl ) );
+	
+	//UAA
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_COMMAND, CMD_BY_NAME, "User-Authorization-Answer", &data.command, ENOENT) );
+	CHECK_FCT( fd_disp_register( test_sip_UAA_cb, DISP_HOW_CC, &data, NULL, &test_sip_UAA_hdl ) );
+	
+	//RTR
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_COMMAND, CMD_BY_NAME, "Registration-Termination-Request", &data.command, ENOENT) );
+	CHECK_FCT( fd_disp_register( test_sip_RTR_cb, DISP_HOW_CC, &data, NULL, &test_sip_RTR_hdl ) );
+	
+	//LIA
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_COMMAND, CMD_BY_NAME, "Location-Info-Answer", &data.command, ENOENT) );
+	CHECK_FCT( fd_disp_register( test_sip_LIA_cb, DISP_HOW_CC, &data, NULL, &test_sip_LIA_hdl ) );
+	
+	//LIA
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_COMMAND, CMD_BY_NAME, "Server-Assignment-Answer", &data.command, ENOENT) );
+	CHECK_FCT( fd_disp_register( test_sip_SAA_cb, DISP_HOW_CC, &data, NULL, &test_sip_SAA_hdl ) );
+	
+	//Callback for unexpected messages
+	CHECK_FCT( fd_disp_register( test_sip_default_cb, DISP_HOW_APPID, &data, NULL, &test_sip_default_hdl ) );
+	
+	/*
+	//We start database connection
+	if(start_mysql_connection())
+		return 1;
+	*/
+	
+	//CHECK_FCT( fd_event_trig_regcb(30, "test_sip", (void *)test_sipSL_LIR_cb ) );
+	CHECK_FCT( fd_event_trig_regcb(30, "test_sip", (void *)test_sip_SAR_cb ) );
+	CHECK_FCT( fd_event_trig_regcb(31, "test_sip", (void *)test_sip_LIR_cb ) );
+	
+	return 0;
+}
+
+//Cleanup callback
+void fd_ext_fini(void)
+{
+	/*
+	if (test_sip_MAR_cb) {
+		(void) fd_disp_unregister(&test_sip_MAR_hdl);
+		CHECK_FCT_DO( fd_sess_handler_destroy(&ts_sess_hdl),return);
+	}
+	*/
+	//We close database connection
+	//close_mysql_connection();
+	
+
+	
+	TRACE_ENTRY();
+	return ;
+}
+
+EXTENSION_ENTRY("test_sip", ts_entry, "dict_sip");
+
diff --git a/extensions/test_sip/test_sip.h b/extensions/test_sip/test_sip.h
new file mode 100644
index 0000000..e2ebf21
--- /dev/null
+++ b/extensions/test_sip/test_sip.h
@@ -0,0 +1,125 @@
+/*********************************************************************************************************
+* Software License Agreement (BSD License)                                                               *
+* Author: Alexandre Westfahl <awestfahl@freediameter.net>						 *
+*													 *
+* Copyright (c) 2010, Alexandre Westfahl, Teraoka Laboratory (Keio University), and the WIDE Project. 	 *		
+*													 *
+* All rights reserved.											 *
+* 													 *
+* Redistribution and use of this software in source and binary forms, with or without modification, are  *
+* permitted provided that the following conditions are met:						 *
+* 													 *
+* * Redistributions of source code must retain the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer.										 *
+*    													 *
+* * Redistributions in binary form must reproduce the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer in the documentation and/or other						 *
+*   materials provided with the distribution.								 *
+* 													 *
+* * Neither the name of the Teraoka Laboratory nor the 							 *
+*   names of its contributors may be used to endorse or 						 *
+*   promote products derived from this software without 						 *
+*   specific prior written permission of Teraoka Laboratory 						 *
+*   													 *
+* 													 *
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED *
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
+* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR *
+* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 	 *
+* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 	 *
+* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR *
+* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF   *
+* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.								 *
+*********************************************************************************************************/
+#include <freeDiameter/extension.h>
+#include <sys/time.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <stdio.h>
+GCC_DIAG_OFF("-Wdeprecated-declarations")
+#include <gcrypt.h>
+GCC_DIAG_ON("-Wdeprecated-declarations")
+#include <string.h>
+#include <mysql.h>
+
+/* The module configuration */
+struct ts_conf {
+	char * destination_sip; 
+	char * destination_realm;
+	char * username;
+	char * password;
+	char * sip_aor;
+};
+extern struct ts_conf * ts_conf;
+
+//Storage for some useful AVPs
+struct sip_dict{
+	struct dict_object * Auth_Session_State;
+	struct dict_object * Auth_Application_Id;
+	struct dict_object * Destination_Host;
+	struct dict_object * User_Name;
+	struct dict_object * Session_Id;
+	struct dict_object * Redirect_Host;
+	struct dict_object * Redirect_Host_Usage;
+	struct dict_object * SIP_Auth_Data_Item;
+	struct dict_object * SIP_Accounting_Information;
+	struct dict_object * SIP_Accounting_Server_URI;
+	struct dict_object * SIP_Credit_Control_Server_URI;
+	struct dict_object * SIP_Server_Assignment_Type;
+	struct dict_object * SIP_Item_Number;
+	struct dict_object * SIP_User_Authorization_Type;
+	struct dict_object * SIP_Supported_User_Data_Type;
+	struct dict_object * SIP_User_Data;
+	struct dict_object * SIP_User_Data_Type;
+	struct dict_object * SIP_User_Data_Contents;
+	struct dict_object * SIP_User_Data_Already_Available;
+	struct dict_object * SIP_Visited_Network_Id;
+	struct dict_object * SIP_Authorization;
+	struct dict_object * SIP_Authenticate;
+	struct dict_object * SIP_Number_Auth_Items;	
+	struct dict_object * SIP_Authentication_Scheme;
+	struct dict_object * SIP_Authentication_Info;	
+	struct dict_object * SIP_Server_URI;
+	struct dict_object * SIP_Server_Capabilities;
+	struct dict_object * SIP_Mandatory_Capability;
+	struct dict_object * SIP_Optional_Capability;
+	struct dict_object * SIP_Method;
+	struct dict_object * SIP_AOR;
+	struct dict_object * SIP_Deregistration_Reason;
+	struct dict_object * SIP_Reason_Code;
+	struct dict_object * SIP_Reason_Info;
+	struct dict_object * Digest_URI;		
+	struct dict_object * Digest_Nonce;
+	struct dict_object * Digest_Nonce_Count;
+	struct dict_object * Digest_CNonce;		
+	struct dict_object * Digest_Realm;		
+	struct dict_object * Digest_Response;	
+	struct dict_object * Digest_Response_Auth;	
+	struct dict_object * Digest_Username;	
+	struct dict_object * Digest_Method;
+	struct dict_object * Digest_QOP;	
+	struct dict_object * Digest_Algorithm;
+	struct dict_object * Digest_HA1;
+	struct dict_object * Destination_Realm;
+};
+
+extern  struct sip_dict  sip_dict;
+extern struct session_handler * ts_sess_hdl;
+
+int ts_entry();
+void fd_ext_fini(void);
+
+int test_sip_LIR_cb();
+int test_sip_UAR_cb();
+int test_sip_SAR_cb();
+int test_sipSL_LIR_cb();
+
+int test_sip_default_cb( struct msg ** msg, struct avp * avp, struct session * sess, void * opaque, enum disp_action * act);
+int test_sip_MAA_cb( struct msg ** msg, struct avp * avp, struct session * sess, void * opaque, enum disp_action * act);
+int test_sip_RTR_cb( struct msg ** msg, struct avp * avp, struct session * sess, void * opaque, enum disp_action * act);
+int test_sip_UAA_cb( struct msg ** msg, struct avp * avp, struct session * sess, void * opaque, enum disp_action * act);
+int test_sip_LIA_cb( struct msg ** msg, struct avp * avp, struct session * sess, void * opaque, enum disp_action * act);
+int test_sip_SAA_cb( struct msg ** msg, struct avp * avp, struct session * sess, void * opaque, enum disp_action * act);
+int test_sipSL_LIA_cb( struct msg ** msg, struct avp * avp, struct session * sess, void * opaque, enum disp_action * act);
diff --git a/extensions/test_sip/test_sip.l b/extensions/test_sip/test_sip.l
new file mode 100644
index 0000000..668591d
--- /dev/null
+++ b/extensions/test_sip/test_sip.l
@@ -0,0 +1,137 @@
+/*********************************************************************************************************
+* Software License Agreement (BSD License)                                                               *
+* Author: Alexandre Westfahl <awestfahl@freediameter.net>						 *
+*													 *
+* Copyright (c) 2010, Alexandre Westfahl, Teraoka Laboratory (Keio University), and the WIDE Project. 	 *		
+*													 *
+* All rights reserved.											 *
+* Based on ta_conf.l (Sebastien Decugis <sdecugis@freediameter.net>)					 *
+* 													 *
+* Redistribution and use of this software in source and binary forms, with or without modification, are  *
+* permitted provided that the following conditions are met:						 *
+* 													 *
+* * Redistributions of source code must retain the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer.										 *
+*    													 *
+* * Redistributions in binary form must reproduce the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer in the documentation and/or other						 *
+*   materials provided with the distribution.								 *
+* 													 *
+* * Neither the name of the Teraoka Laboratory nor the 							 *
+*   names of its contributors may be used to endorse or 						 *
+*   promote products derived from this software without 						 *
+*   specific prior written permission of Teraoka Laboratory 						 *
+*   													 *
+* 													 *
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED *
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
+* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR *
+* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 	 *
+* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 	 *
+* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR *
+* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF   *
+* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.								 *
+*********************************************************************************************************/
+
+
+
+%{
+#include "test_sip.h"
+/* Include yacc tokens definitions */
+#include "test_sip.tab.h"
+
+/* Update the column information */
+#define YY_USER_ACTION { 						\
+	yylloc->first_column = yylloc->last_column + 1; 		\
+	yylloc->last_column = yylloc->first_column + yyleng - 1;	\
+}
+
+/* Avoid warning with newer flex */
+#define YY_NO_INPUT
+
+%}
+
+%option bison-bridge bison-locations
+%option noyywrap
+%option nounput
+
+%%
+
+	/* Update the line count */
+\n			{
+				yylloc->first_line++; 
+				yylloc->last_line++; 
+				yylloc->last_column=0; 
+			}
+	 
+	/* Eat all spaces but not new lines */
+([[:space:]]{-}[\n])+	;
+	/* Eat all comments */
+#.*$			;
+
+	/* Recognize any integer */
+[-]?[[:digit:]]+		{
+				/* Convert this to an integer value */
+				int ret=0;
+				ret = sscanf(yytext, "%i", &yylval->integer);
+				if (ret != 1) {
+					/* No matching: an error occurred */
+					fd_log_debug("Unable to convert the value '%s' to a valid number: %s", yytext, strerror(errno));
+					return LEX_ERROR; /* trig an error in yacc parser */
+					/* Maybe we could REJECT instead of failing here? */
+				}
+				return INTEGER;
+			}
+
+	/* Recognize quoted strings -- we do not support escaped \" in the string currently. */
+\"[^\"]+\"		{
+				/* Match a quoted string. Let's be very permissive. */
+				yylval->string = strdup(yytext+1);
+				if (!yylval->string) {
+					fd_log_debug("Unable to copy the string '%s': %s", yytext, strerror(errno));
+					TRACE_DEBUG(INFO, "strdup failed");
+					return LEX_ERROR; /* trig an error in yacc parser */
+				}
+				yylval->string[strlen(yytext) - 2] = '\0';
+				return QSTRING;
+			}
+
+
+
+
+	/* Recognize the tokens */	
+(?i:"username")	{
+				return TESTSIP_USERNAME;
+			}
+
+(?i:"password")		{
+				return TESTSIP_PASSWORD;
+			}
+
+(?i:"sip_aor")		{
+				return TESTSIP_SIPAOR;
+			}
+
+(?i:"destination_realm")		{
+				return TESTSIP_DESTREALM;
+			}
+
+(?i:"destination_sip")		{
+				return TESTSIP_DESTSIP;
+			}
+			
+
+
+			
+	/* Valid single characters for yyparse */
+[=;]			{ return yytext[0]; }
+
+	/* Unrecognized sequence, if it did not match any previous pattern */
+[^[:space:]"*=>;\n]+	{ 
+				fd_log_debug("Unrecognized text on line %d col %d: '%s'.", yylloc->first_line, yylloc->first_column, yytext);
+			 	return LEX_ERROR; 
+			}
+
+%%
diff --git a/extensions/test_sip/test_sip.y b/extensions/test_sip/test_sip.y
new file mode 100644
index 0000000..e699c28
--- /dev/null
+++ b/extensions/test_sip/test_sip.y
@@ -0,0 +1,175 @@
+/*********************************************************************************************************
+* Software License Agreement (BSD License)                                                               *
+* Author: Alexandre Westfahl <awestfahl@freediameter.net>						 *
+*													 *
+* Copyright (c) 2010, Alexandre Westfahl, Teraoka Laboratory (Keio University), and the WIDE Project. 	 *		
+*													 *
+* All rights reserved.											 *
+* Based on ta_conf.y (Sebastien Decugis <sdecugis@freediameter.net>)					 *
+* 													 *
+* Redistribution and use of this software in source and binary forms, with or without modification, are  *
+* permitted provided that the following conditions are met:						 *
+* 													 *
+* * Redistributions of source code must retain the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer.										 *
+*    													 *
+* * Redistributions in binary form must reproduce the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer in the documentation and/or other						 *
+*   materials provided with the distribution.								 *
+* 													 *
+* * Neither the name of the Teraoka Laboratory nor the 							 *
+*   names of its contributors may be used to endorse or 						 *
+*   promote products derived from this software without 						 *
+*   specific prior written permission of Teraoka Laboratory 						 *
+*   													 *
+* 													 *
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED *
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
+* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR *
+* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 	 *
+* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 	 *
+* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR *
+* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF   *
+* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.								 *
+*********************************************************************************************************/
+
+/* For development only : */
+%debug 
+%error-verbose
+
+/* The parser receives the configuration file filename as parameter */
+%parse-param {char * conffile}
+
+/* Keep track of location */
+%locations 
+%pure-parser
+
+%{
+#include "test_sip.h"
+#include "test_sip.tab.h"	/* bison is not smart enough to define the YYLTYPE before including this code, so... */
+
+#include <string.h>
+#include <errno.h>
+
+/* Forward declaration */
+int yyparse(char * conffile);
+
+/* Parse the configuration file */
+int ts_conf_handle(char * conffile)
+{
+	extern FILE * test_sipin;
+	int ret;
+	
+	TRACE_ENTRY("%p", conffile);
+	
+	TRACE_DEBUG (FULL, "Parsing configuration file: %s...", conffile);
+	
+	test_sipin = fopen(conffile, "r");
+	if (test_sipin == NULL) {
+		ret = errno;
+		fd_log_debug("Unable to open extension configuration file %s for reading: %s", conffile, strerror(ret));
+		TRACE_DEBUG (INFO, "Error occurred, message logged -- configuration file.");
+		return ret;
+	}
+
+	ret = yyparse(conffile);
+
+	fclose(test_sipin);
+
+	if (ret != 0) {
+		TRACE_DEBUG (INFO, "Unable to parse the configuration file.");
+		return EINVAL;
+	}
+	
+	return 0;
+}
+
+/* The Lex parser prototype */
+int test_sipflex(YYSTYPE *lvalp, YYLTYPE *llocp);
+
+/* Function to report the errors */
+void yyerror (YYLTYPE *ploc, char * conffile, char const *s)
+{
+	TRACE_DEBUG(INFO, "Error in configuration parsing");
+	
+	if (ploc->first_line != ploc->last_line)
+		fd_log_debug("%s:%d.%d-%d.%d : %s", conffile, ploc->first_line, ploc->first_column, ploc->last_line, ploc->last_column, s);
+	else if (ploc->first_column != ploc->last_column)
+		fd_log_debug("%s:%d.%d-%d : %s", conffile, ploc->first_line, ploc->first_column, ploc->last_column, s);
+	else
+		fd_log_debug("%s:%d.%d : %s", conffile, ploc->first_line, ploc->first_column, s);
+}
+
+%}
+
+/* Values returned by lex for token */
+%union {
+	char 		*string;	/* The string is allocated by strdup in lex.*/
+	int		 integer;		/* Store integer values */
+}
+
+/* In case of error in the lexical analysis */
+%token 		LEX_ERROR
+
+/* Key words */
+%token 		TESTSIP_DESTREALM
+%token 		TESTSIP_DESTSIP
+%token 		TESTSIP_PASSWORD
+%token 		TESTSIP_SIPAOR
+%token 		TESTSIP_USERNAME
+
+/* Tokens and types for routing table definition */
+/* A (de)quoted string (malloc'd in lex parser; it must be freed after use) */
+%token <string>	QSTRING
+
+/* An integer value */
+%token <integer> INTEGER
+
+/* -------------------------------------- */
+%%
+
+	/* The grammar definition */
+conffile:		/* empty grammar is OK */
+			| conffile destination_realm
+			| conffile destination_sip
+			| conffile username
+			| conffile password
+			| conffile sip_aor
+			;
+
+destination_realm:			TESTSIP_DESTREALM '=' QSTRING ';'
+			{
+				free(ts_conf->destination_realm);
+				ts_conf->destination_realm = $3;
+			}
+			;
+
+destination_sip:			TESTSIP_DESTSIP '=' QSTRING ';'
+			{
+				free(ts_conf->destination_sip);
+				ts_conf->destination_sip = $3;
+			}
+			;
+
+username:			TESTSIP_USERNAME '=' QSTRING ';'
+			{
+				free(ts_conf->username);
+				ts_conf->username = $3;
+			}
+			;
+
+password:			TESTSIP_PASSWORD '=' QSTRING ';'
+			{
+				free(ts_conf->password);
+				ts_conf->password = $3;
+			}
+			;
+
+sip_aor:			TESTSIP_SIPAOR '=' QSTRING ';'
+			{
+				free(ts_conf->sip_aor);
+				ts_conf->sip_aor = $3;
+			}
+			;
diff --git a/extensions/test_sip/userauthorization.c b/extensions/test_sip/userauthorization.c
new file mode 100644
index 0000000..e07a5ad
--- /dev/null
+++ b/extensions/test_sip/userauthorization.c
@@ -0,0 +1,156 @@
+/*********************************************************************************************************
+* Software License Agreement (BSD License)                                                               *
+* Author: Alexandre Westfahl <awestfahl@freediameter.net>						 *
+*													 *
+* Copyright (c) 2010, Alexandre Westfahl, Teraoka Laboratory (Keio University), and the WIDE Project. 	 *		
+*													 *
+* All rights reserved.											 *
+* 													 *
+* Redistribution and use of this software in source and binary forms, with or without modification, are  *
+* permitted provided that the following conditions are met:						 *
+* 													 *
+* * Redistributions of source code must retain the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer.										 *
+*    													 *
+* * Redistributions in binary form must reproduce the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer in the documentation and/or other						 *
+*   materials provided with the distribution.								 *
+* 													 *
+* * Neither the name of the Teraoka Laboratory nor the 							 *
+*   names of its contributors may be used to endorse or 						 *
+*   promote products derived from this software without 						 *
+*   specific prior written permission of Teraoka Laboratory 						 *
+*   													 *
+* 													 *
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED *
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
+* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR *
+* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 	 *
+* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 	 *
+* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR *
+* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF   *
+* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.								 *
+*********************************************************************************************************/
+#include "test_sip.h"
+
+//Called to send a UAR
+int test_sip_UAR_cb()
+{
+	struct dict_object * uar_model=NULL;
+	struct msg * message=NULL;
+	struct avp *avp=NULL;
+	union avp_value value;
+	
+	//Fake values START
+	char *sip_aor="sip:aw-lappy@tera.ics.keio.ac.jp";
+	size_t aor_len=strlen(sip_aor); 
+	 char *destination_realm="tera.ics.keio.ac.jp";
+	size_t destination_realmlen=strlen(destination_realm);
+	 char *destination_host="suika.tera.ics.keio.ac.jp";
+	size_t destination_hostlen=strlen(destination_host);
+	 char *username="aw-lappy";
+	size_t usernamelen=strlen(username);
+	 char *visitednetwork="Pink";
+	size_t visitednetworklen=strlen(visitednetwork);
+	int registrationtype = 2;
+	//Fake values STOP
+	
+	//Create the base message for an RTR
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_COMMAND, CMD_BY_NAME, "User-Authorization-Request", &uar_model, ENOENT) );
+	CHECK_FCT( fd_msg_new (uar_model, 0, &message));
+	
+	
+	
+	// Create a new session 
+	{
+		CHECK_FCT( fd_msg_new_session( message, (os0_t)"appsip", CONSTSTRLEN("appsip") ) );
+	}
+	
+	//Add the Auth-Application-Id 
+	{
+		CHECK_FCT( fd_msg_avp_new ( sip_dict.Auth_Application_Id, 0, &avp ) );
+		value.i32 = 6;
+		CHECK_FCT( fd_msg_avp_setvalue ( avp, &value ) );
+		CHECK_FCT( fd_msg_avp_add ( message, MSG_BRW_LAST_CHILD, avp) );
+	}
+	
+	//Auth_Session_State
+	{
+		CHECK_FCT( fd_msg_avp_new ( sip_dict.Auth_Session_State, 0, &avp ) );
+		value.i32=1;
+		CHECK_FCT( fd_msg_avp_setvalue( avp, &value ) );
+		CHECK_FCT( fd_msg_avp_add( message, MSG_BRW_LAST_CHILD, avp ) );
+	}
+	
+	//Origin_Host & Origin_Realm
+	CHECK_FCT( fd_msg_add_origin ( message, 0 ));
+	
+	//Destination_Host
+	{
+		CHECK_FCT( fd_msg_avp_new ( sip_dict.Destination_Host, 0, &avp ) );
+		value.os.data=(unsigned char *)destination_host;
+		value.os.len=destination_hostlen;
+		CHECK_FCT( fd_msg_avp_setvalue( avp, &value ) );
+		CHECK_FCT( fd_msg_avp_add( message, MSG_BRW_LAST_CHILD, avp ) );
+	}
+	//Destination_Realm
+	{
+		CHECK_FCT( fd_msg_avp_new ( sip_dict.Destination_Realm, 0, &avp ) );
+		value.os.data=(unsigned char *)destination_realm;
+		value.os.len=destination_realmlen;
+		CHECK_FCT( fd_msg_avp_setvalue( avp, &value ) );
+		CHECK_FCT( fd_msg_avp_add( message, MSG_BRW_LAST_CHILD, avp ) );
+	}
+	
+	//SIP_AOR
+	{
+		
+		CHECK_FCT( fd_msg_avp_new ( sip_dict.SIP_AOR, 0, &avp ) );
+		value.os.data=(unsigned char *)sip_aor;
+		value.os.len=aor_len;
+		CHECK_FCT( fd_msg_avp_setvalue( avp, &value ) );
+		CHECK_FCT( fd_msg_avp_add( message, MSG_BRW_LAST_CHILD, avp ) );
+		
+	}
+	//Username
+	{
+		
+		CHECK_FCT( fd_msg_avp_new ( sip_dict.User_Name, 0, &avp ) );
+		value.os.data=(unsigned char *)username;
+		value.os.len=usernamelen;
+		CHECK_FCT( fd_msg_avp_setvalue( avp, &value ) );
+		CHECK_FCT( fd_msg_avp_add( message, MSG_BRW_LAST_CHILD, avp ) );
+		
+	}
+	//Visited Network
+	{
+		
+		CHECK_FCT( fd_msg_avp_new ( sip_dict.SIP_Visited_Network_Id, 0, &avp ) );
+		value.os.data=(unsigned char *)visitednetwork;
+		value.os.len=visitednetworklen;
+		CHECK_FCT( fd_msg_avp_setvalue( avp, &value ) );
+		CHECK_FCT( fd_msg_avp_add( message, MSG_BRW_LAST_CHILD, avp ) );
+		
+	}
+	//Authorization Type
+	{
+		
+		CHECK_FCT( fd_msg_avp_new ( sip_dict.SIP_User_Authorization_Type, 0, &avp ) );
+		value.i32=registrationtype;
+		CHECK_FCT( fd_msg_avp_setvalue( avp, &value ) );
+		CHECK_FCT( fd_msg_avp_add( message, MSG_BRW_LAST_CHILD, avp ) );
+		
+	}
+	
+	CHECK_FCT( fd_msg_send( &message, NULL, NULL ));
+	
+	return 0;
+}
+
+int test_sip_UAA_cb( struct msg ** msg, struct avp * paramavp, struct session * sess, void * opaque, enum disp_action * act)
+{
+	
+	return 0;
+}
diff --git a/freeDiameterd/CMakeLists.txt b/freeDiameterd/CMakeLists.txt
new file mode 100644
index 0000000..792afde
--- /dev/null
+++ b/freeDiameterd/CMakeLists.txt
@@ -0,0 +1,22 @@
+# The subproject name
+Project("freeDiameter simple daemon" C)
+
+# Since it uses the libfdcore.h, it needs the include dependencies
+INCLUDE_DIRECTORIES(${LFDCORE_INCLUDES})
+
+# Build the executable
+ADD_EXECUTABLE(freeDiameterd main.c)
+
+# The version
+SET_TARGET_PROPERTIES(freeDiameterd PROPERTIES 
+	VERSION ${FD_PROJECT_VERSION_MAJOR}.${FD_PROJECT_VERSION_MINOR}.${FD_PROJECT_VERSION_REV})
+
+# The link command
+TARGET_LINK_LIBRARIES(freeDiameterd libfdproto libfdcore ${GNUTLS_LIBRARIES})
+
+####
+## INSTALL section ##
+
+INSTALL(TARGETS freeDiameterd
+	RUNTIME DESTINATION ${INSTALL_DAEMON_SUFFIX}
+	COMPONENT freeDiameter-daemon)
diff --git a/freeDiameterd/main.c b/freeDiameterd/main.c
new file mode 100644
index 0000000..c4ecbb4
--- /dev/null
+++ b/freeDiameterd/main.c
@@ -0,0 +1,296 @@
+/*********************************************************************************************************
+* Software License Agreement (BSD License)                                                               *
+* Author: Sebastien Decugis <sdecugis@freediameter.net>							 *
+*													 *
+* Copyright (c) 2015, WIDE Project and NICT								 *
+* All rights reserved.											 *
+* 													 *
+* Redistribution and use of this software in source and binary forms, with or without modification, are  *
+* permitted provided that the following conditions are met:						 *
+* 													 *
+* * Redistributions of source code must retain the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer.										 *
+*    													 *
+* * Redistributions in binary form must reproduce the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer in the documentation and/or other						 *
+*   materials provided with the distribution.								 *
+* 													 *
+* * Neither the name of the WIDE Project or NICT nor the 						 *
+*   names of its contributors may be used to endorse or 						 *
+*   promote products derived from this software without 						 *
+*   specific prior written permission of WIDE Project and 						 *
+*   NICT.												 *
+* 													 *
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED *
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
+* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR *
+* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 	 *
+* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 	 *
+* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR *
+* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF   *
+* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.								 *
+*********************************************************************************************************/
+
+#include <freeDiameter/freeDiameter-host.h>
+#include <freeDiameter/libfdcore.h>
+
+#include <signal.h>
+#include <getopt.h>
+#include <locale.h>
+
+
+/* forward declarations */
+static int main_cmdline(int argc, char *argv[]);
+static void * catch_signals(void * arg);
+static pthread_t signals_thr;
+
+static char *conffile = NULL;
+static int gnutls_debug = 0;
+
+/* gnutls debug */
+static void fd_gnutls_debug(int level, const char * str) {
+	fd_log_debug(" [gnutls:%d] %s", level, str);
+}
+
+
+/* freeDiameter starting point */
+int main(int argc, char * argv[])
+{
+	int ret;
+	sigset_t sig_all;
+	
+	/* Block all signals from the current thread and all its future children -- we will catch everything in catch_signals */
+	sigfillset(&sig_all);
+	ret = pthread_sigmask(SIG_BLOCK, &sig_all, NULL);
+	ASSERT(ret == 0);
+	
+	/* Parse the command-line */
+	ret = main_cmdline(argc, argv);
+	if (ret != 0) {
+		return ret;
+	}
+	
+	/* Initialize the core library */
+	ret = fd_core_initialize();
+	if (ret != 0) {
+		fprintf(stderr, "An error occurred during freeDiameter core library initialization.\n");
+		return ret;
+	}
+	
+	/* Set gnutls debug level ? */
+	if (gnutls_debug) {
+		gnutls_global_set_log_function((gnutls_log_func)fd_gnutls_debug);
+		gnutls_global_set_log_level (gnutls_debug);
+		TRACE_DEBUG(INFO, "Enabled GNUTLS debug at level %d", gnutls_debug);
+	}
+	
+	/* Parse the configuration file */
+	CHECK_FCT_DO( fd_core_parseconf(conffile), goto error );
+	
+	/* Start the servers */
+	CHECK_FCT_DO( fd_core_start(), goto error );
+	
+	/* Allow SIGINT and SIGTERM from this point to terminate the application */
+	CHECK_POSIX_DO( pthread_create(&signals_thr, NULL, catch_signals, NULL), goto error );
+	
+	TRACE_DEBUG(INFO, FD_PROJECT_BINARY " daemon initialized.");
+
+	/* Now, just wait for termination */
+	CHECK_FCT( fd_core_wait_shutdown_complete() );
+	
+	/* Just in case it was not the result of a signal, we cancel signals_thr */
+	fd_thr_term(&signals_thr);
+	
+	return 0;
+error:	
+	CHECK_FCT_DO( fd_core_shutdown(),  );
+	CHECK_FCT( fd_core_wait_shutdown_complete() );
+	fd_thr_term(&signals_thr);
+	return -1;
+}
+
+
+/* Display package version */
+static void main_version_core(void)
+{
+	printf("%s, version %s\n", FD_PROJECT_NAME, fd_core_version);
+}
+
+/* Display package version and general info */
+static void main_version(void)
+{
+	main_version_core();
+	printf( "%s\n", FD_PROJECT_COPYRIGHT);
+	printf( "\nSee " FD_PROJECT_NAME " homepage at http://www.freediameter.net/\n"
+		" for information, updates and bug reports on this software.\n");
+}
+
+/* Print command-line options */
+static void main_help( void )
+{
+	main_version_core();
+	printf(	"  This daemon is an implementation of the Diameter protocol\n"
+		"  used for Authentication, Authorization, and Accounting (AAA).\n");
+	printf("\nUsage:  " FD_PROJECT_BINARY " [OPTIONS]...\n");
+	printf( "  -h, --help             Print help and exit\n"
+  		"  -V, --version          Print version and exit\n"
+  		"  -c, --config=filename  Read configuration from this file instead of the \n"
+		"                           default location (" DEFAULT_CONF_PATH "/" FD_DEFAULT_CONF_FILENAME ").\n");
+ 	printf( "\nDebug:\n"
+  		"  These options are mostly useful for developers\n"
+  		"  -l, --dbglocale         Set the locale for error messages\n"
+  		"  -d, --debug             Increase verbosity of debug messages if default logger is used\n"
+  		"  -q, --quiet             Decrease verbosity if default logger is used\n"
+  		"  -f, --dbg_func <func>   Enable all traces within the function <func>\n"
+  		"  -F, --dbg_file <file.c> Enable all traces within the file <file.c> (basename match)\n"
+  		"  --dbg_gnutls <int>      Enable GNU TLS debug at level <int>\n"
+	);
+}
+
+/* Parse the command-line */
+static int main_cmdline(int argc, char *argv[])
+{
+	int c;
+	int option_index = 0;
+	char * locale;
+	
+      	struct option long_options[] = {
+		{ "help",	no_argument, 		NULL, 'h' },
+		{ "version",	no_argument, 		NULL, 'V' },
+		{ "config",	required_argument, 	NULL, 'c' },
+		{ "debug",	no_argument, 		NULL, 'd' },
+		{ "quiet",	no_argument, 		NULL, 'q' },
+		{ "dbglocale",	optional_argument, 	NULL, 'l' },
+		{ "dbg_func",	required_argument, 	NULL, 'f' },
+		{ "dbg_file",	required_argument, 	NULL, 'F' },
+		{ "dbg_gnutls",	required_argument, 	NULL, 'g' },
+		{ NULL,		0, 			NULL, 0 }
+	};
+	
+	/* Loop on arguments */
+	while (1) {
+		c = getopt_long (argc, argv, "hVc:dql:f:F:g:", long_options, &option_index);
+		if (c == -1) 
+			break;	/* Exit from the loop.  */
+		
+		switch (c) {
+			case 'h':	/* Print help and exit.  */
+				main_help();
+				exit(0);
+
+			case 'V':	/* Print version and exit.  */
+				main_version();
+				exit(0);
+
+			case 'c':	/* Read configuration from this file instead of the default location..  */
+				if (optarg == NULL ) {
+					fprintf(stderr, "Missing argument with --config directive\n");
+					return EINVAL;
+				}
+				conffile = optarg;
+				break;
+
+			case 'l':	/* Change the locale.  */
+				locale = setlocale(LC_ALL, optarg?:"");
+				if (!locale) {
+					fprintf(stderr, "Unable to set locale (%s)\n", optarg);
+					return EINVAL;
+				}
+				break;
+				
+			case 'd':	/* Increase verbosity of debug messages.  */
+				fd_g_debug_lvl--;
+				break;
+				
+			case 'f':	/* Full debug for the function with this name.  */
+				#ifdef DEBUG
+				fd_debug_one_function = optarg;
+				fd_g_debug_lvl = FD_LOG_DEBUG;
+				#else /* DEBUG */
+				fprintf(stderr, "Error: must compile with DEBUG support to use --dbg_func feature!\n");
+				return EINVAL;
+				#endif /* DEBUG */
+				break;
+				
+			case 'F':	/* Full debug for the file with this name.  */
+				#ifdef DEBUG
+				fd_debug_one_file = basename(optarg);
+				fd_g_debug_lvl = FD_LOG_DEBUG;
+				#else /* DEBUG */
+				fprintf(stderr, "Error: must compile with DEBUG support to use --dbg_file feature!\n");
+				return EINVAL;
+				#endif /* DEBUG */
+				break;
+				
+			case 'g':	/* Set a debug level and function for GNU TLS calls.  */
+				gnutls_debug = (int)atoi(optarg);
+				break;
+				
+			case 'q':	/* Decrease verbosity then remove debug messages.  */
+				fd_g_debug_lvl++;
+				break;
+
+			case '?':	/* Invalid option.  */
+				/* `getopt_long' already printed an error message.  */
+				fprintf(stderr, "getopt_long found an invalid character\n");
+				return EINVAL;
+
+			default:	/* bug: option not considered.  */
+				fprintf(stderr, "A command-line option is missing in parser: %c\n", c);
+				ASSERT(0);
+				return EINVAL;
+		}
+	}
+		
+	return 0;
+}
+
+/* Handle some signals */
+static void * catch_signals(void * arg)
+{
+	sigset_t ss;
+	fd_log_threadname ( "signals catcher" );
+	
+	sigemptyset(&ss);
+	
+	/* Signals that terminate the daemon */
+	sigaddset(&ss, SIGTERM);
+	sigaddset(&ss, SIGINT);
+	
+	/* Signals that send an event */
+	sigaddset(&ss, SIGUSR1);
+	sigaddset(&ss, SIGUSR2);
+	
+	/* We unblock all other signals, so that their default handler is used (such as SIGTSTP) */
+	CHECK_SYS_DO( pthread_sigmask( SIG_SETMASK, &ss, NULL ), goto out );
+	
+	/* Now loop on the reception of the signal */
+	while (1) {
+		int sig, *ps;
+		
+		/* Wait to receive the next signal */
+		CHECK_POSIX_DO( sigwait(&ss, &sig), break );
+		
+		TRACE_DEBUG(FULL, "Signal %d caught", sig);
+		
+		switch (sig) {
+			case SIGUSR1:
+			case SIGUSR2:
+				CHECK_MALLOC_DO( ps = malloc(sizeof(int)), goto out);
+				*ps = sig;
+				CHECK_FCT_DO( fd_event_send(fd_g_config->cnf_main_ev, FDEV_TRIGGER, sizeof(int), ps), goto out );
+				break;
+				
+			case SIGINT:
+			case SIGTERM:
+				CHECK_FCT_DO( fd_core_shutdown(), goto out );
+
+		}
+	}
+out:	
+	/* Better way to handle this ? */
+	ASSERT(0);
+	return NULL;
+}
diff --git a/include/freeDiameter/CMakeLists.txt b/include/freeDiameter/CMakeLists.txt
new file mode 100644
index 0000000..4db3293
--- /dev/null
+++ b/include/freeDiameter/CMakeLists.txt
@@ -0,0 +1,249 @@
+#CMake configuration for freeDiameter include directory
+
+Project("freeDiameter includes directory" C)
+
+########################
+# Configurable parameters
+
+# Disable SCTP support completely ?
+OPTION(DISABLE_SCTP "Disable SCTP support?" OFF)
+IF (NOT DISABLE_SCTP)
+	OPTION(DEBUG_SCTP "Verbose SCTP (for debug)?" OFF)
+	OPTION(SCTP_USE_MAPPED_ADDRESSES "Use v6-mapped v4 addresses in SCTP (workaround some SCTP limitations)?" OFF)
+ENDIF (NOT DISABLE_SCTP)
+
+# Find TODO items in the code easily ?
+OPTION(ERRORS_ON_TODO "(development) Generate compilation errors on TODO items ?" OFF)
+
+# In DEBUG mode, each log can contain pid, calling function and file for easy debug. Set to ON to display this information.
+OPTION(DEBUG_WITH_META "Show calling location in logs?" OFF)
+	
+# Create the absolute path for searching extensions
+SET(DEFAULT_EXTENSIONS_PATH ${CMAKE_INSTALL_PREFIX}/${INSTALL_EXTENSIONS_SUFFIX})
+
+# IDNA considerations
+OPTION(DIAMID_IDNA_IGNORE "Ignore completely invalid characters in Diameter Identities (process blindly)?" OFF)
+IF (NOT DIAMID_IDNA_IGNORE)
+	OPTION (DIAMID_IDNA_REJECT "Reject internationalized Diameter Identities, do not attempt to convert it (stringprep) ?" OFF)
+ENDIF (NOT DIAMID_IDNA_IGNORE)
+
+# Disable expiration of connections with dynamically connected peers as per RFC 3539 ? (default is enabled)
+# Note: if someone needs, we could also make the delay configurable here...
+OPTION(DISABLE_PEER_EXPIRY "Disable RFC3539 Peers Connections Expiration after inactivity?" OFF)
+
+# The following workaround increases compatibility with some implementations without breaking anything in freeDiameter, 
+# so it can be enabled without risk. We keep it disabled by default anyway for those people who use freeDiameter to check the 
+# compliancy of their implementation with the Diameter RFC...
+OPTION(WORKAROUND_ACCEPT_INVALID_VSAI "Do not reject a CER/CEA with a Vendor-Specific-Application-Id AVP containing both Auth- and Acct- application AVPs?" OFF)
+
+MARK_AS_ADVANCED(DISABLE_SCTP DEBUG_SCTP SCTP_USE_MAPPED_ADDRESSES ERRORS_ON_TODO DEBUG_WITH_META DIAMID_IDNA_IGNORE DIAMID_IDNA_REJECT DISABLE_PEER_EXPIRY WORKAROUND_ACCEPT_INVALID_VSAI)
+
+########################
+### System checks part
+
+INCLUDE (CheckLibraryExists)
+INCLUDE (CheckFunctionExists)
+INCLUDE (CheckIncludeFiles)
+INCLUDE (CheckSymbolExists) 
+INCLUDE (CheckCSourceCompiles)
+INCLUDE (TestBigEndian)
+
+
+### System checks -- mandatory support
+
+# We need the getopt_long function
+CHECK_FUNCTION_EXISTS (getopt_long HAVE_LONG_OPTIONS)
+IF (NOT HAVE_LONG_OPTIONS)
+   MESSAGE(SEND_ERROR "The getopt_long function is not found, please add needed library in build system")
+ENDIF (NOT HAVE_LONG_OPTIONS)
+
+# getifaddrs ?
+CHECK_FUNCTION_EXISTS (getifaddrs HAVE_GETIFADDRS)
+IF (NOT HAVE_GETIFADDRS)
+   MESSAGE(SEND_ERROR "The getifaddrs function is currently required by freeDiameter.")
+ENDIF (NOT HAVE_GETIFADDRS)
+
+
+### System checks -- for freeDiameter-host.h
+
+# Check byte ordering
+TEST_BIG_ENDIAN(HOST_BIG_ENDIAN)
+
+# Check if ntohll is provided on the system
+CHECK_SYMBOL_EXISTS(ntohll netinet/in.h HAVE_NTOHLL)
+
+# malloc.h ?
+CHECK_INCLUDE_FILES (malloc.h HAVE_MALLOC_H)
+
+# strndup ? Missing on OS X
+CHECK_FUNCTION_EXISTS (strndup HAVE_STRNDUP)
+
+
+### System checks -- for includes / link
+
+# pthreads
+INCLUDE(FindThreads)
+SET(CMAKE_THREAD_LIBS_INIT ${CMAKE_THREAD_LIBS_INIT} PARENT_SCOPE)
+
+# clock_gettime
+SET(HAVE_CLOCK_GETTIME "")
+CHECK_FUNCTION_EXISTS (clock_gettime HAVE_NATIVE_CLOCK_GETTIME)
+IF (HAVE_NATIVE_CLOCK_GETTIME)
+   SET(CLOCK_GETTIME_LIBS "")
+   SET(HAVE_CLOCK_GETTIME 1)
+ELSE (HAVE_NATIVE_CLOCK_GETTIME)
+   CHECK_LIBRARY_EXISTS (rt clock_gettime "" HAVE_LIBRT)
+   IF (HAVE_LIBRT)
+     SET(CLOCK_GETTIME_LIBS "-lrt")
+     SET(HAVE_CLOCK_GETTIME 1)
+   ELSE (HAVE_LIBRT)
+     CHECK_LIBRARY_EXISTS (posix4 clock_gettime "" HAVE_LIBPOSIX4)
+     IF (HAVE_LIBPOSIX4)
+       SET(CLOCK_GETTIME_LIBS "-lposix4")
+       SET(HAVE_CLOCK_GETTIME 1)
+     ENDIF (HAVE_LIBPOSIX4)
+   ENDIF (HAVE_LIBRT)
+ENDIF (HAVE_NATIVE_CLOCK_GETTIME)
+SET(CLOCK_GETTIME_LIBS ${CLOCK_GETTIME_LIBS} PARENT_SCOPE)
+
+# dlopen and dlclose: CMAKE_DL_LIBS
+
+# We need the sctp_connectx function among others
+# We need the IPPROTO_SCTP symbol from sys/socket.h, netinet/in.h or netinet/sctp.h
+IF(NOT DISABLE_SCTP)
+	CHECK_FUNCTION_EXISTS(sctp_connectx HAVE_NATIVE_SCTP)
+	IF(NOT HAVE_NATIVE_SCTP)
+		FIND_PACKAGE(SCTP REQUIRED)
+	ENDIF(NOT HAVE_NATIVE_SCTP)
+	# Now check the number of args of this function, since it changed between Ubuntu 9.04 and 9.10
+   	SET(CHECK_SCTP_CONNECTX_4_ARGS_SOURCE_CODE "
+		#include <unistd.h>
+		#include <netinet/sctp.h>
+		int main() {
+		   return sctp_connectx(0, NULL, 0, NULL);
+		}
+		")
+	SET(CMAKE_REQUIRED_INCLUDES ${SCTP_INCLUDE_DIR})
+	SET(CMAKE_REQUIRED_LIBRARIES ${SCTP_LIBRARIES})
+	CHECK_C_SOURCE_COMPILES("${CHECK_SCTP_CONNECTX_4_ARGS_SOURCE_CODE}" SCTP_CONNECTX_4_ARGS)
+ELSE (NOT DISABLE_SCTP)
+	MESSAGE(STATUS "Disabled SCTP support.")
+ENDIF(NOT DISABLE_SCTP)
+SET(SCTP_INCLUDE_DIR ${SCTP_INCLUDE_DIR} PARENT_SCOPE)
+SET(SCTP_LIBRARIES ${SCTP_LIBRARIES} PARENT_SCOPE)
+
+# IDNA process: we use libidn from GNU (unless the function & header files are included in libc)
+IF(NOT DIAMID_IDNA_IGNORE  AND NOT DIAMID_IDNA_REJECT)
+	FIND_PACKAGE(IDNA)
+   	SET(CHECK_IDNA_SOURCE_CODE "
+		#include <idna.h>
+		int main() {
+		   return idna_to_ascii_8z(NULL, NULL, 0);
+		}
+		")
+	SET(CMAKE_REQUIRED_INCLUDES ${IDNA_INCLUDE_DIR})
+	SET(CMAKE_REQUIRED_LIBRARIES ${IDNA_LIBRARIES})
+	CHECK_C_SOURCE_COMPILES("${CHECK_IDNA_SOURCE_CODE}" HAS_IDNA_SUPPORT)
+	IF(NOT HAS_IDNA_SUPPORT)
+		MESSAGE(SEND_ERROR "Unable to find idna.h header or idna_to_ascii_8z function, please install libidn-dev or equivalent, or set DIAMID_IDNA_IGNORE or DIAMID_IDNA_REJECT")
+	ENDIF(NOT HAS_IDNA_SUPPORT)
+ELSE (NOT DIAMID_IDNA_IGNORE  AND NOT DIAMID_IDNA_REJECT)
+	MESSAGE(STATUS "Non-default Internationalized Domain Names (IDN) behavior selected (no stringprep).")
+ENDIF(NOT DIAMID_IDNA_IGNORE  AND NOT DIAMID_IDNA_REJECT)
+SET(IDNA_INCLUDE_DIR ${IDNA_INCLUDE_DIR} PARENT_SCOPE)
+SET(IDNA_LIBRARIES ${IDNA_LIBRARIES} PARENT_SCOPE)
+
+
+# Require GNU TLS for building the library
+FIND_PACKAGE(GnuTLS REQUIRED)
+SET(GNUTLS_INCLUDE_DIR ${GNUTLS_INCLUDE_DIR} PARENT_SCOPE)
+SET(GNUTLS_LIBRARIES ${GNUTLS_LIBRARIES} PARENT_SCOPE)
+
+find_path(GCRYPT_INCLUDE_DIR NAMES gcrypt.h)
+If ( NOT GCRYPT_INCLUDE_DIR )
+	MESSAGE(SEND_ERROR "Unable to find gcrypt.h, please install libgcrypt-dev or equivalent")
+Endif ( NOT GCRYPT_INCLUDE_DIR )
+MARK_AS_ADVANCED(GCRYPT_INCLUDE_DIR)
+SET(GCRYPT_INCLUDE_DIR ${GCRYPT_INCLUDE_DIR} PARENT_SCOPE)
+
+# Also we need libgcrypt to... display its version :(
+find_library(GCRYPT_LIBRARY 
+  NAMES gcrypt
+)
+If ( NOT GCRYPT_LIBRARY )
+	MESSAGE(SEND_ERROR "Unable to find libgcrypt, please install libgcrypt or equivalent")
+Endif ( NOT GCRYPT_LIBRARY )
+SET(GCRYPT_LIBRARY ${GCRYPT_LIBRARY} PARENT_SCOPE)
+
+
+# Check if AI_ADDRCONFIG is available on the system
+CHECK_SYMBOL_EXISTS(AI_ADDRCONFIG "netdb.h" HAVE_AI_ADDRCONFIG)
+
+
+# Check if barriers are available (for test_fifo)
+SET(CMAKE_REQUIRED_INCLUDES "pthread.h")
+SET(CMAKE_REQUIRED_LIBRARIES ${CMAKE_THREAD_LIBS_INIT})
+CHECK_FUNCTION_EXISTS (pthread_barrier_wait HAVE_PTHREAD_BAR)
+SET(HAVE_PTHREAD_BAR ${HAVE_PTHREAD_BAR} PARENT_SCOPE)
+
+
+##########################
+
+# Additional hg version when relevant, stored in version.h
+if (EXISTS "${CMAKE_SOURCE_DIR}/.hg")
+	# Search for hg binary to use
+	FIND_PROGRAM(HGCOMMAND hg)
+	if (HGCOMMAND)
+		# Ok, add the custom target so that hg is executed at every build
+		ADD_CUSTOM_TARGET(version_information
+				   COMMAND ${CMAKE_COMMAND} -D HGCOMMAND="${HGCOMMAND}" -D SRC="${CMAKE_CURRENT_SOURCE_DIR}/version.h.in" -D DST="${CMAKE_CURRENT_BINARY_DIR}/version.h" -P "${CMAKE_SOURCE_DIR}/cmake/Modules/GetVersionWithHg.cmake"
+				   DEPENDS "${CMAKE_SOURCE_DIR}/.hg/dirstate"
+				   WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
+				   COMMENT "Retrieving version of the hg repository"
+				   )
+	else (HGCOMMAND)
+		# Display at least "unknown" rev in this case
+		SET(FD_PROJECT_VERSION_HG "unknown")
+		CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/version.h.in ${CMAKE_CURRENT_BINARY_DIR}/version.h)
+		ADD_CUSTOM_TARGET(version_information DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/version.h)
+	endif(HGCOMMAND)
+else (EXISTS "${CMAKE_SOURCE_DIR}/.hg")
+	# We use the pure version number without extension
+	CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/version.h.in ${CMAKE_CURRENT_BINARY_DIR}/version.h)
+	ADD_CUSTOM_TARGET(version_information DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/version.h)
+endif (EXISTS "${CMAKE_SOURCE_DIR}/.hg")
+
+
+##########################
+
+# LFDPROTO_LIBS = libraries required by the libfdproto.
+SET(LFDPROTO_LIBS ${CLOCK_GETTIME_LIBS} ${CMAKE_THREAD_LIBS_INIT} ${IDNA_LIBRARIES} PARENT_SCOPE)
+# And includes paths
+SET(LFDPROTO_INCLUDES ${IDNA_INCLUDE_DIR} PARENT_SCOPE)
+# Dependencies: the libraries required by any code linking to libfdproto.
+SET(LFDPROTO_LINK_INTERFACES ${CMAKE_THREAD_LIBS_INIT} PARENT_SCOPE)
+
+# LFDCORE_LIBS = libraries required by the libfdcore (in addition to libfdproto and its dependencies)
+SET(LFDCORE_LIBS ${CLOCK_GETTIME_LIBS} ${CMAKE_DL_LIBS} ${SCTP_LIBRARIES} ${GCRYPT_LIBRARY} ${GNUTLS_LIBRARIES} PARENT_SCOPE)
+# And includes paths
+SET(LFDCORE_INCLUDES ${SCTP_INCLUDE_DIR} ${GNUTLS_INCLUDE_DIR} ${GCRYPT_INCLUDE_DIR} PARENT_SCOPE)
+# And dependencies
+SET(LFDCORE_LINK_INTERFACES "" PARENT_SCOPE) 
+		# We don't force other libraries, the programs will link with what it needs
+                # (such as libgnutls if it uses GNUTLS_DEBUG() macro
+		# or libfdproto if it uses some of its interfaces directly)
+		# See freeDiameterd/CMakeLists.txt for an example.
+
+##########################
+
+# Generate the host.h file
+CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/freeDiameter-host.h.in ${CMAKE_CURRENT_BINARY_DIR}/freeDiameter-host.h)
+
+####
+## INSTALL section ##
+
+# The headers from this directory are required to develop new extensions for freeDiameter.
+INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/freeDiameter-host.h libfdproto.h libfdcore.h extension.h
+	DESTINATION ${INSTALL_HEADERS_SUFFIX}
+	COMPONENT freeDiameter-dev)
+
diff --git a/include/freeDiameter/extension.h b/include/freeDiameter/extension.h
new file mode 100644
index 0000000..1d6ea7f
--- /dev/null
+++ b/include/freeDiameter/extension.h
@@ -0,0 +1,103 @@
+/*********************************************************************************************************
+* Software License Agreement (BSD License)                                                               *
+* Author: Sebastien Decugis <sdecugis@freediameter.net>							 *
+*													 *
+* Copyright (c) 2013, WIDE Project and NICT								 *
+* All rights reserved.											 *
+* 													 *
+* Redistribution and use of this software in source and binary forms, with or without modification, are  *
+* permitted provided that the following conditions are met:						 *
+* 													 *
+* * Redistributions of source code must retain the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer.										 *
+*    													 *
+* * Redistributions in binary form must reproduce the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer in the documentation and/or other						 *
+*   materials provided with the distribution.								 *
+* 													 *
+* * Neither the name of the WIDE Project or NICT nor the 						 *
+*   names of its contributors may be used to endorse or 						 *
+*   promote products derived from this software without 						 *
+*   specific prior written permission of WIDE Project and 						 *
+*   NICT.												 *
+* 													 *
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED *
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
+* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR *
+* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 	 *
+* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 	 *
+* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR *
+* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF   *
+* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.								 *
+*********************************************************************************************************/
+
+#ifndef _EXTENSION_H
+#define _EXTENSION_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Include definition of freeDiameter API */
+#include <freeDiameter/freeDiameter-host.h>
+#include <freeDiameter/libfdcore.h>
+
+/* Macro that define the entry point of the extension */
+#define EXTENSION_ENTRY(_name, _function, _depends...)					\
+const char *fd_ext_depends[] = { _name , ## _depends , NULL };				\
+static int extension_loaded = 0;							\
+int fd_ext_init(int major, int minor, char * conffile) {				\
+	if ((major != FD_PROJECT_VERSION_MAJOR)						\
+		|| (minor != FD_PROJECT_VERSION_MINOR)) {				\
+		TRACE_ERROR("This extension (" _name ") was compiled for a different version of freeDiameter.");	\
+		TRACE_DEBUG(INFO, "daemon %d.%d != ext %d.%d",				\
+			major, minor,							\
+			FD_PROJECT_VERSION_MAJOR, FD_PROJECT_VERSION_MINOR);		\
+		return EINVAL;								\
+	}										\
+	if (extension_loaded) {								\
+		TRACE_ERROR("Extension (" _name ") cannot be loaded twice!");		\
+		return ENOTSUP;								\
+	}										\
+	LOG_N("Loading (" _name ") extension.");					\
+	return (_function)(conffile);							\
+}						
+    
+#define EXTENSION_ENTRY2(_name, _dictfunc, _rulesfunction, _depends...)					\
+EXTENSION_ENTRY(_name, _dictfunc, ## _depends )					\
+int fd_ext_init2(int major, int minor, char * conffile) {				\
+    if ((major != FD_PROJECT_VERSION_MAJOR)						\
+        || (minor != FD_PROJECT_VERSION_MINOR)) {				\
+        TRACE_ERROR("This extension (" _name ") was compiled for a different version of freeDiameter.");	\
+        TRACE_DEBUG(INFO, "daemon %d.%d != ext %d.%d",				\
+            major, minor,							\
+            FD_PROJECT_VERSION_MAJOR, FD_PROJECT_VERSION_MINOR);		\
+        return EINVAL;								\
+    }										\
+    if (extension_loaded) {								\
+        TRACE_ERROR("Extension (" _name ") cannot be loaded twice!");		\
+        return ENOTSUP;								\
+    }										\
+    extension_loaded++;								\
+    return (_rulesfunction)(conffile);							\
+}							\
+int fd_ext_parselocalrules(char *conffile) {					\
+    return (_rulesfunction)(conffile);					\
+}									
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _EXTENSION_H */
+
+#if 0
+static int dict_entry(char * conffile)                                  
+{                                       
+        int x = (_dictfunc)(conffile);                                  \
+        if (x != 0) return x;                                   \
+        return (_rulesfunction)(conffile);                                      \
+} 
+#endif
diff --git a/include/freeDiameter/freeDiameter-host.h.in b/include/freeDiameter/freeDiameter-host.h.in
new file mode 100644
index 0000000..1539b4a
--- /dev/null
+++ b/include/freeDiameter/freeDiameter-host.h.in
@@ -0,0 +1,106 @@
+/*********************************************************************************************************
+* Software License Agreement (BSD License)                                                               *
+* Author: Sebastien Decugis <sdecugis@freediameter.net>							 *
+*													 *
+* Copyright (c) 2015, WIDE Project and NICT								 *
+* All rights reserved.											 *
+* 													 *
+* Redistribution and use of this software in source and binary forms, with or without modification, are  *
+* permitted provided that the following conditions are met:						 *
+* 													 *
+* * Redistributions of source code must retain the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer.										 *
+*    													 *
+* * Redistributions in binary form must reproduce the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer in the documentation and/or other						 *
+*   materials provided with the distribution.								 *
+* 													 *
+* * Neither the name of the WIDE Project or NICT nor the 						 *
+*   names of its contributors may be used to endorse or 						 *
+*   promote products derived from this software without 						 *
+*   specific prior written permission of WIDE Project and 						 *
+*   NICT.												 *
+* 													 *
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED *
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
+* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR *
+* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 	 *
+* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 	 *
+* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR *
+* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF   *
+* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.								 *
+*********************************************************************************************************/
+
+/* Configuration from compile-time */
+#ifndef FD_IS_CONFIG
+#define FD_IS_CONFIG
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#cmakedefine HAVE_NTOHLL
+#cmakedefine HAVE_MALLOC_H
+#cmakedefine HAVE_SIGNALENT_H
+#cmakedefine HAVE_AI_ADDRCONFIG
+#cmakedefine HAVE_CLOCK_GETTIME
+#cmakedefine HAVE_STRNDUP
+#cmakedefine HAVE_PTHREAD_BAR
+
+#cmakedefine HOST_BIG_ENDIAN @HOST_BIG_ENDIAN@
+
+#cmakedefine DISABLE_SCTP
+#cmakedefine DEBUG_SCTP
+#cmakedefine DEBUG_WITH_META
+#cmakedefine SCTP_USE_MAPPED_ADDRESSES
+#cmakedefine SCTP_CONNECTX_4_ARGS
+#cmakedefine SKIP_DLCLOSE
+#cmakedefine DIAMID_IDNA_IGNORE
+#cmakedefine DIAMID_IDNA_REJECT
+#cmakedefine DISABLE_PEER_EXPIRY
+#cmakedefine WORKAROUND_ACCEPT_INVALID_VSAI
+#cmakedefine GNUTLS_VERSION_210
+#cmakedefine GNUTLS_VERSION_212
+#cmakedefine GNUTLS_VERSION_300
+#cmakedefine GNUTLS_VERSION_310
+
+#cmakedefine ERRORS_ON_TODO
+#cmakedefine DEBUG
+
+#cmakedefine FD_PROJECT_BINARY "@FD_PROJECT_BINARY@"
+#cmakedefine FD_PROJECT_NAME "@FD_PROJECT_NAME@"
+#cmakedefine FD_PROJECT_VERSION_MAJOR @FD_PROJECT_VERSION_MAJOR@
+#ifndef FD_PROJECT_VERSION_MAJOR
+# define FD_PROJECT_VERSION_MAJOR 0
+#endif /*FD_PROJECT_VERSION_MAJOR*/
+#cmakedefine FD_PROJECT_VERSION_MINOR @FD_PROJECT_VERSION_MINOR@
+#ifndef FD_PROJECT_VERSION_MINOR
+# define FD_PROJECT_VERSION_MINOR 0
+#endif /*FD_PROJECT_VERSION_MINOR*/
+#cmakedefine FD_PROJECT_VERSION_REV   @FD_PROJECT_VERSION_REV@
+#ifndef FD_PROJECT_VERSION_REV
+# define FD_PROJECT_VERSION_REV 0
+#endif /*FD_PROJECT_VERSION_REV*/
+#cmakedefine FD_PROJECT_VERSION_API   @FD_PROJECT_VERSION_API@
+#ifndef FD_PROJECT_VERSION_API
+# define FD_PROJECT_VERSION_API 0
+#endif /*FD_PROJECT_VERSION_API*/
+#cmakedefine FD_PROJECT_COPYRIGHT "@FD_PROJECT_COPYRIGHT@"
+
+#cmakedefine DEFAULT_CONF_PATH "@DEFAULT_CONF_PATH@"
+#cmakedefine DEFAULT_EXTENSIONS_PATH "@DEFAULT_EXTENSIONS_PATH@"
+
+#ifndef FD_DEFAULT_CONF_FILENAME
+#define FD_DEFAULT_CONF_FILENAME "freeDiameter.conf"
+#endif /* FD_DEFAULT_CONF_FILENAME */
+
+/* Maximum number of hooks handlers that can be registered. Make this compilation option if needed */
+#define FD_HOOK_HANDLE_LIMIT	5
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FD_IS_CONFIG */
diff --git a/include/freeDiameter/libfdcore.h b/include/freeDiameter/libfdcore.h
new file mode 100644
index 0000000..a28a542
--- /dev/null
+++ b/include/freeDiameter/libfdcore.h
@@ -0,0 +1,1211 @@
+/*********************************************************************************************************
+* Software License Agreement (BSD License)                                                               *
+* Author: Sebastien Decugis <sdecugis@freediameter.net>							 *
+*													 *
+* Copyright (c) 2016, WIDE Project and NICT								 *
+* All rights reserved.											 *
+* 													 *
+* Redistribution and use of this software in source and binary forms, with or without modification, are  *
+* permitted provided that the following conditions are met:						 *
+* 													 *
+* * Redistributions of source code must retain the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer.										 *
+*    													 *
+* * Redistributions in binary form must reproduce the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer in the documentation and/or other						 *
+*   materials provided with the distribution.								 *
+* 													 *
+* * Neither the name of the WIDE Project or NICT nor the 						 *
+*   names of its contributors may be used to endorse or 						 *
+*   promote products derived from this software without 						 *
+*   specific prior written permission of WIDE Project and 						 *
+*   NICT.												 *
+* 													 *
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED *
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
+* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR *
+* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 	 *
+* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 	 *
+* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR *
+* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF   *
+* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.								 *
+*********************************************************************************************************/
+
+#ifndef _LIBFDCORE_H
+#define _LIBFDCORE_H
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <freeDiameter/libfdproto.h>
+#include <gnutls/gnutls.h>
+#include <gnutls/x509.h>
+
+/* GNUTLS version */
+#ifndef GNUTLS_VERSION
+#define GNUTLS_VERSION LIBGNUTLS_VERSION
+#endif /* GNUTLS_VERSION */
+
+/* GNUTLS calls debug level */
+#ifndef GNUTLS_DBG_LEVEL
+#define GNUTLS_DBG_LEVEL ANNOYING
+#endif /* GNUTLS_DBG_LEVEL */
+
+
+/* Check the return value of a GNUTLS function, log and propagate */
+#define CHECK_GNUTLS_GEN( faillevel, __call__, __fallback__  ) { 					\
+		CHECK_PRELUDE(__call__);								\
+		if (__ret__ < 0) {									\
+			LOG(faillevel, "TLS ERROR: in '%s' :\t%s",  #__call__ ,  gnutls_strerror(__ret__)); \
+			__fallback__;									\
+		}											\
+}
+
+/* we use this macro to help debugging gnutls usage issues -- just change the content to display what you need */
+#define GNUTLS_TRACE( __call__) {					\
+	TRACE_CALL("Check: %s", #__call__ );				\
+	(__call__);							\
+}
+
+
+#ifndef EXCLUDE_DEPRECATED
+/* Macro for transition, replace with CHECK_GNUTLS_GEN */
+#define CHECK_GNUTLS_DO( __call__, __fallback__ )	\
+	CHECK_GNUTLS_GEN( FD_LOG_ERROR, __call__, __fallback__  )
+
+#endif /* EXCLUDE_DEPRECATED */
+
+
+/*============================================================*/
+/*                      INITIALIZATION                        */
+/*============================================================*/
+
+
+/* Initialize the libfdcore internals. This also initializes libfdproto */
+int fd_core_initialize(void);
+
+/* A string describing the version of the library */
+extern const char fd_core_version[];
+
+/* Parse the freeDiameter.conf configuration file, load the extensions */
+int fd_core_parseconf(const char * conffile);
+
+/* Start the server & client threads */
+int fd_core_start(void);
+
+/* Block until the framework has completed its initialization -- useful for extensions */
+int fd_core_waitstartcomplete(void);
+
+/* Initialize shutdown of the framework */
+int fd_core_shutdown(void);
+
+/* Wait for the shutdown to be complete -- this should always be called after fd_core_shutdown */
+int fd_core_wait_shutdown_complete(void);
+
+
+/*============================================================*/
+/*                          CONFIG                            */
+/*============================================================*/
+
+/* Structure to hold the configuration of the freeDiameter daemon */
+#define	EYEC_CONFIG	0xC011F16
+struct fd_config {
+	int		 cnf_eyec;	/* Eye catcher: EYEC_CONFIG */
+	
+	const char	*cnf_file;	/* Configuration file to parse, default is DEFAULT_CONF_FILE */
+	
+	DiamId_t  	 cnf_diamid;	/* Diameter Identity of the local peer (FQDN -- ASCII) */
+	size_t		 cnf_diamid_len;/* cached length of the previous string */
+	DiamId_t	 cnf_diamrlm;	/* Diameter realm of the local peer, default to realm part of cnf_diamid */
+	size_t		 cnf_diamrlm_len;/* length of the previous string */
+	
+	unsigned int	 cnf_timer_tc;	/* The value in seconds of the default Tc timer */
+	unsigned int 	 cnf_timer_tw;	/* The value in seconds of the default Tw timer */
+	
+	uint16_t	 cnf_port;	/* the local port for legacy Diameter (default: 3868) in host byte order */
+	uint16_t	 cnf_port_tls;	/* the local port for Diameter/TLS (default: 5868) in host byte order */
+	uint16_t	 cnf_port_3436; /* Open an additional server port to listen to old TLS/SCTP clients (RFC3436, freeDiameter versions < 1.2.0) */
+	uint16_t	 cnf_sctp_str;	/* default max number of streams for SCTP associations (def: 30) */
+	struct fd_list	 cnf_endpoints;	/* the local endpoints to bind the server to. list of struct fd_endpoint. default is empty (bind all). After servers are started, this is the actual list of endpoints including port information. */
+	int		 cnf_thr_srv;	/* Number of threads per servers handling the connection state machines */
+	struct fd_list	 cnf_apps;	/* Applications locally supported (except relay, see flags). Use fd_disp_app_support to add one. list of struct fd_app. */
+	uint16_t	 cnf_dispthr;	/* Number of dispatch threads to create */
+	struct {
+		unsigned no_fwd : 1;	/* the peer does not relay messages (0xffffff app id) */
+		unsigned no_ip4 : 1;	/* disable IP */
+		unsigned no_ip6 : 1;	/* disable IPv6 */
+		unsigned no_tcp : 1;	/* disable use of TCP */
+		unsigned no_sctp: 1;	/* disable the use of SCTP */
+		unsigned pr_tcp	: 1;	/* prefer TCP over SCTP */
+		unsigned tls_alg: 1;	/* TLS algorithm for initiated cnx. 0: separate port. 1: inband-security (old) */
+	} 		 cnf_flags;
+	
+	struct {
+		int				 tls_disabled;
+		
+		/* Credentials parameters (backup) */
+		char *  			 cert_file;
+		char *				 key_file;
+		
+		char *  			 ca_file;
+		int				 ca_file_nr;
+		char *  			 crl_file;
+		
+		char *				 prio_string;
+		unsigned int 			 dh_bits;
+		char *				 dh_file;
+		
+		/* GNUTLS parameters */
+		gnutls_priority_t 		 prio_cache;
+		gnutls_dh_params_t 		 dh_cache;
+		
+		/* GNUTLS server credential(s) */
+		gnutls_certificate_credentials_t credentials; /* contains local cert + trust anchors */
+		#ifdef GNUTLS_VERSION_300
+		gnutls_x509_trust_list_t         trustlist; /* the logic to check local certificate has changed */
+		#endif /* GNUTLS_VERSION_300 */
+		
+	} 		 cnf_sec_data;
+	
+	uint32_t	 cnf_orstateid;	/* The value to use in Origin-State-Id, default to random value */
+	struct dictionary *cnf_dict;	/* pointer to the global dictionary */
+	struct fifo	  *cnf_main_ev;	/* events for the daemon's main (struct fd_event items) */
+};
+extern struct fd_config *fd_g_config; /* The pointer to access the global configuration, initalized in main */
+
+
+
+/*============================================================*/
+/*                         PEERS                              */
+/*============================================================*/
+
+/* States of a peer */
+enum peer_state {
+	/* Stable states */
+	STATE_NEW = 0,		/* The peer has been just been created, PSM thread not started yet */
+	STATE_OPEN,		/* Connexion established */
+	
+	/* Peer state machine */
+	STATE_CLOSED,		/* No connection established, will re-attempt after TcTimer. */
+	STATE_CLOSING,		/* the connection is being shutdown (DPR/DPA in progress) */
+	STATE_WAITCNXACK,	/* Attempting to establish transport-level connection */
+	STATE_WAITCNXACK_ELEC,	/* Received a CER from this same peer on an incoming connection (other peer object), while we were waiting for cnx ack */
+	STATE_WAITCEA,		/* Connection established, CER sent, waiting for CEA */
+	/* STATE_WAITRETURNS_ELEC, */	/* This state is not stable and therefore deprecated:
+				   We have sent a CER on our initiated connection, and received a CER from the remote peer on another connection. Election.
+				   If we win the election, we must disconnect the initiated connection and send a CEA on the other => we go to OPEN state.
+				   If we lose, we disconnect the other connection (receiver) and fallback to WAITCEA state. */
+	STATE_OPEN_HANDSHAKE,	/* TLS Handshake and validation are in progress in open state -- we use it only for debug purpose, it is never displayed */
+	
+	/* Failover state machine */
+	STATE_SUSPECT,		/* A DWR was sent and not answered within TwTime. Failover in progress. */
+	STATE_REOPEN,		/* Connection has been re-established, waiting for 3 DWR/DWA exchanges before putting back to service */
+	
+	/* Ordering issues with multistream & state machine. -- see top of p_psm.c for explanation */
+	STATE_OPEN_NEW, 	/* after CEA is sent, until a new message is received. Force ordering in this state */
+	STATE_CLOSING_GRACE,	/* after DPA is sent or received, give a short delay for messages in the pipe to be received. */
+	
+	/* Error state */
+	STATE_ZOMBIE		/* The PSM thread is not running anymore; it must be re-started or peer should be deleted. */
+#define STATE_MAX STATE_ZOMBIE
+};
+/* The following macro is called in freeDiameter/p_psm.c */
+#define DECLARE_STATE_STR()		\
+const char *peer_state_str[] = { 	\
+	  "STATE_NEW"			\
+	, "STATE_OPEN"			\
+	, "STATE_CLOSED"		\
+	, "STATE_CLOSING"		\
+	, "STATE_WAITCNXACK"		\
+	, "STATE_WAITCNXACK_ELEC"	\
+	, "STATE_WAITCEA"		\
+	, "STATE_OPEN_HANDSHAKE"	\
+	, "STATE_SUSPECT"		\
+	, "STATE_REOPEN"		\
+	, "STATE_OPEN_NEW"		\
+	, "STATE_CLOSING_GRACE"		\
+	, "STATE_ZOMBIE"		\
+	};
+extern const char *peer_state_str[];
+#define STATE_STR(state) \
+	(((unsigned)(state)) <= STATE_MAX ? peer_state_str[((unsigned)(state)) ] : "<Invalid>")
+
+/* Constants for the peer_info structure below */
+#define PI_P3_DEFAULT	0	/* Use any available protocol */
+#define PI_P3_IP	1	/* Use only IP to connect to this peer */
+#define PI_P3_IPv6	2	/* resp, IPv6 */
+
+#define PI_P4_DEFAULT	0	/* Attempt any available protocol */
+#define PI_P4_TCP	1	/* Only use TCP */
+#define PI_P4_SCTP	2	/* Only use SCTP */
+
+#define PI_ALGPREF_SCTP	0	/* SCTP is  attempted first (default) */
+#define PI_ALGPREF_TCP	1	/* TCP is attempted first */
+
+#define PI_SEC_DEFAULT	0	/* New TLS security (handshake after connection, protecting also CER/CEA) */
+#define PI_SEC_NONE	1	/* Transparent security with this peer (IPsec) */
+#define PI_SEC_TLS_OLD	2	/* Old TLS security (use Inband-Security-Id AVP during CER/CEA) */
+				/* Set sec = 3 to authorize use of (Inband-Security-Id == NONE) with this peer, sec = 2 only authorizing TLS */
+				
+#define PI_SCTPSEC_DEF	0	/* Use DTLS over SCTP to connect to this peer (default) */
+#define PI_SCTPSEC_3436	1	/* Use TLS over SCTP to connect to this peer (RFC3436) */
+
+#define PI_EXP_NONE	0	/* the peer entry does not expire */
+#define PI_EXP_INACTIVE	1	/* the peer entry expires (i.e. is deleted) after pi_lft seconds without activity */
+
+#define PI_PRST_NONE	0	/* the peer entry is deleted after disconnection / error */
+#define PI_PRST_ALWAYS	1	/* the peer entry is persistant (will be kept as ZOMBIE in case of error) */
+			
+/* Information about a remote peer */
+struct peer_info {
+	
+	DiamId_t	pi_diamid;	/* (supposedly) UTF-8, \0 terminated. The Diameter Identity of the remote peer. */
+	size_t		pi_diamidlen;	/* cached length of pi_diamid */
+	
+	struct {
+		struct {
+			unsigned	pro3 :2;	/* PI_P3_* */
+			unsigned	pro4 :2;	/* PI_P4_* */
+			unsigned	alg :1;		/* PI_ALGPREF_* */
+			unsigned	sec :2;		/* PI_SEC_* */
+			unsigned	sctpsec :1;	/* PI_SCTPSEC_* */
+			unsigned	exp :1;		/* PI_EXP_* */
+			unsigned	persist :1;	/* PI_PRST_* */
+			
+		}		pic_flags;	/* Flags influencing the connection to the remote peer */
+		
+		DiamId_t	pic_realm;	/* If configured, the daemon will check the received realm in CER/CEA matches this. */
+		uint16_t	pic_port; 	/* port to connect to. 0: default. */
+		
+		uint32_t 	pic_lft;	/* lifetime of this peer when inactive (see pic_flags.exp definition) */
+		int		pic_tctimer; 	/* use this value for TcTimer instead of global, if != 0 */
+		int		pic_twtimer; 	/* use this value for TwTimer instead of global, if != 0 */
+		
+		char *		pic_priority;	/* Priority string for GnuTLS if we don't use the default */
+		
+	} config;	/* Configured data (static for this peer entry) */
+	
+	struct {
+		
+		/* enum peer_state	pir_state; */ 
+		/* Since 1.1.0, read the state with fd_peer_getstate(peer). */
+		
+		DiamId_t	pir_realm;	/* The received realm in CER/CEA. */
+		size_t		pir_realmlen;	/* length of the realm */
+		
+		uint32_t	pir_vendorid;	/* Content of the Vendor-Id AVP, or 0 by default */
+		uint32_t	pir_orstate;	/* Origin-State-Id value */
+		os0_t		pir_prodname;	/* copy of Product-Name AVP (\0 terminated) */
+		uint32_t	pir_firmrev;	/* Content of the Firmware-Revision AVP */
+		int		pir_relay;	/* The remote peer advertized the relay application */
+		struct fd_list	pir_apps;	/* applications advertised by the remote peer, except relay (pi_flags.relay) */
+		int		pir_isi;	/* Inband-Security-Id advertised (PI_SEC_* bits) */
+		
+		uint32_t	pir_lastDC;	/* The last Disconnect-Cause value received */
+		
+		int		pir_proto;	/* The L4 protocol currently used with the peer (IPPROTO_TCP or IPPROTO_SCTP) */
+		const gnutls_datum_t 	*pir_cert_list; 	/* The (valid) credentials that the peer has presented, or NULL if TLS is not used */
+								/* This is inspired from http://www.gnu.org/software/gnutls/manual/gnutls.html#ex_003ax509_002dinfo 
+								   see there for example of using this data */
+		unsigned int 	pir_cert_list_size;		/* Number of certificates in the list */
+		
+	} runtime;	/* Data populated after connection, may change between 2 connections -- not used by fd_peer_add */
+	
+	struct fd_list	pi_endpoints;	/* Endpoint(s) of the remote peer (configured, discovered, or advertized). list of struct fd_endpoint. DNS resolved if empty. */
+};
+
+
+struct peer_hdr {
+	struct fd_list	 chain;	/* Link into the list of all the peers, ordered by their Diameter Id (fd_os_cmp) */
+	struct peer_info info;	/* The public data */
+	
+	/* This header is followed by more data in the private peer structure definition */
+};
+
+/* the global list of peers. 
+  Since we are not expecting so many connections, we don't use a hash, but it might be changed.
+  The list items are peer_hdr structures (actually, fd_peer, but the cast is OK) */
+extern struct fd_list fd_g_peers;
+extern pthread_rwlock_t fd_g_peers_rw; /* protect the list */
+
+/*
+ * FUNCTION:	fd_peer_add
+ *
+ * PARAMETERS:
+ *  info 	: Information to create the peer.
+ *  orig_dbg	: A string indicating the origin of the peer information, for debug (ex: conf, redirect, ...)
+ *  cb		: optional, a callback to call (once) when the peer connection is established or failed
+ *  cb_data	: opaque data to pass to the callback.
+ *
+ * DESCRIPTION: 
+ *  Add a peer to the list of peers to which the daemon must maintain a connexion.
+ *
+ *  The content of info parameter is copied, except for the list of endpoints if 
+ * not empty, which is simply moved into the created object. It means that the list
+ * items must have been malloc'd, so that they can be freed.
+ *
+ *  If cb is not null, the callback is called when the connection is in OPEN state or
+ * when an error has occurred. The callback should use the pi_state information to 
+ * determine which one it is. If the first parameter of the called callback is NULL, it 
+ * means that the peer is being destroyed before attempt success / failure. 
+ * cb is called to allow freeing cb_data in  * this case.
+ *
+ *  The orig_dbg string is only useful for easing debug, and can be left to NULL.
+ *
+ * RETURN VALUE:
+ *  0      	: The peer is added.
+ *  EINVAL 	: A parameter is invalid.
+ *  EEXIST 	: A peer with the same Diameter-Id is already in the list.
+ *  (other standard errors may be returned, too, with their standard meaning. Example:
+ *    ENOMEM 	: Memory allocation for the new object element failed.)
+ */
+int fd_peer_add ( struct peer_info * info, const char * orig_dbg, void (*cb)(struct peer_info *, void *), void * cb_data );
+
+/*
+ * FUNCTION:	fd_peer_getbyid
+ *
+ * PARAMETERS:
+ *  diamid 	: an UTF8 string describing the diameter Id of the peer to seek
+ *  diamidlen	: length of the diamid
+ *  igncase	: perform an almost-case-insensitive search? (slower)
+ *  peer	: The peer is stored here if it exists.
+ *
+ * DESCRIPTION: 
+ *   Search a peer by its Diameter-Id.
+ *
+ * RETURN VALUE:
+ *  0   : *peer has been updated (to NULL if the peer is not found).
+ * !0	: An error occurred.
+ */
+int fd_peer_getbyid( DiamId_t diamid, size_t diamidlen, int igncase, struct peer_hdr ** peer );
+
+/* 
+ * FUNCTION:	fd_peer_get_state
+ *
+ * PARAMETERS:
+ *  peer	: The peer which state to read
+ *
+ * DESCRIPTION: 
+ *   Returns the current state of the peer.
+ *
+ * RETURN VALUE:
+ *  -1  : peer is invalid
+ * >=0	: the state of the peer at the time of reading.
+ */
+int fd_peer_get_state(struct peer_hdr *peer);
+
+/* 
+ * FUNCTION:	fd_peer_cnx_proto_info
+ *
+ * PARAMETERS:
+ *  peer	: The peer which information to be read
+ *  buf		: Where to store the protocol information
+ *  len		: available space in bug
+ *
+ * DESCRIPTION: 
+ *   Creates a string describing the current connection to this peer, e.g.: "TCP,TLS,soc#3".
+ *
+ * RETURN VALUE:
+ *  0   : buffer was written
+ * >=0	: error code.
+ */
+int fd_peer_cnx_proto_info(struct peer_hdr *peer, char * buf, size_t len);
+
+/* 
+ * FUNCTION:	fd_peer_get_load_pending
+ *
+ * PARAMETERS:
+ *  peer	: The peer which load to read
+ *  to_receive  : (out) number of requests sent to this peer without matching answer yet.
+ *  to_send     : (out) number of requests received from this peer and not yet answered.
+ *
+ * DESCRIPTION: 
+ *   Returns the current number of requests sent to this peer
+ *  that have not been answered yet. This is an empirical indication
+ *  of the workload of this peer.
+ *
+ * RETURN VALUE:
+ *  0  : The load parameter has been updated. (it should have a positive value always)
+ * !0  : An error occurred
+ */
+int fd_peer_get_load_pending(struct peer_hdr *peer, long * to_receive, long * to_send);
+
+/*
+ * FUNCTION:	fd_peer_validate_register
+ *
+ * PARAMETERS:
+ *  peer_validate 	: Callback as defined below.
+ *
+ * DESCRIPTION: 
+ *  Add a callback to authorize / reject incoming peer connections.
+ * All registered callbacks are called until a callback sets auth = -1 or auth = 1.
+ * If no callback returns a clear decision, the default behavior is applied (reject unknown connections)
+ * The callbacks are called in FILO order of their registration.
+ *
+ * RETURN VALUE:
+ *  0   : The callback is added.
+ * !0	: An error occurred.
+ */
+int fd_peer_validate_register ( int (*peer_validate)(struct peer_info * /* info */, int * /* auth */, int (**cb2)(struct peer_info *)) );
+/*
+ * CALLBACK:	peer_validate
+ *
+ * PARAMETERS:
+ *   info     : Structure containing information about the peer attempting the connection.
+ *   auth     : Store there the result if the peer is accepted (1), rejected (-1), or unknown (0).
+ *   cb2      : If != NULL and in case of PI_SEC_TLS_OLD, another callback to call after handshake (if auth = 1).
+ *
+ * DESCRIPTION: 
+ *   This callback is called when a new connection is being established from an unknown peer,
+ * after the CER is received. An extension must register such callback with peer_validate_register.
+ *
+ *   The callback can learn if the peer has sent Inband-Security-Id AVPs in runtime.pir_isi fields.
+ * It can also learn if a handshake has already been performed in runtime.pir_cert_list field.
+ * The callback must set the value of config.pic_flags.sec appropriately to allow a connection without TLS.
+ *
+ *   If the old TLS mechanism is used,
+ * the extension may also need to check the credentials provided during the TLS
+ * exchange (remote certificate). For this purpose, it may set the address of a new callback
+ * to be called once the handshake is completed. This new callback receives the information
+ * structure as parameter (with pir_cert_list set) and returns 0 if the credentials are correct,
+ * or an error code otherwise. If the error code is received, the connection is closed and the 
+ * peer is destroyed.
+ * Note that freeDiameter already achieves some usual checks. The callback may be used to enforce
+ * additional restrictions.
+ *
+ * RETURN VALUE:
+ *  0      	: The authorization decision has been written in the location pointed by auth.
+ *  !0 		: An error occurred.
+ */
+
+
+
+/*============================================================*/
+/*                         MESSAGES                           */
+/*============================================================*/
+
+/*
+ * FUNCTION:	fd_msg_send, fd_msg_send_timeout  
+ *
+ * PARAMETERS:
+ *  pmsg 	: Location of the message to be sent on the network (set to NULL on function return to avoid double deletion).
+ *  anscb	: A callback to be called when corresponding answer is received, when sending a request (not used with answers)
+ *  anscb_data	: opaque data to be passed back to the anscb (or expirecb) when it is called.
+ *  expirecb    : (only for fd_msg_send_timeout) If the request did not get an answer before timeout, this callback is called.
+ *  timeout     : (only for fd_msg_send_timeout) sets the absolute time until when to wait for an answer. Past this time,
+ *                the expirecb is called with the request and the answer will be discarded if received later.
+ *
+ * DESCRIPTION: 
+ *   Sends a message on the network. (actually simply queues it in a global queue, to be picked by a daemon's thread)
+ * For requests, the end-to-end id must be set (see fd_msg_get_eteid / MSGFL_ALLOC_ETEID).
+ * For answers, the message must be created with function fd_msg_new_answer_from_req.
+ *
+ * The routing module will handle sending to the correct peer, usually based on the Destination-Realm / Destination-Host AVP.
+ *
+ * If the msg is a request, there are two ways of receiving the answer:
+ *  - either having registered a callback in the dispatch module (see fd_disp_register)
+ *  - or provide a anscb callback here. If such callback is provided, it is called before the dispatch callbacks.
+ *    The prototype for this anscb callback function is:
+ *     void anscb(void * data, struct msg ** answer)
+ *	where:
+ *		data   : opaque data that was registered along with the callback.
+ *		answer : location of the pointer to the answer.
+ *      note1: on function return, if *answer is not NULL, the message is passed to the dispatch module for regular callbacks.
+ *	       otherwise, the callback must take care of freeing the message (fd_msg_free).
+ *	note2: the opaque data is not freed by the daemon in any case, extensions should ensure clean handling in fd_ext_fini.
+ * 
+ * If no callback is registered to handle an answer, the message is discarded and an error is logged.
+ *
+ *  fd_msg_send_timeout is similar to fd_msg_send, except that it takes two additional arguments "expirecb" and "timeout". 
+ * If the message parameter is an answer, there is no difference with fd_msg_send.
+ * Otherwise, if the corresponding answer (or error) is received before the timeout date elapses, everything occurs as with fd_msg_send. 
+ * Otherwise, the request is removed from the queue (meaning the matching answer will be discarded upon reception) and passed to the expirecb 
+ * function. Upon return, if the *msg parameter is not NULL, it is freed (not passed to other callbacks). 
+ * expirecb is called in a dedicated thread.
+ * 
+ *    The prototype for the expirecb callback function is:
+ *     void expirecb(void * data, struct peer_hdr * sentto, struct msg ** request)
+ *	where:
+ *		data   : opaque data that was registered along with the callback.
+ *              sentto : pointer to the peer to which the message was sent and no answer received within timeout.
+ *		request: location of the pointer to the request that was not answered.
+ *
+ * RETURN VALUE:
+ *  0      	: The message has been queued for sending (sending may fail asynchronously).
+ *  EINVAL 	: A parameter is invalid (ex: anscb provided but message is not a request).
+ *  ...
+ */
+int fd_msg_send ( struct msg ** pmsg, void (*anscb)(void *, struct msg **), void * data );
+int fd_msg_send_timeout ( struct msg ** pmsg, void (*anscb)(void *, struct msg **), void * data, void (*expirecb)(void *, DiamId_t, size_t, struct msg **), const struct timespec *timeout );
+
+/*
+ * FUNCTION:	fd_msg_rescode_set
+ *
+ * PARAMETERS:
+ *  msg		: A msg object -- it must be an answer.
+ *  rescode	: The name of the returned error code (ex: "DIAMETER_INVALID_AVP")
+ *  errormsg    : (optional) human-readable error message to put in Error-Message AVP
+ *  optavp	: (optional) If provided, the content will be put inside a Failed-AVP
+ *  type_id	: 0 => nothing; 1 => adds Origin-Host and Origin-Realm with local info. 2=> adds Error-Reporting-Host.
+ *
+ * DESCRIPTION: 
+ *   This function adds a Result-Code AVP to a message, and optionally
+ *  - sets the 'E' error flag in the header,
+ *  - adds Error-Message, Error-Reporting-Host and Failed-AVP AVPs.
+ *
+ * RETURN VALUE:
+ *  0      	: Operation complete.
+ *  !0      	: an error occurred.
+ */
+int fd_msg_rescode_set( struct msg * msg, char * rescode, char * errormsg, struct avp * optavp, int type_id );
+
+/* Add Origin-Host, Origin-Realm, (if osi) Origin-State-Id AVPS at the end of the message */
+int fd_msg_add_origin ( struct msg * msg, int osi ); 
+
+/* Generate a new Session-Id and add it at the beginning of the message (opt is added at the end of the sid if provided) */
+int fd_msg_new_session( struct msg * msg, os0_t opt, size_t optlen );
+
+
+/* Parse a message against our dictionary, 
+	return 0 in case of success.
+	log parsing error & return error code in case of failure in parsing. 
+	In addition, if the error code is EBADMSG (the message does not follow our dictionary) 
+		if *msg was a request, *msg is NULL and *error contains the error message ready to send back on return
+		if *msg was an answer, *msg is untouched and *error==*msg if *msg was an error message, *error is null otherwise */
+int fd_msg_parse_or_error( struct msg ** msg, struct msg **error );
+
+
+
+
+/*============================================================*/
+/*                         DISPATCH                           */
+/*============================================================*/
+
+/*
+ * FUNCTION:	fd_disp_app_support
+ *
+ * PARAMETERS:
+ *  app		: The dictionary object corresponding to the Application.
+ *  vendor	: (Optional) the dictionary object of a Vendor to claim support in Vendor-Specific-Application-Id
+ *  auth	: Support auth app part.
+ *  acct	: Support acct app part.
+ *
+ * DESCRIPTION: 
+ *   Registers an application to be advertized in CER/CEA exchanges.
+ *  Messages with an application-id matching a registered value are passed to the dispatch module,
+ * while other messages are simply relayed or an error is returned (if local node does not relay)
+ *
+ * RETURN VALUE:
+ *  0      	: The application support is registered.
+ *  EINVAL 	: A parameter is invalid.
+ */
+int fd_disp_app_support ( struct dict_object * app, struct dict_object * vendor, int auth, int acct );
+
+/* Note: if we want to support capabilities updates, we'll have to add possibility to remove an app as well... */
+
+
+/*============================================================*/
+/*                         ROUTING                            */
+/*============================================================*/
+
+/* This file contains the definitions of types and functions involved in the routing decisions in freeDiameter,
+ * and that can be called by extensions. 
+ *
+ * Three different type of messages must be distinguished:
+ *  - Messages received, and the peer is final recipient (IN messages)
+ *  - Messages received, and the peer is not final recipient (FWD messages)
+ *  - Message is locally generated (OUT messages)
+ *
+ * There are three global message queues (in queues.c) and also peers-specific queues (in struct fd_peer).
+ *
+ * (*) IN messages processing details:
+ *   - the message is received from the remote peer, a FDEVP_CNX_MSG_RECV event is generated for the peer.
+ *   - the PSM thread parses the buffer, does some verifications, handles non routable messages (fd_msg_is_routable)
+ *   - routable messages are queued in the fd_g_incoming global queue.
+ *   - a thread (routing-in) picks the message and takes the decision if it is handled locally or forwarded, 
+ *       based on local capabilities (registered by extensions with fd_disp_app_support).
+ *   - If the message is handled locally, it is queued in fd_g_local.
+ *   - Another thread (dispatch.c) will handle this message and pass it to registered callbacks (see fd_disp_register in libfreeDiameter.h).
+ *
+ * (*) FWD messages details:
+ *   - The process is the same as for IN messages, until the routing-in threads makes its decision that the message is not handled locally.
+ *   - If the local peer does not relay message, an error DIAMETER_APPLICATION_UNSUPPORTED is returned.
+ *   - All callbacks registered with fd_rt_fwd_register are called for the message (see below).
+ *     - these callbacks will typically do proxying work. Note that adding the route-record is handled by the daemon.
+ *   - Once all callbacks have been called, the message is queued in the global fd_g_outgoing queue.
+ *   - The remaining processing is the same as for OUT messages, as described below.
+ *
+ * (*) OUT messages details:
+ *   - The message are picked from fd_g_outgoing (they are queued there as result of forwarding process or call to fd_msg_send.)
+ *   - The (routing-out) thread builds a list of possible destinations for the message, as follow:
+ *      - create a list of all known peers in the "OPEN" state.
+ *      - remove from that list all peers that are in a Route-Record AVP of the message, to avoid routing loops.
+ *      - remove also all peers that have previously replied an error message for this message.
+ *   - If the list is empty, create an error UNABLE_TO_DELIVER (note: should we trig dynamic discovery here???) and reply.
+ *   - Otherwise, call all callbacks registered by function fd_rt_out_register, with the list of peers and the message.
+ *   - Order the resulting list of peers by score (see below), and sent the message to the peer with highest (positive) score.
+ *    - in case the peer is no longer in the "OPEN" state, send the message to the second peer in the list.
+ *      - if no peer is in OPEN state anymore, restart the process of creating the list.
+ *   - Once a peer has been selected, the message is queued into that peer's outgoing queue.
+ *
+ * The following functions allow an extension to register or remove a callback as described above.
+ */
+
+/********** Forwarding callbacks: for Proxy operations ***********/
+
+/* Handle to registered callback */
+struct fd_rt_fwd_hdl;
+
+/* Message direction for the callback */
+enum fd_rt_fwd_dir {
+	RT_FWD_REQ = 1,	/* The callback will be called on forwarded requests only */
+	RT_FWD_ALL = 2,	/* The callback will be called on all forwarded messages (requests and answers )*/
+	RT_FWD_ANS = 3	/* The callback will be called on answers and errors only */
+};	
+
+/*
+ * FUNCTION:	fd_rt_fwd_register
+ *
+ * PARAMETERS:
+ *  rt_fwd_cb	  : The callback function to register (see prototype below).
+ *  cbdata	  : Pointer to pass to the callback when it is called. The data is opaque to the daemon.
+ *  dir           : One of the RT_FWD_* directions defined above.
+ *  handler       : On success, a handler to the registered callback is stored here. 
+ *		   This handler will be used to unregister the cb.
+ *
+ * DESCRIPTION: 
+ *   Register a new callback for forwarded messages. See explanations above. 
+ * Note that there is no guaranteed order for the callbacks calls.
+ *
+ * RETURN VALUE:
+ *  0      	: The callback is registered.
+ *  EINVAL 	: A parameter is invalid.
+ *  ENOMEM	: Not enough memory to complete the operation
+ */
+int fd_rt_fwd_register ( int (*rt_fwd_cb)(void * cbdata, struct msg ** msg), void * cbdata, enum fd_rt_fwd_dir dir, struct fd_rt_fwd_hdl ** handler );
+/*
+ * CALLBACK:	rt_fwd_cb
+ *
+ * PARAMETERS:
+ *  data	: pointer to some data that was passed when the callback was registered (optional).
+ *  msg 	: The message that is being forwarded.
+ *
+ * DESCRIPTION: 
+ *   This callback is called when a message is forwarded to another peer. It may for example add a Proxy-Info AVP.
+ *  The callback may also choose to handle the message in a more complex form. In that case, it must set *msg = NULL
+ *  and handle it differently. In such case, the forwarding thread will stop processing this message.
+ *
+ * RETURN VALUE:
+ *  0      	: Operation complete.
+ *  !0 		: An error occurred -- will result in daemon's termination.
+ */
+
+/*
+ * FUNCTION:	fd_rt_fwd_unregister
+ *
+ * PARAMETERS:
+ *  handler     : The handler of the callback that must be unregistered.
+ *  cbdata	: Will receive the data registered with the callback, that can be freed if needed.
+ *
+ * DESCRIPTION: 
+ *   Removes a callback from the list of registered callbacks.
+ *
+ * RETURN VALUE:
+ *  0      	: The callback is unregistered.
+ *  EINVAL 	: A parameter is invalid.
+ */
+int fd_rt_fwd_unregister ( struct fd_rt_fwd_hdl * handler, void ** cbdata );
+
+
+/********** Out callbacks: for next hop routing decision operations ***********/
+
+/* Handle to registered callback */
+struct fd_rt_out_hdl;
+
+enum fd_rt_out_score {
+	FD_SCORE_NO_DELIVERY	 = -70,	/* We should not send this message to this candidate */
+	FD_SCORE_SENT_REDIRECT	 = -60, /* If this peer previously sent a Redirect indication that applies to this message */
+	FD_SCORE_INI		 =  -2, /* All candidates are initialized with this value */
+	FD_SCORE_LOAD_BALANCE	 =   1,	/* Use this to differentiate between several peers with the same score */
+	FD_SCORE_DEFAULT	 =   5,	/* The peer is a default route for all messages */
+	FD_SCORE_DEFAULT_REALM	 =  10,	/* The peer is a default route for this realm */
+	FD_SCORE_REALM		 =  15,	/* The peer belongs to Destination-Realm of the message */
+	FD_SCORE_REDIR_HOST	 =  25,	/* If there is a redirect rule with ALL_HOST for these message and peer */
+	FD_SCORE_REDIR_APP	 =  30,	/* If there is a redirect rule with ALL_APPLICATION for these message and peer */
+	FD_SCORE_REDIR_REALM	 =  35,	/* If there is a redirect rule with ALL_REALM for these message and peer */
+	FD_SCORE_REDIR_REALM_APP =  40,	/* If there is a redirect rule with REALM_AND_APPLICATION for these message and peer */
+	FD_SCORE_REDIR_USER	 =  45,	/* If there is a redirect rule with ALL_USER for these message and peer */
+	FD_SCORE_REDIR_SESSION	 =  50,	/* If there is a redirect rule with ALL_SESSION for these message and peer */
+	FD_SCORE_REDIR_ONCE	 =  55,	/* If there is a redirect rule with DONT_CACHE for these message and peer */
+	FD_SCORE_FINALDEST	 = 100	/* If the peer is the final recipient of the message (i.e. matching Destination-Host), it receives a big score. */
+};
+
+/*
+ * FUNCTION:	fd_rt_out_register
+ *
+ * PARAMETERS:
+ *  rt_out_cb	  : The callback function to register (see prototype below).
+ *  cbdata	  : Pointer to pass to the callback when it is called. The data is opaque to the daemon.
+ *  priority      : Order for calling this callback. The callbacks are called in reverse priority order (higher priority = called sooner).
+ *  handler       : On success, a handler to the registered callback is stored here. 
+ *		   This handler will be used to unregister the cb.
+ *
+ * DESCRIPTION: 
+ *   Register a new callback to handle OUT routing decisions. See explanations above. 
+ *
+ * RETURN VALUE:
+ *  0      	: The callback is registered.
+ *  EINVAL 	: A parameter is invalid.
+ *  ENOMEM	: Not enough memory to complete the operation
+ */
+int fd_rt_out_register ( int (*rt_out_cb)(void * cbdata, struct msg ** pmsg, struct fd_list * candidates), void * cbdata, int priority, struct fd_rt_out_hdl ** handler );
+/*
+ * CALLBACK:	rt_out_cb
+ *
+ * PARAMETERS:
+ *  cbdata	: pointer to some data that was registered with the callback.
+ *  pmsg 	: pointer to the message that must be sent. upon return if *msg is NULL, the processing stops and the message is not sent.
+ *  list        : The list of peers to which the message may be sent to, as returned by fd_rtd_candidate_extract
+ *
+ * DESCRIPTION: 
+ *   This callback must attribute a score (preferably from FD_SCORE_*) to each candidate peer in the list.
+ *  Once all registered callbacks have been called, the message is sent to the candidate with the highest score.
+ *  Note that each callback must *add* its locally-attributed score to the candidate current "score" parameter, not replace it!
+ *  Note also that this callback must be re-entrant since it may be called by several threads at the same time 
+ *  (for different messages)
+ *
+ * RETURN VALUE:
+ *  0      	: Operation complete.
+ *  !0 		: An error occurred.
+ */
+
+/*
+ * FUNCTION:	fd_rt_out_unregister
+ *
+ * PARAMETERS:
+ *  handler     : The handler of the callback that must be unregistered.
+ *  cbdata	: Will receive the data registered with the callback, that can be freed if needed.
+ *
+ * DESCRIPTION: 
+ *   Removes a callback from the list of registered callbacks.
+ *
+ * RETURN VALUE:
+ *  0      	: The callback is unregistered.
+ *  EINVAL 	: A parameter is invalid.
+ */
+int fd_rt_out_unregister ( struct fd_rt_out_hdl * handler, void ** cbdata );
+
+
+/*============================================================*/
+/*                         EVENTS                             */
+/*============================================================*/
+
+struct fd_event {
+	int	 code; /* codespace depends on the queue */
+	size_t 	 size;
+	void    *data;
+};
+
+/* Daemon's codespace: 1000->1999 (1500->1999 defined in fdcore-internal.h) */
+enum {
+	 FDEV_TERMINATE_INT= 1000	/* request to terminate. DO NOT USE. Use fd_core_shutdown() instead.  */
+	,FDEV_TRIGGER			/* Trigger available for extensions. size is sizeof(int), data is int * */
+};
+
+int fd_event_send(struct fifo *queue, int code, size_t datasz, void * data);
+int fd_event_get(struct fifo *queue, int * code, size_t * datasz, void ** data);
+int fd_event_timedget(struct fifo *queue, struct timespec * timeout, int timeoutcode, int * code, size_t * datasz, void ** data);
+void fd_event_destroy(struct fifo **queue, void (*free_cb)(void * data));
+const char * fd_ev_str(int event);
+
+/* for extensions */
+int fd_event_trig_regcb(int trigger_val, const char * module, void (*cb)(void));
+
+#ifndef SWIG
+DECLARE_FD_DUMP_PROTOTYPE(fd_event_trig_dump);
+
+/* The "old" FD_EV_DUMP_* events are replaced with direct calls to the following dump functions */
+DECLARE_FD_DUMP_PROTOTYPE(fd_conf_dump);
+
+DECLARE_FD_DUMP_PROTOTYPE(fd_ext_dump);
+#else /* SWIG */
+DECLARE_FD_DUMP_PROTOTYPE_simple(fd_event_trig_dump);
+DECLARE_FD_DUMP_PROTOTYPE_simple(fd_conf_dump);
+DECLARE_FD_DUMP_PROTOTYPE_simple(fd_ext_dump);
+#endif /* SWIG */
+DECLARE_FD_DUMP_PROTOTYPE(fd_servers_dump, int details);
+DECLARE_FD_DUMP_PROTOTYPE(fd_peer_dump_list, int details);
+DECLARE_FD_DUMP_PROTOTYPE(fd_peer_dump, struct peer_hdr * p, int details);
+
+/*============================================================*/
+/*                         ENDPOINTS                          */
+/*============================================================*/
+
+struct fd_endpoint {
+	struct fd_list  chain;	/* link in cnf_endpoints list */
+	
+	union {
+		sSS		ss;	/* the socket information. List is always ordered by ss value (memcmp) -- see fd_ep_add_merge */
+		sSA4		sin;
+		sSA6		sin6;
+		sSA		sa;
+	}
+#ifdef SWIG /* nested anonymous unions are not supported yet */
+			s
+#endif /* SWIG */
+	;
+	
+#define	EP_FL_CONF	(1 << 0)	/* This endpoint is statically configured in a configuration file */
+#define	EP_FL_DISC	(1 << 1)	/* This endpoint was resolved from the Diameter Identity or other DNS query */
+#define	EP_FL_ADV	(1 << 2)	/* This endpoint was advertized in Diameter CER/CEA exchange */
+#define	EP_FL_LL	(1 << 3)	/* Lower layer mechanism provided this endpoint */
+#define	EP_FL_PRIMARY	(1 << 4)	/* This endpoint is primary in a multihomed SCTP association */
+#define	EP_ACCEPTALL	(1 << 15)	/* This flag allows bypassing the address filter in fd_ep_add_merge. */
+	uint32_t	flags;		/* Additional information about the endpoint */
+		
+	/* To add: a validity timestamp for DNS records ? How do we retrieve this lifetime from DNS ? */
+};
+
+int fd_ep_add_merge( struct fd_list * list, sSA * sa, socklen_t sl, uint32_t flags );
+int fd_ep_filter( struct fd_list * list, uint32_t flags );
+int fd_ep_filter_family( struct fd_list * list, int af );
+int fd_ep_clearflags( struct fd_list * list, uint32_t flags );
+DECLARE_FD_DUMP_PROTOTYPE(fd_ep_dump_one, int preamble, struct fd_endpoint * ep );
+DECLARE_FD_DUMP_PROTOTYPE(fd_ep_dump, int preamble, int indent, struct fd_list * eps  );
+
+
+/*============================================================*/
+/*                         APPLICATIONS IDs                   */
+/*============================================================*/
+
+struct fd_app {
+	struct fd_list	 chain;	/* link in cnf_apps list. List ordered by appid. */
+	struct {
+		unsigned auth   : 1;
+		unsigned acct   : 1;
+	}		 flags;
+	vendor_id_t	 vndid; /* if not 0, Vendor-Specific-App-Id AVP will be used */
+	application_id_t appid;	/* The identifier of the application */
+};
+	
+int fd_app_merge(struct fd_list * list, application_id_t aid, vendor_id_t vid, int auth, int acct);
+int fd_app_check(struct fd_list * list, application_id_t aid, struct fd_app **detail);
+int fd_app_check_common(struct fd_list * list1, struct fd_list * list2, int * common_found);
+int fd_app_empty(struct fd_list * list);
+
+
+
+/*============================================================*/
+/*                         MONITORING                         */
+/*============================================================*/
+
+/* These functions allow an extension to collect state information about the
+ * framework, as well as being hooked at some key checkpoints in the processing
+ * for logging or statistics purpose.
+ */
+ 
+
+/* CALLBACK: 	fd_hook_cb
+ *
+ * PARAMETERS:
+ *  type	: The type of hook that triggered this call, in case same cb is registered for several hooks.
+ *  msg 	: If relevant, the pointer to the message triggering the call. NULL otherwise.
+ *  peer        : If relevant, the pointer to the peer associated with the call. NULL otherwise.
+ *  other	: For some callbacks, the remaining information is passed in this parameter. See each hook detail.
+ *  permsgdata  : Structure associated with a given message, across several hooks. 
+ *                 A different structure is associated with requests and corresponding answers. 
+ *                 See fd_hook_data_hdl below for details.
+ *                 If no fd_hook_data_hdl is registered with this callback, this parameter is always NULL
+ *  regdata     : Data pointer stored at registration, opaque for the framework.
+ *
+ * DESCRIPTION: 
+ *   When such callback is registered with fd_hook_register function, it will be called on matching events with 
+ * the parameters as described in the list of fd_hook_type below. One can use this mechanism for e.g.:
+ *  - log completely the messages for safety / backup
+ *  - create statistics information on the throughput
+ *  - ...
+ *
+ *  IMPORTANT: the callback MUST NOT change the memory pointed by the different parameters (peer, message, ...)
+ *
+ * RETURN VALUE:
+ *  none.
+ */
+ 
+/* The available hooks in the framework */
+enum fd_hook_type {
+
+	HOOK_DATA_RECEIVED = 0,
+		/* Hook called as soon as a message has been received from the network, after TLS & boundary processing.
+		 - {msg} is NULL.
+		 - {peer} is NULL.
+		 - {other} is a pointer to a struct fd_cnx_rcvdata containing the received buffer.
+		 - {permsgdata} points to either a new empty structure allocated for this message (cf. fd_hook_data_hdl), or NULL if no hdl is registered.
+		 */
+		 
+	HOOK_MESSAGE_RECEIVED,
+		/* Hook called when a message has been received and the structure has been parsed successfully (list of AVPs).
+		 - {msg} points to the parsed message. At this time, the objects have not been dictionary resolved. If you
+		   try to call fd_msg_parse_dict, it will slow down the operation of a relay agent.
+		 - {peer} is set if the message is received from a peer's connection, and NULL if the message is from a new client
+		   connected and not yet identified
+		 - {other} is NULL, or a char * identifying the connection when {peer} is null.
+		 - {permsgdata} points to either a new empty structure allocated for this message or the one passed to HOOK_DATA_RECEIVED if used.
+		 */
+	
+	HOOK_MESSAGE_LOCAL,
+		/* Hook called when a request message has been created locally by an extension and is being sent.
+		 - {msg} points to the message.
+		 - {peer} is NULL
+		 - {other} is NULL
+		 - {permsgdata} points to a new empty structure allocated for this request (cf. fd_hook_data_hdl)
+		 */
+	
+	HOOK_MESSAGE_SENDING,
+		/* Hook called when a message is about to be sent to a peer. The message pointer cannot be modified here, but the content of the message
+		  could still be changed (for example add or remove some AVP. This is the last chance.
+		 - {msg} points to the message. Some objects may not have been dictionary resolved. If you
+		   try to call fd_msg_parse_dict, it will slow down the operation of the instance.
+		 - {peer} is the one the message is being sent to.
+		 - {other} is NULL.
+		 - {permsgdata} points to existing structure if any, or a new structure otherwise. 
+		 */
+	
+	HOOK_MESSAGE_SENT,
+		/* Hook called when a message has been sent to a peer. The message might be freed as soon as the hook function returns,
+		   so it is not safe to store the pointer for asynchronous processing.
+		 - {msg} points to the sent message. Again, the objects may not have been dictionary resolved. If you
+		   try to call fd_msg_parse_dict, it will slow down the operation of a relay agent.
+		 - {peer} is set if the message is sent to a peer's connection, and NULL if the message is sent to a new client
+		   connected and not yet identified, or being rejected
+		 - {other} is NULL.
+		 - {permsgdata} points to existing structure if any, or a new structure otherwise. 
+		 */
+	
+	HOOK_MESSAGE_FAILOVER,
+		/* Hook called when a message that was sent to a peer is being requeued, because e.g. the connection was torn down.
+		   In that case the message will go again through the routing process.
+		 - {msg} points to the corresponding request message (the answer is discarded). Again, the objects may not have been dictionary resolved. If you
+		   try to call fd_msg_parse_dict, it might slow down the operation of a relay agent, although this hook is not on the normal execution path.
+		 - {peer} is the peer this message was previously sent to.
+		 - {other} is NULL.
+		 - {permsgdata} points to existing structure if any, or a new structure otherwise. 
+		 */
+	
+	HOOK_MESSAGE_PARSING_ERROR,
+		/* Hook called when a message being processed cannot be parsed successfully.
+		 - {msg} points to the message if buffer was parsed successfully, or NULL otherwise. You should not call fd_msg_parse_dict on this in any case.
+		 - {peer} is NULL or the peer that received the message. If NULL and the message is not NULL, you can still retrieve the source from the message itself.
+		 - {other} is a char * pointer to the error message (human-readable) if {msg} is not NULL, a pointer to struct fd_cnx_rcvdata containing the received buffer otherwise.
+		 - {permsgdata} points to existing structure associated with this message (or new structure if no previous hook was registered). 
+		 */
+		 
+	HOOK_MESSAGE_ROUTING_ERROR,
+		/* Hook called when a message being processed by the routing thread meets an error such as no remaining available peer for sending, based on routing callbacks decisions (maybe after retries).
+		 - {msg} points to the message. Again, the objects may not have been dictionary resolved. If you
+		   try to call fd_msg_parse_dict, it might slow down the operation of a relay agent, although this hook is not on the normal execution path.
+		 - {peer} is NULL.
+		 - {other} is a char * pointer to the error message (human-readable).
+		 - {permsgdata} points to existing structure associated with this message (or new structure if no previous hook was registered). 
+		 */
+	
+	HOOK_MESSAGE_ROUTING_FORWARD,
+		/* Hook called when a received message is deemed to be not handled locally by the routing_dispatch process.
+		   The decision of knowing which peer it will be sent to is not made yet (or if an error will be returned).
+		   The hook is trigged before the callbacks registered with fd_rt_fwd_register are called.
+		 - {msg} points to the message. Again, the objects may not have been dictionary resolved. 
+		    If you try to call fd_msg_parse_dict, it will slow down the operation of a relay agent.
+		 - {peer} is NULL.
+		 - {other} is NULL.
+		 - {permsgdata} points to existing structure associated with this message (or new structure if no previous hook was registered). 
+		 */
+	
+	HOOK_MESSAGE_ROUTING_LOCAL,
+		/* Hook called when a received message is handled locally by the routing_dispatch process (i.e., not forwarded).
+		   The hook is trigged before the callbacks registered with fd_disp_register are called.
+		 - {msg} points to the message. Here, the message has been already parsed completely & successfully.
+		 - {peer} is NULL.
+		 - {other} is NULL.
+		 - {permsgdata} points to existing structure associated with this message (or new structure if no previous hook was registered). 
+		 */
+	
+	HOOK_MESSAGE_DROPPED,
+		/* Hook called when a message is being discarded by the framework because of some error condition (normal or abnormal).
+		   It is probably a good idea to log this for analysis / backup.
+		 - {msg} points to the message, which will be freed as soon as the hook returns.
+		 - {peer} may be NULL or a peer related to the event.
+		 - {other} is a char * pointer to the error message (human-readable).
+		 - {permsgdata} points to existing structure associated with this message (or new structure if no previous hook was registered).
+		 */
+	
+	HOOK_PEER_CONNECT_FAILED,
+		/* Hook called when a connection attempt to/from a remote peer has failed. This hook is also called when the peer was in OPEN state and the connection is broken.
+		 - {msg} may be NULL (lower layer error, e.g. connection timeout) or points to a message showing the error (either invalid incoming message, or the CEA message sent or received with an error code).
+		 - {peer} may be NULL for incoming requests from unknown peers being rejected, otherwise it points to the peer structure associated with the attempt.
+		 - {other} is a char * pointer to the error message (human-readable).
+		 - {permsgdata} is always NULL for this hook.
+		 */
+	
+	HOOK_PEER_CONNECT_SUCCESS,
+		/* Hook called when a connection attempt to/from a remote peer has succeeded (the peer moves to OPEN_HANDSHAKE or OPEN state).
+		    In case of deprecated TLS handshake after the CER/CEA exchange, this hook can still be followed by HOOK_PEER_CONNECT_FAILED if TLS handshake fails.
+		 - {msg} points to the CEA message sent or received (with a success code) -- in case it is sent, you can always get access to the matching CER.
+		 - {peer} points to the peer structure.
+		 - {other} is NULL.
+		 - {permsgdata} is always NULL for this hook.
+		 */
+	
+	HOOK_MESSAGE_PARSING_ERROR2,
+		/* Hook called after an error message has been generated due to a dictionary parsing error.
+		 - {msg} points to the error message that has been generated.
+		 - {peer} is NULL. You can still retrieve the source from the message itself.
+		 - {other} is NULL
+		 - {permsgdata} points to existing structure associated with this message (or new structure if no previous hook was registered). 
+		 Use this hook if you need to populate more data in the error being returned, from the error message. 
+		 (e.g. some AVP need to be added to replies even if error case.
+		 */
+#define HOOK_LAST	HOOK_MESSAGE_PARSING_ERROR2
+};
+
+
+/* Type of the {permsgdata} pointer. It is up to each extension to define its own structure. This is opaque for the framework. */
+struct fd_hook_permsgdata;
+
+/* A handle that will be associated with the extension, and with the permsgdata structures. */
+struct fd_hook_data_hdl;
+
+/* The following structure is what is passed to the HOOK_DATA_RECEIVED hook */
+struct fd_cnx_rcvdata {
+	size_t  length;
+	uint8_t * buffer; /* internal note: the buffer is padded with a struct fd_msg_pmdl, not accounted for in length */
+};
+
+/* Function to register a new fd_hook_data_hdl. Should be called by your extension init function.
+ * The arguments are the functions called to initialize a new fd_hook_permsgdata and to free this structure when the corresponding message is being freed.
+ */
+/*
+ * FUNCTION:	fd_hook_data_register
+ *
+ * PARAMETERS:
+ *  permsgdata_size     : the size of the fd_hook_permsgdata structure. 
+ *  permsgdata_init_cb  : function called to initialize a new fd_hook_permsgdata structure, when a hook will be called for a message that does not have such structure yet. 
+ *                           The memory is already allocated and blanked, so you can pass NULL if no further handling is required.
+ *  permsgdata_fini_cb  : function called when a message is being disposed. It should free the resources associated with the fd_hook_permsgdata. 
+ *                           You can pass NULL if no special handling is required. The memory of the permsgdata structure itself will be freed by the framework.
+ *  new_handle          : On success, a handler to the registered callback is stored here. 
+ *		             This handler will be used to unregister the cb.
+ *
+ * DESCRIPTION: 
+ *   Register a new fd_hook_data_hdl. This handle is used during hooks registration (see below) in order to associate data with the messages, to allow keeping tracking of the message easily.
+ *  Note that these handlers are statically allocated and cannot be unregistered. FD_HOOK_HANDLE_LIMIT handlers can be registered at maximum (recompile libfdproto if you change this value)
+ *
+ * RETURN VALUE:
+ *  0      	: The callback is registered.
+ *  EINVAL 	: A parameter is invalid.
+ *  ENOSPC	: Too many handles already registered. You may need to increase the limit in the code.
+ */
+int fd_hook_data_register(
+	size_t permsgdata_size,
+	void (*permsgdata_init_cb) (struct fd_hook_permsgdata *),
+        void (*permsgdata_fini_cb) (struct fd_hook_permsgdata *),
+        struct fd_hook_data_hdl **new_handle
+);
+
+/* A handler associated with a registered hook callback (for cleanup) */
+struct fd_hook_hdl; 
+
+/* Helper for building a mask of hooks for registration */
+#define HOOK_MASK(hooklist...)	fd_hook_mask_helper(0, ## hooklist, -1)
+
+/*
+ * FUNCTION:	fd_hook_register
+ *
+ * PARAMETERS:
+ *  type_mask	  : A bitmask of fd_hook_type bits for which this cb is registered, e.g. HOOK_MASK( HOOK_MESSAGE_RECEIVED, HOOK_MESSAGE_SENT )
+ *  fd_hook_cb	  : The callback function to register (see prototype above).
+ *  regdata	  : Pointer to pass to the callback when it is called. The data is opaque to the daemon.
+ *  data_hdl      : If permsgdata is requested for the hooks, a handler registered with fd_hook_data_register. NULL otherwise.
+ *  handler       : On success, a handler to the registered callback is stored here. 
+ *		   This handler can be used to unregister the cb.
+ *
+ * DESCRIPTION: 
+ *   Register a new hook in the framework. See explanations above.
+ *
+ * RETURN VALUE:
+ *  0      	: The callback is registered.
+ *  EEXIST      : Another callback is already registered for this type of hook (HOOK_DATA_RECEIVED).
+ *  EINVAL 	: A parameter is invalid.
+ *  ENOMEM	: Not enough memory to complete the operation
+ */
+int fd_hook_register (  uint32_t type_mask, 
+			void (*fd_hook_cb)(enum fd_hook_type type, struct msg * msg, struct peer_hdr * peer, void * other, struct fd_hook_permsgdata *pmd, void * regdata), 
+			void  *regdata, 
+			struct fd_hook_data_hdl *data_hdl,
+			struct fd_hook_hdl ** handler );
+
+/* Remove a hook registration */
+int fd_hook_unregister( struct fd_hook_hdl * handler );
+
+
+/* Use the following function to retrieve any pmd structure associated with a request matching the current answer. Returns NULL in case of error / no such structure */
+struct fd_hook_permsgdata * fd_hook_get_request_pmd(struct fd_hook_data_hdl *data_hdl, struct msg * answer);
+
+/* The following is used by HOOK_MASK macro */
+uint32_t fd_hook_mask_helper(int dummy, ...);
+
+/*============================================================*/
+
+/*
+ * The following allows an extension to retrieve stat information on the different fifo queues involved in the freeDiameter framework.
+ * There are three global queues, plus per-peer queues.
+ * This information can be used to build SNMP-like data for example, or quickly get a status of the framework to find the loaded path of execution / bottlenecks.
+ */
+enum fd_stat_type {
+	/* For the following, no peer is associated with the stat */
+	STAT_G_LOCAL= 1,	/* Get statistics for the global queue of messages processed by local extensions */
+	STAT_G_INCOMING,	/* Get statistics for the global queue of received messages to be processed by routing_in thread */
+	STAT_G_OUTGOING,	/* Get statistics for the global queue of messages to be processed by routing_out thread */
+	
+	/* For the following, the peer must be provided */
+	STAT_P_PSM,		/* Peer state machine queue (events to be processed for this peer, including received messages) */
+	STAT_P_TOSEND,		/* Queue of messages for sending to this peer */
+};
+
+/*
+ * FUNCTION:	fd_stat_getstats
+ *
+ * PARAMETERS:
+ *  stat	  : Which queue is being queried
+ *  peer	  : (depending on the stat parameter) which peer is being queried
+ *  current_count : (out) The number of items in the queue currently
+ *  limit_count   : (out) The max number of items the queue accepts before becoming blocking -- 0 means no max.
+ *  highest_count : (out) The highest count the queue has reached since startup
+ *  total_count	  : (out) Total number of items that this queue has processed (always growing, use deltas for monitoring)
+ *  total	  : (out) Cumulated time all items spent in this queue, including blocking time (always growing, use deltas for monitoring)
+ *  blocking      : (out) Cumulated time threads trying to post new items were blocked (queue full).
+ *  last          : (out) For the last element retrieved from the queue, how long it took between posting (including blocking) and poping
+ *  
+ * DESCRIPTION: 
+ *   Get statistics information about a given queue. 
+ *  Any of the (out) parameters can be NULL if not requested.
+ *
+ * RETURN VALUE:
+ *  0      	: The callback is registered.
+ *  EINVAL 	: A parameter is invalid.
+ */
+int fd_stat_getstats(enum fd_stat_type stat, struct peer_hdr * peer, 
+			int * current_count, int * limit_count, int * highest_count, long long * total_count,
+			struct timespec * total, struct timespec * blocking, struct timespec * last);
+
+/*============================================================*/
+/*                         EOF                                */
+/*============================================================*/
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _LIBFDCORE_H */
diff --git a/include/freeDiameter/libfdproto.h b/include/freeDiameter/libfdproto.h
new file mode 100644
index 0000000..e0d0744
--- /dev/null
+++ b/include/freeDiameter/libfdproto.h
@@ -0,0 +1,3254 @@
+/*********************************************************************************************************
+* Software License Agreement (BSD License)                                                               *
+* Author: Sebastien Decugis <sdecugis@freediameter.net>							 *
+*													 *
+* Copyright (c) 2015, WIDE Project and NICT								 *
+* All rights reserved.											 *
+* 													 *
+* Redistribution and use of this software in source and binary forms, with or without modification, are  *
+* permitted provided that the following conditions are met:						 *
+* 													 *
+* * Redistributions of source code must retain the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer.										 *
+*    													 *
+* * Redistributions in binary form must reproduce the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer in the documentation and/or other						 *
+*   materials provided with the distribution.								 *
+* 													 *
+* * Neither the name of the WIDE Project or NICT nor the 						 *
+*   names of its contributors may be used to endorse or 						 *
+*   promote products derived from this software without 						 *
+*   specific prior written permission of WIDE Project and 						 *
+*   NICT.												 *
+* 													 *
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED *
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
+* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR *
+* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 	 *
+* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 	 *
+* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR *
+* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY S_OUT OF THE USE OF THIS SOFTWARE, EVEN IF   *
+* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.								 *
+*********************************************************************************************************/
+
+/* This file contains the definitions of functions and types used by the libfreeDiameter library.
+ *
+ * This library is meant to be used by both the freeDiameter daemon and its extensions.
+ * It provides the tools to manipulate Diameter messages and related data.
+ * This file should always be included as #include <freeDiameter/libfreeDiameter.h>
+ *
+ * If any change is made to this file, you must increment the FD_PROJECT_VERSION_API version.
+ *
+ * The file contains the following parts:
+ *	DEBUG
+ *	MACROS
+ *      OCTET STRINGS
+ *	THREADS
+ *	LISTS
+ *	DICTIONARY
+ *	SESSIONS
+ *	MESSAGES
+ *	DISPATCH
+ *	QUEUES
+ */
+
+#ifndef _LIBFDPROTO_H
+#define _LIBFDPROTO_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef FD_IS_CONFIG
+#error "You must include 'freeDiameter-host.h' before this file."
+#endif /* FD_IS_CONFIG */
+
+#include <pthread.h>
+#include <sched.h>
+#include <string.h>
+#include <assert.h>
+#include <errno.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <sys/socket.h>
+#include <netdb.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <stdarg.h>
+
+#include <libgen.h>	/* for basename */
+
+#ifdef SWIG
+#define _ATTRIBUTE_PRINTFLIKE_(_f,_v)
+#else
+#define _ATTRIBUTE_PRINTFLIKE_(_f,_v) __attribute__ ((format (printf, _f, _v)))
+#endif /* SWIG */
+
+/* Remove some deprecated warnings from some gnutls versions, when possible */
+#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
+
+/*============================================================*/
+/*                       CONSTANTS                            */
+/*============================================================*/
+
+#define DIAMETER_PORT		3868
+#define DIAMETER_SECURE_PORT	5868
+
+
+/*============================================================*/
+/*                          INIT                              */
+/*============================================================*/
+
+/* This function must be called first, before any call to another library function */
+int fd_libproto_init(void); /* note if you are using libfdcore, it handles this already */
+
+/* Call this one when the application terminates, to destroy internal threads */
+void fd_libproto_fini(void);
+
+/* Retrieve the version of the binary */
+extern const char fd_libproto_version[];
+
+/*============================================================*/
+/*                          DEBUG                             */
+/*============================================================*/
+
+
+/*
+ * FUNCTION:	fd_log
+ *
+ * PARAMETERS:
+ *  loglevel	: Integer, how important the message is. Valid values are macros FD_LOG_*
+ *  format 	: Same format string as in the printf function
+ *  ...		: Same list as printf
+ *
+ * DESCRIPTION: 
+ * Write information to log.
+ * The format and arguments may contain UTF-8 encoded data. The
+ * output medium is expected to support this encoding.
+ *
+ * RETURN VALUE:
+ *  None.
+ */
+void fd_log ( int, const char *, ... ) _ATTRIBUTE_PRINTFLIKE_(2,3);
+#ifndef SWIG
+void fd_log_va( int, const char *, va_list);
+#endif /* SWIG */
+
+/* these are internal objects of the debug facility, 
+might be useful to control the behavior from outside */
+extern pthread_mutex_t	fd_log_lock;
+extern char * fd_debug_one_function;
+extern char * fd_debug_one_file;
+
+/*
+ * FUNCTION:	fd_log_threadname
+ *
+ * PARAMETERS:
+ *  name 	: \0-terminated string containing a name to identify the current thread.
+ *
+ * DESCRIPTION: 
+ *  Name the current thread, useful for debugging multi-threaded problems.
+ *
+ * This function assumes that a global thread-specific key called "fd_log_thname" exists
+ * in the address space of the current process.
+ *
+ * RETURN VALUE:
+ *  None.
+ */
+void fd_log_threadname ( const char * name );
+extern pthread_key_t	fd_log_thname;
+
+/*
+ * FUNCTION:	fd_log_time
+ *
+ * PARAMETERS:
+ *  ts	 	: The timestamp to log, or NULL for "now"
+ *  buf 	: An array where the time must be stored
+ *  len		: size of the buffer
+ *  incl_date   : The day of year is included in the output
+ *  incl_ms     : millisecond value is included in the output
+ *
+ * DESCRIPTION: 
+ *  Writes the timestamp (in human readable format) in a buffer. 
+ *
+ * RETURN VALUE:
+ *  pointer to buf.
+ */
+char * fd_log_time ( struct timespec * ts, char * buf, size_t len, int incl_date, int incl_ms );
+
+/*
+ * FUNCTION:    fd_log_handler_register
+ * MACRO:
+ *
+ * PARAMETERS:
+ *  loglevel    : priority of the message
+ *  format      : Same format string as in the printf function
+ *  va_list     : Argument list
+ *
+ * DESCRIPTION:
+ * Register an external method for logging purposes.
+ *
+ * RETURN VALUE:
+ * int          : Success or failure
+ */
+int fd_log_handler_register ( void (*logger)(int loglevel, const char * format, va_list args) );
+
+/*
+ * FUNCTION:    fd_log_handler_unregister
+ * MACRO:
+ *
+ * PARAMETERS:
+ *
+ * DESCRIPTION:
+ * Unregister the external logging function.
+ *
+ * RETURN VALUE:
+ * int          : Success or failure
+ */
+int fd_log_handler_unregister ( void );
+
+
+/* All dump functions follow this same prototype:
+ * PARAMETERS:
+ *   buf   : *buf can be NULL on entry, it will be malloc'd. Otherwise it is realloc'd if needed.
+ *   len   : the current size of the buffer (in/out)
+ *   offset: (optional) if provided, starts writing dump at offset in the buffer, and updated upon exit. if NULL, starts at offset O.
+ *
+ * RETURN VALUE:
+ *   *buf upon success, NULL upon failure.
+ *
+ * REMARKS:
+ *  - After the buffer has been used, it should be freed.
+ *  - Depending on the function, the created string may be multi-line. However, it should never be terminated with a '\n'.
+ */
+#define DECLARE_FD_DUMP_PROTOTYPE( function_name, args... )	\
+	char * function_name(char ** buf, size_t *len, size_t *offset, ##args)
+
+#ifdef SWIG
+#define DECLARE_FD_DUMP_PROTOTYPE_simple( function_name )	\
+	char * function_name(char ** buf, size_t *len, size_t *offset)
+#endif /* SWIG */
+	
+
+/* Helper functions for the *dump functions that add into a buffer */
+DECLARE_FD_DUMP_PROTOTYPE( fd_dump_extend, const char * format, ... ) _ATTRIBUTE_PRINTFLIKE_(4,5);
+DECLARE_FD_DUMP_PROTOTYPE( fd_dump_extend_hexdump, uint8_t *data, size_t datalen, size_t trunc, size_t wrap );
+
+
+/* Some helpers macro for writing such *_dump routine */
+#define FD_DUMP_STD_PARAMS  buf, len, offset
+#define FD_DUMP_HANDLE_OFFSET()  size_t o = 0; if (!offset) offset = &o; if (buf && (*buf) && !(*offset)) **buf='\0'
+#define FD_DUMP_HANDLE_TRAIL()	while ((*buf) && (*offset > 0) && ((*buf)[*offset - 1] == '\n')) { *offset -= 1; (*buf)[*offset] = '\0'; }
+
+
+
+/*============================================================*/
+/*                    DEBUG MACROS                            */
+/*============================================================*/
+
+#ifndef ASSERT
+#define ASSERT(x) assert(x)
+#endif /* ASSERT */
+
+/* log levels definitions, that are passed to the logger */
+#define FD_LOG_ANNOYING  0  /* very verbose loops and such "overkill" traces. Only active when the framework is compiled in DEBUG mode. */
+#define FD_LOG_DEBUG     1  /* Get a detailed sense of what is going on in the framework. Use this level for normal debug */
+#define FD_LOG_NOTICE    3  /* Normal execution states worth noting */
+#define FD_LOG_ERROR     5  /* Recoverable or expected error conditions */
+#define FD_LOG_FATAL     6  /* Unrecoverable error, e.g. malloc fail, etc. that requires the framework to shutdown */
+
+/* The level used by the default logger, can be changed by command-line arguments. Ignored for other loggers. */
+extern int fd_g_debug_lvl;
+
+/* Some portability code to get nice function name in __PRETTY_FUNCTION__ */
+#if (!defined( __func__)) && (__STDC_VERSION__ < 199901L)
+# if __GNUC__ >= 2
+#  define __func__ __FUNCTION__
+# else /* __GNUC__ >= 2 */
+#  define __func__ "<unknown>"
+# endif /* __GNUC__ >= 2 */
+#endif /*(!defined( __func__)) && (__STDC_VERSION__ < 199901L) */
+#ifndef __PRETTY_FUNCTION__
+#define __PRETTY_FUNCTION__ __func__
+#endif /* __PRETTY_FUNCTION__ */
+
+/* A version of __FILE__ without the full path. This is specific to each C file being compiled */
+static char * file_bname = NULL;
+static char * file_bname_init(char * full) { file_bname = basename(full); return file_bname; }
+#define __STRIPPED_FILE__	(file_bname ?: file_bname_init((char *)__FILE__))
+
+
+
+/* In DEBUG mode, we add meta-information along each trace. This makes multi-threading problems easier to debug. */
+#if (defined(DEBUG) && defined(DEBUG_WITH_META))
+# define STD_TRACE_FMT_STRING "pid:%s in %s@%s:%d: "
+# define STD_TRACE_FMT_ARGS   , ((char *)pthread_getspecific(fd_log_thname) ?: "unnamed"), __PRETTY_FUNCTION__, __STRIPPED_FILE__, __LINE__
+#else /* DEBUG && DEBUG_WITH_META */
+# define STD_TRACE_FMT_STRING ""
+# define STD_TRACE_FMT_ARGS
+#endif /* DEBUG && DEBUG_WITH_META */
+
+/*************************
+  The general debug macro
+ *************************/
+#define LOG(printlevel,format,args... ) \
+	fd_log((printlevel), STD_TRACE_FMT_STRING format STD_TRACE_FMT_ARGS, ## args)
+
+/*
+ * Use the following macros in the code to get traces with location & pid in debug mode: 
+ */
+#ifdef DEBUG
+# define LOG_A(format,args... ) \
+		do { if ((fd_debug_one_function && !strcmp(fd_debug_one_function, __PRETTY_FUNCTION__)) \
+		 || (fd_debug_one_file && !strcmp(fd_debug_one_file, __STRIPPED_FILE__) ) ) {		\
+		 	LOG(FD_LOG_DEBUG,"[DBG_MATCH] " format,##args);					\
+		} else {										\
+			LOG(FD_LOG_ANNOYING,format,##args);						\
+		} } while (0)
+#else /* DEBUG */
+# define LOG_A(format,args... ) /* not defined in release */
+#endif /* DEBUG */
+
+/* Debug information useful to follow in detail what is going on */
+#define LOG_D(format,args... ) \
+		LOG(FD_LOG_DEBUG, format, ##args)
+
+/* Report a normal message that is useful for normal admin monitoring */
+#define LOG_N(format,args... ) \
+		LOG(FD_LOG_NOTICE, format,##args)
+
+/* Report an error */
+#define LOG_E(format,args... ) \
+		LOG(FD_LOG_ERROR, format, ##args)
+
+/* Report a fatal error */
+#define LOG_F(format,args... ) \
+		LOG(FD_LOG_FATAL, format, ##args)
+
+
+/*************
+ Derivatives
+ ************/
+/* Trace a binary buffer content */
+#define LOG_BUFFER(printlevel, prefix, buf, bufsz, suffix ) {								\
+	int __i;													\
+	size_t __sz = (size_t)(bufsz);											\
+	uint8_t * __buf = (uint8_t *)(buf);										\
+	char __strbuf[1024+1];												\
+	for (__i = 0; (__i < __sz) && (__i<(sizeof(__strbuf)/2)); __i++) {						\
+		sprintf(__strbuf + (2 * __i), "%02hhx", __buf[__i]);     						\
+	}														\
+        fd_log(printlevel, STD_TRACE_FMT_STRING "%s%s%s" STD_TRACE_FMT_ARGS,  						\
+               (prefix), __strbuf, (suffix));										\
+}
+
+/* Split a multi-line buffer into separate calls to the LOG function. */
+#define LOG_SPLIT(printlevel, per_line_prefix, mlbuf, per_line_suffix ) {						\
+	char * __line = (mlbuf), *__next;										\
+	char * __p = (per_line_prefix), *__s = (per_line_suffix);							\
+	while ((__next = strchr(__line, '\n')) != NULL) {								\
+		LOG(printlevel, "%s%.*s%s", __p ?:"", (int)(__next - __line), __line, __s ?:"");			\
+		__line = __next + 1;											\
+	}														\
+	LOG(printlevel, "%s%s%s", __p ?:"", __line, __s ?:"");								\
+}
+
+/* Helper for function entry -- for very detailed trace of the execution */
+#define TRACE_ENTRY(_format,_args... ) \
+		LOG_A("[enter] %s(" _format ") {" #_args "}", __PRETTY_FUNCTION__, ##_args );
+
+/* Helper for debugging by adding traces -- for debuging a specific location of the code */
+#define TRACE_HERE()	\
+		LOG_F(" -- debug checkpoint %d -- ", fd_breakhere());
+int fd_breakhere(void);
+
+/* Helper for tracing the CHECK_* macros below -- very very verbose code execution! */
+#define TRACE_CALL( str... ) 	\
+	 	LOG_A( str )
+
+/* For development only, to keep track of TODO locations in the code */
+#ifndef ERRORS_ON_TODO
+# define TODO( _msg, _args... ) \
+		LOG_F( "TODO: " _msg , ##_args);
+#else /* ERRORS_ON_TODO */
+# define TODO( _msg, _args... ) \
+		"TODO" = _msg ## _args; /* just a stupid compilation error to spot the todo */
+#endif /* ERRORS_ON_TODO */
+
+
+/*============================================================*/
+/*                  ERROR CHECKING MACRO                      */
+/*============================================================*/
+
+/* Macros to check a return value and branch out in case of error.
+ * These macro additionally provide the logging information.
+ *
+ * The name "__ret__" is always available in the __fallback__ parameter and contains the error code.
+ */
+ 
+#define CHECK_PRELUDE(__call__) 			\
+		int __ret__; 				\
+		TRACE_CALL("Check: %s", #__call__ );	\
+		__ret__ = (__call__)
+	
+#define DEFAULT_FB	return __ret__;
+
+/* System check: error case if < 0, error value in errno */
+#define CHECK_SYS_GEN( faillevel, __call__, __fallback__  ) { 						\
+		CHECK_PRELUDE(__call__);								\
+		if (__ret__ < 0) {									\
+			__ret__ = errno;								\
+			LOG(faillevel, "ERROR: in '%s' :\t%s",  #__call__ , strerror(__ret__));    	\
+			__fallback__;									\
+		}											\
+}
+
+
+/* Check the return value of a function and execute fallback in case of error or special value */
+#define CHECK_FCT_GEN2( faillevel, __call__, __speval__, __fallback1__, __fallback2__ ) {		\
+		CHECK_PRELUDE(__call__);								\
+		if (__ret__ != 0) {									\
+			if (__ret__ == (__speval__)) {							\
+				__fallback1__;								\
+			} else {									\
+				LOG(faillevel, "ERROR: in '%s' :\t%s", #__call__ , strerror(__ret__));	\
+				__fallback2__;								\
+			}										\
+		}											\
+}
+
+/* Check the return value of a function and execute fallback in case of error (return value different from 0) */
+#define CHECK_FCT_GEN( faillevel, __call__, __fallback__) \
+	       CHECK_FCT_GEN2( faillevel, (__call__), 0, , (__fallback__) )
+
+/* Check that a memory allocator did not return NULL, otherwise log an error and execute fallback */
+#define CHECK_MALLOC_GEN( faillevel, __call__, __fallback__ ) { 				       \
+	       void *  __ptr__; 								       \
+	       TRACE_CALL("Check: %s", #__call__ );						       \
+	       __ptr__ = (void *)(__call__);							       \
+	       if (__ptr__ == NULL) {								       \
+		       int __ret__ = errno;							       \
+		       LOG(faillevel, "ERROR: in '%s' :\t%s",  #__call__ , strerror(__ret__));         \
+		       __fallback__;								       \
+	       }										       \
+}
+
+/* Check parameters at function entry, execute fallback on error */
+#define CHECK_PARAMS_GEN( faillevel, __bool__, __fallback__ ) {					       \
+	       TRACE_CALL("Check: %s", #__bool__ );						       \
+	       if ( ! (__bool__) ) {								       \
+		       int __ret__ = EINVAL;							       \
+		       LOG(faillevel, "ERROR: invalid parameter '%s'",  #__bool__ );  	       	       \
+		       __fallback__;								       \
+	       }										       \
+}
+
+
+/*============================================================*/
+/*          COMPATIBILITY MACROS, TO BE REMOVED		      */
+/*============================================================*/
+/* Redefine the old macros for transition of the code */
+#ifndef EXCLUDE_DEPRECATED
+
+#define MARK_DEPRECATED	/* __attribute__ ((deprecated)) */
+
+enum old_levels {
+	NONE = 0,
+	INFO = 1,
+	FULL = 2,
+	ANNOYING = 4,
+	FCTS = 6,
+	CALL = 9
+} MARK_DEPRECATED;
+
+static __inline__ int old_TRACE_BOOL( enum old_levels level, const char * file, const char * func ) MARK_DEPRECATED
+{
+	if ((fd_debug_one_function && !strcmp(fd_debug_one_function, func))
+		|| (fd_debug_one_file && !strcmp(fd_debug_one_file, file) ))
+		return 2; /* Level override */
+	if ((int)level <= fd_g_debug_lvl)
+		return 1; /* Normal level */
+	return 0;  /* No trace */
+}
+#define TRACE_BOOL(level)  old_TRACE_BOOL((level), __STRIPPED_FILE__, __PRETTY_FUNCTION__)
+
+#ifndef SWIG
+static __inline__ void fd_log_deprecated( int level, const char *format, ... ) MARK_DEPRECATED
+{ 
+	va_list ap;
+	va_start(ap, format);
+	fd_log_va(level, format, ap);
+	va_end(ap);
+}
+#else /* SWIG */
+void fd_log_deprecated( int level, const char *format, ... );
+#endif /* SWIG */
+static __inline__ void replace_me() MARK_DEPRECATED { }
+
+#define TRACE_BUFFER(...) replace_me();
+#define TRACE_NOTICE(...) replace_me();
+
+
+/* Use the LOG_* instead, or use the new *_dump functions when dumping an object */
+#define fd_log_debug(format,args...)  fd_log_deprecated(FD_LOG_DEBUG, format, ## args)
+#define fd_log_notice(format,args...) fd_log_deprecated(FD_LOG_NOTICE, format, ## args)
+#define fd_log_error(format,args...)  fd_log_deprecated(FD_LOG_ERROR, format, ## args)
+
+/* old macro for traces. To be replaced by appropriate LOG_* macros. */
+# define TRACE_DEBUG(oldlevel, format,args... ) {					\
+		int __l__;								\
+		if ((__l__ = TRACE_BOOL(oldlevel))) {					\
+			if      (oldlevel <= NONE) { LOG_E(format,##args); }		\
+			else if (oldlevel <= INFO) { LOG_N(format,##args); }		\
+			else if (__l__ == 2)       { LOG_N(format,##args); }		\
+			else if (oldlevel <= FULL) { LOG_D(format,##args); }		\
+			else                       { LOG_A(format,##args); }		\
+}		}
+
+/* the following macro must be replaced with LOG_E or LOG_F */
+# define TRACE_ERROR	LOG_E
+
+
+/* The following macros are missing the faillevel information, which indicates at what log level the error case should be displayed. */
+# define CHECK_SYS_DO( __call__, __fallback__  ) { 							\
+		CHECK_PRELUDE(__call__);								\
+		if (__ret__ < 0) {									\
+			__ret__ = errno;								\
+			TRACE_ERROR("ERROR: in '%s' :\t%s",  #__call__ , strerror(__ret__));    	\
+			__fallback__;									\
+		}											\
+}
+
+# define CHECK_SYS( __call__  ) \
+		CHECK_SYS_DO( (__call__), return __ret__  )
+
+
+# define CHECK_POSIX_DO2( __call__, __speval__, __fallback1__, __fallback2__ ) {			\
+		CHECK_PRELUDE(__call__);								\
+		if (__ret__ != 0) {									\
+			if (__ret__ == (__speval__)) {							\
+				__fallback1__;								\
+			} else {									\
+				TRACE_ERROR("ERROR: in '%s' :\t%s", #__call__ , strerror(__ret__));	\
+				__fallback2__;								\
+			}										\
+		}											\
+}
+
+# define CHECK_POSIX_DO( __call__, __fallback__ )	\
+		CHECK_POSIX_DO2( (__call__), 0, , __fallback__ )
+
+# define CHECK_POSIX( __call__ )	\
+		CHECK_POSIX_DO( (__call__), return __ret__ )
+		
+# define CHECK_MALLOC_DO( __call__, __fallback__ ) { 				   		       \
+	       void *  __ptr__; 								       \
+	       TRACE_CALL("Check: %s", #__call__ );						       \
+	       __ptr__ = (void *)(__call__);							       \
+	       if (__ptr__ == NULL) {								       \
+		       int __ret__ = errno;							       \
+		      TRACE_ERROR("ERROR: in '%s' :\t%s",  #__call__ , strerror(__ret__));             \
+		       __fallback__;								       \
+	       }										       \
+}
+
+# define CHECK_MALLOC( __call__ )	\
+		CHECK_MALLOC_DO( (__call__), return __ret__ )
+	
+# define CHECK_PARAMS_DO( __bool__, __fallback__ ) {					       	       \
+	       TRACE_CALL("Check: %s", #__bool__ );						       \
+	       if ( ! (__bool__) ) {								       \
+		       int __ret__ = EINVAL;							       \
+		       TRACE_ERROR("ERROR: Invalid parameter '%s', %d",  #__bool__, __ret__ );         \
+		       __fallback__;								       \
+	       }										       \
+}
+
+# define CHECK_PARAMS( __bool__ )	\
+		CHECK_PARAMS_DO( (__bool__), return __ret__ )
+
+# define CHECK_FCT_DO	CHECK_POSIX_DO
+# define CHECK_FCT	CHECK_POSIX
+
+#endif /* EXCLUDE_DEPRECATED */
+	       
+
+/*============================================================*/
+/*	Optimized code: remove all debugging code	      */
+/*============================================================*/
+#ifdef STRIP_DEBUG_CODE
+#undef LOG_D
+#undef LOG_N
+#undef LOG_E
+#undef LOG_F
+#undef LOG_BUFFER
+
+#define LOG_D(format,args... ) /* noop */
+#define LOG_N(format,args...) fd_log(FD_LOG_NOTICE, format, ## args)
+#define LOG_E(format,args...) fd_log(FD_LOG_ERROR, format, ## args)
+#define LOG_F(format,args...) fd_log(FD_LOG_FATAL, format, ## args)
+#define LOG_BUFFER(printlevel, level, prefix, buf, bufsz, suffix ) {								\
+	if (printlevel > FD_LOG_DEBUG) {											\
+		int __i;													\
+		size_t __sz = (size_t)(bufsz);											\
+		uint8_t * __buf = (uint8_t *)(buf);										\
+		char * __strbuf[1024+1];											\
+		for (__i = 0; (__i < __sz) && (__i<(sizeof(__strbuf)/2); __i++) {						\
+			sprintf(__strbuf + (2 * __i), "%02.2hhx", __buf[__i]);     						\
+		}														\
+                fd_log(printlevel, prefix"%s"suffix, __strbuf);									\
+	}
+#endif /* STRIP_DEBUG_CODE */
+
+/*============================================================*/
+/*		    OTHER MACROS			      */
+/*============================================================*/
+/* helper macros (pre-processor hacks to allow macro arguments) */
+#define __tostr( arg )  #arg
+#define _stringize( arg ) __tostr( arg )
+#define __agr( arg1, arg2 ) arg1 ## arg2
+#define _aggregate( arg1, arg2 ) __agr( arg1, arg2 )
+
+/* Some aliases to socket addresses structures */
+#define sSS	struct sockaddr_storage
+#define sSA	struct sockaddr
+#define sSA4	struct sockaddr_in
+#define sSA6	struct sockaddr_in6
+
+/* The sockaddr length of a sSS structure */
+#define sSAlen( _sa_ )	\
+	( (socklen_t) ( (((sSA *)_sa_)->sa_family == AF_INET) ? (sizeof(sSA4)) :		\
+				((((sSA *)_sa_)->sa_family == AF_INET6) ? (sizeof(sSA6)) :	\
+					0 ) ) )
+#define sSAport( _sa_ )	\
+	( (socklen_t) ( (((sSA *)_sa_)->sa_family == AF_INET) ? (((sSA4 *)(_sa_))->sin_port) :		\
+				((((sSA *)_sa_)->sa_family == AF_INET6) ? (((sSA6 *)(_sa_))->sin6_port) :	\
+					0 ) ) )
+
+DECLARE_FD_DUMP_PROTOTYPE(fd_sa_dump, sSA * sa, int flags);
+#define sSA_DUMP_STRLEN	(INET6_ADDRSTRLEN + 1 + 32 + 2)
+void fd_sa_sdump_numeric(char * buf /* must be at least sSA_DUMP_STRLEN */, sSA * sa);
+
+
+/* A l4 protocol name (TCP / SCTP) */
+#ifdef DISABLE_SCTP
+#define IPPROTO_NAME( _proto )					\
+	(((_proto) == IPPROTO_TCP) ? "TCP" :			\
+			"Unknown")
+#else /* DISABLE_SCTP */
+#define IPPROTO_NAME( _proto )					\
+	( ((_proto) == IPPROTO_TCP) ? "TCP" :			\
+		(((_proto) == IPPROTO_SCTP) ? "SCTP" :		\
+			"Unknown"))
+#endif /* DISABLE_SCTP */
+
+/* Define the value of IP loopback address */
+#ifndef INADDR_LOOPBACK 
+#define INADDR_LOOPBACK	inet_addr("127.0.0.1")
+#endif /* INADDR_LOOPBACK */
+
+#ifndef INADDR_BROADCAST
+#define	INADDR_BROADCAST	((in_addr_t) 0xffffffff)
+#endif /* INADDR_BROADCAST */
+
+/* An IP equivalent to IN6_IS_ADDR_LOOPBACK */
+#ifndef IN_IS_ADDR_LOOPBACK
+#define IN_IS_ADDR_LOOPBACK(a) \
+  ((((long int) (a)->s_addr) & ntohl(0xff000000)) == ntohl(0x7f000000))
+#endif /* IN_IS_ADDR_LOOPBACK */
+
+/* An IP equivalent to IN6_IS_ADDR_UNSPECIFIED */
+#ifndef IN_IS_ADDR_UNSPECIFIED
+#define IN_IS_ADDR_UNSPECIFIED(a) \
+  (((long int) (a)->s_addr) == 0x00000000)
+#endif /* IN_IS_ADDR_UNSPECIFIED */
+
+/* create a V4MAPPED address */
+#define IN6_ADDR_V4MAP( a6, a4 ) {			\
+	((uint32_t *)(a6))[0] = 0;			\
+	((uint32_t *)(a6))[1] = 0;			\
+	((uint32_t *)(a6))[2] = htonl(0xffff);		\
+	((uint32_t *)(a6))[3] = (uint32_t)(a4);		\
+}
+
+/* Retrieve a v4 value from V4MAPPED address ( takes a s6_addr as param) */
+#define IN6_ADDR_V4UNMAP( a6 ) 				\
+	(((in_addr_t *)(a6))[3])
+
+
+/* We provide macros to convert 64 bit values to and from network byte-order, on systems where it is not already provided. */
+#ifndef HAVE_NTOHLL	/* Defined by the cmake step, if the ntohll symbol is defined on the system */
+# if HOST_BIG_ENDIAN
+    /* In big-endian systems, we don't have to change the values, since the order is the same as network */
+#   define ntohll(x) (x)
+#   define htonll(x) (x)
+# else /* HOST_BIG_ENDIAN */
+    /* For these systems, we must reverse the bytes. Use ntohl and htonl on sub-32 blocs, and inverse these blocs. */
+#   define ntohll(x) (typeof (x))( (((uint64_t)ntohl( (uint32_t)(x))) << 32 ) | ((uint64_t) ntohl( ((uint64_t)(x)) >> 32 ))) 
+#   define htonll(x) (typeof (x))( (((uint64_t)htonl( (uint32_t)(x))) << 32 ) | ((uint64_t) htonl( ((uint64_t)(x)) >> 32 ))) 
+# endif /* HOST_BIG_ENDIAN */
+#endif /* HAVE_NTOHLL */
+
+/* This macro will give the next multiple of 4 for an integer (used for padding sizes of AVP). */
+#define PAD4(_x) ((_x) + ( (4 - (_x)) & 3 ) )
+
+/* Useful to display any value as (safe) ASCII (will garbage UTF-8 output...) */
+#define ASCII(_c) ( ((_c < 32) || (_c > 127)) ? ( _c ? '?' : ' ' ) : _c )
+
+/* Compare timespec structures */
+#define TS_IS_INFERIOR( ts1, ts2 ) 		\
+	(    ((ts1)->tv_sec  < (ts2)->tv_sec ) 	\
+	  || (((ts1)->tv_sec  == (ts2)->tv_sec ) && ((ts1)->tv_nsec < (ts2)->tv_nsec) ))
+
+/* Compute diff between two timespecs (pointers) */
+#define TS_DIFFERENCE( tsdiff, tsstart, tsend )	{					\
+	if ((tsend)->tv_nsec < (tsstart)->tv_nsec ) {					\
+		(tsdiff)->tv_sec = (tsend)->tv_sec - (tsstart)->tv_sec - 1;		\
+		(tsdiff)->tv_nsec = (tsend)->tv_nsec + 1000000000 - (tsstart)->tv_nsec;	\
+	} else {									\
+		(tsdiff)->tv_sec  = (tsend)->tv_sec  - (tsstart)->tv_sec;		\
+		(tsdiff)->tv_nsec = (tsend)->tv_nsec - (tsstart)->tv_nsec;		\
+	}}
+		
+
+/* This gives a good size for buffered reads */
+#ifndef BUFSIZ
+#define BUFSIZ 96
+#endif /* BUFSIZ */
+
+/* This gives the length of a const string */
+#define CONSTSTRLEN( str ) (sizeof(str) - 1)
+
+
+/*============================================================*/
+/*                         PORTABILITY                        */
+/*============================================================*/
+#ifndef HAVE_CLOCK_GETTIME
+  #define CLOCK_REALTIME  0
+  #include <sys/time.h>
+  int clock_gettime(int clk_id, struct timespec* ts);
+#endif /* HAVE_CLOCK_GETTIME */
+
+#ifndef HAVE_STRNDUP
+char * strndup (char *str, size_t len);
+#endif /* HAVE_STRNDUP */
+
+
+/*============================================================*/
+/*                         BINARY STRINGS                     */
+/*============================================================*/
+
+/* Compute a hash value of a binary string. 
+The hash must remain local to this machine, there is no guarantee that same input
+will give same output on a different system (endianness) */
+uint32_t fd_os_hash ( uint8_t * string, size_t len );
+
+/* This type used for binary strings that contain no \0 except as their last character. 
+It means some string operations can be used on it. */
+typedef uint8_t * os0_t;
+
+/* Same as strdup but for os0_t strings */
+os0_t os0dup_int(os0_t s, size_t l);
+#define os0dup( _s, _l)  (void *)os0dup_int((os0_t)(_s), _l)
+
+/* Check that an octet string value can be used as os0_t */
+static __inline__ int fd_os_is_valid_os0(uint8_t * os, size_t oslen) {
+	/* The only situation where it is not valid is when it contains a \0 inside the octet string */
+	return (memchr(os, '\0', oslen) == NULL);
+}
+
+/* The following type denotes a verified DiameterIdentity value (that contains only pure letters, digits, hyphen, dot) */
+typedef char * DiamId_t;
+
+/* Maximum length of a hostname we accept */
+#ifndef HOST_NAME_MAX
+#define HOST_NAME_MAX 512
+#endif /* HOST_NAME_MAX */
+
+/* Check if a binary string contains a valid Diameter Identity value.
+  rfc3588 states explicitely that such a Diameter Identity consists only of ASCII characters. */
+int fd_os_is_valid_DiameterIdentity(uint8_t * os, size_t ossz);
+
+/* The following function validates a string as a Diameter Identity or applies the IDNA transformation on it 
+ if *inoutsz is != 0 on entry, *id may not be \0-terminated.
+ memory has the following meaning: 0: *id can be realloc'd. 1: *id must be malloc'd on output (was static)
+*/
+int fd_os_validate_DiameterIdentity(char ** id, size_t * inoutsz, int memory);
+
+/* Create an order relationship for binary strings (not needed to be \0 terminated). 
+   It does NOT mimic strings relationships so that it is more efficient. It is case sensitive.
+   (the strings are actually first ordered by their lengh, then by their bytes contents)
+   returns: -1 if os1 < os2;  +1 if os1 > os2;  0 if they are equal */
+int fd_os_cmp_int(os0_t os1, size_t os1sz, os0_t os2, size_t os2sz);
+#define fd_os_cmp(_o1, _l1, _o2, _l2)  fd_os_cmp_int((os0_t)(_o1), _l1, (os0_t)(_o2), _l2)
+
+/* A roughly case-insensitive variant, which actually only compares ASCII chars (0-127) in a case-insentitive maneer 
+  -- it does not support locales where a lowercase letter uses more space than upper case, such as ß -> ss
+ It is slower than fd_os_cmp.
+ Note that the result is NOT the same as strcasecmp !!!
+ 
+ This function gives the same order as fd_os_cmp, except when it finds 2 strings to be equal.
+ However this is not always sufficient:
+ 	for example fd_os_cmp gives: "Ac" < "aB" < "aa"
+	if you attempt to fd_os_almostcasesrch "Aa" you will actually have to go past "aB" which is > "Aa".
+	Therefore you can use the maybefurther parameter.
+	This parameter is 1 on return if os1 may have been stored further that os2 (assuming os2 values are ordered by fd_os_cmp)
+	and 0 if we are sure that it is not the case.
+	When looping through a list of fd_os_cmp classified values, this parameter must be used to stop looping, in addition to the comp result.
+ */
+int fd_os_almostcasesrch_int(uint8_t * os1, size_t os1sz, uint8_t * os2, size_t os2sz, int * maybefurther);
+#define fd_os_almostcasesrch(_o1, _l1, _o2, _l2, _mb)  fd_os_almostcasesrch_int((os0_t)(_o1), _l1, (os0_t)(_o2), _l2, _mb)
+
+/* Analyze a DiameterURI and return its components. 
+  Return EINVAL if the URI is not valid. 
+  *diamid is malloc'd on function return and must be freed (it is processed by fd_os_validate_DiameterIdentity).
+  *secure is 0 (no security) or 1 (security enabled) on return.
+  *port is 0 (default) or a value in host byte order on return.
+  *transport is 0 (default) or IPPROTO_* on return.
+  *proto is 0 (default) or 'd' (diameter), 'r' (radius), or 't' (tacacs+) on return.
+  */
+int fd_os_parse_DiameterURI(uint8_t * uri, size_t urisz, DiamId_t * diamid, size_t * diamidlen, int * secure, uint16_t * port, int * transport, char *proto);
+
+/*============================================================*/
+/*                          THREADS                           */
+/*============================================================*/
+
+/* Terminate a thread */
+static __inline__ int fd_thr_term(pthread_t * th)
+{
+	void * th_ret = NULL;
+	
+	CHECK_PARAMS(th);
+	
+	/* Test if it was already terminated */
+	if (*th == (pthread_t)NULL)
+		return 0;
+	
+	/* Cancel the thread if it is still running - ignore error if it was already terminated */
+	(void) pthread_cancel(*th);
+	
+	/* Then join the thread */
+	CHECK_POSIX( pthread_join(*th, &th_ret) );
+	
+	if (th_ret == PTHREAD_CANCELED) {
+		TRACE_DEBUG(ANNOYING, "The thread %p was canceled", (void *)*th);
+	} else {
+		TRACE_DEBUG(CALL, "The thread %p returned %p", (void *)*th, th_ret);
+	}
+	
+	/* Clean the location */
+	*th = (pthread_t)NULL;
+	
+	return 0;
+}
+
+
+/*************
+ Cancelation cleanup handlers for common objects 
+ *************/
+static __inline__ void fd_cleanup_mutex( void * mutex )
+{
+	CHECK_POSIX_DO( pthread_mutex_unlock((pthread_mutex_t *)mutex), /* */);
+}
+		
+static __inline__ void fd_cleanup_rwlock( void * rwlock )
+{
+	CHECK_POSIX_DO( pthread_rwlock_unlock((pthread_rwlock_t *)rwlock), /* */);
+}
+
+static __inline__ void fd_cleanup_buffer( void * buffer )
+{
+	free(buffer);
+}
+static __inline__ void fd_cleanup_socket(void * sockptr)
+{
+	if (sockptr && (*(int *)sockptr > 0)) {
+		CHECK_SYS_DO( close(*(int *)sockptr), /* ignore */ );
+		*(int *)sockptr = -1;
+	}
+}
+
+
+/*============================================================*/
+/*                          LISTS                             */
+/*============================================================*/
+
+/* The following structure represents a chained list element  */
+struct fd_list {
+	struct fd_list 	*next; /* next element in the list */
+	struct fd_list 	*prev; /* previous element in the list */
+	struct fd_list 	*head; /* head of the list */
+	void		*o;    /* additional pointer, used for any purpose (ex: start of the parent object) */
+};
+
+/* Initialize a list element */
+#define FD_LIST_INITIALIZER( _list_name ) \
+	{ .next = & _list_name, .prev = & _list_name, .head = & _list_name, .o = NULL }
+#define FD_LIST_INITIALIZER_O( _list_name, _obj ) \
+	{ .next = & _list_name, .prev = & _list_name, .head = & _list_name, .o = _obj }
+void fd_list_init ( struct fd_list * list, void * obj );
+
+/* Return boolean, true if the list is empty */
+#define FD_IS_LIST_EMPTY( _list ) ((((struct fd_list *)(_list))->head == (_list)) && (((struct fd_list *)(_list))->next == (_list)))
+
+/* Insert an item in a list at known position */
+void fd_list_insert_after  ( struct fd_list * ref, struct fd_list * item );
+void fd_list_insert_before ( struct fd_list * ref, struct fd_list * item );
+
+/* Move all elements from a list at the end of another */
+void fd_list_move_end(struct fd_list * ref, struct fd_list * senti);
+
+/* Insert an item in an ordered list -- ordering function must be provided. If duplicate object found, EEXIST and it is returned in ref_duplicate */
+int fd_list_insert_ordered( struct fd_list * head, struct fd_list * item, int (*cmp_fct)(void *, void *), void ** ref_duplicate);
+
+/* Unlink an item from a list */
+void fd_list_unlink ( struct fd_list * item );
+
+
+
+
+/*============================================================*/
+/*                        DICTIONARY                          */
+/*============================================================*/
+
+/* Structure that contains the complete dictionary definitions */
+struct dictionary;
+
+/* Structure that contains a dictionary object */
+struct dict_object;
+
+/* Types of object in the dictionary. */
+enum dict_object_type {
+	DICT_VENDOR	= 1,	/* Vendor */
+	DICT_APPLICATION,	/* Diameter Application */
+	DICT_TYPE,		/* AVP data type */
+	DICT_ENUMVAL,		/* Named constant (value of an enumerated AVP type) */
+	DICT_AVP,		/* AVP */
+	DICT_COMMAND,		/* Diameter Command */
+	DICT_RULE		/* a Rule for AVP in command or grouped AVP */
+#define DICT_TYPE_MAX	DICT_RULE
+};
+	
+/* Initialize a dictionary */
+int fd_dict_init(struct dictionary ** dict);
+/* Destroy a dictionary */
+int fd_dict_fini(struct dictionary ** dict);
+
+/*
+ * FUNCTION:	fd_dict_new
+ *
+ * PARAMETERS:
+ *  dict	: Pointer to the dictionnary where the object is created
+ *  type 	: What kind of object must be created
+ *  data 	: pointer to the data for the object. 
+ *          	 type parameter is used to determine the type of data (see below for detail).
+ *  parent 	: a reference to a parent object, if needed.
+ *  ref 	: upon successful creation, reference to new object is stored here if !null.
+ *
+ * DESCRIPTION: 
+ *  Create a new object in the dictionary. 
+ *  See following object sections in this header file for more information on data and parent parameters format.
+ *
+ * RETURN VALUE:
+ *  0      	: The object is created in the dictionary.
+ *  EINVAL 	: A parameter is invalid.
+ *  EEXIST 	: This object is already defined in the dictionary (with conflicting data). 
+ *                If "ref" is not NULL, it points to the existing element on return.
+ *  (other standard errors may be returned, too, with their standard meaning. Example:
+ *    ENOMEM 	: Memory allocation for the new object element failed.)
+ */
+int fd_dict_new ( struct dictionary * dict, enum dict_object_type type, void * data, struct dict_object * parent, struct dict_object ** ref );
+
+/*
+ * FUNCTION: 	fd_dict_search
+ *
+ * PARAMETERS:
+ *  dict	: Pointer to the dictionnary where the object is searched
+ *  type 	: type of object that is being searched
+ *  criteria 	: how the object must be searched. See object-related sections below for more information.
+ *  what 	: depending on criteria, the data that must be searched.
+ *  result 	: On successful return, pointer to the object is stored here.
+ *  retval	: this value is returned if the object is not found and result is not NULL.
+ *
+ * DESCRIPTION: 
+ *   Perform a search in the dictionary. 
+ *   See the object-specific sections below to find how to look for each objects.
+ *   If the "result" parameter is NULL, the function is used to check if an object is in the dictionary.
+ *   Otherwise, a reference to the object is stored in result if found.
+ *   If result is not NULL and the object is not found, retval is returned (should be 0 or ENOENT usually)
+ *
+ * RETURN VALUE:
+ *  0      	: The object has been found in the dictionary, or *result is NULL.
+ *  EINVAL 	: A parameter is invalid.
+ *  ENOENT	: No matching object has been found, and result was NULL.
+ */
+int fd_dict_search ( struct dictionary * dict, enum dict_object_type type, int criteria, const void * what, struct dict_object ** result, int retval );
+
+/* Special case: get the generic error command object */
+int fd_dict_get_error_cmd(struct dictionary * dict, struct dict_object ** obj);
+
+/*
+ * FUNCTION:	fd_dict_getval
+ *
+ * PARAMETERS:
+ *  object 	: Pointer to a dictionary object.
+ *  data 	: pointer to a structure to hold the data for the object.
+ *          	  The type is the same as "data" parameter in fd_dict_new function.
+ *
+ * DESCRIPTION: 
+ *  Retrieve content of a dictionary object.
+ *  See following object sections in this header file for more information on data and parent parameters format.
+ *
+ * RETURN VALUE:
+ *  0      	: The content of the object has been retrieved.
+ *  EINVAL 	: A parameter is invalid.
+ */
+int fd_dict_getval ( struct dict_object * object, void * val);
+int fd_dict_gettype ( struct dict_object * object, enum dict_object_type * type);
+int fd_dict_getdict ( struct dict_object * object, struct dictionary ** dict);
+
+/* Debug functions */
+DECLARE_FD_DUMP_PROTOTYPE(fd_dict_dump_object, struct dict_object * obj);
+DECLARE_FD_DUMP_PROTOTYPE(fd_dict_dump, struct dictionary * dict);
+
+/* Function to access full contents of the dictionary, see doc in dictionary.c */
+int fd_dict_getlistof(int criteria, void * parent, struct fd_list ** sentinel);
+
+/* Function to remove an entry from the dictionary.
+  This cannot be used if the object has children (for example a vendor with vendor-specific AVPs).
+  In such case, the children must be removed first. */
+int fd_dict_delete(struct dict_object * obj);
+
+/*
+ ***************************************************************************
+ *
+ * Vendor object 
+ *
+ * These types are used to manage vendors in the dictionary
+ *
+ ***************************************************************************
+ */
+
+/* Type to hold a Vendor ID: "SMI Network Management Private Enterprise Codes" (RFC3232) */
+typedef uint32_t	vendor_id_t;
+
+/* Type to hold data associated to a vendor */
+struct dict_vendor_data {
+	vendor_id_t	 vendor_id;	/* ID of a vendor */
+	char *	 	 vendor_name;	/* The name of this vendor */
+};
+
+/* The criteria for searching a vendor object in the dictionary */
+enum {
+	VENDOR_BY_ID = 10,	/* "what" points to a vendor_id_t */
+	VENDOR_BY_NAME,		/* "what" points to a char * */
+	VENDOR_OF_APPLICATION,	/* "what" points to a struct dict_object containing an application (see below) */
+	VENDOR_OF_AVP,		/* "what" points to a struct dict_object containing an avp (see below) */
+};
+
+/***
+ *  API usage :
+
+Note: the value of "vendor_name" is copied when the object is created, and the string may be disposed afterwards.
+On the other side, when value is retrieved with dict_getval, the string is not copied and MUST NOT be freed. It will
+be freed automatically along with the object itself with call to dict_fini later.
+ 
+- fd_dict_new:
+ The "parent" parameter is not used for vendors. 
+ Sample code to create a vendor:
+ {
+	 int ret;
+	 struct dict_object * myvendor;
+	 struct dict_vendor_data myvendordata = { 23455, "my vendor name" };  -- just an example...
+	 ret = fd_dict_new ( dict, DICT_VENDOR, &myvendordata, NULL, &myvendor );
+ }
+
+- fd_dict_search:
+ Sample codes to look for a vendor object, by its id or name:
+ {
+	 int ret;
+	 struct dict_object * vendor_found;
+	 vendor_id_t vendorid = 23455;
+	 ret = fd_dict_search ( dict, DICT_VENDOR, VENDOR_BY_ID, &vendorid, &vendor_found, ENOENT);
+	 - or -
+	 ret = fd_dict_search ( dict, DICT_VENDOR, VENDOR_BY_NAME, "my vendor name", &vendor_found, ENOENT);
+ }
+ 
+ - fd_dict_getval:
+ Sample code to retrieve the data from a vendor object:
+ {
+	 int ret;
+	 struct dict_object * myvendor;
+	 struct dict_vendor_data myvendordata;
+	 ret = fd_dict_search ( dict, DICT_VENDOR, VENDOR_BY_NAME, "my vendor name", &myvendor, ENOENT);
+	 ret = fd_dict_getval ( myvendor, &myvendordata );
+	 printf("my vendor id: %d\n", myvendordata.vendor_id );
+ }
+		 
+*/
+		
+/* Special function: */
+uint32_t * fd_dict_get_vendorid_list(struct dictionary * dict);
+	 
+/*
+ ***************************************************************************
+ *
+ * Application object 
+ *
+ * These types are used to manage Diameter applications in the dictionary
+ *
+ ***************************************************************************
+ */
+
+/* Type to hold a Diameter application ID: IANA assigned value for this application. */
+typedef uint32_t	application_id_t;
+
+/* Type to hold data associated to an application */
+struct dict_application_data {
+	application_id_t	 application_id;	/* ID of the application */
+	char *	 		 application_name;	/* The name of this application */
+};
+
+/* The criteria for searching an application object in the dictionary */
+enum {
+	APPLICATION_BY_ID = 20,		/* "what" points to a application_id_t */
+	APPLICATION_BY_NAME,		/* "what" points to a char * */
+	APPLICATION_OF_TYPE,		/* "what" points to a struct dict_object containing a type object (see below) */
+	APPLICATION_OF_COMMAND		/* "what" points to a struct dict_object containing a command (see below) */
+};
+
+/***
+ *  API usage :
+
+The "parent" parameter of dict_new may point to a vendor object to inform of what vendor defines the application.
+for standard-track applications, the "parent" parameter should be NULL.
+The vendor associated to an application is retrieved with VENDOR_OF_APPLICATION search criteria on vendors.
+
+- fd_dict_new:
+ Sample code for application creation:
+ {
+	 int ret;
+	 struct dict_object * vendor;
+	 struct dict_object * appl;
+	 struct dict_vendor_data vendor_data = {
+		 23455,
+		 "my vendor name"
+	 };
+	 struct dict_application_data app_data = {
+		 9789,
+		 "my vendor's application"
+	 };
+	
+	 ret = fd_dict_new ( dict, DICT_VENDOR, &vendor_data, NULL, &vendor );
+	 ret = fd_dict_new ( dict, DICT_APPLICATION, &app_data, vendor, &appl );
+ }
+
+- fd_dict_search:
+ Sample code to retrieve the vendor of an application
+ {
+	 int ret;
+	 struct dict_object * vendor, * appli;
+	 
+	 ret = fd_dict_search ( dict, DICT_APPLICATION, APPLICATION_BY_NAME, "my vendor's application", &appli, ENOENT);
+	 ret = fd_dict_search ( dict, DICT_VENDOR, VENDOR_OF_APPLICATION, appli, &vendor, ENOENT);
+ }
+ 
+ - fd_dict_getval:
+ Sample code to retrieve the data from an application object:
+ {
+	 int ret;
+	 struct dict_object * appli;
+	 struct dict_application_data appl_data;
+	 ret = fd_dict_search ( dict, DICT_APPLICATION, APPLICATION_BY_NAME, "my vendor's application", &appli, ENOENT);
+	 ret = fd_dict_getval ( appli, &appl_data );
+	 printf("my application id: %s\n", appl_data.application_id );
+ }
+
+*/
+
+/*
+ ***************************************************************************
+ *
+ * Type object 
+ *
+ * These types are used to manage AVP data types in the dictionary
+ *
+ ***************************************************************************
+ */
+
+/* Type to store any AVP value */ 
+union avp_value {
+	struct {
+		uint8_t *data;	/* bytes buffer */
+		size_t   len;	/* length of the data buffer */
+	}           os;		/* Storage for an octet string */
+	int32_t     i32;	/* integer 32 */
+	int64_t     i64;	/* integer 64 */
+	uint32_t    u32;	/* unsigned 32 */
+	uint64_t    u64;	/* unsigned 64 */
+	float       f32;	/* float 32 */
+	double 	    f64;	/* float 64 */
+};
+
+/* These are the basic AVP types defined in RFC3588bis */
+enum dict_avp_basetype {
+	AVP_TYPE_GROUPED,
+	AVP_TYPE_OCTETSTRING,
+	AVP_TYPE_INTEGER32,
+	AVP_TYPE_INTEGER64,
+	AVP_TYPE_UNSIGNED32,
+	AVP_TYPE_UNSIGNED64,
+	AVP_TYPE_FLOAT32,
+	AVP_TYPE_FLOAT64
+#define AVP_TYPE_MAX AVP_TYPE_FLOAT64
+};
+
+/* Callbacks that can be associated with a derived type to easily interpret the AVP value. */
+/*
+ * CALLBACK:	dict_avpdata_interpret
+ *
+ * PARAMETERS:
+ *   val         : Pointer to the AVP value that must be interpreted.
+ *   interpreted : The result of interpretation is stored here. The format and meaning depends on each type.
+ *
+ * DESCRIPTION: 
+ *   This callback can be provided with a derived type in order to facilitate the interpretation of formated data.
+ *  For example, when an AVP of type "Address" is received, it can be used to convert the octetstring into a struct sockaddr.
+ *  This callback is not called directly, but through the message's API msg_avp_value_interpret function.
+ *
+ * RETURN VALUE:
+ *  0      	: Operation complete.
+ *  !0 		: An error occurred, the error code is returned.
+ */
+typedef int (*dict_avpdata_interpret) (union avp_value * value, void * interpreted);
+/*
+ * CALLBACK:	dict_avpdata_encode
+ *
+ * PARAMETERS:
+ *   data	: The formated data that must be stored in the AVP value.
+ *   val	: Pointer to the AVP value storage area where the data must be stored.
+ *
+ * DESCRIPTION: 
+ *   This callback can be provided with a derived type in order to facilitate the encoding of formated data.
+ *  For example, it can be used to convert a struct sockaddr in an AVP value of type Address.
+ *  This callback is not called directly, but through the message's API msg_avp_value_encode function.
+ *  If the callback is defined for an OctetString based type, the created string must be malloc'd. free will be called 
+ *  automatically later.
+ *
+ * RETURN VALUE:
+ *  0      	: Operation complete.
+ *  !0 		: An error occurred, the error code is returned.
+ */
+typedef int (*dict_avpdata_encode) (void * data, union avp_value * val);
+
+/*
+ * CALLBACK:	dict_avpdata_check
+ *
+ * PARAMETERS:
+ *   val	: Pointer to the AVP value that was received and needs to be sanity checked.
+ *   data      : a parameter stored in the type structure (to enable more generic check functions)
+ *   error_msg: upon erroneous value, a string describing the error can be returned here (it will be strcpy by caller). This description will be returned in the error message, if any. 
+ *
+ * DESCRIPTION: 
+ *   This callback can be provided with a derived type in order to improve the operation of the
+ *  fd_msg_parse_dict function. When this callback is present, the value of the AVP that has
+ * been parsed is passed to this function for finer granularity check. For example for some 
+ * speccific AVP, the format of an OCTETSTRING value can be further checked, or the
+ * interger value can be verified.
+ *
+ * RETURN VALUE:
+ *  0      	: The value is valid.
+ *  !0          : An error occurred, the error code is returned. It is advised to return EINVAL on incorrect val
+ */
+typedef int (*dict_avpdata_check) (void * data, union avp_value * val, char ** error_msg);
+
+
+
+/* Type to hold data associated to a derived AVP data type */
+struct dict_type_data {
+	enum dict_avp_basetype	 type_base;	/* How the data of such AVP must be interpreted */
+	char *	 		 type_name;	/* The name of this type */
+	dict_avpdata_interpret	 type_interpret;/* cb to convert the AVP value in more comprehensive format (or NULL) */
+	dict_avpdata_encode	 type_encode;	/* cb to convert formatted data into an AVP value (or NULL) */
+	DECLARE_FD_DUMP_PROTOTYPE((*type_dump), union avp_value * val); /* cb called by fd_msg_dump_* for this type of data (if != NULL). Returned string must be freed.  */
+	dict_avpdata_check       type_check;
+	void  *                          type_check_param;
+};
+
+/* The criteria for searching a type object in the dictionary */
+enum {
+	TYPE_BY_NAME = 30,		/* "what" points to a char * */
+	TYPE_OF_ENUMVAL,		/* "what" points to a struct dict_object containing an enumerated constant (DICT_ENUMVAL, see below). */
+	TYPE_OF_AVP			/* "what" points to a struct dict_object containing an AVP object. */
+};
+
+/****
+ Callbacks defined in libfdproto/dictionary_functions.c file -- see that file for usage. 
+ */
+
+/* Convert an Address type AVP into a struct sockaddr_storage */
+int fd_dictfct_Address_encode(void * data, union avp_value * avp_value);
+int fd_dictfct_Address_interpret(union avp_value * avp_value, void * interpreted);
+DECLARE_FD_DUMP_PROTOTYPE(fd_dictfct_Address_dump, union avp_value * avp_value);
+
+/* Display the content of an AVP of type UTF8String in the log file */
+DECLARE_FD_DUMP_PROTOTYPE(fd_dictfct_UTF8String_dump, union avp_value * avp_value);
+
+/* For Time AVPs, map with time_t value directly */
+int fd_dictfct_Time_encode(void * data, union avp_value * avp_value);
+int fd_dictfct_Time_interpret(union avp_value * avp_value, void * interpreted);
+DECLARE_FD_DUMP_PROTOTYPE(fd_dictfct_Time_dump, union avp_value * avp_value);
+
+
+/* For string AVP, the following type_check function provides simple basic check for specific characters presence, e.g. use "@." for trivial email address check */
+int fd_dictfct_CharInOS_check(void * data, union avp_value * val, char ** error_msg);
+
+
+/****/
+
+/***
+ *  API usage :
+
+- fd_dict_new:
+ The "parent" parameter may point to an application object, when a type is defined by a Diameter application. 
+ 
+ Sample code:
+ {
+	 int ret;
+	 struct dict_object * mytype;
+	 struct dict_type_data mytypedata = 
+		{ 
+		 AVP_TYPE_OCTETSTRING,
+		 "Address",
+		 NULL,
+		 NULL
+		};
+	 ret = fd_dict_new ( dict, DICT_TYPE, &mytypedata, NULL, &mytype );
+ }
+
+- fd_dict_search:
+ Sample code:
+ {
+	 int ret;
+	 struct dict_object * address_type;
+	 ret = fd_dict_search ( dict, DICT_TYPE, TYPE_BY_NAME, "Address", &address_type, ENOENT);
+ }
+ 
+*/
+
+/*
+ ***************************************************************************
+ *
+ * Enumerated values object 
+ *
+ * These types are used to manage named constants of some AVP,
+ * for enumerated types. freeDiameter allows constants for types others than Unsigned32
+ *
+ ***************************************************************************
+ */
+
+/* Type to hold data of named constants for AVP */
+struct dict_enumval_data {
+	char *	 	 enum_name;	/* The name of this constant */
+	union avp_value  enum_value;	/* Value of the constant. Union term depends on parent type's base type. */
+};
+
+/* The criteria for searching a constant in the dictionary */
+enum {
+	ENUMVAL_BY_STRUCT = 40,	/* "what" points to a struct dict_enumval_request as defined below */
+	ENUMVAL_BY_NAME,	/* This cannot be used for researches */
+	ENUMVAL_BY_VALUE	/* This cannot be used for researches */
+};
+
+struct dict_enumval_request {
+	/* Identifier of the parent type, one of the following must not be NULL */
+	struct dict_object	*type_obj;
+	char *			 type_name;
+	
+	/* Search criteria for the constant */
+	struct dict_enumval_data search; /* search.enum_value is used only if search.enum_name == NULL */
+};
+
+/***
+ *  API usage :
+
+- fd_dict_new:
+ The "parent" parameter must point to a derived type object. 
+ Sample code to create a type "Boolean" with two constants "True" and "False":
+ {
+	 int ret;
+	 struct dict_object * type_boolean;
+	 struct dict_type_data type_boolean_data = 
+		{ 
+		 AVP_TYPE_INTEGER32,
+		 "Boolean",
+		 NULL,
+		 NULL
+		};
+	 struct dict_enumval_data boolean_false =
+	 	{
+		 .enum_name="False",
+		 .enum_value.i32 = 0
+	 	};
+	 struct dict_enumval_data boolean_true =
+	 	{
+		 .enum_name="True",
+		 .enum_value.i32 = -1
+	 	};
+	 ret = fd_dict_new ( dict, DICT_TYPE, &type_boolean_data, NULL, &type_boolean );
+	 ret = fd_dict_new ( dict, DICT_ENUMVAL, &boolean_false, type_boolean, NULL );
+	 ret = fd_dict_new ( dict, DICT_ENUMVAL, &boolean_true , type_boolean, NULL );
+	 
+ }
+
+- fd_dict_search:
+ Sample code to look for a constant name, by its value:
+ {
+	 int ret;
+	 struct dict_object * value_found;
+	 struct dict_enumval_request boolean_by_value =
+	 	{
+		 .type_name = "Boolean",
+		 .search.enum_name=NULL,
+		 .search.enum_value.i32 = -1
+	 	};
+	 
+	 ret = fd_dict_search ( dict, DICT_ENUMVAL, ENUMVAL_BY_STRUCT, &boolean_by_value, &value_found, ENOENT);
+ }
+ 
+ - fd_dict_getval:
+ Sample code to retrieve the data from a constant object:
+ {
+	 int ret;
+	 struct dict_object * value_found;
+	 struct dict_enumval_data boolean_data = NULL;
+	 struct dict_enumval_request boolean_by_value =
+	 	{
+		 .type_name = "Boolean",
+		 .search.enum_name=NULL,
+		 .search.enum_value.i32 = 0
+	 	};
+	 
+	 ret = fd_dict_search ( dict, DICT_ENUMVAL, ENUMVAL_BY_STRUCT, &boolean_by_value, &value_found, ENOENT);
+	 ret = fd_dict_getval ( value_found, &boolean_data );
+	 printf(" Boolean with value 0: %s", boolean_data.enum_name );
+ }
+*/
+	 
+/*
+ ***************************************************************************
+ *
+ * AVP object 
+ *
+ * These objects are used to manage AVP definitions in the dictionary
+ *
+ ***************************************************************************
+ */
+
+/* Type to hold an AVP code. For vendor 0, these codes are assigned by IANA. Otherwise, it is managed by the vendor */
+typedef uint32_t	avp_code_t;
+
+/* Values of AVP flags */
+#define	AVP_FLAG_VENDOR	  	0x80
+#define	AVP_FLAG_MANDATORY	0x40
+#define	AVP_FLAG_RESERVED3	0x20
+#define	AVP_FLAG_RESERVED4	0x10
+#define	AVP_FLAG_RESERVED5	0x08
+#define	AVP_FLAG_RESERVED6	0x04
+#define	AVP_FLAG_RESERVED7	0x02
+#define	AVP_FLAG_RESERVED8	0x01
+
+/* For dumping flags and values */
+#define DUMP_AVPFL_str	"%c%c%s%s%s%s%s%s"
+#define DUMP_AVPFL_val(_val) (_val & AVP_FLAG_VENDOR)?'V':'-' , (_val & AVP_FLAG_MANDATORY)?'M':'-',	\
+				(_val & AVP_FLAG_RESERVED3)?"3":"", (_val & AVP_FLAG_RESERVED4)?"4":"", \
+				(_val & AVP_FLAG_RESERVED5)?"5":"", (_val & AVP_FLAG_RESERVED6)?"6":"", (_val & AVP_FLAG_RESERVED7)?"7":"", (_val & AVP_FLAG_RESERVED8)?"8":""
+
+/* Type to hold data associated to an avp */
+struct dict_avp_data {
+	avp_code_t	 	 avp_code;	/* Code of the avp */
+	vendor_id_t	 	 avp_vendor;	/* Vendor of the AVP, or 0 */
+	char *			 avp_name;	/* Name of this AVP */
+	uint8_t		 	 avp_flag_mask;	/* Mask of fixed AVP flags */
+	uint8_t		 	 avp_flag_val;	/* Values of the fixed flags */
+	enum dict_avp_basetype 	 avp_basetype;	/* Basic type of data found in the AVP */
+};
+
+/* The criteria for searching an avp object in the dictionary */
+enum {
+	AVP_BY_CODE = 50,	/* "what" points to an avp_code_t, vendor is always 0 */
+	AVP_BY_NAME,		/* "what" points to a char *, vendor is always 0 */
+	AVP_BY_NAME_ALL_VENDORS,/* "what" points to a string. Might be quite slow... */
+	AVP_BY_STRUCT,		/* "what" points to a struct dict_avp_request_ex (see below) */
+			
+	/* kept for backward compatibility, better use AVP_BY_STRUCT above instead */
+	AVP_BY_CODE_AND_VENDOR,	/* "what" points to a struct dict_avp_request (see below), where avp_vendor and avp_code are set */
+	AVP_BY_NAME_AND_VENDOR	/* "what" points to a struct dict_avp_request (see below), where avp_vendor and avp_name are set */
+};
+
+/* Struct used for some researchs */
+struct dict_avp_request_ex {
+	struct {
+		/* Only one of the following fields must be set. */
+		struct dict_object * 	vendor;		/* most efficient if already known, set to NULL to ignore */
+		vendor_id_t	 	vendor_id; 	/* set to 0 to ignore -- prefer AVP_BY_CODE or AVP_BY_NAME for vendor 0 */
+		const char *			vendor_name;	/* set to NULL to ignore */
+	} avp_vendor;
+	
+	struct {
+		/* Only one of the following fields must be set */
+		avp_code_t	 avp_code; /* set to 0 to ignore */
+		const char *		 avp_name; /* set to NULL to ignore */
+	} avp_data;
+};
+
+struct dict_avp_request {
+	vendor_id_t	 avp_vendor;
+	avp_code_t	 avp_code;
+	char *		 avp_name;
+};
+
+
+
+/***
+ *  API usage :
+
+If "parent" parameter is not NULL during AVP creation, it must point to a DICT_TYPE object. 
+The extended type is then attached to the AVP. In case where it is an enumerated type, the value of 
+AVP is automatically interpreted in debug messages, and in message checks.
+The derived type of an AVP can be retrieved with: dict_search ( DICT_TYPE, TYPE_OF_AVP, avp, ... )
+
+To create the rules (ABNF) for children of Grouped AVP, see the DICT_RULE related part.
+
+- fd_dict_new:
+ Sample code for AVP creation:
+ {
+	 int ret;
+	 struct dict_object * user_name_avp;
+	 struct dict_object * boolean_type;
+	 struct dict_object * sample_boolean_avp;
+	 struct dict_avp_data user_name_data = {
+		 1,					// code
+		 0,					// vendor
+		 "User-Name",				// name
+		 AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,	// fixed mask: V and M values must always be defined as follow. other flags can be set or cleared
+		 AVP_FLAG_MANDATORY,			// the V flag must be cleared, the M flag must be set.
+		 AVP_TYPE_OCTETSTRING			// User-Name AVP contains OctetString data (further precision such as UTF8String can be given with a parent derived type)
+	 };
+	 struct dict_avp_data sample_boolean_data = {
+		 31337,
+		 23455,
+		 "Sample-Boolean",
+		 AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,
+		 AVP_FLAG_VENDOR,
+		 AVP_TYPE_INTEGER32			// This MUST be the same as parent type's
+	 };
+	
+ 	 -- Create an AVP with a base type --
+	 ret = fd_dict_new ( dict, DICT_AVP, &user_name_data, NULL, &user_name_avp );
+	 
+	 -- Create an AVP with a derived type --
+	 ret = fd_dict_search ( dict, DICT_TYPE, TYPE_BY_NAME, "Boolean", &boolean_type, ENOENT);
+	 ret = fd_dict_new ( dict, DICT_AVP, &sample_boolean_data , boolean_type, &sample_boolean_avp );
+	 
+ }
+
+- fd_dict_search:
+ Sample code to look for an AVP
+ {
+	 int ret;
+	 struct dict_object * avp_username;
+	 struct dict_object * avp_sampleboolean;
+	 struct dict_avp_request avpvendorboolean =
+	 	{
+		 .avp_vendor = 23455,
+		 .avp_name   = "Sample-Boolean"
+	 	};
+	 
+	 ret = fd_dict_search ( dict, DICT_AVP, AVP_BY_NAME, "User-Name", &avp_username, ENOENT);
+	 
+	 ret = fd_dict_search ( dict, DICT_AVP, AVP_BY_NAME_AND_VENDOR, &avpvendorboolean, &avp_sampleboolean, ENOENT);
+
+	 -- this would also work, but be slower, because it has to search all vendor dictionaries --
+	 ret = fd_dict_search ( dict, DICT_AVP, AVP_BY_NAME_ALL_VENDORS, "Sample-Boolean", &avp_sampleboolean, ENOENT);
+	 
+ }
+ 
+ - fd_dict_getval:
+ Sample code to retrieve the data from an AVP object:
+ {
+	 int ret;
+	 struct dict_object * avp_username;
+	 struct dict_avp_data user_name_data;
+	 ret = fd_dict_search ( dict, DICT_AVP, AVP_BY_NAME, "User-Name", &avp_username, ENOENT);
+	 ret = fd_dict_getval ( avp_username, &user_name_data );
+	 printf("User-Name code: %d\n", user_name_data.avp_code );
+ }
+
+*/
+
+/*
+ ***************************************************************************
+ *
+ * Command object 
+ *
+ * These types are used to manage commands objects in the dictionary
+ *
+ ***************************************************************************
+ */
+
+/* Type to hold a Diameter command code: IANA assigned values. 0x0-0x7fffff=standard, 0x800000-0xfffffd=vendors, 0xfffffe-0xffffff=experimental */
+typedef uint32_t	command_code_t;
+
+/* Values of command flags */
+#define CMD_FLAG_REQUEST	0x80
+#define CMD_FLAG_PROXIABLE	0x40
+#define CMD_FLAG_ERROR		0x20
+#define CMD_FLAG_RETRANSMIT	0x10
+#define CMD_FLAG_RESERVED5	0x08
+#define CMD_FLAG_RESERVED6	0x04
+#define CMD_FLAG_RESERVED7	0x02
+#define CMD_FLAG_RESERVED8	0x01
+
+/* For dumping flags and values */
+#define DUMP_CMDFL_str	"%c%c%c%c%s%s%s%s"
+#define DUMP_CMDFL_val(_val) (_val & CMD_FLAG_REQUEST)?'R':'-' , (_val & CMD_FLAG_PROXIABLE)?'P':'-' , (_val & CMD_FLAG_ERROR)?'E':'-' , (_val & CMD_FLAG_RETRANSMIT)?'T':'-', \
+				(_val & CMD_FLAG_RESERVED5)?"5":"", (_val & CMD_FLAG_RESERVED6)?"6":"", (_val & CMD_FLAG_RESERVED7)?"7":"", (_val & CMD_FLAG_RESERVED8)?"8":""
+
+/* Type to hold data associated to a command */
+struct dict_cmd_data {
+	command_code_t	 cmd_code;	/* code of the command */
+	char *		 cmd_name;	/* Name of the command */
+	uint8_t		 cmd_flag_mask;	/* Mask of fixed-value flags */
+	uint8_t		 cmd_flag_val;	/* values of the fixed flags */
+};
+
+/* The criteria for searching an avp object in the dictionary */
+enum {
+	CMD_BY_NAME = 60,	/* "what" points to a char * */
+	CMD_BY_CODE_R,		/* "what" points to a command_code_t. The "Request" command is returned. */
+	CMD_BY_CODE_A,		/* "what" points to a command_code_t. The "Answer" command is returned. */
+	CMD_ANSWER		/* "what" points to a struct dict_object of a request command. The corresponding "Answer" command is returned. */
+};
+
+
+/***
+ *  API usage :
+
+The "parent" parameter of dict_new may point to an application object to inform of what application defines the command.
+The application associated to a command is retrieved with APPLICATION_OF_COMMAND search criteria on applications.
+
+To create the rules for children of commands, see the DICT_RULE related part.
+
+Note that the "Request" and "Answer" commands are two independant objects. This allows to have different rules for each.
+
+- fd_dict_new:
+ Sample code for command creation:
+ {
+	 int ret;
+	 struct dict_object * cer;
+	 struct dict_object * cea;
+	 struct dict_cmd_data ce_data = {
+		 257,					// code
+		 "Capabilities-Exchange-Request",	// name
+		 CMD_FLAG_REQUEST,			// mask
+		 CMD_FLAG_REQUEST			// value. Only the "R" flag is constrained here, set.
+	 };
+	
+	 ret = fd_dict_new (dict,  DICT_COMMAND, &ce_data, NULL, &cer );
+	 
+	 ce_data.cmd_name = "Capabilities-Exchange-Answer";
+	 ce_data.cmd_flag_val = 0;			// Same constraint on "R" flag, but this time it must be cleared.
+
+	 ret = fd_dict_new ( dict, DICT_COMMAND, &ce_data, NULL, &cea );
+ }
+
+- fd_dict_search:
+ Sample code to look for a command
+ {
+	 int ret;
+	 struct dict_object * cer, * cea;
+	 command_code_t	code = 257;
+	 ret = fd_dict_search ( dict, DICT_COMMAND, CMD_BY_NAME, "Capabilities-Exchange-Request", &cer, ENOENT);
+	 ret = fd_dict_search ( dict, DICT_COMMAND, CMD_BY_CODE_R, &code, &cer, ENOENT);
+ }
+ 
+ - fd_dict_getval:
+ Sample code to retrieve the data from a command object:
+ {
+	 int ret;
+	 struct dict_object * cer;
+	 struct dict_object * cea;
+	 struct dict_cmd_data cea_data;
+	 ret = fd_dict_search ( dict, DICT_COMMAND, CMD_BY_NAME, "Capabilities-Exchange-Request", &cer, ENOENT);
+	 ret = fd_dict_search ( dict, DICT_COMMAND, CMD_ANSWER, cer, &cea, ENOENT);
+	 ret = fd_dict_getval ( cea, &cea_data );
+	 printf("Answer to CER: %s\n", cea_data.cmd_name );
+ }
+
+*/
+
+/*
+ ***************************************************************************
+ *
+ * Rule object
+ *
+ * These objects are used to manage rules in the dictionary (ABNF implementation)
+ * This is used for checking messages validity (more powerful than a DTD)
+ *
+ ***************************************************************************
+ */
+
+/* This defines the kind of rule that is defined */
+enum rule_position {
+	RULE_FIXED_HEAD = 1,	/* The AVP must be at the head of the group. The rule_order field is used to specify the position. */
+	RULE_REQUIRED,		/* The AVP must be present in the parent, but its position is not defined. */
+	RULE_OPTIONAL,		/* The AVP may be present in the message. Used to specify a max number of occurences for example */
+	RULE_FIXED_TAIL		/* The AVP must be at the end of the group. The rule_order field is used to specify the position. */
+};
+
+/* Content of a RULE object data */
+struct dict_rule_data {
+	struct dict_object	*rule_avp;	/* Pointer to the AVP object that is concerned by this rule */
+	enum rule_position	 rule_position;	/* The position in which the rule_avp must appear in the parent */
+	unsigned		 rule_order;	/* for RULE_FIXED_* rules, the place. 1,2,3.. for HEAD rules; ...,3,2,1 for TAIL rules. */
+	int	 		 rule_min;	/* Minimum number of occurences. -1 means "default": 0 for optional rules, 1 for other rules */
+	int			 rule_max;	/* Maximum number of occurences. -1 means no maximum. 0 means the AVP is forbidden. */
+};
+
+/* The criteria for searching a rule in the dictionary */
+enum {
+	RULE_BY_AVP_AND_PARENT = 70	/* "what" points to a struct dict_rule_request -- see below. This is used to query "what is the rule for this AVP in this group?" */
+};
+
+/* Structure for querying the dictionary about a rule */
+struct dict_rule_request {
+	struct dict_object	*rule_parent;	/* The grouped avp or command to which the rule apply */
+	struct dict_object	*rule_avp;	/* The AVP concerned by this rule */
+};
+
+
+/***
+ *  API usage :
+
+The "parent" parameter can not be NULL. It points to the object (grouped avp or command) to which this rule apply (i.e. for which the ABNF is defined).
+
+- fd_dict_new:
+ Sample code for rule creation. Let's create the Proxy-Info grouped AVP for example.
+ {
+	int ret;
+	struct dict_object * proxy_info_avp;
+	struct dict_object * proxy_host_avp;
+	struct dict_object * proxy_state_avp;
+	struct dict_object * diameteridentity_type;
+	struct dict_rule_data rule_data;
+	struct dict_type_data di_type_data = { AVP_TYPE_OCTETSTRING, "DiameterIdentity", NULL, NULL };
+	struct dict_avp_data proxy_info_data = { 284, 0, "Proxy-Info", AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, AVP_FLAG_MANDATORY, AVP_TYPE_GROUPED };
+	struct dict_avp_data proxy_host_data = { 280, 0, "Proxy-Host", AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, AVP_FLAG_MANDATORY, AVP_TYPE_OCTETSTRING };
+	struct dict_avp_data proxy_state_data = { 33, 0, "Proxy-State",AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, AVP_FLAG_MANDATORY, AVP_TYPE_OCTETSTRING };
+	
+	-- Create the parent AVP
+	ret = fd_dict_new ( dict, DICT_AVP, &proxy_info_data, NULL, &proxy_info_avp );
+	
+	-- Create the first child AVP.
+	ret = fd_dict_new ( dict, DICT_TYPE, &di_type_data, NULL, &diameteridentity_type );
+	ret = fd_dict_new ( dict, DICT_AVP, &proxy_host_data, diameteridentity_type, &proxy_host_avp );
+	
+	-- Create the other child AVP
+	ret = fd_dict_new ( dict, DICT_AVP, &proxy_state_data, NULL, &proxy_state_avp );
+	
+	-- Now we can create the rules. Both children AVP are mandatory.
+	rule_data.rule_position = RULE_REQUIRED;
+	rule_data.rule_min = -1;
+	rule_data.rule_max = -1;
+	
+	rule_data.rule_avp = proxy_host_avp;
+	ret = fd_dict_new ( dict, DICT_RULE, &rule_data, proxy_info_avp, NULL );
+	
+	rule_data.rule_avp = proxy_state_avp;
+	ret = fd_dict_new ( dict, DICT_RULE, &rule_data, proxy_info_avp, NULL );
+}
+
+- fd_dict_search and fd_dict_getval are similar to previous examples.
+
+*/
+		
+/* Define some hard-coded values */
+/* Application */
+#define AI_RELAY			0xffffffff
+
+/* Commands Codes */
+#define CC_CAPABILITIES_EXCHANGE	257
+#define CC_RE_AUTH			258
+#define CC_ACCOUNTING			271
+#define CC_ABORT_SESSION		274
+#define CC_SESSION_TERMINATION		275
+#define CC_DEVICE_WATCHDOG		280
+#define CC_DISCONNECT_PEER		282
+
+/* AVPs (Vendor 0) */
+#define AC_USER_NAME			1
+#define AC_PROXY_STATE			33
+#define AC_HOST_IP_ADDRESS		257
+#define AC_AUTH_APPLICATION_ID		258
+#define AC_ACCT_APPLICATION_ID		259
+#define AC_VENDOR_SPECIFIC_APPLICATION_ID 260
+#define AC_REDIRECT_HOST_USAGE		261
+#define AC_REDIRECT_MAX_CACHE_TIME	262
+#define AC_SESSION_ID 			263
+#define AC_ORIGIN_HOST			264
+#define AC_SUPPORTED_VENDOR_ID		265
+#define AC_VENDOR_ID			266
+#define AC_FIRMWARE_REVISION		267
+#define AC_RESULT_CODE			268
+#define AC_PRODUCT_NAME			269
+#define AC_DISCONNECT_CAUSE		273
+#define ACV_DC_REBOOTING			0
+#define ACV_DC_BUSY				1
+#define ACV_DC_NOT_FRIEND			2
+#define AC_ORIGIN_STATE_ID		278
+#define AC_FAILED_AVP			279
+#define AC_PROXY_HOST			280
+#define AC_ERROR_MESSAGE		281
+#define AC_ROUTE_RECORD			282
+#define AC_DESTINATION_REALM		283
+#define AC_PROXY_INFO			284
+#define AC_REDIRECT_HOST		292
+#define AC_DESTINATION_HOST		293
+#define AC_ERROR_REPORTING_HOST		294
+#define AC_ORIGIN_REALM			296
+#define AC_INBAND_SECURITY_ID		299
+#define ACV_ISI_NO_INBAND_SECURITY		0
+#define ACV_ISI_TLS				1
+
+/* Error codes from Base protocol
+(reference: http://www.iana.org/assignments/aaa-parameters/aaa-parameters.xml#aaa-parameters-4)
+Note that currently, rfc3588bis-26 has some different values for some of these 
+*/
+#define ER_DIAMETER_MULTI_ROUND_AUTH			1001
+
+#define ER_DIAMETER_SUCCESS				2001
+#define ER_DIAMETER_LIMITED_SUCCESS			2002
+
+#define ER_DIAMETER_COMMAND_UNSUPPORTED			3001 /* 5019 ? */
+#define ER_DIAMETER_UNABLE_TO_DELIVER			3002
+#define ER_DIAMETER_REALM_NOT_SERVED			3003
+#define ER_DIAMETER_TOO_BUSY				3004
+#define ER_DIAMETER_LOOP_DETECTED			3005
+#define ER_DIAMETER_REDIRECT_INDICATION			3006
+#define ER_DIAMETER_APPLICATION_UNSUPPORTED		3007
+#define ER_DIAMETER_INVALID_HDR_BITS			3008 /* 5020 ? */
+#define ER_DIAMETER_INVALID_AVP_BITS			3009 /* 5021 ? */
+#define ER_DIAMETER_UNKNOWN_PEER			3010 /* 5018 ? */
+
+#define ER_DIAMETER_AUTHENTICATION_REJECTED		4001
+#define ER_DIAMETER_OUT_OF_SPACE			4002
+#define ER_ELECTION_LOST				4003
+
+#define ER_DIAMETER_AVP_UNSUPPORTED			5001
+#define ER_DIAMETER_UNKNOWN_SESSION_ID			5002
+#define ER_DIAMETER_AUTHORIZATION_REJECTED		5003
+#define ER_DIAMETER_INVALID_AVP_VALUE			5004
+#define ER_DIAMETER_MISSING_AVP				5005
+#define ER_DIAMETER_RESOURCES_EXCEEDED			5006
+#define ER_DIAMETER_CONTRADICTING_AVPS			5007
+#define ER_DIAMETER_AVP_NOT_ALLOWED			5008
+#define ER_DIAMETER_AVP_OCCURS_TOO_MANY_TIMES		5009
+#define ER_DIAMETER_NO_COMMON_APPLICATION		5010
+#define ER_DIAMETER_UNSUPPORTED_VERSION			5011
+#define ER_DIAMETER_UNABLE_TO_COMPLY			5012
+#define ER_DIAMETER_INVALID_BIT_IN_HEADER		5013 /* 3011 ? */
+#define ER_DIAMETER_INVALID_AVP_LENGTH			5014
+#define ER_DIAMETER_INVALID_MESSAGE_LENGTH		5015 /* 3012 ? */
+#define ER_DIAMETER_INVALID_AVP_BIT_COMBO		5016 /* deprecated? */
+#define ER_DIAMETER_NO_COMMON_SECURITY			5017
+
+
+/*============================================================*/
+/*                         SESSIONS                           */
+/*============================================================*/
+
+/* Modules that want to associate a state with a Session-Id must first register a handler of this type */
+struct session_handler;
+
+/* This opaque structure represents a session associated with a Session-Id */
+struct session;
+
+/* The state information that a module associate with a session -- each module defines its own data format */
+struct sess_state; /* declare this in your own extension */
+
+typedef DECLARE_FD_DUMP_PROTOTYPE((*session_state_dump), struct sess_state * st);
+
+/* The following function must be called to activate the session expiry mechanism */
+int fd_sess_start(void);
+
+/*
+ * FUNCTION:	fd_sess_handler_create
+ *
+ * PARAMETERS:
+ *  handler	: location where the new handler must be stored.
+ *  cleanup	: a callback function that must be called when the session with associated data is destroyed.
+ *  dumper      : if not NULL, will be called during fd_sess_dump to display the data associated with a session. NULL otherwise.
+ *  opaque      : A pointer that is passed to the cleanup callback -- the content is never examined by the framework.
+ *
+ * DESCRIPTION: 
+ *  Create a new session handler. This is needed by a module to associate a state with a session object.
+ * The cleanup handler is called when the session timeout expires, or fd_sess_destroy is called. It must free
+ * the state associated with the session, and eventually trig other actions (send a STR, ...).
+ *
+ * RETURN VALUE:
+ *  0      	: The new handler has been created.
+ *  EINVAL 	: A parameter is invalid.
+ *  ENOMEM	: Not enough memory to complete the operation
+ */
+int fd_sess_handler_create ( struct session_handler ** handler, void (*cleanup)(struct sess_state * state, os0_t sid, void * opaque), session_state_dump dumper, void * opaque );
+
+	
+/*
+ * FUNCTION:	fd_sess_handler_destroy
+ *
+ * PARAMETERS:
+ *  handler	: location of an handler created by fd_sess_handler_create.
+ *  opaque      : the opaque pointer registered with the callback is restored here (if ! NULL).
+ *
+ * DESCRIPTION: 
+ *  This destroys a session handler (typically called when an application is shutting down).
+ * If sessions states are registered with this handler, the cleanup callback is called on them.
+ *
+ * RETURN VALUE:
+ *  0      	: The handler was destroyed.
+ *  EINVAL 	: A parameter is invalid.
+ *  ENOMEM	: Not enough memory to complete the operation
+ */
+int fd_sess_handler_destroy ( struct session_handler ** handler, void **opaque );
+
+
+
+/*
+ * FUNCTION:	fd_sess_new
+ *
+ * PARAMETERS:
+ *  session	  : The location where the session object will be created upon success.
+ *  diamid	  : a Diameter Identity, or NULL.
+ *  diamidlen	  : if diamid is \0-terminated, this can be 0. Otherwise, the length of diamid.
+ *  opt           : Additional string, or NULL. Usage is described below.
+ *  optlen	  : if opt is \0-terminated, this can be 0. Otherwise, the length of opt.
+ *
+ * DESCRIPTION: 
+ *   Create a new session object. The Session-Id string associated with this session is generated as follow:
+ *  If diamId parameter is provided, the string is created according to the RFC: <diamId>;<high32>;<low32>[;opt] where
+ *    diamId is a Diameter Identity.
+ *    high32 and low32 are the parts of a monotonic 64 bits counter initialized to (time, 0) at startup.
+ *    opt is an optional string that can be concatenated to the identifier.
+ *  If diamId is NULL, the string is exactly the content of opt.
+ *
+ * RETURN VALUE:
+ *  0      	: The session is created, the initial msg refcount is 1.
+ *  EINVAL 	: A parameter is invalid.
+ *  EALREADY	: A session with the same name already exists (returned in *session), the msg refcount is increased.
+ *  ENOMEM	: Not enough memory to complete the operation
+ */
+int fd_sess_new ( struct session ** session, DiamId_t diamid, size_t diamidlen, uint8_t * opt, size_t optlen );
+
+/*
+ * FUNCTION:	fd_sess_fromsid
+ *
+ * PARAMETERS:
+ *  sid	  	: pointer to a string containing a Session-Id (should be UTF-8).
+ *  len		: length of the sid string (which does not need to be '\0'-terminated)
+ *  session	: On success, pointer to the session object created / retrieved.
+ *  isnew	: if not NULL, set to 1 on return if the session object has been created, 0 if it was simply retrieved.
+ *
+ * DESCRIPTION: 
+ *   Retrieve a session object from a Session-Id string. In case no session object was previously existing with this 
+ *  id, a new object is silently created (equivalent to fd_sess_new with flag SESSION_NEW_FULL).
+ *
+ * RETURN VALUE:
+ *  0      	: The session parameter has been updated.
+ *  EINVAL 	: A parameter is invalid.
+ *  ENOMEM	: Not enough memory to complete the operation
+ */
+int fd_sess_fromsid ( uint8_t * sid, size_t len, struct session ** session, int * isnew);
+
+/* only use the following in specific situations, e.g. app_radgw extension. They are normally handled by the framework only */
+int fd_sess_fromsid_msg ( uint8_t * sid, size_t len, struct session ** session, int * isnew); 
+int fd_sess_ref_msg ( struct session * session );
+
+/*
+ * FUNCTION:	fd_sess_getsid
+ *
+ * PARAMETERS:
+ *  session	: Pointer to a session object.
+ *  sid	  	: On success, the location of the sid is stored here.
+ *
+ * DESCRIPTION: 
+ *   Retrieve the session identifier (Session-Id) corresponding to a session object.
+ *  The returned sid is a \0-terminated binary string which might be UTF-8 (but there is no guarantee in the framework).
+ *  It may be used for example to set the value of an AVP.
+ *  Note that the sid string is not copied, just its reference... do not free it!
+ *
+ * RETURN VALUE:
+ *  0      	: The sid & len parameters have been updated.
+ *  EINVAL 	: A parameter is invalid.
+ */
+int fd_sess_getsid ( struct session * session, os0_t * sid, size_t * sidlen );
+
+/*
+ * FUNCTION:	fd_sess_settimeout
+ *
+ * PARAMETERS:
+ *  session	: The session for which to set the timeout.
+ *  timeout	: The date when the session times out.
+ *
+ * DESCRIPTION: 
+ *   Set the lifetime for a given session object. This function may be 
+ * called several times on the same object to update the timeout value.
+ *   When the timeout date is reached, the cleanup handler of each 
+ * module that registered data with this session is called, then the 
+ * session is cleared.
+ *
+ *   There is a possible race condition between cleanup of the session
+ * and use of its data; applications should ensure that they are not 
+ * using data from a session that is about to expire / expired.
+ *
+ * RETURN VALUE:
+ *  0      	: The session timeout has been updated.
+ *  EINVAL 	: A parameter is invalid.
+ */
+int fd_sess_settimeout( struct session * session, const struct timespec * timeout );
+
+/*
+ * FUNCTION:	fd_sess_destroy
+ *
+ * PARAMETERS:
+ *  session	: Pointer to a session object.
+ *
+ * DESCRIPTION: 
+ *   Destroys all associated states of a session, if any.
+ * Equivalent to a session timeout expired, but the effect is immediate.
+ * The session itself is marked as deleted, and will be freed when it is not referenced 
+ * by any message anymore.
+ *
+ * RETURN VALUE:
+ *  0      	: The session no longer exists.
+ *  EINVAL 	: A parameter is invalid.
+ */
+int fd_sess_destroy ( struct session ** session );
+
+/*
+ * FUNCTION:	fd_sess_reclaim
+ *
+ * PARAMETERS:
+ *  session	: Pointer to a session object.
+ *
+ * DESCRIPTION: 
+ *   Equivalent to fd_sess_destroy, only if no session_state is associated with the session.
+ *  Otherwise, this function has no effect (except that it sets *session to NULL).
+ *
+ * RETURN VALUE:
+ *  0      	: The session was reclaimed.
+ *  EINVAL 	: A parameter is invalid.
+ */
+int fd_sess_reclaim ( struct session ** session );
+
+
+
+
+/*
+ * FUNCTION:	fd_sess_state_store
+ *
+ * PARAMETERS:
+ *  handler	: The handler with which the state is registered.
+ *  session	: The session object with which the state is registered.
+ *  state	: An application state (opaque data) to store with the session.
+ *
+ * DESCRIPTION: 
+ *  Stores an application state with a session. This state can later be retrieved
+ * with fd_sess_state_retrieve, or implicitly in the cleanup handler when the session
+ * is destroyed.
+ *
+ * RETURN VALUE:
+ *  0      	: The state has been stored.
+ *  EINVAL 	: A parameter is invalid.
+ *  EALREADY	: Data was already associated with this session and client.
+ *  ENOMEM	: Not enough memory to complete the operation
+ */
+int fd_sess_state_store ( struct session_handler * handler, struct session * session, struct sess_state ** state );
+
+/*
+ * FUNCTION:	fd_sess_state_retrieve
+ *
+ * PARAMETERS:
+ *  handler	: The handler with which the state was registered.
+ *  session	: The session object with which the state was registered.
+ *  state	: Location where the state must be saved if it is found.
+ *
+ * DESCRIPTION: 
+ *  Retrieves a state saved by fd_sess_state_store.
+ * After this function has been called, the state is no longer associated with 
+ * the session. A new call to fd_sess_state_store must be performed in order to
+ * store again the data with the session.
+ *
+ * RETURN VALUE:
+ *  0      	: *state is updated (NULL or points to the state if it was found).
+ *  EINVAL 	: A parameter is invalid.
+ */
+int fd_sess_state_retrieve ( struct session_handler * handler, struct session * session, struct sess_state ** state ); 
+
+
+/* For debug */
+DECLARE_FD_DUMP_PROTOTYPE(fd_sess_dump, struct session * session, int with_states);
+DECLARE_FD_DUMP_PROTOTYPE(fd_sess_dump_hdl, struct session_handler * handler);
+
+/* For statistics / monitoring: get the number of struct session in memory */
+int fd_sess_getcount(uint32_t *cnt);
+
+/*============================================================*/
+/*                         ROUTING                            */
+/*============================================================*/
+
+/* The following functions are helpers for the routing module. 
+  The routing data is stored in the message itself. */
+
+/* Structure that contains the routing data for a message */
+struct rt_data;
+
+/* Following functions are helpers to create the routing data of a message */
+int  fd_rtd_init(struct rt_data ** rtd);
+void fd_rtd_free(struct rt_data ** rtd);
+
+/* Add a peer to the candidates list. */
+int  fd_rtd_candidate_add(struct rt_data * rtd, DiamId_t peerid, size_t peeridlen, DiamId_t realm, size_t realmlen);
+
+/* Remove a peer from the candidates (if it is found). The search is case-insensitive. */
+void fd_rtd_candidate_del(struct rt_data * rtd, uint8_t * id, size_t idsz);
+
+/* Extract the list of valid candidates, and initialize their scores to 0 */
+void fd_rtd_candidate_extract(struct rt_data * rtd, struct fd_list ** candidates, int ini_score);
+
+/* If a peer returned a protocol error for this message, save it so that we don't try to send it there again. Optionally retrieve the current list of candidates. */
+int  fd_rtd_error_add(struct rt_data * rtd, DiamId_t sentto, size_t senttolen, uint8_t * origin, size_t originsz, uint32_t rcode, struct fd_list ** candidates, int * sendingattemtps);
+
+/* Only retrieve the number of times this message has been processed by the routing-out mechanism (i.e. number of times it was failed over) */
+int  fd_rtd_get_nb_attempts(struct rt_data * rtd, int * sendingattemtps);
+
+/* The extracted list items have the following structure: */
+struct rtd_candidate {
+	struct fd_list	chain;	/* link in the list returned by the previous fcts */
+	DiamId_t	diamid;	/* the diameter Id of the peer */
+	size_t		diamidlen; /* cached size of the diamid string */
+	DiamId_t	realm;	/* the diameter realm of the peer */
+	size_t		realmlen; /* cached size of realm */
+	int		score;	/* the current routing score for this peer, see fd_rt_out_register definition for details */
+};
+
+/* Reorder the list of peers by score */
+int  fd_rtd_candidate_reorder(struct fd_list * candidates);
+
+/* Note : it is fine for a callback to add a new entry in the candidates list after the list has been extracted. The diamid must then be malloc'd. */
+/* Beware that this could lead to routing loops */
+
+/*============================================================*/
+/*                         MESSAGES                           */
+/*============================================================*/
+
+/* The following types are opaque */
+struct	msg;	/* A message: command with children AVPs (possibly grand children) */
+struct	avp;	/* AVP object */
+
+/* Some details about chaining:
+ *
+ *  A message is made of a header ( msg ) and 0 or more AVPs ( avp ).
+ * The structure is a kind of tree, where some AVPs (grouped AVPs) can contain other AVPs.
+ * Example:
+ * msg
+ *  |-avp
+ *  |-gavp
+ *  |   |-avp
+ *  |   |-avp
+ *  |   \-avp
+ *  |-avp
+ *  \-avp
+ *
+ */
+
+/* The following type is used to point to either a msg or an AVP */
+typedef void msg_or_avp;
+
+/* The Diameter protocol version */
+#define DIAMETER_VERSION	1
+
+/* In the two following types, some fields are marked (READONLY). 
+ * This means that the content of these fields will be overwritten by the daemon so modifying it is useless.
+ */
+
+/* The following structure represents the header of a message. All data is in host byte order. */
+struct msg_hdr {
+	uint8_t		 msg_version;		/* (READONLY) Version of Diameter: must be DIAMETER_VERSION. */
+	uint32_t	 msg_length;		/* (READONLY)(3 bytes) indicates the length of the message */
+	uint8_t		 msg_flags;		/* Message flags: CMD_FLAG_* */
+	command_code_t	 msg_code;		/* (3 bytes) the command-code. See dictionary-api.h for more detail */
+	application_id_t msg_appl;		/* The application issuing this message */
+	uint32_t	 msg_hbhid;		/* The Hop-by-Hop identifier of the message */
+	uint32_t	 msg_eteid;		/* The End-to-End identifier of the message */
+};
+
+/* The following structure represents the visible content of an AVP. All data is in host byte order. */
+struct avp_hdr {
+	avp_code_t	 avp_code;		/* the AVP Code */
+	uint8_t		 avp_flags;		/* AVP_FLAG_* flags */
+	uint32_t	 avp_len;		/* (READONLY)(Only 3 bytes are used) the length of the AVP as described in the RFC */
+	vendor_id_t	 avp_vendor;		/* Only used if AVP_FLAG_VENDOR is present */
+	union avp_value *avp_value;		/* pointer to the value of the AVP. NULL means that the value is not set / not understood.
+						   One should not directly change this value. Use the msg_avp_setvalue function instead.
+						   The content of the pointed structure can be changed directly, with this restriction:
+						     if the AVP is an OctetString, and you change the value of the pointer avp_value->os.data, then
+						     you must call free() on the previous value, and the new one must be free()-able.
+						 */
+};
+
+/* The following enum is used to browse inside message hierarchy (msg, gavp, avp) */
+enum msg_brw_dir {
+	MSG_BRW_NEXT = 1,	/* Get the next element at the same level, or NULL if this is the last element. */
+	MSG_BRW_PREV,		/* Get the previous element at the same level, or NULL if this is the first element. */
+	MSG_BRW_FIRST_CHILD,	/* Get the first child AVP of this element, if any. */
+	MSG_BRW_LAST_CHILD,	/* Get the last child AVP of this element, if any. */
+	MSG_BRW_PARENT,		/* Get the parent element of this element, if any. Only the msg_t object has no parent. */
+	MSG_BRW_WALK		/* This is equivalent to FIRST_CHILD or NEXT or PARENT->next, first that is not NULL. Use this to walk inside all AVPs. */
+};
+
+/* Some flags used in the functions below */
+#define AVPFL_SET_BLANK_VALUE	   0x01	/* When creating an AVP, initialize its value to a blank area */
+#define AVPFL_SET_RAWDATA_FROM_AVP 0x02 /* When creating an AVP, initialize its rawdata area from an existing AVP -- it is only blank padding (for error reporting) */
+#define AVPFL_MAX		   AVPFL_SET_RAWDATA_FROM_AVP	/* The biggest valid flag value */
+	
+#define MSGFL_ALLOC_ETEID	0x01	/* When creating a message, a new end-to-end ID is allocated and set in the message */
+#define MSGFL_ANSW_ERROR	0x02	/* When creating an answer message, set the 'E' bit and use the generic error ABNF instead of command-specific ABNF */
+#define MSGFL_ANSW_NOSID	0x04	/* When creating an answer message, do not add the Session-Id even if present in request */
+#define MSGFL_ANSW_NOPROXYINFO	0x08	/* When creating an answer message, do not add the Proxy-Info AVPs presents in request */
+#define MSGFL_MAX		MSGFL_ANSW_NOPROXYINFO	/* The biggest valid flag value */
+
+/**************************************************/
+/*   Message creation, manipulation, disposal     */
+/**************************************************/
+/*
+ * FUNCTION:	fd_msg_avp_new
+ *
+ * PARAMETERS:
+ *  model 	: Pointer to a DICT_AVP dictionary object describing the avp to create, or NULL if flags are used.
+ *  flags	: Flags to use in creation (AVPFL_*, see above).
+ *  avp 	: Upon success, pointer to the new avp is stored here. It points to reference AVP upon function call when flags are used.
+ *
+ * DESCRIPTION: 
+ *   Create a new AVP instance.
+ *
+ * RETURN VALUE:
+ *  0      	: The AVP is created.
+ *  EINVAL 	: A parameter is invalid.
+ *  (other standard errors may be returned, too, with their standard meaning. Example:
+ *    ENOMEM 	: Memory allocation for the new avp failed.)
+ */
+int fd_msg_avp_new ( struct dict_object * model, int flags, struct avp ** avp );
+
+/*
+ * FUNCTION:	fd_msg_new
+ *
+ * PARAMETERS:
+ *  model 	: Pointer to a DICT_COMMAND dictionary object describing the message to create, or NULL.
+ *  flags	: combination of MSGFL_* flags.
+ *  msg 	: Upon success, pointer to the new message is stored here.
+ *
+ * DESCRIPTION: 
+ *   Create a new empty Diameter message. 
+ *
+ * RETURN VALUE:
+ *  0      	: The message is created.
+ *  EINVAL 	: A parameter is invalid.
+ *  (other standard errors may be returned, too, with their standard meaning. Example:
+ *    ENOMEM 	: Memory allocation for the new message failed.)
+ */
+int fd_msg_new ( struct dict_object * model, int flags, struct msg ** msg );
+int fd_msg_new_appl ( struct dict_object * model, struct dict_object * appl, int flags, struct msg ** msg );
+
+/*
+ * FUNCTION:	msg_new_answer_from_req
+ *
+ * PARAMETERS:
+ *  dict	: Pointer to the dictionary containing the model of the query.
+ *  msg		: The location of the query on function call. Updated by the location of answer message on return.
+ *  flag        : Pass MSGFL_ANSW_ERROR to indicate if the answer is an error message (will set the 'E' bit)
+ *              : See other MSGFL_ANSW_* definition above for other flags.
+ *
+ * DESCRIPTION: 
+ *   This function creates the empty answer message corresponding to a request.
+ *  The header is set properly (R flag, ccode, appid, hbhid, eteid)
+ *  The Session-Id AVP is copied if present.
+ *  The calling code should usually call fd_msg_rescode_set function on the answer.
+ *  Upon return, the original query may be retrieved by calling fd_msg_answ_getq on the message.
+ *
+ * RETURN VALUE:
+ *  0      	: Operation complete.
+ *  !0      	: an error occurred.
+ */
+int fd_msg_new_answer_from_req ( struct dictionary * dict, struct msg ** msg, int flag );
+
+/*
+ * FUNCTION:	fd_msg_browse
+ *
+ * PARAMETERS:
+ *  reference 	: Pointer to a struct msg or struct avp.
+ *  dir         : Direction for browsing
+ *  found       : If not NULL, updated with the element that has been found, if any, or NULL if no element was found / an error occurred.
+ *  depth	: If not NULL, points to an integer representing the "depth" of this object in the tree. This is a relative value, updated on return.
+ *
+ * DESCRIPTION: 
+ *   Explore the content of a message object (hierarchy). If "found" is null, only error checking is performed.
+ *  If "depth" is provided, it is updated as follow on successful function return:
+ *   - not modified for MSG_BRW_NEXT and MSG_BRW_PREV.
+ *   - *depth = *depth + 1 for MSG_BRW_FIRST_CHILD and MSG_BRW_LAST_CHILD.
+ *   - *depth = *depth - 1 for MSG_BRW_PARENT.
+ *   - *depth = *depth + X for MSG_BRW_WALK, with X between 1 (returned the 1st child) and -N (returned the Nth parent's next).
+ *
+ * RETURN VALUE:
+ *  0      	: found has been updated (if non NULL).
+ *  EINVAL 	: A parameter is invalid.
+ *  ENOENT	: No element has been found where requested, and "found" was NULL (otherwise, *found is set to NULL and 0 is returned). 
+ */
+int fd_msg_browse_internal ( msg_or_avp * reference, enum msg_brw_dir dir, msg_or_avp ** found, int * depth );
+/* Macro to avoid having to cast the third parameter everywhere */
+#define fd_msg_browse( ref, dir, found, depth )	\
+	fd_msg_browse_internal( (ref), (dir), (void *)(found), (depth) )
+
+
+/*
+ * FUNCTION:	fd_msg_avp_add
+ *
+ * PARAMETERS:
+ *  reference 	: Pointer to a valid msg or avp.
+ *  dir         : location where the new AVP should be inserted, relative to the reference. MSG_BRW_PARENT and MSG_BRW_WALK are not valid.
+ *  avp         : pointer to the AVP object that must be inserted.
+ *
+ * DESCRIPTION: 
+ *   Adds an AVP into an object that can contain it: grouped AVP or message.
+ * Note that the added AVP will be freed at the same time as the object it is added to, 
+ * so it should not be freed after the call to this function.
+ *
+ * RETURN VALUE:
+ *  0      	: The AVP has been added.
+ *  EINVAL 	: A parameter is invalid.
+ */
+int fd_msg_avp_add ( msg_or_avp * reference, enum msg_brw_dir dir, struct avp *avp);
+
+/*
+ * FUNCTION:	fd_msg_search_avp
+ *
+ * PARAMETERS:
+ *  msg 	: The message structure in which to search the AVP.
+ *  what 	: The dictionary model of the AVP to search.
+ *  avp		: location where the AVP reference is stored if found.
+ *
+ * DESCRIPTION: 
+ *   Search the first top-level AVP of a given model inside a message.
+ * Note: only the first instance of the AVP is returned by this function.
+ * Note: only top-level AVPs are searched, not inside grouped AVPs.
+ * Use msg_browse if you need more advanced research features.
+ *
+ * RETURN VALUE:
+ *  0      	: The AVP has been found.
+ *  EINVAL 	: A parameter is invalid.
+ *  ENOENT	: No AVP has been found, and "avp" was NULL (otherwise, *avp is set to NULL and 0 returned).
+ */
+int fd_msg_search_avp ( struct msg * msg, struct dict_object * what, struct avp ** avp );
+
+/*
+ * FUNCTION:	fd_msg_free
+ *
+ * PARAMETERS:
+ *  object      : pointer to the message or AVP object that must be unlinked and freed.
+ *
+ * DESCRIPTION: 
+ *   Unlink and free a message or AVP object and its children.
+ *  If the object is an AVP linked into a message, the AVP is removed before being freed.
+ *
+ * RETURN VALUE:
+ *  0      	: The message has been freed.
+ *  EINVAL 	: A parameter is invalid.
+ */
+int fd_msg_free ( msg_or_avp * object );
+
+/***************************************/
+/*   Dump functions                    */
+/***************************************/
+/*
+ * FUNCTION:	fd_msg_dump_*
+ *
+ * PARAMETERS:
+ *  see definition of DECLARE_FD_DUMP_PROTOTYPE,
+ *  obj		 : A msg or avp object to dump.
+ *  dict         : the dictionary to use if parsing is requested (optional)
+ *  force_parsing: by default these functions do not parse the object but dump hexa values in that case.
+ *                 use !0 to force parsing. If parsing fails, the hexa dump is still provided.
+ *  recurse      : allow the function to go through the children objects if any to dump more information. might require parsing.
+ *
+ * DESCRIPTION: 
+ *   These functions dump the content of a message or avp into a buffer
+ * either recursively or only the object itself.
+ *
+ * RETURN VALUE:
+ *   - see DECLARE_FD_DUMP_PROTOTYPE,
+ */
+/* one-line dump with only short information */
+DECLARE_FD_DUMP_PROTOTYPE( fd_msg_dump_summary, msg_or_avp *obj, struct dictionary *dict, int force_parsing, int recurse );
+/* one-line dump with all the contents of the message */
+DECLARE_FD_DUMP_PROTOTYPE( fd_msg_dump_full, msg_or_avp *obj, struct dictionary *dict, int force_parsing, int recurse );
+/* multi-line human-readable dump similar to wireshark output */
+DECLARE_FD_DUMP_PROTOTYPE( fd_msg_dump_treeview, msg_or_avp *obj, struct dictionary *dict, int force_parsing, int recurse );
+
+
+/*********************************************/
+/*   Message metadata management functions   */
+/*********************************************/
+/*
+ * FUNCTION:	fd_msg_model
+ *
+ * PARAMETERS:
+ *  reference 	: Pointer to a valid msg or avp.
+ *  model       : on success, pointer to the dictionary model of this command or AVP. NULL if the model is unknown.
+ *
+ * DESCRIPTION: 
+ *   Retrieve the dictionary object describing this message or avp. If the object is unknown or the fd_msg_parse_dict has not been called,
+ *  *model is set to NULL.
+ *
+ * RETURN VALUE:
+ *  0      	: The model has been set.
+ *  EINVAL 	: A parameter is invalid.
+ */
+int fd_msg_model ( msg_or_avp * reference, struct dict_object ** model );
+
+/*
+ * FUNCTION:	fd_msg_hdr
+ *
+ * PARAMETERS:
+ *  msg 	: Pointer to a valid message object.
+ *  pdata 	: Upon success, pointer to the msg_hdr structure of this message. The fields may be modified.
+ *
+ * DESCRIPTION: 
+ *   Retrieve location of modifiable section of a message. 
+ *
+ * RETURN VALUE:
+ *  0      	: The location has been written.
+ *  EINVAL 	: A parameter is invalid.
+ */
+int fd_msg_hdr ( struct msg *msg, struct msg_hdr ** pdata );
+
+/*
+ * FUNCTION:	fd_msg_avp_hdr
+ *
+ * PARAMETERS:
+ *  avp 	: Pointer to a valid avp object.
+ *  pdata 	: Upon success, pointer to the avp_hdr structure of this avp. The fields may be modified.
+ *
+ * DESCRIPTION: 
+ *   Retrieve location of modifiable data of an avp. 
+ *
+ * RETURN VALUE:
+ *  0      	: The location has been written.
+ *  EINVAL 	: A parameter is invalid.
+ */
+int fd_msg_avp_hdr ( struct avp *avp, struct avp_hdr ** pdata );
+
+/*
+ * FUNCTION:	fd_msg_answ_associate, fd_msg_answ_getq, fd_msg_answ_detach
+ *
+ * PARAMETERS:
+ *  answer	: the received answer message
+ *  query	: the corresponding query that had been sent
+ *
+ * DESCRIPTION:
+ *  fd_msg_answ_associate associates a query msg with the received answer. 
+ * Query is retrieved with fd_msg_answ_getq.
+ * If answer message is freed, the query is also freed.
+ * If the msg_answ_detach function is called, the association is removed.
+ * This is meant to be called from the daemon only.
+ *
+ * RETURN VALUE:
+ *  0 	  : ok
+ *  EINVAL: a parameter is invalid
+ */
+int fd_msg_answ_associate( struct msg * answer, struct msg * query );
+int fd_msg_answ_getq     ( struct msg * answer, struct msg ** query );
+int fd_msg_answ_detach   ( struct msg * answer );
+
+/*
+ * FUNCTION:	fd_msg_anscb_associate, fd_msg_anscb_get
+ *
+ * PARAMETERS:
+ *  msg		: the request message
+ *  anscb	: the callback to associate with the message
+ *  data	: the data to pass to the callback
+ *  expirecb    : the expiration callback to associate with the message
+ *  timeout     : (optional, use NULL if no timeout) a timeout associated with calling the cb.
+ *
+ * DESCRIPTION:
+ *  Associate or retrieve callbacks with an message.
+ * This is meant to be called from the daemon only.
+ *
+ * RETURN VALUE:
+ *  0 	  : ok
+ *  EINVAL: a parameter is invalid
+ */
+int fd_msg_anscb_associate( struct msg * msg, void ( *anscb)(void *, struct msg **), void  * data, void (*expirecb)(void *, DiamId_t, size_t, struct msg **), const struct timespec *timeout );
+int fd_msg_anscb_get( struct msg * msg, void (**anscb)(void *, struct msg **), void (**expirecb)(void *, DiamId_t, size_t, struct msg **), void ** data );
+int fd_msg_anscb_reset(struct msg * msg, int clear_anscb, int clear_expirecb);
+struct timespec *fd_msg_anscb_gettimeout( struct msg * msg ); /* returns NULL or a valid non-0 timespec */
+
+/*
+ * FUNCTION:	fd_msg_rt_associate, fd_msg_rt_get
+ *
+ * PARAMETERS:
+ *  msg		: the query message to be sent
+ *  list	: the ordered list of possible next-peers
+ *
+ * DESCRIPTION:
+ *  Associate a routing list with a query, and retrieve it.
+ * If the message is freed, the list is also freed.
+ *
+ * RETURN VALUE:
+ *  0 	  : ok
+ *  EINVAL: a parameter is invalid
+ */
+int fd_msg_rt_associate( struct msg * msg, struct rt_data * rtd );
+int fd_msg_rt_get      ( struct msg * msg, struct rt_data ** rtd );
+
+/*
+ * FUNCTION:	fd_msg_is_routable
+ *
+ * PARAMETERS:
+ *  msg		: A msg object.
+ *
+ * DESCRIPTION: 
+ *   This function returns a boolean telling if a given message is routable in the Diameter network, 
+ *  or if it is a local link message only (ex: CER/CEA, DWR/DWA, ...).
+ *
+ * RETURN VALUE:
+ *  0      	: The message is not routable / an error occurred.
+ *  1      	: The message is routable.
+ */
+int fd_msg_is_routable ( struct msg * msg );
+
+/*
+ * FUNCTION:	fd_msg_source_(g/s)et
+ *
+ * PARAMETERS:
+ *  msg		: A msg object.
+ *  diamid,len	: The diameter id of the peer from which this message was received.
+ *  dict	: a dictionary with definition of Route-Record AVP (for fd_msg_source_setrr)
+ *
+ * DESCRIPTION: 
+ *   Store or retrieve the diameted id of the peer from which this message was received.
+ * Will be used for example by the routing module to add the Route-Record AVP in forwarded requests,
+ * or to direct answers to the appropriate peer.
+ *
+ * RETURN VALUE:
+ *  0      	: Operation complete.
+ *  !0      	: an error occurred.
+ */
+int fd_msg_source_set( struct msg * msg, DiamId_t diamid, size_t diamidlen );
+int fd_msg_source_setrr( struct msg * msg, DiamId_t diamid, size_t diamidlen, struct dictionary * dict );
+int fd_msg_source_get( struct msg * msg, DiamId_t *diamid, size_t * diamidlen );
+
+/*
+ * FUNCTION:	fd_msg_eteid_get
+ *
+ * PARAMETERS:
+ *  -
+ *
+ * DESCRIPTION: 
+ *   Get a new unique end-to-end id value for the local peer.
+ *
+ * RETURN VALUE:
+ *  The new assigned value. No error code is defined.
+ */
+uint32_t fd_msg_eteid_get ( void );
+
+
+/*
+ * FUNCTION:	fd_msg_sess_get
+ *
+ * PARAMETERS:
+ *  dict	: the dictionary that contains the Session-Id AVP definition
+ *  msg		: A valid message.
+ *  session	: Location to store the session pointer when retrieved.
+ *  isnew	: Indicates if the session has been created.
+ *
+ * DESCRIPTION:
+ *  This function retrieves or creates the session object corresponding to a message.
+ * If the message does not contain a Session-Id AVP, *session == NULL on return.
+ * Note that the Session-Id AVP must never be modified after created in a message.
+ *
+ * RETURN VALUE:
+ *  0 : success
+ * !0 : standard error code.
+ */
+int fd_msg_sess_get(struct dictionary * dict, struct msg * msg, struct session ** session, int * isnew);
+
+/* This one is used by the libfdcore, you should use fd_msg_new_session rather than fd_sess_new, when possible */
+int fd_msg_sess_set(struct msg * msg, struct session * session);
+
+
+/* Helper for the hooks mechanism, for use from libfdcore */
+struct fd_msg_pmdl {
+	struct fd_list sentinel; /* if the sentinel.o field is NULL, the structure is not initialized. Otherwise it points to the cleanup function in libfdcore. */
+	pthread_mutex_t lock;
+};
+struct fd_msg_pmdl * fd_msg_pmdl_get(struct msg * msg);
+
+
+/***************************************/
+/*   Manage AVP values                 */
+/***************************************/
+
+/*
+ * FUNCTION:	fd_msg_avp_setvalue
+ *
+ * PARAMETERS:
+ *  avp 	: Pointer to a valid avp object with a NULL avp_value pointer. The model must be known.
+ *  value 	: pointer to an avp_value. The content will be COPIED into the internal storage area. 
+ *		 If data type is an octetstring, the data is also copied.
+ * 		 If value is a NULL pointer, the previous data is erased and value is unset in the AVP.
+ *
+ * DESCRIPTION: 
+ *   Initialize the avp_value field of an AVP header.
+ *
+ * RETURN VALUE:
+ *  0      	: The avp_value pointer has been set.
+ *  EINVAL 	: A parameter is invalid.
+ */
+int fd_msg_avp_setvalue ( struct avp *avp, union avp_value *value );
+
+/*
+ * FUNCTION:	fd_msg_avp_value_encode
+ *
+ * PARAMETERS:
+ *  avp 	: Pointer to a valid avp object with a NULL avp_value. The model must be known.
+ *  data 	: Pointer to the data that must be encoded as AVP value and stored in the AVP.
+ *		 This is only valid for AVPs of derived type for which type_data_encode callback is set. (ex: Address type)
+ *
+ * DESCRIPTION: 
+ *   Initialize the avp_value field of an AVP object from formatted data, using the AVP's type "type_data_encode" callback.
+ *
+ * RETURN VALUE:
+ *  0      	: The avp_value has been set.
+ *  EINVAL 	: A parameter is invalid.
+ *  ENOTSUP 	: There is no appropriate callback registered with this AVP's type.
+ */
+int fd_msg_avp_value_encode ( void *data, struct avp *avp );
+/*
+ * FUNCTION:	fd_msg_avp_value_interpret
+ *
+ * PARAMETERS:
+ *  avp 	: Pointer to a valid avp object with a non-NULL avp_value value.
+ *  data 	: Upon success, formatted interpretation of the AVP value is stored here.
+ *
+ * DESCRIPTION: 
+ *   Interpret the content of an AVP of Derived type and store the result in data pointer. The structure
+ * of the data pointer is dependent on the AVP type. This function calls the "type_data_interpret" callback 
+ * of the type.
+ *
+ * RETURN VALUE:
+ *  0      	: The avp_value has been set.
+ *  EINVAL 	: A parameter is invalid.
+ *  ENOTSUP 	: There is no appropriate callback registered with this AVP's type.
+ */
+int fd_msg_avp_value_interpret ( struct avp *avp, void *data );
+
+
+/***************************************/
+/*   Message parsing functions         */
+/***************************************/
+
+/*
+ * FUNCTION:	fd_msg_bufferize
+ *
+ * PARAMETERS:
+ *  msg		: A valid msg object. All AVPs must have a value set. 
+ *  buffer 	: Upon success, this points to a buffer (malloc'd) containing the message ready for network transmission (or security transformations). 
+ *		 The buffer may be freed after use.
+ *  len		: if not NULL, the size of the buffer is written here. In any case, this size is updated in the msg header.
+ *
+ * DESCRIPTION: 
+ *   Renders a message in memory as a buffer that can be sent over the network to the next peer.
+ *
+ * RETURN VALUE:
+ *  0      	: The location has been written.
+ *  EINVAL 	: The buffer does not contain a valid Diameter message.
+ *  ENOMEM	: Unable to allocate enough memory to create the buffer object.
+ */
+int fd_msg_bufferize ( struct msg * msg, uint8_t ** buffer, size_t * len );
+
+/*
+ * FUNCTION:	fd_msg_parse_buffer
+ *
+ * PARAMETERS:
+ *  buffer 	: Pointer to a buffer containing a message received from the network. 
+ *  buflen	: the size in bytes of the buffer.
+ *  msg		: Upon success, this points to a valid msg object. No AVP value is resolved in this object, nor grouped AVP.
+ *
+ * DESCRIPTION: 
+ *   This function parses a buffer an creates a msg object to represent the structure of the message.
+ *  Since no dictionary lookup is performed, the values of the AVPs are not interpreted. To interpret the values,
+ *  the returned message object must be passed to fd_msg_parse_dict function.
+ *  The buffer pointer is saved inside the message and will be freed when not needed anymore.
+ *
+ * RETURN VALUE:
+ *  0      	: The location has been written.
+ *  ENOMEM	: Unable to allocate enough memory to create the msg object.
+ *  EBADMSG	: The buffer does not contain a valid Diameter message (or is truncated).
+ *  EINVAL 	: A parameter is invalid.
+ */
+int fd_msg_parse_buffer ( uint8_t ** buffer, size_t buflen, struct msg ** msg );
+
+/* Parsing Error Information structure */
+struct fd_pei {
+	char *		pei_errcode;	/* name of the error code to use */
+	struct avp *	pei_avp;	/* pointer to invalid (in original message) or missing AVP (to be freed) */
+	int		pei_avp_free;	/* Set to 1 if the pei_avp must be freed */
+	char *		pei_message;	/* Overwrite default message if needed */
+	int		pei_protoerr; 	/* do we set the 'E' bit in the error message ? */
+};
+
+/*
+ * FUNCTION:	fd_msg_parse_dict
+ *
+ * PARAMETERS:
+ *  object	: A msg or AVP object as returned by fd_msg_parse_buffer.
+ *  dict	: the dictionary containing the objects definitions to use for resolving all AVPs.
+ *  error_info	: If not NULL, will contain the detail about error upon return. May be used to generate an error reply.
+ *
+ * DESCRIPTION: 
+ *   This function looks up for the command and each children AVP definitions in the dictionary.
+ *  If the dictionary definition is found, avp_model is set and the value of the AVP is interpreted accordingly and:
+ *   - for grouped AVPs, the children AVP are created and interpreted also.
+ *   - for numerical AVPs, the value is converted to host byte order and saved in the avp_value field.
+ *   - for octetstring AVPs, the string is copied into a new buffer and its address is saved in avp_value. 
+ *  If the dictionary definition is not found, avp_model is set to NULL and
+ *  the content of the AVP is saved as an octetstring in an internal structure. avp_value is NULL.
+ *  As a result, after this function has been called, there is no more dependency of the msg object to the message buffer, that is freed.
+ *
+ * RETURN VALUE:
+ *  0      	: The message has been fully parsed as described.
+ *  EINVAL 	: The msg parameter is invalid for this operation.
+ *  ENOMEM	: Unable to allocate enough memory to complete the operation.
+ *  ENOTSUP	: No dictionary definition for the command or one of the mandatory AVP was found.
+ */
+int fd_msg_parse_dict ( msg_or_avp * object, struct dictionary * dict, struct fd_pei * error_info );
+
+/*
+ * FUNCTION:	fd_msg_parse_rules
+ *
+ * PARAMETERS:
+ *  object	: A msg or grouped avp object that must be verified.
+ *  dict	: The dictionary containing the rules definitions.
+ *  error_info	: If not NULL, the first problem information will be saved here.
+ *
+ * DESCRIPTION: 
+ *   Check that the children of the object do not conflict with the dictionary rules (ABNF compliance).
+ *
+ * RETURN VALUE:
+ *  0      	: The message has been fully parsed and complies to the defined rules.
+ *  EBADMSG	: A conflict was detected, or a mandatory AVP is unknown in the dictionary.
+ *  EINVAL 	: The msg or avp object is invalid for this operation.
+ *  ENOMEM	: Unable to allocate enough memory to complete the operation.
+ */
+int fd_msg_parse_rules ( msg_or_avp * object, struct dictionary * dict, struct fd_pei * error_info);
+
+
+
+/*
+ * FUNCTION:	fd_msg_update_length
+ *
+ * PARAMETERS:
+ *  object 	: Pointer to a valid msg or avp. 
+ *
+ * DESCRIPTION: 
+ *   Update the length field of the object passed as parameter.
+ * As a side effect, all children objects are also updated. Therefore, all avp_value fields of
+ * the children AVPs must be set, or an error will occur.
+ *
+ * RETURN VALUE:
+ *  0      	: The size has been recomputed.
+ *  EINVAL 	: A parameter is invalid.
+ */
+int fd_msg_update_length ( msg_or_avp * object );
+
+
+/*============================================================*/
+/*                         DISPATCH                           */
+/*============================================================*/
+
+/* Dispatch module (passing incoming messages to extensions registered callbacks)
+ * is split between the library and the daemon.
+ *
+ * The library provides the support for associating dispatch callbacks with
+ * dictionary objects.
+ *
+ * The daemon is responsible for calling the callbacks for a message when appropriate.
+ *
+ *
+ * The dispatch module has two main roles:
+ *  - help determine if a message can be handled locally (during the routing step)
+ *        This decision involves only the application-id of the message.
+ *  - pass the message to the callback(s) that will handle it (during the dispatch step)
+ *
+ * The first role is handled by the daemon.
+ *
+ * About the second, these are the possibilities for registering a dispatch callback:
+ *
+ * -> For All messages.
+ *  This callback is called for all messages that are handled locally. This should be used only
+ *  for debug purpose.
+ *
+ * -> by AVP value (constants only).
+ *  This callback will be called when a message is received and contains an AVP with a specified enumerated value.
+ *
+ * -> by AVP.
+ *  This callback will be called when the received message contains a certain AVP.
+ *
+ * -> by command-code.
+ *  This callback will be called when the message is a specific command (and 'R' flag).
+ *
+ * -> by application.
+ *  This callback will be called when the message has a specific application-id.
+ *
+ * ( by vendor: would this be useful? it may be added later)
+ */
+enum disp_how {
+	DISP_HOW_ANY = 1,		/* Any message. This should be only used for debug. */
+	DISP_HOW_APPID,			/* Any message with the specified application-id */
+	DISP_HOW_CC,			/* Messages of the specified command-code (request or answer). App id may be specified. */
+	DISP_HOW_AVP,			/* Messages containing a specific AVP. Command-code and App id may be specified. */
+	DISP_HOW_AVP_ENUMVAL		/* Messages containing a specific AVP with a specific enumerated value. Command-code and App id may be specified. */
+};
+/*
+ * Several criteria may be selected at the same time, for example command-code AND application id.
+ *
+ * If several callbacks are registered for the same object, they are called in the order they were registered.
+ * The order in which the callbacks are called is:
+ *  DISP_HOW_ANY
+ *  DISP_HOW_AVP_ENUMVAL & DISP_HOW_AVP
+ *  DISP_HOW_CC
+ *  DISP_HOW_APPID
+ */
+
+/* When a callback is registered, a "when" argument is passed in addition to the disp_how value,
+ * to specify which values the criteria must match. */
+struct disp_when {
+	struct dict_object *	app;
+	struct dict_object *	command;
+	struct dict_object *	avp;
+	struct dict_object *	value;
+};
+
+/* Note that all the dictionary objects should really belong to the same dictionary!
+ *
+ * Here is the details on this "when" argument, depending on the disp_how value.
+ *
+ * DISP_HOW_ANY.
+ *  In this case, "when" must be NULL.
+ *
+ * DISP_HOW_APPID.
+ *  Only the "app_id" field must be set, other fields are ignored. It points to a dictionary object of type DICT_APPLICATION.
+ *
+ * DISP_HOW_CC.
+ *  The "command" field must be defined and point to a dictionary object of type DICT_COMMAND.
+ *  The "app_id" may be also set. In the case it is set, it restricts the callback to be called only with this command-code and app id.
+ *  The other fields are ignored.
+ *
+ * DISP_HOW_AVP.
+ *  The "avp" field of the structure must be set and point to a dictionary object of type DICT_AVP.
+ *  The "app_id" field may be set to restrict the messages matching to a specific app id.
+ *  The "command" field may also be set to a valid DICT_COMMAND object.
+ *  The content of the "value" field is ignored.
+ *
+ * DISP_HOW_AVP_ENUMVAL.
+ *  All fields have the same constraints and meaning as in DISP_REG_AVP. In addition, the "value" field must be set
+ *  and points to a valid DICT_ENUMVAL object. 
+ *
+ * Here is a sumary of the fields: ( M : must be set; m : may be set; 0 : ignored )
+ *  field:     app_id    command     avp    value
+ * APPID :       M          0         0       0
+ * CC    :       m          M         0       0
+ * AVP   :       m          m         M       0
+ * ENUMVA:       m          m         M       M
+ */
+
+enum disp_action {
+	DISP_ACT_CONT,	/* The next handler should be called, unless *msg == NULL. */
+	DISP_ACT_SEND,	/* The updated message must be sent. No further callback is called. */
+	DISP_ACT_ERROR	/* An error must be created and sent as a reply -- not valid for callbacks, only for fd_msg_dispatch. */
+};
+/* The callbacks that are registered have the following prototype:
+ *  	int dispatch_callback( struct msg ** msg, struct avp * avp, struct session * session, enum disp_action * action );
+ *
+ * CALLBACK:	dispatch_callback
+ *
+ * PARAMETERS:
+ *  msg 	: the received message on function entry. may be updated to answer on return (see description)
+ *  avp 	: for callbacks registered with DISP_HOW_AVP or DISP_HOW_AVP_ENUMVAL, direct link to the triggering AVP.
+ *  session	: if the message contains a Session-Id AVP, the corresponding session object, NULL otherwise.
+ *  opaque      : An opaque pointer that is registered along the session handler.
+ *  action	: upon return, this tells the daemon what to do next.
+ *
+ * DESCRIPTION: 
+ *   Called when a received message matchs the condition for which the callback was registered.
+ * This callback may do any kind of processing on the message, including:
+ *  - create an answer for a request.
+ *  - proxy a request or message, add / remove the Proxy-Info AVP, then forward the message.
+ *  - update a routing table or start a connection with a new peer, then forward the message.
+ *  - ...
+ * 
+ * When *action == DISP_ACT_SEND on callback return, the msg pointed by *msg is passed to the routing module for sending.
+ * When *action == DISP_ACT_CONT, the next registered callback is called.
+ *  When the last callback gives also DISP_ACT_CONT action value, a default handler is called. It's behavior is as follow:
+ *   - if the message is an answer, it is discarded.
+ *   - if the message is a request, it is passed again to the routing stack, and marked as non-local handling.
+ *
+ * RETURN VALUE:
+ *  0      	: The callback executed successfully and updated *action appropriately.
+ *  !0		: standard errors. In case of error, the message is discarded.
+ */
+
+/* This structure represents a handler for a registered callback, allowing its de-registration */
+struct disp_hdl;
+
+/*
+ * FUNCTION:	fd_disp_register
+ *
+ * PARAMETERS:
+ *  cb 		  : The callback function to register (see dispatch_callback description above).
+ *  how	  	  : How the callback must be registered.
+ *  when          : Values that must match, depending on the how argument.
+ *  opaque        : A pointer that is passed back to the handler. The content is not interpreted by the framework.
+ *  handle        : On success, a handler to the registered callback is stored here if not NULL. 
+ *		   This handler can be used to unregister the cb.
+ *
+ * DESCRIPTION: 
+ *   Register a new callback to handle messages delivered locally.
+ *
+ * RETURN VALUE:
+ *  0      	: The callback is registered.
+ *  EINVAL 	: A parameter is invalid.
+ *  ENOMEM	: Not enough memory to complete the operation
+ */
+int fd_disp_register ( int (*cb)( struct msg **, struct avp *, struct session *, void *, enum disp_action *), 
+			enum disp_how how, struct disp_when * when, void * opaque, struct disp_hdl ** handle );
+
+/*
+ * FUNCTION:	fd_disp_unregister
+ *
+ * PARAMETERS:
+ *  handle       : Location of the handle of the callback that must be unregistered.
+ *  opaque       : If not NULL, the opaque data that was registered is restored here.
+ *
+ * DESCRIPTION: 
+ *   Removes a callback previously registered by fd_disp_register.
+ *
+ * RETURN VALUE:
+ *  0      	: The callback is unregistered.
+ *  EINVAL 	: A parameter is invalid.
+ */
+int fd_disp_unregister ( struct disp_hdl ** handle, void ** opaque );
+
+/* Destroy all handlers */
+void fd_disp_unregister_all ( void );
+
+/*
+ * FUNCTION:	fd_msg_dispatch
+ *
+ * PARAMETERS:
+ *  msg 	: A msg object that have already been fd_msg_parse_dict.
+ *  session	: The session corresponding to this object, if any.
+ *  action	: Upon return, the action that must be taken on the message
+ *  error_code	: Upon return with action == DISP_ACT_ERROR, contains the error (such as "DIAMETER_UNABLE_TO_COMPLY")
+ *  drop_reason : if set on return, the message must be freed for this reason.
+ *  drop_msg    : if drop_reason is set, this points to the message to be freed while *msg is NULL.
+ *
+ * DESCRIPTION: 
+ *   Call all handlers registered for a given message.
+ *  The session must have already been resolved on entry.
+ *  The msg pointed may be updated during this process.
+ *  Upon return, the action parameter points to what must be done next.
+ *
+ * RETURN VALUE:
+ *  0      	: Success.
+ *  EINVAL 	: A parameter is invalid.
+ *  (other errors)
+ */
+int fd_msg_dispatch ( struct msg ** msg, struct session * session, enum disp_action *action, char ** error_code, char ** drop_reason, struct msg ** drop_msg );
+
+
+
+/*============================================================*/
+/*                     QUEUES                                 */
+/*============================================================*/
+
+/* Management of FIFO queues of elements */
+
+/* A queue is an opaque object */
+struct fifo;
+
+/*
+ * FUNCTION:	fd_fifo_new
+ *
+ * PARAMETERS:
+ *  queue	: Upon success, a pointer to the new queue is saved here.
+ *  max		: max number of items in the queue. Above this number, adding a new item becomes a
+ *		  blocking operation. Use 0 to disable this maximum.
+ *
+ * DESCRIPTION: 
+ *  Create a new empty queue.
+ *
+ * RETURN VALUE :
+ *  0		: The queue has been initialized successfully.
+ *  EINVAL 	: The parameter is invalid.
+ *  ENOMEM	: Not enough memory to complete the creation.  
+ */
+int fd_fifo_new ( struct fifo ** queue, int max );
+
+/*
+ * FUNCTION:	fd_fifo_del
+ *
+ * PARAMETERS:
+ *  queue	: Pointer to an empty queue to delete.
+ *
+ * DESCRIPTION: 
+ *  Destroys a queue. This is only possible if no thread is waiting for an element,
+ * and the queue is empty.
+ *
+ * RETURN VALUE:
+ *  0		: The queue has been destroyed successfully.
+ *  EINVAL 	: The parameter is invalid.
+ */
+int fd_fifo_del ( struct fifo  ** queue );
+
+/*
+ * FUNCTION:	fd_fifo_move
+ *
+ * PARAMETERS:
+ *  oldq	: Location of a FIFO that is to be emptied.
+ *  newq	: A FIFO that will receive the old data.
+ *  loc_update	: if non NULL, a place to store the pointer to new FIFO atomically with the move.
+ *
+ * DESCRIPTION: 
+ *  Empties a queue and move its content to another one atomically.
+ *
+ * RETURN VALUE:
+ *  0		: The queue has been destroyed successfully.
+ *  EINVAL 	: A parameter is invalid.
+ */
+int fd_fifo_move ( struct fifo * oldq, struct fifo * newq, struct fifo ** loc_update );
+
+/*
+ * FUNCTION:	fd_fifo_getstats
+ *
+ * PARAMETERS:
+ *  queue	  : The queue from which to retrieve the information.
+ *  current_count : How many items in the queue at the time of execution. This changes each time an item is pushed or poped.
+ *  limit_count   : The maximum number of items allowed in this queue. This is specified during queue creation.
+ *  highest_count : The maximum number of items this queue has contained. This enables to see if limit_count count was reached.
+ *  total_count   : the total number of items that went through the queue (already pop'd). Always increasing.
+ *  total	  : Cumulated time all items spent in this queue, including blocking time (always growing, use deltas for monitoring)
+ *  blocking      : Cumulated time threads trying to post new items were blocked (queue full).
+ *  last          : For the last element retrieved from the queue, how long it take between posting (including blocking) and poping
+ *  
+ * DESCRIPTION: 
+ *  Retrieve the timing information associated with a queue, for monitoring purpose.
+ *
+ * RETURN VALUE:
+ *  0		: The statistics have been updated.
+ *  EINVAL 	: A parameter is invalid.
+ */
+int fd_fifo_getstats( struct fifo * queue, int * current_count, int * limit_count, int * highest_count, long long * total_count, 
+				           struct timespec * total, struct timespec * blocking, struct timespec * last);
+
+/*
+ * FUNCTION:	fd_fifo_length
+ *
+ * PARAMETERS:
+ *  queue	: The queue from which to retrieve the number of elements.
+ *
+ * DESCRIPTION: 
+ *  Retrieve the number of elements in a queue, without error checking.
+ *
+ * RETURN VALUE:
+ *  The number of items currently queued.
+ */
+int fd_fifo_length ( struct fifo * queue );
+
+/*
+ * FUNCTION:	fd_fifo_setthrhd
+ *
+ * PARAMETERS:
+ *  queue	: The queue for which the thresholds are being set.
+ *  data	: An opaque pointer that is passed to h_cb and l_cb callbacks.
+ *  high        : The high-level threshold. If the number of elements in the queue increase to this value, h_cb is called.
+ *  h_cb        : if not NULL, a callback to call when the queue lengh is bigger than "high".
+ *  low         : The low-level threshold. Must be < high.
+ *  l_cb        : If the number of elements decrease to low, this callback is called.
+ *
+ * DESCRIPTION: 
+ *  This function allows to adjust the number of producer / consumer threads of a queue.
+ * If the consumer are slower than the producers, the number of elements in the queue increase.
+ * By setting a "high" value, we allow a callback to be called when this number is too high.
+ * The typical use would be to create an additional consumer thread in this callback.
+ * If the queue continues to grow, the callback will be called again when the length is 2 * high, then 3*high, ... N * high
+ * (the callback itself should implement a limit on the number of consumers that can be created)
+ * When the queue starts to decrease, and the number of elements go under ((N - 1) * high + low, the l_cb callback is called
+ * and would typially stop one of the consumer threads. If the queue continues to reduce, l_cb is again called at (N-2)*high + low,
+ * and so on.
+ *
+ * Since there is no destructor for the data pointer, if cleanup operations are required, they should be performed in
+ * l_cb when the length of the queue is becoming < low.
+ *
+ * Note that the callbacks are called synchronously, during fd_fifo_post or fd_fifo_get. Their operation should be quick.
+ *
+ * RETURN VALUE:
+ *  0		: The thresholds have been set
+ *  EINVAL 	: A parameter is invalid.
+ */
+int fd_fifo_setthrhd ( struct fifo * queue, void * data, uint16_t high, void (*h_cb)(struct fifo *, void **), uint16_t low, void (*l_cb)(struct fifo *, void **) );
+
+/*
+ * FUNCTION:	fd_fifo_post
+ *
+ * PARAMETERS:
+ *  queue	: The queue in which the element must be posted.
+ *  item	: The element that is put in the queue.
+ *
+ * DESCRIPTION: 
+ *  An element is added in a queue. Elements are retrieved from the queue in FIFO order
+ *  with the fd_fifo_get, fd_fifo_tryget, or fd_fifo_timedget functions.
+ *
+ * RETURN VALUE:
+ *  0		: The element is queued.
+ *  EINVAL 	: A parameter is invalid.
+ *  ENOMEM 	: Not enough memory to complete the operation.
+ */
+int fd_fifo_post_int ( struct fifo * queue, void ** item );
+#define fd_fifo_post(queue, item) \
+	fd_fifo_post_int((queue), (void *)(item))
+
+/* Similar function but does not block. It can cause the number of items in the queue to exceed the maximum set. Do not use for normal operation,
+only for failure recovery for example. */
+int fd_fifo_post_noblock( struct fifo * queue, void ** item );
+
+/*
+ * FUNCTION:	fd_fifo_get
+ *
+ * PARAMETERS:
+ *  queue	: The queue from which the first element must be retrieved.
+ *  item	: On return, the first element of the queue is stored here.
+ *
+ * DESCRIPTION: 
+ *  This function retrieves the first element from a queue. If the queue is empty, the function will block the 
+ * thread until a new element is posted to the queue, or until the thread is canceled (in which case the 
+ * function does not return).
+ *
+ * RETURN VALUE:
+ *  0		: A new element has been retrieved.
+ *  EINVAL 	: A parameter is invalid.
+ */
+int fd_fifo_get_int ( struct fifo * queue, void ** item );
+#define fd_fifo_get(queue, item) \
+	fd_fifo_get_int((queue), (void *)(item))
+
+/*
+ * FUNCTION:	fd_fifo_tryget
+ *
+ * PARAMETERS:
+ *  queue	: The queue from which the element must be retrieved.
+ *  item	: On return, the first element of the queue is stored here.
+ *
+ * DESCRIPTION: 
+ *  This function is similar to fd_fifo_get, except that it will not block if 
+ * the queue is empty, but return EWOULDBLOCK instead.
+ *
+ * RETURN VALUE:
+ *  0		: A new element has been retrieved.
+ *  EINVAL 	: A parameter is invalid.
+ *  EWOULDBLOCK : The queue was empty.
+ */
+int fd_fifo_tryget_int ( struct fifo * queue, void ** item );
+#define fd_fifo_tryget(queue, item) \
+	fd_fifo_tryget_int((queue), (void *)(item))
+
+/*
+ * FUNCTION:	fd_fifo_timedget
+ *
+ * PARAMETERS:
+ *  queue	: The queue from which the element must be retrieved.
+ *  item	: On return, the element is stored here.
+ *  abstime	: the absolute time until which we allow waiting for an item.
+ *
+ * DESCRIPTION: 
+ *  This function is similar to fd_fifo_get, except that it will block if the queue is empty 
+ * only until the absolute time abstime (see pthread_cond_timedwait for + info).
+ * If the queue is still empty when the time expires, the function returns ETIMEDOUT
+ *
+ * RETURN VALUE:
+ *  0		: A new item has been retrieved.
+ *  EINVAL 	: A parameter is invalid.
+ *  ETIMEDOUT   : The time out has passed and no item has been received.
+ */
+int fd_fifo_timedget_int ( struct fifo * queue, void ** item, const struct timespec *abstime );
+#define fd_fifo_timedget(queue, item, abstime) \
+	fd_fifo_timedget_int((queue), (void *)(item), (abstime))
+
+
+/*
+ * FUNCTION:	fd_fifo_select
+ *
+ * PARAMETERS:
+ *  queue	: The queue to test.
+ *  abstime	: the absolute time until which we can block waiting for an item. If NULL, the function returns immediatly.
+ *
+ * DESCRIPTION: 
+ *  This function is similar to select(), it waits for data to be available in the queue
+ * until the abstime is expired.
+ * Upon function entry, even if abstime is already expired the data availability is tested.
+ *
+ * RETURN VALUE:
+ *  0		: timeout expired without available data.
+ *  <0		: An error occurred (e.g., -EINVAL...)
+ *  >0		: data is available. The next call to fd_fifo_get will not block.
+ */
+int fd_fifo_select ( struct fifo * queue, const struct timespec *abstime );
+
+
+
+/* Dump a fifo list and optionally its inner elements -- beware of deadlocks! */
+typedef DECLARE_FD_DUMP_PROTOTYPE((*fd_fifo_dump_item_cb), void * item); /* This function should be 1 line if possible, or use indent level. Ends with '\n' */
+DECLARE_FD_DUMP_PROTOTYPE(fd_fifo_dump, char * name, struct fifo * queue, fd_fifo_dump_item_cb dump_item);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _LIBFDPROTO_H */
diff --git a/include/freeDiameter/version.h.in b/include/freeDiameter/version.h.in
new file mode 100644
index 0000000..9b0fa61
--- /dev/null
+++ b/include/freeDiameter/version.h.in
@@ -0,0 +1,3 @@
+/* Following variable is expended at build time based on the result of "hg id" command */
+#cmakedefine FD_PROJECT_VERSION_HG
+#define FD_PROJECT_VERSION_HG_VAL "@FD_PROJECT_VERSION_HG@"
diff --git a/libfdcore/CMakeLists.txt b/libfdcore/CMakeLists.txt
new file mode 100644
index 0000000..503437d
--- /dev/null
+++ b/libfdcore/CMakeLists.txt
@@ -0,0 +1,85 @@
+# The subproject name
+Project("freeDiameter core library" C)
+
+# Configuration for newer cmake
+cmake_policy(VERSION 2.6)
+if (POLICY CMP0022)
+	cmake_policy(SET CMP0022 OLD)
+endif (POLICY CMP0022)
+
+# Configuration parser
+BISON_FILE(fdd.y)
+FLEX_FILE(fdd.l)
+SET_SOURCE_FILES_PROPERTIES(lex.fdd.c fdd.tab.c PROPERTIES COMPILE_FLAGS "-I ${CMAKE_CURRENT_SOURCE_DIR}")
+
+# List of source files
+SET(FDCORE_SRC
+	fdcore-internal.h
+	apps.c
+	cnxctx.h
+	config.c
+	core.c
+	cnxctx.c
+	endpoints.c
+	events.c
+	extensions.c
+	fifo_stats.c
+	hooks.c
+	dict_base_proto.c
+	messages.c
+	queues.c
+	peers.c
+	p_ce.c
+	p_cnx.c
+	p_dw.c
+	p_dp.c
+	p_expiry.c
+	p_out.c
+	p_psm.c
+	p_sr.c
+	routing_dispatch.c
+	server.c
+	tcp.c
+	version.c
+	)
+
+IF(NOT DISABLE_SCTP)
+	SET(FDCORE_SRC ${FDCORE_SRC} sctp.c sctp3436.c)
+ENDIF(NOT DISABLE_SCTP)
+
+SET(FDCORE_GEN_SRC
+		lex.fdd.c
+		fdd.tab.c
+		fdd.tab.h
+	)
+	
+# Save the list of files for the tests 
+SET(FDCORE_SRC ${FDCORE_SRC} PARENT_SCOPE)
+SET(FDCORE_GEN_SRC ${FDCORE_GEN_SRC} PARENT_SCOPE)
+
+# Include path
+INCLUDE_DIRECTORIES(${LFDCORE_INCLUDES})
+INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR})
+
+# Build the executable
+ADD_LIBRARY(libfdcore SHARED ${FDCORE_SRC} ${FDCORE_GEN_SRC})
+ADD_DEPENDENCIES(libfdcore version_information)
+
+# Avoid the liblib name, and set the version
+SET_TARGET_PROPERTIES(libfdcore PROPERTIES 
+	OUTPUT_NAME "fdcore"
+	SOVERSION ${FD_PROJECT_VERSION_API}
+	VERSION ${FD_PROJECT_VERSION_MAJOR}.${FD_PROJECT_VERSION_MINOR}.${FD_PROJECT_VERSION_REV}
+	LINK_INTERFACE_LIBRARIES "${LFDCORE_LINK_INTERFACES}")
+
+# The library itself needs other libraries 
+LINK_DIRECTORIES(${CURRENT_BINARY_DIR}/../libfdproto)
+TARGET_LINK_LIBRARIES(libfdcore libfdproto ${LFDCORE_LIBS})
+
+
+####
+## INSTALL section ##
+
+INSTALL(TARGETS libfdcore
+	LIBRARY DESTINATION ${INSTALL_LIBRARY_SUFFIX}
+	COMPONENT freeDiameter-common)
diff --git a/libfdcore/apps.c b/libfdcore/apps.c
new file mode 100644
index 0000000..a0811d9
--- /dev/null
+++ b/libfdcore/apps.c
@@ -0,0 +1,152 @@
+/*********************************************************************************************************
+* Software License Agreement (BSD License)                                                               *
+* Author: Sebastien Decugis <sdecugis@freediameter.net>							 *
+*													 *
+* Copyright (c) 2011, WIDE Project and NICT								 *
+* All rights reserved.											 *
+* 													 *
+* Redistribution and use of this software in source and binary forms, with or without modification, are  *
+* permitted provided that the following conditions are met:						 *
+* 													 *
+* * Redistributions of source code must retain the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer.										 *
+*    													 *
+* * Redistributions in binary form must reproduce the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer in the documentation and/or other						 *
+*   materials provided with the distribution.								 *
+* 													 *
+* * Neither the name of the WIDE Project or NICT nor the 						 *
+*   names of its contributors may be used to endorse or 						 *
+*   promote products derived from this software without 						 *
+*   specific prior written permission of WIDE Project and 						 *
+*   NICT.												 *
+* 													 *
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED *
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
+* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR *
+* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 	 *
+* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 	 *
+* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR *
+* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF   *
+* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.								 *
+*********************************************************************************************************/
+
+#include "fdcore-internal.h"
+
+/* Merge information into a list of apps */
+int fd_app_merge(struct fd_list * list, application_id_t aid, vendor_id_t vid, int auth, int acct)
+{
+	struct fd_list * li;
+	int skip = 0;
+	
+	/* List is ordered by appid. Avoid duplicates */
+	for (li = list; li->next != list; li = li->next) {
+		struct fd_app * na = (struct fd_app *)(li->next);
+		if (na->appid < aid)
+			continue;
+		
+		if (na->appid > aid)
+			break;
+		
+		/* Otherwise, we merge with existing entry -- ignore vendor id in this case */
+		skip = 1;
+		
+		if (auth)
+			na->flags.auth = 1;
+		if (acct)
+			na->flags.acct = 1;
+		break;
+	}
+	
+	if (!skip) {			
+		struct fd_app  * new = NULL;
+
+		CHECK_MALLOC( new = malloc(sizeof(struct fd_app)) );
+		memset(new, 0, sizeof(struct fd_app));
+		fd_list_init(&new->chain, NULL);
+		new->flags.auth = (auth ? 1 : 0);
+		new->flags.acct = (acct ? 1 : 0);
+		new->vndid = vid;
+		new->appid = aid;
+		fd_list_insert_after(li, &new->chain);
+	}
+	
+	return 0;
+}
+
+/* Check if a given application id is in a list */
+int fd_app_check(struct fd_list * list, application_id_t aid, struct fd_app **detail)
+{
+	struct fd_list * li;
+	
+	TRACE_ENTRY("%p %d %p", list, aid, detail);
+	CHECK_PARAMS(list && detail);
+	
+	*detail = NULL;
+	
+	/* Search in the list */
+	for (li = list->next; li != list; li = li->next) {
+		struct fd_app * a = (struct fd_app *)li;
+		if (a->appid < aid)
+			continue;
+		
+		if (a->appid == aid)
+			*detail = a;
+		break;
+	}
+	
+	return 0;
+}
+
+/* Check if two lists have at least one common application */
+int fd_app_check_common(struct fd_list * list1, struct fd_list * list2, int * common_found)
+{
+	struct fd_list * li1, *li2;
+	
+	TRACE_ENTRY("%p %p %p", list1, list2, common_found);
+	CHECK_PARAMS( list1 && list2 && common_found );
+	
+	/* Both lists are ordered, so advance both pointers at the same time */
+	for (li1 = list1->next, li2 = list2->next;  (li1 != list1) && (li2 != list2); ) {
+		struct fd_app * a1 = (struct fd_app *)li1, *a2 = (struct fd_app *)li2;
+		if (a1->appid < a2->appid) {
+			li1 = li1->next;
+			continue;
+		}
+		if (a1->appid > a2->appid) {
+			li2 = li2->next;
+			continue;
+		}
+		/* They are equal, compare the applications */
+		if ((a1->flags.auth && a2->flags.auth) || (a1->flags.acct && a2->flags.acct)) {
+			/* found! */
+			*common_found = 1;
+			return 0;
+		}
+		
+		/* This application is not common, advance both lists */
+		li1 = li1->next;
+		li2 = li2->next;
+	}
+	
+	/* We did not find a common app */
+	*common_found = 0;
+	return 0;
+}
+
+/* Remove the apps from a list */
+int fd_app_empty(struct fd_list * list)
+{
+	TRACE_ENTRY("%p", list);
+	CHECK_PARAMS( list );
+	
+	while (!FD_IS_LIST_EMPTY(list)) {
+		struct fd_list * li = list->next;
+		fd_list_unlink(li);
+		free(li);
+	}
+	
+	return 0;
+}
diff --git a/libfdcore/cnxctx.c b/libfdcore/cnxctx.c
new file mode 100644
index 0000000..1fc336e
--- /dev/null
+++ b/libfdcore/cnxctx.c
@@ -0,0 +1,2045 @@
+/*********************************************************************************************************
+* Software License Agreement (BSD License)                                                               *
+* Author: Sebastien Decugis <sdecugis@freediameter.net>							 *
+*													 *
+* Copyright (c) 2015, WIDE Project and NICT								 *
+* All rights reserved.											 *
+* 													 *
+* Redistribution and use of this software in source and binary forms, with or without modification, are  *
+* permitted provided that the following conditions are met:						 *
+* 													 *
+* * Redistributions of source code must retain the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer.										 *
+*    													 *
+* * Redistributions in binary form must reproduce the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer in the documentation and/or other						 *
+*   materials provided with the distribution.								 *
+* 													 *
+* * Neither the name of the WIDE Project or NICT nor the 						 *
+*   names of its contributors may be used to endorse or 						 *
+*   promote products derived from this software without 						 *
+*   specific prior written permission of WIDE Project and 						 *
+*   NICT.												 *
+* 													 *
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED *
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
+* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR *
+* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 	 *
+* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 	 *
+* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR *
+* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF   *
+* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.								 *
+*********************************************************************************************************/
+
+#include "fdcore-internal.h"
+#include "cnxctx.h"
+
+#include <net/if.h>
+#include <ifaddrs.h> /* for getifaddrs */
+#include <sys/uio.h> /* writev */
+
+/* The maximum size of Diameter message we accept to receive (<= 2^24) to avoid too big mallocs in case of trashed headers */
+#ifndef DIAMETER_MSG_SIZE_MAX
+#define DIAMETER_MSG_SIZE_MAX	65535	/* in bytes */
+#endif /* DIAMETER_MSG_SIZE_MAX */
+
+
+/* Connections contexts (cnxctx) in freeDiameter are wrappers around the sockets and TLS operations .
+ * They are used to hide the details of the processing to the higher layers of the daemon.
+ * They are always oriented on connections (TCP or SCTP), connectionless modes (UDP or SCTP) are not supported.
+ */
+
+/* Lifetime of a cnxctx object:
+ * 1) Creation
+ *    a) a server socket:
+ *       - create the object with fd_cnx_serv_tcp or fd_cnx_serv_sctp
+ *       - start listening incoming connections: fd_cnx_serv_listen
+ *       - accept new clients with fd_cnx_serv_accept.
+ *    b) a client socket:
+ *       - connect to a remote server with fd_cnx_cli_connect
+ *
+ * 2) Initialization
+ *    - if TLS is started first, call fd_cnx_handshake
+ *    - otherwise to receive clear messages, call fd_cnx_start_clear. fd_cnx_handshake can be called later.
+ *
+ * 3) Usage
+ *    - fd_cnx_receive, fd_cnx_send : exchange messages on this connection (send is synchronous, receive is not, but blocking).
+ *    - fd_cnx_recv_setaltfifo : when a message is received, the event is sent to an external fifo list. fd_cnx_receive does not work when the alt_fifo is set.
+ *    - fd_cnx_getid : retrieve a descriptive string for the connection (for debug)
+ *    - fd_cnx_getremoteid : identification of the remote peer (IP address or fqdn)
+ *    - fd_cnx_getcred : get the remote peer TLS credentials, after handshake
+ *
+ * 4) End
+ *    - fd_cnx_destroy
+ */
+
+/*******************************************/
+/*     Creation of a connection object     */
+/*******************************************/
+
+/* Initialize a context structure */
+static struct cnxctx * fd_cnx_init(int full)
+{
+	struct cnxctx * conn = NULL;
+
+	TRACE_ENTRY("%d", full);
+
+	CHECK_MALLOC_DO( conn = malloc(sizeof(struct cnxctx)), return NULL );
+	memset(conn, 0, sizeof(struct cnxctx));
+
+	if (full) {
+		CHECK_FCT_DO( fd_fifo_new ( &conn->cc_incoming, 5 ), return NULL );
+	}
+
+	return conn;
+}
+
+#define CC_ID_HDR "{----} "
+
+/* Create and bind a server socket to the given endpoint and port */
+struct cnxctx * fd_cnx_serv_tcp(uint16_t port, int family, struct fd_endpoint * ep)
+{
+	struct cnxctx * cnx = NULL;
+	sSS dummy;
+	sSA * sa = (sSA *) &dummy;
+
+	TRACE_ENTRY("%hu %d %p", port, family, ep);
+
+	CHECK_PARAMS_DO( port, return NULL );
+	CHECK_PARAMS_DO( ep || family, return NULL );
+	CHECK_PARAMS_DO( (! family) || (family == AF_INET) || (family == AF_INET6), return NULL );
+	CHECK_PARAMS_DO( (! ep) || (ep->ss.ss_family == AF_INET) || (ep->ss.ss_family == AF_INET6), return NULL );
+	CHECK_PARAMS_DO( (! ep) || (!family) || (ep->ss.ss_family == family), return NULL );
+
+	/* The connection object */
+	CHECK_MALLOC_DO( cnx = fd_cnx_init(0), return NULL );
+
+	/* Prepare the socket address information */
+	if (ep) {
+		memcpy(sa, &ep->ss, sizeof(sSS));
+	} else {
+		memset(&dummy, 0, sizeof(dummy));
+		sa->sa_family = family;
+	}
+	if (sa->sa_family == AF_INET) {
+		((sSA4 *)sa)->sin_port = htons(port);
+		cnx->cc_family = AF_INET;
+	} else {
+		((sSA6 *)sa)->sin6_port = htons(port);
+		cnx->cc_family = AF_INET6;
+	}
+
+	/* Create the socket */
+	CHECK_FCT_DO( fd_tcp_create_bind_server( &cnx->cc_socket, sa, sSAlen(sa) ), goto error );
+
+	/* Generate the name for the connection object */
+	{
+		char addrbuf[INET6_ADDRSTRLEN];
+		int  rc;
+		rc = getnameinfo(sa, sSAlen(sa), addrbuf, sizeof(addrbuf), NULL, 0, NI_NUMERICHOST);
+		if (rc)
+			snprintf(addrbuf, sizeof(addrbuf), "[err:%s]", gai_strerror(rc));
+		snprintf(cnx->cc_id, sizeof(cnx->cc_id), CC_ID_HDR "TCP srv [%s]:%hu (%d)", addrbuf, port, cnx->cc_socket);
+	}
+
+	cnx->cc_proto = IPPROTO_TCP;
+
+	return cnx;
+
+error:
+	fd_cnx_destroy(cnx);
+	return NULL;
+}
+
+/* Same function for SCTP, with a list of local endpoints to bind to */
+struct cnxctx * fd_cnx_serv_sctp(uint16_t port, struct fd_list * ep_list)
+{
+#ifdef DISABLE_SCTP
+	TRACE_DEBUG(INFO, "This function should never been called when SCTP is disabled...");
+	ASSERT(0);
+	CHECK_FCT_DO( ENOTSUP, );
+	return NULL;
+#else /* DISABLE_SCTP */
+	struct cnxctx * cnx = NULL;
+
+	TRACE_ENTRY("%hu %p", port, ep_list);
+
+	CHECK_PARAMS_DO( port, return NULL );
+
+	/* The connection object */
+	CHECK_MALLOC_DO( cnx = fd_cnx_init(0), return NULL );
+
+	if (fd_g_config->cnf_flags.no_ip6) {
+		cnx->cc_family = AF_INET;
+	} else {
+		cnx->cc_family = AF_INET6; /* can create socket for both IP and IPv6 */
+	}
+	
+	/* Create the socket */
+	CHECK_FCT_DO( fd_sctp_create_bind_server( &cnx->cc_socket, cnx->cc_family, ep_list, port ), goto error );
+
+	/* Generate the name for the connection object */
+	snprintf(cnx->cc_id, sizeof(cnx->cc_id), CC_ID_HDR "SCTP srv :%hu (%d)", port, cnx->cc_socket);
+
+	cnx->cc_proto = IPPROTO_SCTP;
+
+	return cnx;
+
+error:
+	fd_cnx_destroy(cnx);
+	return NULL;
+#endif /* DISABLE_SCTP */
+}
+
+/* Allow clients to connect on the server socket */
+int fd_cnx_serv_listen(struct cnxctx * conn)
+{
+	CHECK_PARAMS( conn );
+
+	switch (conn->cc_proto) {
+		case IPPROTO_TCP:
+			CHECK_FCT(fd_tcp_listen(conn->cc_socket));
+			break;
+
+#ifndef DISABLE_SCTP
+		case IPPROTO_SCTP:
+			CHECK_FCT(fd_sctp_listen(conn->cc_socket));
+			break;
+#endif /* DISABLE_SCTP */
+
+		default:
+			CHECK_PARAMS(0);
+	}
+
+	return 0;
+}
+
+/* Accept a client (blocking until a new client connects) -- cancelable */
+struct cnxctx * fd_cnx_serv_accept(struct cnxctx * serv)
+{
+	struct cnxctx * cli = NULL;
+	sSS ss;
+	socklen_t ss_len = sizeof(ss);
+	int cli_sock = 0;
+
+	TRACE_ENTRY("%p", serv);
+	CHECK_PARAMS_DO(serv, return NULL);
+	
+	/* Accept the new connection -- this is blocking until new client enters or until cancellation */
+	CHECK_SYS_DO( cli_sock = accept(serv->cc_socket, (sSA *)&ss, &ss_len), return NULL );
+	
+	CHECK_MALLOC_DO( cli = fd_cnx_init(1), { shutdown(cli_sock, SHUT_RDWR); close(cli_sock); return NULL; } );
+	cli->cc_socket = cli_sock;
+	cli->cc_family = serv->cc_family;
+	cli->cc_proto = serv->cc_proto;
+	
+	/* Set the timeout */
+	fd_cnx_s_setto(cli->cc_socket);
+	
+	/* Generate the name for the connection object */
+	{
+		char addrbuf[INET6_ADDRSTRLEN];
+		char portbuf[10];
+		int  rc;
+		
+		rc = getnameinfo((sSA *)&ss, ss_len, addrbuf, sizeof(addrbuf), portbuf, sizeof(portbuf), NI_NUMERICHOST | NI_NUMERICSERV);
+		if (rc) {
+			snprintf(addrbuf, sizeof(addrbuf), "[err:%s]", gai_strerror(rc));
+			portbuf[0] = '\0';
+		}
+		
+		/* Numeric values for debug... */
+		snprintf(cli->cc_id, sizeof(cli->cc_id), CC_ID_HDR "%s from [%s]:%s (%d<-%d)", 
+				IPPROTO_NAME(cli->cc_proto), addrbuf, portbuf, serv->cc_socket, cli->cc_socket);
+		
+		
+		/* ...Name for log messages */
+		rc = getnameinfo((sSA *)&ss, ss_len, cli->cc_remid, sizeof(cli->cc_remid), NULL, 0, 0);
+		if (rc)
+			snprintf(cli->cc_remid, sizeof(cli->cc_remid), "[err:%s]", gai_strerror(rc));
+	}
+	
+	LOG_D("Incoming connection: '%s' <- '%s'   {%s}", fd_cnx_getid(serv), cli->cc_remid, cli->cc_id);
+
+#ifndef DISABLE_SCTP
+	/* SCTP-specific handlings */
+	if (cli->cc_proto == IPPROTO_SCTP) {
+		/* Retrieve the number of streams */
+		CHECK_FCT_DO( fd_sctp_get_str_info( cli->cc_socket, &cli->cc_sctp_para.str_in, &cli->cc_sctp_para.str_out, NULL ), {fd_cnx_destroy(cli); return NULL;} );
+		if (cli->cc_sctp_para.str_out < cli->cc_sctp_para.str_in)
+			cli->cc_sctp_para.pairs = cli->cc_sctp_para.str_out;
+		else
+			cli->cc_sctp_para.pairs = cli->cc_sctp_para.str_in;
+		
+		LOG_A( "%s : client '%s' (SCTP:%d, %d/%d streams)", fd_cnx_getid(serv), fd_cnx_getid(cli), cli->cc_socket, cli->cc_sctp_para.str_in, cli->cc_sctp_para.str_out);
+	}
+#endif /* DISABLE_SCTP */
+
+	return cli;
+}
+
+/* Client side: connect to a remote server -- cancelable */
+struct cnxctx * fd_cnx_cli_connect_tcp(sSA * sa /* contains the port already */, socklen_t addrlen)
+{
+	int sock = 0;
+	struct cnxctx * cnx = NULL;
+	char sa_buf[sSA_DUMP_STRLEN];
+	
+	TRACE_ENTRY("%p %d", sa, addrlen);
+	CHECK_PARAMS_DO( sa && addrlen, return NULL );
+	
+	fd_sa_sdump_numeric(sa_buf, sa);
+	
+	LOG_D("Connecting to TCP %s...", sa_buf);
+	
+	/* Create the socket and connect, which can take some time and/or fail */
+	{
+		int ret = fd_tcp_client( &sock, sa, addrlen );
+		if (ret != 0) {
+			LOG_D("TCP connection to %s failed: %s", sa_buf, strerror(ret));
+			return NULL;
+		}
+	}
+	
+	/* Once the socket is created successfuly, prepare the remaining of the cnx */
+	CHECK_MALLOC_DO( cnx = fd_cnx_init(1), { shutdown(sock, SHUT_RDWR); close(sock); return NULL; } );
+	
+	cnx->cc_socket = sock;
+	cnx->cc_family = sa->sa_family;
+	cnx->cc_proto  = IPPROTO_TCP;
+	
+	/* Set the timeout */
+	fd_cnx_s_setto(cnx->cc_socket);
+	
+	/* Generate the names for the object */
+	{
+		int  rc;
+		
+		snprintf(cnx->cc_id, sizeof(cnx->cc_id), CC_ID_HDR "TCP,#%d->%s", cnx->cc_socket, sa_buf);
+		
+		/* ...Name for log messages */
+		rc = getnameinfo(sa, addrlen, cnx->cc_remid, sizeof(cnx->cc_remid), NULL, 0, 0);
+		if (rc)
+			snprintf(cnx->cc_remid, sizeof(cnx->cc_remid), "[err:%s]", gai_strerror(rc));
+	}
+	
+	LOG_A("TCP connection to %s succeed (socket:%d).", sa_buf, sock);
+	
+	return cnx;
+}
+
+/* Same for SCTP, accepts a list of remote addresses to connect to (see sctp_connectx for how they are used) */
+struct cnxctx * fd_cnx_cli_connect_sctp(int no_ip6, uint16_t port, struct fd_list * list)
+{
+#ifdef DISABLE_SCTP
+	TRACE_DEBUG(INFO, "This function should never be called when SCTP is disabled...");
+	ASSERT(0);
+	CHECK_FCT_DO( ENOTSUP, );
+	return NULL;
+#else /* DISABLE_SCTP */
+	int sock = 0;
+	struct cnxctx * cnx = NULL;
+	char sa_buf[sSA_DUMP_STRLEN];
+	sSS primary;
+	
+	TRACE_ENTRY("%p", list);
+	CHECK_PARAMS_DO( list && !FD_IS_LIST_EMPTY(list), return NULL );
+	
+	fd_sa_sdump_numeric(sa_buf, &((struct fd_endpoint *)(list->next))->sa);
+	
+	LOG_D("Connecting to SCTP %s:%hu...", sa_buf, port);
+	
+	{
+		int ret = fd_sctp_client( &sock, no_ip6, port, list );
+		if (ret != 0) {
+			LOG_D("SCTP connection to [%s,...] failed: %s", sa_buf, strerror(ret));
+			return NULL;
+		}
+	}
+	
+	/* Once the socket is created successfuly, prepare the remaining of the cnx */
+	CHECK_MALLOC_DO( cnx = fd_cnx_init(1), { shutdown(sock, SHUT_RDWR); close(sock); return NULL; } );
+	
+	cnx->cc_socket = sock;
+	cnx->cc_family = no_ip6 ? AF_INET : AF_INET6;
+	cnx->cc_proto  = IPPROTO_SCTP;
+	
+	/* Set the timeout */
+	fd_cnx_s_setto(cnx->cc_socket);
+	
+	/* Retrieve the number of streams and primary address */
+	CHECK_FCT_DO( fd_sctp_get_str_info( sock, &cnx->cc_sctp_para.str_in, &cnx->cc_sctp_para.str_out, &primary ), goto error );
+	if (cnx->cc_sctp_para.str_out < cnx->cc_sctp_para.str_in)
+		cnx->cc_sctp_para.pairs = cnx->cc_sctp_para.str_out;
+	else
+		cnx->cc_sctp_para.pairs = cnx->cc_sctp_para.str_in;
+	
+	fd_sa_sdump_numeric(sa_buf, (sSA *)&primary);
+	
+	/* Generate the names for the object */
+	{
+		int  rc;
+		
+		snprintf(cnx->cc_id, sizeof(cnx->cc_id), CC_ID_HDR "SCTP,#%d->%s", cnx->cc_socket, sa_buf);
+		
+		/* ...Name for log messages */
+		rc = getnameinfo((sSA *)&primary, sSAlen(&primary), cnx->cc_remid, sizeof(cnx->cc_remid), NULL, 0, 0);
+		if (rc)
+			snprintf(cnx->cc_remid, sizeof(cnx->cc_remid), "[err:%s]", gai_strerror(rc));
+	}
+	
+	LOG_A("SCTP connection to %s succeed (socket:%d, %d/%d streams).", sa_buf, sock, cnx->cc_sctp_para.str_in, cnx->cc_sctp_para.str_out);
+	
+	return cnx;
+
+error:
+	fd_cnx_destroy(cnx);
+	return NULL;
+#endif /* DISABLE_SCTP */
+}
+
+/* Return a string describing the connection, for debug */
+char * fd_cnx_getid(struct cnxctx * conn)
+{
+	CHECK_PARAMS_DO( conn, return "" );
+	return conn->cc_id;
+}
+
+/* Return the protocol of a connection */
+int fd_cnx_getproto(struct cnxctx * conn)
+{
+	CHECK_PARAMS_DO( conn, return 0 );
+	return conn->cc_proto;
+}
+
+/* Set the hostname to check during handshake */
+void fd_cnx_sethostname(struct cnxctx * conn, DiamId_t hn)
+{
+	CHECK_PARAMS_DO( conn, return );
+	conn->cc_tls_para.cn = hn;
+}
+
+/* We share a lock with many threads but we hold it only very short time so it is OK */
+static pthread_mutex_t state_lock = PTHREAD_MUTEX_INITIALIZER;
+uint32_t fd_cnx_getstate(struct cnxctx * conn)
+{
+	uint32_t st;
+	CHECK_POSIX_DO( pthread_mutex_lock(&state_lock), { ASSERT(0); } );
+	st = conn->cc_state;
+	CHECK_POSIX_DO( pthread_mutex_unlock(&state_lock), { ASSERT(0); } );
+	return st;
+}
+int  fd_cnx_teststate(struct cnxctx * conn, uint32_t flag)
+{
+	uint32_t st;
+	CHECK_POSIX_DO( pthread_mutex_lock(&state_lock), { ASSERT(0); } );
+	st = conn->cc_state;
+	CHECK_POSIX_DO( pthread_mutex_unlock(&state_lock), { ASSERT(0); } );
+	return st & flag;
+}
+void fd_cnx_update_id(struct cnxctx * conn) {
+	if (conn->cc_state & CC_STATUS_CLOSING)
+		conn->cc_id[1] = 'C';
+	else
+		conn->cc_id[1] = '-';
+	
+	if (conn->cc_state & CC_STATUS_ERROR)
+		conn->cc_id[2] = 'E';
+	else
+		conn->cc_id[2] = '-';
+	
+	if (conn->cc_state & CC_STATUS_SIGNALED)
+		conn->cc_id[3] = 'S';
+	else
+		conn->cc_id[3] = '-';
+	
+	if (conn->cc_state & CC_STATUS_TLS)
+		conn->cc_id[4] = 'T';
+	else
+		conn->cc_id[4] = '-';
+}
+void fd_cnx_addstate(struct cnxctx * conn, uint32_t orstate)
+{
+	CHECK_POSIX_DO( pthread_mutex_lock(&state_lock), { ASSERT(0); } );
+	conn->cc_state |= orstate;
+	fd_cnx_update_id(conn);
+	CHECK_POSIX_DO( pthread_mutex_unlock(&state_lock), { ASSERT(0); } );
+}
+void fd_cnx_setstate(struct cnxctx * conn, uint32_t abstate)
+{
+	CHECK_POSIX_DO( pthread_mutex_lock(&state_lock), { ASSERT(0); } );
+	conn->cc_state = abstate;
+	fd_cnx_update_id(conn);
+	CHECK_POSIX_DO( pthread_mutex_unlock(&state_lock), { ASSERT(0); } );
+}
+
+
+/* Return the TLS state of a connection */
+int fd_cnx_getTLS(struct cnxctx * conn)
+{
+	CHECK_PARAMS_DO( conn, return 0 );
+	return fd_cnx_teststate(conn, CC_STATUS_TLS);
+}
+
+/* Mark the connection to tell if OOO delivery is permitted (only for SCTP) */
+int fd_cnx_unordered_delivery(struct cnxctx * conn, int is_allowed)
+{
+	CHECK_PARAMS( conn );
+	conn->cc_sctp_para.unordered = is_allowed;
+	return 0;
+}
+
+/* Return true if the connection supports unordered delivery of messages */
+int fd_cnx_is_unordered_delivery_supported(struct cnxctx * conn)
+{
+	CHECK_PARAMS_DO( conn, return 0 );
+	#ifndef DISABLE_SCTP
+	if (conn->cc_proto == IPPROTO_SCTP)
+		return (conn->cc_sctp_para.str_out > 1);
+	#endif /* DISABLE_SCTP */
+	return 0;
+}
+
+
+/* Get the list of endpoints (IP addresses) of the local and remote peers on this connection */
+int fd_cnx_getremoteeps(struct cnxctx * conn, struct fd_list * eps)
+{
+	TRACE_ENTRY("%p %p", conn, eps);
+	CHECK_PARAMS(conn && eps);
+	
+	/* Check we have a full connection object, not a listening socket (with no remote) */
+	CHECK_PARAMS( conn->cc_incoming );
+
+	/* Retrieve the peer endpoint(s) of the connection */
+	switch (conn->cc_proto) {
+		case IPPROTO_TCP: {
+			sSS ss;
+			socklen_t sl;
+			CHECK_FCT(fd_tcp_get_remote_ep(conn->cc_socket, &ss, &sl));
+			CHECK_FCT(fd_ep_add_merge( eps, (sSA *)&ss, sl, EP_FL_LL | EP_FL_PRIMARY ));
+		}
+		break;
+
+		#ifndef DISABLE_SCTP
+		case IPPROTO_SCTP: {
+			CHECK_FCT(fd_sctp_get_remote_ep(conn->cc_socket, eps));
+		}
+		break;
+		#endif /* DISABLE_SCTP */
+
+		default:
+			CHECK_PARAMS(0);
+	}
+
+	return 0;
+}
+
+/* Get a string describing the remote peer address (ip address or fqdn) */
+char * fd_cnx_getremoteid(struct cnxctx * conn)
+{
+	CHECK_PARAMS_DO( conn, return "" );
+	return conn->cc_remid;
+}
+
+static int fd_cnx_may_dtls(struct cnxctx * conn);
+
+/* Get a short string representing the connection */
+int fd_cnx_proto_info(struct cnxctx * conn, char * buf, size_t len) 
+{
+	CHECK_PARAMS( conn );
+	
+	if (fd_cnx_teststate(conn, CC_STATUS_TLS)) {
+		snprintf(buf, len, "%s,%s,soc#%d", IPPROTO_NAME(conn->cc_proto), fd_cnx_may_dtls(conn) ? "DTLS" : "TLS", conn->cc_socket);
+	} else {
+		snprintf(buf, len, "%s,soc#%d", IPPROTO_NAME(conn->cc_proto), conn->cc_socket);
+	}
+	
+	return 0;
+}
+
+/* Retrieve a list of all IP addresses of the local system from the kernel, using getifaddrs */
+int fd_cnx_get_local_eps(struct fd_list * list)
+{
+	struct ifaddrs *iflist, *cur;
+	
+	CHECK_SYS(getifaddrs(&iflist));
+	
+	for (cur = iflist; cur != NULL; cur = cur->ifa_next) {
+		if (cur->ifa_flags & IFF_LOOPBACK)
+			continue;
+		
+		if (cur->ifa_addr == NULL) /* may happen with ppp interfaces */
+			continue;
+		
+		if (fd_g_config->cnf_flags.no_ip4 && (cur->ifa_addr->sa_family == AF_INET))
+			continue;
+		
+		if (fd_g_config->cnf_flags.no_ip6 && (cur->ifa_addr->sa_family == AF_INET6))
+			continue;
+		
+		CHECK_FCT(fd_ep_add_merge( list, cur->ifa_addr, sSAlen(cur->ifa_addr), EP_FL_LL ));
+	}
+	
+	freeifaddrs(iflist);
+	
+	return 0;
+}
+
+
+/**************************************/
+/*     Use of a connection object     */
+/**************************************/
+
+/* An error occurred on the socket */
+void fd_cnx_markerror(struct cnxctx * conn)
+{
+	TRACE_ENTRY("%p", conn);
+	CHECK_PARAMS_DO( conn, goto fatal );
+	
+	TRACE_DEBUG(FULL, "Error flag set for socket %d (%s, %s)", conn->cc_socket, conn->cc_id, conn->cc_remid);
+
+	/* Mark the error */
+	fd_cnx_addstate(conn, CC_STATUS_ERROR);
+	
+	/* Report the error if not reported yet, and not closing */
+	if (!fd_cnx_teststate(conn, CC_STATUS_CLOSING | CC_STATUS_SIGNALED ))  {
+		TRACE_DEBUG(FULL, "Sending FDEVP_CNX_ERROR event");
+		CHECK_FCT_DO( fd_event_send( fd_cnx_target_queue(conn), FDEVP_CNX_ERROR, 0, NULL), goto fatal);
+		fd_cnx_addstate(conn, CC_STATUS_SIGNALED);
+	}
+	
+	return;
+fatal:
+	/* An unrecoverable error occurred, stop the daemon */
+	ASSERT(0);
+	CHECK_FCT_DO(fd_core_shutdown(), );	
+}
+
+/* Set the timeout option on the socket */
+void fd_cnx_s_setto(int sock) 
+{
+	struct timeval tv;
+	
+	/* Set a timeout on the socket so that in any case we are not stuck waiting for something */
+	memset(&tv, 0, sizeof(tv));
+	tv.tv_usec = 100000L;	/* 100ms, to react quickly to head-of-the-line blocking. */
+	CHECK_SYS_DO( setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)),  );
+	CHECK_SYS_DO( setsockopt(sock, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(tv)),  );
+}
+
+
+#ifdef GNUTLS_VERSION_300
+/* The pull_timeout function for gnutls */
+static int fd_cnx_s_select (struct cnxctx * conn, unsigned int ms)
+{
+	fd_set rfds;
+	struct timeval tv;
+	
+	FD_ZERO (&rfds);
+	FD_SET (conn->cc_socket, &rfds);
+	
+	tv.tv_sec = ms / 1000;
+	tv.tv_usec = (ms * 1000) % 1000000;
+	
+	return select (conn->cc_socket + 1, &rfds, NULL, NULL, &tv);
+}		
+#endif /* GNUTLS_VERSION_300 */
+
+/* A recv-like function, taking a cnxctx object instead of socket as entry. We use it to quickly react to timeouts without traversing GNUTLS wrapper each time */
+ssize_t fd_cnx_s_recv(struct cnxctx * conn, void *buffer, size_t length)
+{
+	ssize_t ret = 0;
+	int timedout = 0;
+again:
+	ret = recv(conn->cc_socket, buffer, length, 0);
+	/* Handle special case of timeout / interrupts */
+	if ((ret < 0) && ((errno == EAGAIN) || (errno == EINTR))) {
+		pthread_testcancel();
+		if (! fd_cnx_teststate(conn, CC_STATUS_CLOSING ))
+			goto again; /* don't care, just ignore */
+		if (!timedout) {
+			timedout ++; /* allow for one timeout while closing */
+			goto again;
+		}
+	}
+	
+	/* Mark the error */
+	if (ret <= 0) {
+		CHECK_SYS_DO(ret, /* continue, this is only used to log the error here */);
+		fd_cnx_markerror(conn);
+	}
+	
+	return ret;
+}
+
+/* Send */
+static ssize_t fd_cnx_s_sendv(struct cnxctx * conn, const struct iovec * iov, int iovcnt)
+{
+	ssize_t ret = 0;
+	struct timespec ts, now;
+	CHECK_SYS_DO(  clock_gettime(CLOCK_REALTIME, &ts), return -1 );
+again:
+	ret = writev(conn->cc_socket, iov, iovcnt);
+	/* Handle special case of timeout */
+	if ((ret < 0) && ((errno == EAGAIN) || (errno == EINTR))) {
+		ret = -errno;
+		pthread_testcancel();
+		
+		/* Check how much time we were blocked for this sending. */
+		CHECK_SYS_DO(  clock_gettime(CLOCK_REALTIME, &now), return -1 );
+		if ( ((now.tv_sec - ts.tv_sec) * 1000 + ((now.tv_nsec - ts.tv_nsec) / 1000000L)) > MAX_HOTL_BLOCKING_TIME) {
+			LOG_D("Unable to send any data for %dms, closing the connection", MAX_HOTL_BLOCKING_TIME);
+		} else if (! fd_cnx_teststate(conn, CC_STATUS_CLOSING )) {
+			goto again; /* don't care, just ignore */
+		}
+		
+		/* propagate the error */
+		errno = -ret;
+		ret = -1;
+		CHECK_SYS_DO(ret, /* continue */);
+	}
+	
+	/* Mark the error */
+	if (ret <= 0)
+		fd_cnx_markerror(conn);
+	
+	return ret;
+}
+
+/* Send, for older GNUTLS */
+#ifndef GNUTLS_VERSION_212
+static ssize_t fd_cnx_s_send(struct cnxctx * conn, const void *buffer, size_t length)
+{
+	struct iovec iov;
+	iov.iov_base = (void *)buffer;
+	iov.iov_len  = length;
+	return fd_cnx_s_sendv(conn, &iov, 1);
+}
+#endif /* GNUTLS_VERSION_212 */
+
+#define ALIGNOF(t) ((char *)(&((struct { char c; t _h; } *)0)->_h) - (char *)0)  /* Could use __alignof__(t) on some systems but this is more portable probably */
+#define PMDL_PADDED(len) ( ((len) + ALIGNOF(struct fd_msg_pmdl) - 1) & ~(ALIGNOF(struct fd_msg_pmdl) - 1) )
+
+size_t fd_msg_pmdl_sizewithoverhead(size_t datalen)
+{
+	return PMDL_PADDED(datalen) + sizeof(struct fd_msg_pmdl);
+}
+
+struct fd_msg_pmdl * fd_msg_pmdl_get_inbuf(uint8_t * buf, size_t datalen)
+{
+	return (struct fd_msg_pmdl *)(buf + PMDL_PADDED(datalen));
+} 
+
+static int fd_cnx_init_msg_buffer(uint8_t * buffer, size_t expected_len, struct fd_msg_pmdl ** pmdl)
+{
+	*pmdl = fd_msg_pmdl_get_inbuf(buffer, expected_len);
+	fd_list_init(&(*pmdl)->sentinel, NULL);
+	CHECK_POSIX(pthread_mutex_init(&(*pmdl)->lock, NULL) );
+	return 0;
+}
+
+static uint8_t * fd_cnx_alloc_msg_buffer(size_t expected_len, struct fd_msg_pmdl ** pmdl)
+{
+	uint8_t * ret = NULL;
+	
+	CHECK_MALLOC_DO(  ret = malloc( fd_msg_pmdl_sizewithoverhead(expected_len) ), return NULL );
+	CHECK_FCT_DO( fd_cnx_init_msg_buffer(ret, expected_len, pmdl), {free(ret); return NULL;} );
+	return ret;
+}
+
+#ifndef DISABLE_SCTP /* WE use this function only in SCTP code */
+static uint8_t * fd_cnx_realloc_msg_buffer(uint8_t * buffer, size_t expected_len, struct fd_msg_pmdl ** pmdl)
+{
+	uint8_t * ret = NULL;
+	
+	CHECK_MALLOC_DO(  ret = realloc( buffer, fd_msg_pmdl_sizewithoverhead(expected_len) ), return NULL );
+	CHECK_FCT_DO( fd_cnx_init_msg_buffer(ret, expected_len, pmdl), {free(ret); return NULL;} );
+	return ret;
+}
+#endif /* DISABLE_SCTP */
+
+static void free_rcvdata(void * arg) 
+{
+	struct fd_cnx_rcvdata * data = arg;
+	struct fd_msg_pmdl * pmdl = fd_msg_pmdl_get_inbuf(data->buffer, data->length);
+	(void) pthread_mutex_destroy(&pmdl->lock);
+	free(data->buffer);
+}
+
+/* Receiver thread (TCP & noTLS) : incoming message is directly saved into the target queue */
+static void * rcvthr_notls_tcp(void * arg)
+{
+	struct cnxctx * conn = arg;
+	
+	TRACE_ENTRY("%p", arg);
+	CHECK_PARAMS_DO(conn && (conn->cc_socket > 0), goto out);
+	
+	/* Set the thread name */
+	{
+		char buf[48];
+		snprintf(buf, sizeof(buf), "Receiver (%d) TCP/noTLS)", conn->cc_socket);
+		fd_log_threadname ( buf );
+	}
+	
+	ASSERT( conn->cc_proto == IPPROTO_TCP );
+	ASSERT( ! fd_cnx_teststate(conn, CC_STATUS_TLS ) );
+	ASSERT( fd_cnx_target_queue(conn) );
+	
+	/* Receive from a TCP connection: we have to rebuild the message boundaries */
+	do {
+		uint8_t header[4];
+		struct fd_cnx_rcvdata rcv_data;
+		struct fd_msg_pmdl *pmdl=NULL;
+		ssize_t ret = 0;
+		size_t	received = 0;
+
+		do {
+			ret = fd_cnx_s_recv(conn, &header[received], sizeof(header) - received);
+			if (ret <= 0) {
+				goto out; /* Stop the thread, the event was already sent */
+			}
+
+			received += ret;
+			
+			if (header[0] != DIAMETER_VERSION)
+				break; /* No need to wait for 4 bytes in this case */
+		} while (received < sizeof(header));
+
+		rcv_data.length = ((size_t)header[1] << 16) + ((size_t)header[2] << 8) + (size_t)header[3];
+
+		/* Check the received word is a valid begining of a Diameter message */
+		if ((header[0] != DIAMETER_VERSION)	/* defined in <libfdproto.h> */
+		   || (rcv_data.length > DIAMETER_MSG_SIZE_MAX)) { /* to avoid too big mallocs */
+			/* The message is suspect */
+			LOG_E( "Received suspect header [ver: %d, size: %zd] from '%s', assuming disconnection", (int)header[0], rcv_data.length, conn->cc_remid);
+			fd_cnx_markerror(conn);
+			goto out; /* Stop the thread, the recipient of the event will cleanup */
+		}
+
+		/* Ok, now we can really receive the data */
+		CHECK_MALLOC_DO(  rcv_data.buffer = fd_cnx_alloc_msg_buffer( rcv_data.length, &pmdl ), goto fatal );
+		memcpy(rcv_data.buffer, header, sizeof(header));
+
+		while (received < rcv_data.length) {
+			pthread_cleanup_push(free_rcvdata, &rcv_data); /* In case we are canceled, clean the partialy built buffer */
+			ret = fd_cnx_s_recv(conn, rcv_data.buffer + received, rcv_data.length - received);
+			pthread_cleanup_pop(0);
+
+			if (ret <= 0) {
+				free_rcvdata(&rcv_data);
+				goto out;
+			}
+			received += ret;
+		}
+		
+		fd_hook_call(HOOK_DATA_RECEIVED, NULL, NULL, &rcv_data, pmdl);
+		
+		/* We have received a complete message, pass it to the daemon */
+		CHECK_FCT_DO( fd_event_send( fd_cnx_target_queue(conn), FDEVP_CNX_MSG_RECV, rcv_data.length, rcv_data.buffer), 
+			{ 
+				free_rcvdata(&rcv_data);
+				goto fatal; 
+			} );
+		
+	} while (conn->cc_loop);
+	
+out:
+	TRACE_DEBUG(FULL, "Thread terminated");	
+	return NULL;
+	
+fatal:
+	/* An unrecoverable error occurred, stop the daemon */
+	CHECK_FCT_DO(fd_core_shutdown(), );
+	goto out;
+}
+
+#ifndef DISABLE_SCTP
+/* Receiver thread (SCTP & noTLS) : incoming message is directly saved into cc_incoming, no need to care for the stream ID */
+static void * rcvthr_notls_sctp(void * arg)
+{
+	struct cnxctx * conn = arg;
+	struct fd_cnx_rcvdata rcv_data;
+	int	  event;
+	
+	TRACE_ENTRY("%p", arg);
+	CHECK_PARAMS_DO(conn && (conn->cc_socket > 0), goto fatal);
+	
+	/* Set the thread name */
+	{
+		char buf[48];
+		snprintf(buf, sizeof(buf), "Receiver (%d) SCTP/noTLS)", conn->cc_socket);
+		fd_log_threadname ( buf );
+	}
+	
+	ASSERT( conn->cc_proto == IPPROTO_SCTP );
+	ASSERT( ! fd_cnx_teststate(conn, CC_STATUS_TLS ) );
+	ASSERT( fd_cnx_target_queue(conn) );
+	
+	do {
+		struct fd_msg_pmdl *pmdl=NULL;
+		CHECK_FCT_DO( fd_sctp_recvmeta(conn, NULL, &rcv_data.buffer, &rcv_data.length, &event), goto fatal );
+		if (event == FDEVP_CNX_ERROR) {
+			fd_cnx_markerror(conn);
+			goto out;
+		}
+		
+		if (event == FDEVP_CNX_SHUTDOWN) {
+			/* Just ignore the notification for now, we will get another error later anyway */
+			continue;
+		}
+
+		if (event == FDEVP_CNX_MSG_RECV) {
+			CHECK_MALLOC_DO( rcv_data.buffer = fd_cnx_realloc_msg_buffer(rcv_data.buffer, rcv_data.length, &pmdl), goto fatal );
+			fd_hook_call(HOOK_DATA_RECEIVED, NULL, NULL, &rcv_data, pmdl);
+		}
+		CHECK_FCT_DO( fd_event_send( fd_cnx_target_queue(conn), event, rcv_data.length, rcv_data.buffer), goto fatal );
+		
+	} while (conn->cc_loop || (event != FDEVP_CNX_MSG_RECV));
+	
+out:
+	TRACE_DEBUG(FULL, "Thread terminated");	
+	return NULL;
+
+fatal:
+	/* An unrecoverable error occurred, stop the daemon */
+	CHECK_FCT_DO(fd_core_shutdown(), );
+	goto out;
+}
+#endif /* DISABLE_SCTP */
+
+/* Start receving messages in clear (no TLS) on the connection */
+int fd_cnx_start_clear(struct cnxctx * conn, int loop)
+{
+	TRACE_ENTRY("%p %i", conn, loop);
+	
+	CHECK_PARAMS( conn && fd_cnx_target_queue(conn) && (!fd_cnx_teststate(conn, CC_STATUS_TLS)) && (!conn->cc_loop));
+	
+	/* Release resources in case of a previous call was already made */
+	CHECK_FCT_DO( fd_thr_term(&conn->cc_rcvthr), /* continue */);
+	
+	/* Save the loop request */
+	conn->cc_loop = loop;
+	
+	switch (conn->cc_proto) {
+		case IPPROTO_TCP:
+			/* Start the tcp_notls thread */
+			CHECK_POSIX( pthread_create( &conn->cc_rcvthr, NULL, rcvthr_notls_tcp, conn ) );
+			break;
+#ifndef DISABLE_SCTP
+		case IPPROTO_SCTP:
+			/* Start the tcp_notls thread */
+			CHECK_POSIX( pthread_create( &conn->cc_rcvthr, NULL, rcvthr_notls_sctp, conn ) );
+			break;
+#endif /* DISABLE_SCTP */
+		default:
+			TRACE_DEBUG(INFO, "Unknown protocol: %d", conn->cc_proto);
+			ASSERT(0);
+			return ENOTSUP;
+	}
+			
+	return 0;
+}
+
+
+
+
+/* Returns 0 on error, received data size otherwise (always >= 0). This is not used for DTLS-protected associations. */
+static ssize_t fd_tls_recv_handle_error(struct cnxctx * conn, gnutls_session_t session, void * data, size_t sz)
+{
+	ssize_t ret;
+again:	
+	CHECK_GNUTLS_DO( ret = gnutls_record_recv(session, data, sz), 
+		{
+			switch (ret) {
+				case GNUTLS_E_REHANDSHAKE: 
+					if (!fd_cnx_teststate(conn, CC_STATUS_CLOSING)) {
+						CHECK_GNUTLS_DO( ret = gnutls_handshake(session),
+							{
+								if (TRACE_BOOL(INFO)) {
+									fd_log_debug("TLS re-handshake failed on socket %d (%s) : %s", conn->cc_socket, conn->cc_id, gnutls_strerror(ret));
+								}
+								goto end;
+							} );
+					}
+
+				case GNUTLS_E_AGAIN:
+				case GNUTLS_E_INTERRUPTED:
+					if (!fd_cnx_teststate(conn, CC_STATUS_CLOSING))
+						goto again;
+					TRACE_DEBUG(FULL, "Connection is closing, so abord gnutls_record_recv now.");
+					break;
+
+				case GNUTLS_E_UNEXPECTED_PACKET_LENGTH:
+					/* The connection is closed */
+					TRACE_DEBUG(FULL, "Got 0 size while reading the socket, probably connection closed...");
+					break;
+				
+				default:
+					if (gnutls_error_is_fatal (ret) == 0) {
+						LOG_N("Ignoring non-fatal GNU TLS error: %s", gnutls_strerror (ret));
+						goto again;
+					}
+					LOG_E("Fatal GNUTLS error: %s", gnutls_strerror (ret));
+			}
+		} );
+		
+	if (ret == 0)
+		CHECK_GNUTLS_DO( gnutls_bye(session, GNUTLS_SHUT_RDWR),  );
+	
+end:	
+	if (ret <= 0)
+		fd_cnx_markerror(conn);
+	return ret;
+}
+
+/* Wrapper around gnutls_record_send to handle some error codes. This is also used for DTLS-protected associations */
+static ssize_t fd_tls_send_handle_error(struct cnxctx * conn, gnutls_session_t session, void * data, size_t sz)
+{
+	ssize_t ret;
+	struct timespec ts, now;
+	CHECK_SYS_DO(  clock_gettime(CLOCK_REALTIME, &ts), return -1 );
+again:	
+	CHECK_GNUTLS_DO( ret = gnutls_record_send(session, data, sz),
+		{
+			pthread_testcancel();
+			switch (ret) {
+				case GNUTLS_E_REHANDSHAKE: 
+					if (!fd_cnx_teststate(conn, CC_STATUS_CLOSING)) {
+						CHECK_GNUTLS_DO( ret = gnutls_handshake(session),
+							{
+								if (TRACE_BOOL(INFO)) {
+									fd_log_debug("TLS re-handshake failed on socket %d (%s) : %s", conn->cc_socket, conn->cc_id, gnutls_strerror(ret));
+								}
+								goto end;
+							} );
+					}
+
+				case GNUTLS_E_AGAIN:
+				case GNUTLS_E_INTERRUPTED:
+					CHECK_SYS_DO(  clock_gettime(CLOCK_REALTIME, &now), return -1 );
+					if ( ((now.tv_sec - ts.tv_sec) * 1000 + ((now.tv_nsec - ts.tv_nsec) / 1000000L)) > MAX_HOTL_BLOCKING_TIME) {
+						LOG_D("Unable to send any data for %dms, closing the connection", MAX_HOTL_BLOCKING_TIME);
+					} else if (! fd_cnx_teststate(conn, CC_STATUS_CLOSING )) {
+						goto again;
+					}
+					break;
+
+				default:
+					if (gnutls_error_is_fatal (ret) == 0) {
+						LOG_N("Ignoring non-fatal GNU TLS error: %s", gnutls_strerror (ret));
+						goto again;
+					}
+					LOG_E("Fatal GNUTLS error: %s", gnutls_strerror (ret));
+			}
+		} );
+end:	
+	if (ret <= 0)
+		fd_cnx_markerror(conn);
+		
+	return ret;
+}
+
+
+/* The function that receives TLS data and re-builds a Diameter message -- it exits only on error or cancelation */
+/* 	   For the case of DTLS, since we are not using SCTP_UNORDERED, the messages over a single stream are ordered.
+	   Furthermore, as long as messages are shorter than the MTU [2^14 = 16384 bytes], they are delivered in a single
+	   record, as far as I understand. 
+	   For larger messages, however, it is possible that pieces of messages coming from different streams can get interleaved. 
+	   As a result, we do not use the following function for DTLS reception, because we use the sequence number to rebuild the
+	   messages. */
+int fd_tls_rcvthr_core(struct cnxctx * conn, gnutls_session_t session)
+{
+	/* No guarantee that GnuTLS preserves the message boundaries, so we re-build it as in TCP. */
+	do {
+		uint8_t header[4];
+		struct fd_cnx_rcvdata rcv_data;
+		struct fd_msg_pmdl *pmdl=NULL;
+		ssize_t ret = 0;
+		size_t	received = 0;
+
+		do {
+			ret = fd_tls_recv_handle_error(conn, session, &header[received], sizeof(header) - received);
+			if (ret <= 0) {
+				/* The connection is closed */
+				goto out;
+			}
+			received += ret;
+		} while (received < sizeof(header));
+
+		rcv_data.length = ((size_t)header[1] << 16) + ((size_t)header[2] << 8) + (size_t)header[3];
+
+		/* Check the received word is a valid beginning of a Diameter message */
+		if ((header[0] != DIAMETER_VERSION)	/* defined in <libfreeDiameter.h> */
+		   || (rcv_data.length > DIAMETER_MSG_SIZE_MAX)) { /* to avoid too big mallocs */
+			/* The message is suspect */
+			LOG_E( "Received suspect header [ver: %d, size: %zd] from '%s', assume disconnection", (int)header[0], rcv_data.length, conn->cc_remid);
+			fd_cnx_markerror(conn);
+			goto out;
+		}
+
+		/* Ok, now we can really receive the data */
+		CHECK_MALLOC(  rcv_data.buffer = fd_cnx_alloc_msg_buffer( rcv_data.length, &pmdl ) );
+		memcpy(rcv_data.buffer, header, sizeof(header));
+
+		while (received < rcv_data.length) {
+			pthread_cleanup_push(free_rcvdata, &rcv_data); /* In case we are canceled, clean the partialy built buffer */
+			ret = fd_tls_recv_handle_error(conn, session, rcv_data.buffer + received, rcv_data.length - received);
+			pthread_cleanup_pop(0);
+
+			if (ret <= 0) {
+				free_rcvdata(&rcv_data);
+				goto out;
+			}
+			received += ret;
+		}
+		
+		fd_hook_call(HOOK_DATA_RECEIVED, NULL, NULL, &rcv_data, pmdl);
+		
+		/* We have received a complete message, pass it to the daemon */
+		CHECK_FCT_DO( ret = fd_event_send( fd_cnx_target_queue(conn), FDEVP_CNX_MSG_RECV, rcv_data.length, rcv_data.buffer), 
+			{ 
+				free_rcvdata(&rcv_data);
+				CHECK_FCT_DO(fd_core_shutdown(), );
+				return ret; 
+			} );
+		
+	} while (1);
+	
+out:
+	return ENOTCONN;
+}
+
+/* Receiver thread (TLS & 1 stream SCTP or TCP)  */
+static void * rcvthr_tls_single(void * arg)
+{
+	struct cnxctx * conn = arg;
+	
+	TRACE_ENTRY("%p", arg);
+	CHECK_PARAMS_DO(conn && (conn->cc_socket > 0), return NULL );
+	
+	/* Set the thread name */
+	{
+		char buf[48];
+		snprintf(buf, sizeof(buf), "Receiver (%d) TLS/single stream", conn->cc_socket);
+		fd_log_threadname ( buf );
+	}
+	
+	ASSERT( fd_cnx_teststate(conn, CC_STATUS_TLS) );
+	ASSERT( fd_cnx_target_queue(conn) );
+
+	/* The next function only returns when there is an error on the socket */	
+	CHECK_FCT_DO(fd_tls_rcvthr_core(conn, conn->cc_tls_para.session), /* continue */);
+
+	TRACE_DEBUG(FULL, "Thread terminated");	
+	return NULL;
+}
+
+/* Prepare a gnutls session object for handshake */
+int fd_tls_prepare(gnutls_session_t * session, int mode, int dtls, char * priority, void * alt_creds)
+{
+	if (dtls) {
+		LOG_E("DTLS sessions not yet supported");
+		return ENOTSUP;
+	}
+
+	/* Create the session context */
+	CHECK_GNUTLS_DO( gnutls_init (session, mode), return ENOMEM );
+
+	/* Set the algorithm suite */
+	if (priority) {
+		const char * errorpos;
+		CHECK_GNUTLS_DO( gnutls_priority_set_direct( *session, priority, &errorpos ), 
+			{ TRACE_DEBUG(INFO, "Error in priority string '%s' at position: '%s'", priority, errorpos); return EINVAL; } );
+	} else {
+		CHECK_GNUTLS_DO( gnutls_priority_set( *session, fd_g_config->cnf_sec_data.prio_cache ), return EINVAL );
+	}
+
+	/* Set the credentials of this side of the connection */
+	CHECK_GNUTLS_DO( gnutls_credentials_set (*session, GNUTLS_CRD_CERTIFICATE, alt_creds ?: fd_g_config->cnf_sec_data.credentials), return EINVAL );
+
+	/* Request the remote credentials as well */
+	if (mode == GNUTLS_SERVER) {
+		gnutls_certificate_server_set_request (*session, GNUTLS_CERT_REQUIRE);
+	}
+		
+	return 0;
+}
+
+#ifndef GNUTLS_VERSION_300
+
+/* Verify remote credentials after successful handshake (return 0 if OK, EINVAL otherwise) */
+int fd_tls_verify_credentials(gnutls_session_t session, struct cnxctx * conn, int verbose)
+{
+	int i, ret = 0;
+	unsigned int gtret;
+	const gnutls_datum_t *cert_list;
+	unsigned int cert_list_size;
+	gnutls_x509_crt_t cert;
+	time_t now;
+	
+	TRACE_ENTRY("%p %d", conn, verbose);
+	CHECK_PARAMS(conn);
+	
+	/* Trace the session information -- http://www.gnu.org/software/gnutls/manual/gnutls.html#Obtaining-session-information */
+	#ifdef DEBUG
+	if (verbose) {
+		const char *tmp;
+		gnutls_kx_algorithm_t kx;
+  		gnutls_credentials_type_t cred;
+		
+		LOG_D("TLS Session information for connection '%s':", conn->cc_id);
+
+		/* print the key exchange's algorithm name */
+		GNUTLS_TRACE( kx = gnutls_kx_get (session) );
+		GNUTLS_TRACE( tmp = gnutls_kx_get_name (kx) );
+		LOG_D("\t - Key Exchange: %s", tmp);
+
+		/* Check the authentication type used and switch
+		* to the appropriate. */
+		GNUTLS_TRACE( cred = gnutls_auth_get_type (session) );
+		switch (cred)
+		{
+			case GNUTLS_CRD_IA:
+				LOG_D("\t - TLS/IA session");
+				break;
+
+			case GNUTLS_CRD_PSK:
+				/* This returns NULL in server side. */
+				if (gnutls_psk_client_get_hint (session) != NULL)
+					LOG_D("\t - PSK authentication. PSK hint '%s'",
+						gnutls_psk_client_get_hint (session));
+				/* This returns NULL in client side. */
+				if (gnutls_psk_server_get_username (session) != NULL)
+					LOG_D("\t - PSK authentication. Connected as '%s'",
+						gnutls_psk_server_get_username (session));
+				break;
+
+			case GNUTLS_CRD_ANON:	/* anonymous authentication */
+				LOG_D("\t - Anonymous DH using prime of %d bits",
+					gnutls_dh_get_prime_bits (session));
+				break;
+
+			case GNUTLS_CRD_CERTIFICATE:	/* certificate authentication */
+				/* Check if we have been using ephemeral Diffie-Hellman. */
+				if (kx == GNUTLS_KX_DHE_RSA || kx == GNUTLS_KX_DHE_DSS) {
+					LOG_D("\t - Ephemeral DH using prime of %d bits",
+						gnutls_dh_get_prime_bits (session));
+				}
+				break;
+#ifdef ENABLE_SRP				
+			case GNUTLS_CRD_SRP:
+				LOG_D("\t - SRP session with username %s",
+					gnutls_srp_server_get_username (session));
+				break;
+#endif /* ENABLE_SRP */
+
+			default:
+				fd_log_debug("\t - Different type of credentials for the session (%d).", cred);
+				break;
+
+		}
+
+		/* print the protocol's name (ie TLS 1.0) */
+		tmp = gnutls_protocol_get_name (gnutls_protocol_get_version (session));
+		LOG_D("\t - Protocol: %s", tmp);
+
+		/* print the certificate type of the peer. ie X.509 */
+		tmp = gnutls_certificate_type_get_name (gnutls_certificate_type_get (session));
+		LOG_D("\t - Certificate Type: %s", tmp);
+
+		/* print the compression algorithm (if any) */
+		tmp = gnutls_compression_get_name (gnutls_compression_get (session));
+		LOG_D("\t - Compression: %s", tmp);
+
+		/* print the name of the cipher used. ie 3DES. */
+		tmp = gnutls_cipher_get_name (gnutls_cipher_get (session));
+		LOG_D("\t - Cipher: %s", tmp);
+
+		/* Print the MAC algorithms name. ie SHA1 */
+		tmp = gnutls_mac_get_name (gnutls_mac_get (session));
+		LOG_D("\t - MAC: %s", tmp);
+	}
+	#endif /* DEBUG */
+	
+	/* First, use built-in verification */
+	CHECK_GNUTLS_DO( gnutls_certificate_verify_peers2 (session, &gtret), return EINVAL );
+	if (gtret) {
+		LOG_E("TLS: Remote certificate invalid on socket %d (Remote: '%s')(Connection: '%s') :", conn->cc_socket, conn->cc_remid, conn->cc_id);
+		if (gtret & GNUTLS_CERT_INVALID)
+			LOG_E(" - The certificate is not trusted (unknown CA? expired?)");
+		if (gtret & GNUTLS_CERT_REVOKED)
+			LOG_E(" - The certificate has been revoked.");
+		if (gtret & GNUTLS_CERT_SIGNER_NOT_FOUND)
+			LOG_E(" - The certificate hasn't got a known issuer.");
+		if (gtret & GNUTLS_CERT_SIGNER_NOT_CA)
+			LOG_E(" - The certificate signer is not a CA, or uses version 1, or 3 without basic constraints.");
+		if (gtret & GNUTLS_CERT_INSECURE_ALGORITHM)
+			LOG_E(" - The certificate signature uses a weak algorithm.");
+		return EINVAL;
+	}
+	
+	/* Code from http://www.gnu.org/software/gnutls/manual/gnutls.html#Verifying-peer_0027s-certificate */
+	if (gnutls_certificate_type_get (session) != GNUTLS_CRT_X509) {
+		LOG_E("TLS: Remote peer did not present a certificate, other mechanisms are not supported yet. socket %d (Remote: '%s')(Connection: '%s') :", conn->cc_socket, conn->cc_remid, conn->cc_id);
+		return EINVAL;
+	}
+	
+	GNUTLS_TRACE( cert_list = gnutls_certificate_get_peers (session, &cert_list_size) );
+	if (cert_list == NULL)
+		return EINVAL;
+	
+	now = time(NULL);
+	
+	#ifdef DEBUG
+		char serial[40];
+		char dn[128];
+		size_t size;
+		unsigned int algo, bits;
+		time_t expiration_time, activation_time;
+		
+		LOG_D("TLS Certificate information for connection '%s' (%d certs provided):", conn->cc_id, cert_list_size);
+		for (i = 0; i < cert_list_size; i++)
+		{
+
+			CHECK_GNUTLS_DO( gnutls_x509_crt_init (&cert), return EINVAL);
+			CHECK_GNUTLS_DO( gnutls_x509_crt_import (cert, &cert_list[i], GNUTLS_X509_FMT_DER), return EINVAL);
+		
+			LOG_A(" Certificate %d info:", i);
+
+			GNUTLS_TRACE( expiration_time = gnutls_x509_crt_get_expiration_time (cert) );
+			GNUTLS_TRACE( activation_time = gnutls_x509_crt_get_activation_time (cert) );
+
+			LOG( i ? FD_LOG_ANNOYING : FD_LOG_DEBUG, "\t - Certificate is valid since: %.24s", ctime (&activation_time));
+			LOG( i ? FD_LOG_ANNOYING : FD_LOG_DEBUG, "\t - Certificate expires: %.24s", ctime (&expiration_time));
+
+			/* Print the serial number of the certificate. */
+			size = sizeof (serial);
+			gnutls_x509_crt_get_serial (cert, serial, &size);
+			
+			{
+				int j;
+				char buf[1024];
+				snprintf(buf, sizeof(buf), "\t - Certificate serial number: ");
+				for (j = 0; j < size; j++) {
+					snprintf(buf+strlen(buf), sizeof(buf)-strlen(buf), "%02hhx", serial[j]);
+				}
+				LOG( i ? FD_LOG_ANNOYING : FD_LOG_DEBUG, "%s", buf);
+			}
+
+			/* Extract some of the public key algorithm's parameters */
+			GNUTLS_TRACE( algo = gnutls_x509_crt_get_pk_algorithm (cert, &bits) );
+			LOG( i ? FD_LOG_ANNOYING : FD_LOG_DEBUG, "\t - Certificate public key: %s",
+			      gnutls_pk_algorithm_get_name (algo));
+
+			/* Print the version of the X.509 certificate. */
+			LOG( i ? FD_LOG_ANNOYING : FD_LOG_DEBUG, "\t - Certificate version: #%d",
+			      gnutls_x509_crt_get_version (cert));
+
+			size = sizeof (dn);
+			GNUTLS_TRACE( gnutls_x509_crt_get_dn (cert, dn, &size) );
+			LOG( i ? FD_LOG_ANNOYING : FD_LOG_DEBUG, "\t - DN: %s", dn);
+
+			size = sizeof (dn);
+			GNUTLS_TRACE( gnutls_x509_crt_get_issuer_dn (cert, dn, &size) );
+			LOG( i ? FD_LOG_ANNOYING : FD_LOG_DEBUG, "\t - Issuer's DN: %s", dn);
+
+			GNUTLS_TRACE( gnutls_x509_crt_deinit (cert) );
+		}
+	#endif /* DEBUG */
+
+	/* Check validity of all the certificates */
+	for (i = 0; i < cert_list_size; i++)
+	{
+		time_t deadline;
+		
+		CHECK_GNUTLS_DO( gnutls_x509_crt_init (&cert), return EINVAL);
+		CHECK_GNUTLS_DO( gnutls_x509_crt_import (cert, &cert_list[i], GNUTLS_X509_FMT_DER), return EINVAL);
+		
+		GNUTLS_TRACE( deadline = gnutls_x509_crt_get_expiration_time(cert) );
+		if ((deadline != (time_t)-1) && (deadline < now)) {
+			LOG_E("TLS: Remote certificate invalid on socket %d (Remote: '%s')(Connection: '%s') :", conn->cc_socket, conn->cc_remid, conn->cc_id);
+			LOG_E(" - The certificate %d in the chain is expired", i);
+			ret = EINVAL;
+		}
+		
+		GNUTLS_TRACE( deadline = gnutls_x509_crt_get_activation_time(cert) );
+		if ((deadline != (time_t)-1) && (deadline > now)) {
+			LOG_E("TLS: Remote certificate invalid on socket %d (Remote: '%s')(Connection: '%s') :", conn->cc_socket, conn->cc_remid, conn->cc_id);
+			LOG_E(" - The certificate %d in the chain is not yet activated", i);
+			ret = EINVAL;
+		}
+		
+		if ((i == 0) && (conn->cc_tls_para.cn)) {
+			if (!gnutls_x509_crt_check_hostname (cert, conn->cc_tls_para.cn)) {
+				LOG_E("TLS: Remote certificate invalid on socket %d (Remote: '%s')(Connection: '%s') :", conn->cc_socket, conn->cc_remid, conn->cc_id);
+				LOG_E(" - The certificate hostname does not match '%s'", conn->cc_tls_para.cn);
+				ret = EINVAL;
+			}
+		}
+		
+		GNUTLS_TRACE( gnutls_x509_crt_deinit (cert) );
+	}
+
+	return ret;
+}
+
+#else /* GNUTLS_VERSION_300 */
+
+/* Verify remote credentials DURING handshake (return gnutls status) */
+int fd_tls_verify_credentials_2(gnutls_session_t session)
+{
+	/* inspired from gnutls 3.x guidelines */
+	unsigned int status;
+	const gnutls_datum_t *cert_list = NULL;
+	unsigned int cert_list_size;
+	gnutls_x509_crt_t cert;
+	struct cnxctx * conn;
+	int hostname_verified = 0;
+
+	TRACE_ENTRY("%p", session);
+	
+	/* get the associated connection */
+	conn = gnutls_session_get_ptr (session);
+	
+	/* Trace the session information -- http://www.gnu.org/software/gnutls/manual/gnutls.html#Obtaining-session-information */
+#ifdef DEBUG
+		const char *tmp;
+		gnutls_credentials_type_t cred;
+		gnutls_kx_algorithm_t kx;
+		int dhe, ecdh;
+
+		dhe = ecdh = 0;
+
+		LOG_A("TLS Session information for connection '%s':", conn->cc_id);
+		
+		/* print the key exchange's algorithm name
+		*/
+		GNUTLS_TRACE( kx = gnutls_kx_get (session) );
+		GNUTLS_TRACE( tmp = gnutls_kx_get_name (kx) );
+		LOG_D("\t- Key Exchange: %s", tmp);
+
+		/* Check the authentication type used and switch
+		* to the appropriate.
+		*/
+		GNUTLS_TRACE( cred = gnutls_auth_get_type (session) );
+		switch (cred)
+		{
+			case GNUTLS_CRD_IA:
+				LOG_D("\t - TLS/IA session");
+				break;
+
+
+			#ifdef ENABLE_SRP
+			case GNUTLS_CRD_SRP:
+				LOG_D("\t - SRP session with username %s",
+					gnutls_srp_server_get_username (session));
+				break;
+			#endif
+
+			case GNUTLS_CRD_PSK:
+				/* This returns NULL in server side.
+				*/
+				if (gnutls_psk_client_get_hint (session) != NULL)
+					LOG_D("\t - PSK authentication. PSK hint '%s'",
+						gnutls_psk_client_get_hint (session));
+				/* This returns NULL in client side.
+				*/
+				if (gnutls_psk_server_get_username (session) != NULL)
+					LOG_D("\t - PSK authentication. Connected as '%s'",
+						gnutls_psk_server_get_username (session));
+
+				if (kx == GNUTLS_KX_ECDHE_PSK)
+					ecdh = 1;
+				else if (kx == GNUTLS_KX_DHE_PSK)
+					dhe = 1;
+				break;
+
+			case GNUTLS_CRD_ANON:      /* anonymous authentication */
+				LOG_D("\t - Anonymous DH using prime of %d bits",
+					gnutls_dh_get_prime_bits (session));
+				if (kx == GNUTLS_KX_ANON_ECDH)
+					ecdh = 1;
+				else if (kx == GNUTLS_KX_ANON_DH)
+					dhe = 1;
+				break;
+
+			case GNUTLS_CRD_CERTIFICATE:       /* certificate authentication */
+
+				/* Check if we have been using ephemeral Diffie-Hellman.
+				*/
+				if (kx == GNUTLS_KX_DHE_RSA || kx == GNUTLS_KX_DHE_DSS)
+					dhe = 1;
+				else if (kx == GNUTLS_KX_ECDHE_RSA || kx == GNUTLS_KX_ECDHE_ECDSA)
+					ecdh = 1;
+				
+				/* Now print some info on the remote certificate */
+				if (gnutls_certificate_type_get (session) == GNUTLS_CRT_X509) {
+					gnutls_datum_t cinfo;
+
+					cert_list = gnutls_certificate_get_peers (session, &cert_list_size);
+
+					LOG_D("\t Peer provided %d certificates.", cert_list_size);
+
+					if (cert_list_size > 0)
+					{
+						int ret;
+
+						/* we only print information about the first certificate.
+						*/
+						gnutls_x509_crt_init (&cert);
+
+						gnutls_x509_crt_import (cert, &cert_list[0], GNUTLS_X509_FMT_DER);
+
+												LOG_A("\t Certificate info:");
+
+						/* This is the preferred way of printing short information about
+						 a certificate. */
+
+						ret = gnutls_x509_crt_print (cert, GNUTLS_CRT_PRINT_ONELINE, &cinfo);
+						if (ret == 0)
+						{
+						  LOG_D("\t\t%s", cinfo.data);
+						  gnutls_free (cinfo.data);
+						}
+						
+						if (conn->cc_tls_para.cn) {
+							if (!gnutls_x509_crt_check_hostname (cert, conn->cc_tls_para.cn)) {
+								LOG_E("\tTLS: Remote certificate invalid on socket %d (Remote: '%s')(Connection: '%s') :", conn->cc_socket, conn->cc_remid, conn->cc_id);
+								LOG_E("\t - The certificate hostname does not match '%s'", conn->cc_tls_para.cn);
+								gnutls_x509_crt_deinit (cert);
+								return GNUTLS_E_CERTIFICATE_ERROR;
+							}
+							
+						}
+
+						hostname_verified = 1;
+
+						gnutls_x509_crt_deinit (cert);
+
+					}
+    				}
+				break;
+
+			default:
+				LOG_E("\t - unknown session type (%d)", cred);
+
+		}                           /* switch */
+
+		if (ecdh != 0)
+			LOG_D("\t - Ephemeral ECDH using curve %s",
+				gnutls_ecc_curve_get_name (gnutls_ecc_curve_get (session)));
+		else if (dhe != 0)
+			LOG_D("\t - Ephemeral DH using prime of %d bits",
+				gnutls_dh_get_prime_bits (session));
+
+		/* print the protocol's name (ie TLS 1.0) 
+		*/
+		tmp = gnutls_protocol_get_name (gnutls_protocol_get_version (session));
+		LOG_D("\t - Protocol: %s", tmp);
+
+		/* print the certificate type of the peer.
+		* ie X.509
+		*/
+		tmp = gnutls_certificate_type_get_name (gnutls_certificate_type_get (session));
+		LOG_D("\t - Certificate Type: %s", tmp);
+
+		/* print the compression algorithm (if any)
+		*/
+		tmp = gnutls_compression_get_name (gnutls_compression_get (session));
+		LOG_D("\t - Compression: %s", tmp);
+
+		/* print the name of the cipher used.
+		* ie 3DES.
+		*/
+		tmp = gnutls_cipher_get_name (gnutls_cipher_get (session));
+		LOG_D("\t - Cipher: %s", tmp);
+
+		/* Print the MAC algorithms name.
+		* ie SHA1
+		*/
+		tmp = gnutls_mac_get_name (gnutls_mac_get (session));
+		LOG_D("\t - MAC: %s", tmp);
+	
+#endif /* DEBUG */		
+
+	/* This verification function uses the trusted CAs in the credentials
+	* structure. So you must have installed one or more CA certificates.
+	*/
+	CHECK_GNUTLS_DO( gnutls_certificate_verify_peers2 (session, &status), return GNUTLS_E_CERTIFICATE_ERROR );
+	if (status & GNUTLS_CERT_INVALID) {
+		LOG_E("TLS: Remote certificate invalid on socket %d (Remote: '%s')(Connection: '%s') :", conn->cc_socket, conn->cc_remid, conn->cc_id);
+		if (status & GNUTLS_CERT_SIGNER_NOT_FOUND)
+			LOG_E(" - The certificate hasn't got a known issuer.");
+
+		if (status & GNUTLS_CERT_REVOKED)
+			LOG_E(" - The certificate has been revoked.");
+
+		if (status & GNUTLS_CERT_EXPIRED)
+			LOG_E(" - The certificate has expired.");
+
+		if (status & GNUTLS_CERT_NOT_ACTIVATED)
+			LOG_E(" - The certificate is not yet activated.");
+	}	
+	if (status & GNUTLS_CERT_INVALID)
+	{
+		return GNUTLS_E_CERTIFICATE_ERROR;
+	}
+	
+	/* Up to here the process is the same for X.509 certificates and
+	* OpenPGP keys. From now on X.509 certificates are assumed. This can
+	* be easily extended to work with openpgp keys as well.
+	*/
+	if ((!hostname_verified) && (conn->cc_tls_para.cn)) {
+		if (gnutls_certificate_type_get (session) != GNUTLS_CRT_X509) {
+			LOG_E("TLS: Remote credentials are not x509, rejected on socket %d (Remote: '%s')(Connection: '%s') :", conn->cc_socket, conn->cc_remid, conn->cc_id);
+			return GNUTLS_E_CERTIFICATE_ERROR;
+		}
+
+		CHECK_GNUTLS_DO( gnutls_x509_crt_init (&cert), return GNUTLS_E_CERTIFICATE_ERROR );
+
+		cert_list = gnutls_certificate_get_peers (session, &cert_list_size);
+		CHECK_PARAMS_DO( cert_list, return GNUTLS_E_CERTIFICATE_ERROR );
+
+		CHECK_GNUTLS_DO( gnutls_x509_crt_import (cert, &cert_list[0], GNUTLS_X509_FMT_DER), return GNUTLS_E_CERTIFICATE_ERROR );
+
+		if (!gnutls_x509_crt_check_hostname (cert, conn->cc_tls_para.cn)) {
+			LOG_E("TLS: Remote certificate invalid on socket %d (Remote: '%s')(Connection: '%s') :", conn->cc_socket, conn->cc_remid, conn->cc_id);
+			LOG_E(" - The certificate hostname does not match '%s'", conn->cc_tls_para.cn);
+			gnutls_x509_crt_deinit (cert);
+			return GNUTLS_E_CERTIFICATE_ERROR;
+		}
+
+		gnutls_x509_crt_deinit (cert);
+	}
+
+	/* notify gnutls to continue handshake normally */
+	return 0;
+}
+
+#endif /* GNUTLS_VERSION_300 */
+
+static int fd_cnx_may_dtls(struct cnxctx * conn) {
+#ifndef DISABLE_SCTP
+	if ((conn->cc_proto == IPPROTO_SCTP) && (conn->cc_tls_para.algo == ALGO_HANDSHAKE_DEFAULT))
+		return 1;
+#endif /* DISABLE_SCTP */
+	return 0;
+}
+
+#ifndef DISABLE_SCTP
+static int fd_cnx_uses_dtls(struct cnxctx * conn) {
+	return fd_cnx_may_dtls(conn) && (fd_cnx_teststate(conn, CC_STATUS_TLS));
+}
+#endif /* DISABLE_SCTP */
+
+/* TLS handshake a connection; no need to have called start_clear before. Reception is active if handhsake is successful */
+int fd_cnx_handshake(struct cnxctx * conn, int mode, int algo, char * priority, void * alt_creds)
+{
+	int dtls = 0;
+	
+	TRACE_ENTRY( "%p %d %d %p %p", conn, mode, algo, priority, alt_creds);
+	CHECK_PARAMS( conn && (!fd_cnx_teststate(conn, CC_STATUS_TLS)) && ( (mode == GNUTLS_CLIENT) || (mode == GNUTLS_SERVER) ) && (!conn->cc_loop) );
+
+	/* Save the mode */
+	conn->cc_tls_para.mode = mode;
+	conn->cc_tls_para.algo = algo;
+	
+	/* Cancel receiving thread if any -- it should already be terminated anyway, we just release the resources */
+	CHECK_FCT_DO( fd_thr_term(&conn->cc_rcvthr), /* continue */);
+	
+	/* Once TLS handshake is done, we don't stop after the first message */
+	conn->cc_loop = 1;
+	
+	dtls = fd_cnx_may_dtls(conn);
+	
+	/* Prepare the master session credentials and priority */
+	CHECK_FCT( fd_tls_prepare(&conn->cc_tls_para.session, mode, dtls, priority, alt_creds) );
+
+	/* Special case: multi-stream TLS is not natively managed in GNU TLS, we use a wrapper library */
+	if ((!dtls) && (conn->cc_sctp_para.pairs > 1)) {
+#ifdef DISABLE_SCTP
+		ASSERT(0);
+		CHECK_FCT( ENOTSUP );
+#else /* DISABLE_SCTP */
+		/* Initialize the wrapper, start the demux thread */
+		CHECK_FCT( fd_sctp3436_init(conn) );
+#endif /* DISABLE_SCTP */
+	} else {
+		/* Set the transport pointer passed to push & pull callbacks */
+		GNUTLS_TRACE( gnutls_transport_set_ptr( conn->cc_tls_para.session, (gnutls_transport_ptr_t) conn ) );
+
+		/* Set the push and pull callbacks */
+		if (!dtls) {
+			#ifdef GNUTLS_VERSION_300
+			GNUTLS_TRACE( gnutls_transport_set_pull_timeout_function( conn->cc_tls_para.session, (void *)fd_cnx_s_select ) );
+			#endif /* GNUTLS_VERSION_300 */
+			GNUTLS_TRACE( gnutls_transport_set_pull_function(conn->cc_tls_para.session, (void *)fd_cnx_s_recv) );
+			#ifndef GNUTLS_VERSION_212
+			GNUTLS_TRACE( gnutls_transport_set_push_function(conn->cc_tls_para.session, (void *)fd_cnx_s_send) );
+			#else /* GNUTLS_VERSION_212 */
+			GNUTLS_TRACE( gnutls_transport_set_vec_push_function(conn->cc_tls_para.session, (void *)fd_cnx_s_sendv) );
+			#endif /* GNUTLS_VERSION_212 */
+		} else {
+			TODO("DTLS push/pull functions");
+			return ENOTSUP;
+		}
+	}
+	
+	/* additional initialization for gnutls 3.x */
+	#ifdef GNUTLS_VERSION_300
+		/* the verify function has already been set in the global initialization in config.c */
+	
+	/* fd_tls_verify_credentials_2 uses the connection */
+	gnutls_session_set_ptr (conn->cc_tls_para.session, (void *) conn);
+	
+	if ((conn->cc_tls_para.cn != NULL) && (mode == GNUTLS_CLIENT)) {
+		/* this might allow virtual hosting on the remote peer */
+		CHECK_GNUTLS_DO( gnutls_server_name_set (conn->cc_tls_para.session, GNUTLS_NAME_DNS, conn->cc_tls_para.cn, strlen(conn->cc_tls_para.cn)), /* ignore failure */);
+	}
+	
+	#endif /* GNUTLS_VERSION_300 */
+
+	#ifdef GNUTLS_VERSION_310
+	GNUTLS_TRACE( gnutls_handshake_set_timeout( conn->cc_tls_para.session, GNUTLS_DEFAULT_HANDSHAKE_TIMEOUT));
+	#endif /* GNUTLS_VERSION_310 */
+	
+	/* Mark the connection as protected from here, so that the gnutls credentials will be freed */
+	fd_cnx_addstate(conn, CC_STATUS_TLS);
+	
+	/* Handshake master session */
+	{
+		int ret;
+	
+		CHECK_GNUTLS_DO( ret = gnutls_handshake(conn->cc_tls_para.session),
+			{
+				if (TRACE_BOOL(INFO)) {
+					fd_log_debug("TLS Handshake failed on socket %d (%s) : %s", conn->cc_socket, conn->cc_id, gnutls_strerror(ret));
+				}
+				fd_cnx_markerror(conn);
+				return EINVAL;
+			} );
+
+		#ifndef GNUTLS_VERSION_300
+		/* Now verify the remote credentials are valid -- only simple tests here */
+		CHECK_FCT_DO( fd_tls_verify_credentials(conn->cc_tls_para.session, conn, 1), 
+			{  
+				CHECK_GNUTLS_DO( gnutls_bye(conn->cc_tls_para.session, GNUTLS_SHUT_RDWR),  );
+				fd_cnx_markerror(conn);
+				return EINVAL;
+			});
+		#endif /* GNUTLS_VERSION_300 */
+	}
+	
+	/* Multi-stream TLS: handshake other streams as well */
+	if ((!dtls) && (conn->cc_sctp_para.pairs > 1)) {
+#ifndef DISABLE_SCTP
+		/* Start reading the messages from the master session. That way, if the remote peer closed, we are not stuck inside handshake */
+		CHECK_FCT(fd_sctp3436_startthreads(conn, 0));
+
+		/* Resume all additional sessions from the master one. */
+		CHECK_FCT(fd_sctp3436_handshake_others(conn, priority, alt_creds));
+
+		/* Start decrypting the messages from all threads and queuing them in target queue */
+		CHECK_FCT(fd_sctp3436_startthreads(conn, 1));
+#endif /* DISABLE_SCTP */
+	} else {
+		/* Start decrypting the data */
+		if (!dtls) {
+			CHECK_POSIX( pthread_create( &conn->cc_rcvthr, NULL, rcvthr_tls_single, conn ) );
+		} else {
+			TODO("Signal the dtls_push function that multiple streams can be used from this point.");
+			TODO("Create DTLS rcvthr (must reassembly based on seq numbers & stream id ?)");
+			return ENOTSUP;
+		}
+	}
+	
+	return 0;
+}
+
+/* Retrieve TLS credentials of the remote peer, after handshake */
+int fd_cnx_getcred(struct cnxctx * conn, const gnutls_datum_t **cert_list, unsigned int *cert_list_size)
+{
+	TRACE_ENTRY("%p %p %p", conn, cert_list, cert_list_size);
+	CHECK_PARAMS( conn && fd_cnx_teststate(conn, CC_STATUS_TLS) && cert_list && cert_list_size );
+	
+	/* This function only works for X.509 certificates. */
+	CHECK_PARAMS( gnutls_certificate_type_get (conn->cc_tls_para.session) == GNUTLS_CRT_X509 );
+	
+	GNUTLS_TRACE( *cert_list = gnutls_certificate_get_peers (conn->cc_tls_para.session, cert_list_size) );
+	if (*cert_list == NULL) {
+		TRACE_DEBUG(INFO, "No certificate was provided by remote peer / an error occurred.");
+		return EINVAL;
+	}
+
+	TRACE_DEBUG( FULL, "Saved certificate chain (%d certificates) in peer structure.", *cert_list_size);
+	
+	return 0;
+}
+
+/* Receive next message. if timeout is not NULL, wait only until timeout. This function only pulls from a queue, mgr thread is filling that queue aynchrounously. */
+/* if the altfifo has been set on this conn object, this function must not be called */
+int fd_cnx_receive(struct cnxctx * conn, struct timespec * timeout, unsigned char **buf, size_t * len)
+{
+	int    ev;
+	size_t ev_sz;
+	void * ev_data;
+	
+	TRACE_ENTRY("%p %p %p %p", conn, timeout, buf, len);
+	CHECK_PARAMS(conn && (conn->cc_socket > 0) && buf && len);
+	CHECK_PARAMS(conn->cc_rcvthr != (pthread_t)NULL);
+	CHECK_PARAMS(conn->cc_alt == NULL);
+
+	/* Now, pull the first event */
+get_next:
+	if (timeout) {
+		CHECK_FCT( fd_event_timedget(conn->cc_incoming, timeout, FDEVP_PSM_TIMEOUT, &ev, &ev_sz, &ev_data) );
+	} else {
+		CHECK_FCT( fd_event_get(conn->cc_incoming, &ev, &ev_sz, &ev_data) );
+	}
+	
+	switch (ev) {
+		case FDEVP_CNX_MSG_RECV:
+			/* We got one */
+			*len = ev_sz;
+			*buf = ev_data;
+			return 0;
+			
+		case FDEVP_PSM_TIMEOUT:
+			TRACE_DEBUG(FULL, "Timeout event received");
+			return ETIMEDOUT;
+			
+		case FDEVP_CNX_EP_CHANGE:
+			/* We ignore this event */
+			goto get_next;
+			
+		case FDEVP_CNX_ERROR:
+			TRACE_DEBUG(FULL, "Received ERROR event on the connection");
+			return ENOTCONN;
+	}
+	
+	TRACE_DEBUG(INFO, "Received unexpected event %d (%s)", ev, fd_pev_str(ev));
+	return EINVAL;
+}
+
+/* Where the events are sent */
+struct fifo * fd_cnx_target_queue(struct cnxctx * conn)
+{
+	struct fifo *q;
+	CHECK_POSIX_DO( pthread_mutex_lock(&state_lock), { ASSERT(0); } );
+	q = conn->cc_alt ?: conn->cc_incoming;
+	CHECK_POSIX_DO( pthread_mutex_unlock(&state_lock), { ASSERT(0); } );
+	return q;
+}
+
+/* Set an alternate FIFO list to send FDEVP_CNX_* events to */
+int fd_cnx_recv_setaltfifo(struct cnxctx * conn, struct fifo * alt_fifo)
+{
+	int ret;
+	TRACE_ENTRY( "%p %p", conn, alt_fifo );
+	CHECK_PARAMS( conn && alt_fifo && conn->cc_incoming );
+	
+	/* The magic function does it all */
+	CHECK_POSIX_DO( pthread_mutex_lock(&state_lock), { ASSERT(0); } );
+	CHECK_FCT_DO( ret = fd_fifo_move( conn->cc_incoming, alt_fifo, &conn->cc_alt ), );
+	CHECK_POSIX_DO( pthread_mutex_unlock(&state_lock), { ASSERT(0); } );
+	
+	return ret;
+}
+
+/* Send function when no multi-stream is involved, or sending on stream #0 (send() always use stream 0)*/
+static int send_simple(struct cnxctx * conn, unsigned char * buf, size_t len)
+{
+	ssize_t ret;
+	size_t sent = 0;
+	TRACE_ENTRY("%p %p %zd", conn, buf, len);
+	do {
+		if (fd_cnx_teststate(conn, CC_STATUS_TLS)) {
+			CHECK_GNUTLS_DO( ret = fd_tls_send_handle_error(conn, conn->cc_tls_para.session, buf + sent, len - sent),  );
+		} else {
+			struct iovec iov;
+			iov.iov_base = buf + sent;
+			iov.iov_len  = len - sent;
+			CHECK_SYS_DO( ret = fd_cnx_s_sendv(conn, &iov, 1), );
+		}
+		if (ret <= 0)
+			return ENOTCONN;
+		
+		sent += ret;
+	} while ( sent < len );
+	return 0;
+}
+
+/* Send a message -- this is synchronous -- and we assume it's never called by several threads at the same time (on the same conn), so we don't protect. */
+int fd_cnx_send(struct cnxctx * conn, unsigned char * buf, size_t len)
+{
+	TRACE_ENTRY("%p %p %zd", conn, buf, len);
+	
+	CHECK_PARAMS(conn && (conn->cc_socket > 0) && (! fd_cnx_teststate(conn, CC_STATUS_ERROR)) && buf && len);
+
+	TRACE_DEBUG(FULL, "Sending %zdb %sdata on connection %s", len, fd_cnx_teststate(conn, CC_STATUS_TLS) ? "TLS-protected ":"", conn->cc_id);
+	
+	switch (conn->cc_proto) {
+		case IPPROTO_TCP:
+			CHECK_FCT( send_simple(conn, buf, len) );
+			break;
+		
+#ifndef DISABLE_SCTP
+		case IPPROTO_SCTP: {
+			int dtls = fd_cnx_uses_dtls(conn);
+			if (!dtls) {
+				int stream = 0;
+				if (conn->cc_sctp_para.unordered) {
+					int limit;
+					if (fd_cnx_teststate(conn, CC_STATUS_TLS))
+						limit = conn->cc_sctp_para.pairs;
+					else
+						limit = conn->cc_sctp_para.str_out;
+					
+					if (limit > 1) {
+						conn->cc_sctp_para.next += 1;
+						conn->cc_sctp_para.next %= limit;
+						stream = conn->cc_sctp_para.next;
+					}
+				}
+				
+				if (stream == 0) {
+					/* We can use default function, it sends over stream #0 */
+					CHECK_FCT( send_simple(conn, buf, len) );
+				} else {
+					if (!fd_cnx_teststate(conn, CC_STATUS_TLS)) {
+						struct iovec iov;
+						iov.iov_base = buf;
+						iov.iov_len  = len;
+						
+						CHECK_SYS_DO( fd_sctp_sendstrv(conn, stream, &iov, 1), { fd_cnx_markerror(conn); return ENOTCONN; } );
+					} else {
+						/* push the data to the appropriate session */
+						ssize_t ret;
+						size_t sent = 0;
+						ASSERT(conn->cc_sctp3436_data.array != NULL);
+						do {
+							CHECK_GNUTLS_DO( ret = fd_tls_send_handle_error(conn, conn->cc_sctp3436_data.array[stream].session, buf + sent, len - sent), );
+							if (ret <= 0)
+								return ENOTCONN;
+
+							sent += ret;
+						} while ( sent < len );
+					}
+				}
+			} else {
+				/* DTLS */
+				/* Multistream is handled at lower layer in the push/pull function */
+				CHECK_FCT( send_simple(conn, buf, len) );
+			}
+		}
+		break;
+#endif /* DISABLE_SCTP */
+	
+		default:
+			TRACE_DEBUG(INFO, "Unknown protocol: %d", conn->cc_proto);
+			ASSERT(0);
+			return ENOTSUP;	/* or EINVAL... */
+	}
+	
+	return 0;
+}
+
+
+/**************************************/
+/*     Destruction of connection      */
+/**************************************/
+
+/* Destroy a conn structure, and shutdown the socket */
+void fd_cnx_destroy(struct cnxctx * conn)
+{
+	TRACE_ENTRY("%p", conn);
+	
+	CHECK_PARAMS_DO(conn, return);
+	
+	fd_cnx_addstate(conn, CC_STATUS_CLOSING);
+	
+	/* Initiate shutdown of the TLS session(s): call gnutls_bye(WR), then read until error */
+	if (fd_cnx_teststate(conn, CC_STATUS_TLS)) {
+#ifndef DISABLE_SCTP
+		int dtls = fd_cnx_uses_dtls(conn);
+		if ((!dtls) && (conn->cc_sctp_para.pairs > 1)) {
+			if (! fd_cnx_teststate(conn, CC_STATUS_ERROR )) {
+				/* Bye on master session */
+				CHECK_GNUTLS_DO( gnutls_bye(conn->cc_tls_para.session, GNUTLS_SHUT_WR), fd_cnx_markerror(conn) );
+			}
+
+			if (! fd_cnx_teststate(conn, CC_STATUS_ERROR ) ) {
+				/* and other stream pairs */
+				fd_sctp3436_bye(conn);
+			}
+
+			if (! fd_cnx_teststate(conn, CC_STATUS_ERROR ) ) {
+				/* Now wait for all decipher threads to terminate */
+				fd_sctp3436_waitthreadsterm(conn);
+			} else {
+				/* Abord the threads, the connection is dead already */
+				fd_sctp3436_stopthreads(conn);
+			}
+
+			/* Deinit gnutls resources */
+			fd_sctp3436_gnutls_deinit_others(conn);
+			if (conn->cc_tls_para.session) {
+				GNUTLS_TRACE( gnutls_deinit(conn->cc_tls_para.session) );
+				conn->cc_tls_para.session = NULL;
+			}
+			
+			/* Destroy the wrapper (also stops the demux thread) */
+			fd_sctp3436_destroy(conn);
+
+		} else {
+#endif /* DISABLE_SCTP */
+		/* We are TLS, but not using the sctp3436 wrapper layer */
+			if (! fd_cnx_teststate(conn, CC_STATUS_ERROR ) ) {
+				/* Master session */
+				CHECK_GNUTLS_DO( gnutls_bye(conn->cc_tls_para.session, GNUTLS_SHUT_WR), fd_cnx_markerror(conn) );
+			}
+
+			if (! fd_cnx_teststate(conn, CC_STATUS_ERROR ) ) {
+				/* In this case, just wait for thread rcvthr_tls_single to terminate */
+				if (conn->cc_rcvthr != (pthread_t)NULL) {
+					CHECK_POSIX_DO(  pthread_join(conn->cc_rcvthr, NULL), /* continue */  );
+					conn->cc_rcvthr = (pthread_t)NULL;
+				}
+			} else {
+				/* Cancel the receiver thread in case it did not already terminate */
+				CHECK_FCT_DO( fd_thr_term(&conn->cc_rcvthr), /* continue */ );
+			}
+			
+			/* Free the resources of the TLS session */
+			if (conn->cc_tls_para.session) {
+				GNUTLS_TRACE( gnutls_deinit(conn->cc_tls_para.session) );
+				conn->cc_tls_para.session = NULL;
+			}
+#ifndef DISABLE_SCTP
+		}
+#endif /* DISABLE_SCTP */
+	}
+	
+	/* Terminate the thread in case it is not done yet -- is there any such case left ?*/
+	CHECK_FCT_DO( fd_thr_term(&conn->cc_rcvthr), /* continue */ );
+		
+	/* Shut the connection down */
+	if (conn->cc_socket > 0) {
+		shutdown(conn->cc_socket, SHUT_RDWR);
+		close(conn->cc_socket);
+		conn->cc_socket = -1;
+	}
+	
+	/* Empty and destroy FIFO list */
+	if (conn->cc_incoming) {
+		fd_event_destroy( &conn->cc_incoming, free );
+	}
+	
+	/* Free the object */
+	free(conn);
+	
+	/* Done! */
+	return;
+}
diff --git a/libfdcore/cnxctx.h b/libfdcore/cnxctx.h
new file mode 100644
index 0000000..dcc4bea
--- /dev/null
+++ b/libfdcore/cnxctx.h
@@ -0,0 +1,153 @@
+/*********************************************************************************************************
+* Software License Agreement (BSD License)                                                               *
+* Author: Sebastien Decugis <sdecugis@freediameter.net>							 *
+*													 *
+* Copyright (c) 2013, WIDE Project and NICT								 *
+* All rights reserved.											 *
+* 													 *
+* Redistribution and use of this software in source and binary forms, with or without modification, are  *
+* permitted provided that the following conditions are met:						 *
+* 													 *
+* * Redistributions of source code must retain the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer.										 *
+*    													 *
+* * Redistributions in binary form must reproduce the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer in the documentation and/or other						 *
+*   materials provided with the distribution.								 *
+* 													 *
+* * Neither the name of the WIDE Project or NICT nor the 						 *
+*   names of its contributors may be used to endorse or 						 *
+*   promote products derived from this software without 						 *
+*   specific prior written permission of WIDE Project and 						 *
+*   NICT.												 *
+* 													 *
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED *
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
+* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR *
+* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 	 *
+* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 	 *
+* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR *
+* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF   *
+* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.								 *
+*********************************************************************************************************/
+
+/* This file contains the definitions for internal use in the connection context files */
+
+#ifndef _CNXCTX_H
+#define _CNXCTX_H
+
+/* Maximum time we allow a connection to be blocked because of head-of-the-line buffers. After this delay, connection is considered in error. */
+#define MAX_HOTL_BLOCKING_TIME	1000	/* ms */
+
+/* The connection context structure */
+struct cnxctx {
+	char		cc_id[60];	/* The name of this connection. the first 5 chars are reserved for flags display (cc_state). */
+	char		cc_remid[60];	/* Id of remote peer */
+	
+	int 		cc_socket;	/* The socket object of the connection -- <=0 if no socket is created */
+
+	int 		cc_family;	/* AF_INET or AF_INET6 (mixed) */
+	int 		cc_proto;	/* IPPROTO_TCP or IPPROTO_SCTP */
+	
+	uint32_t	cc_state;	/* True if the object is being destroyed: we don't send events anymore. access with fd_cnx_getstate() */
+	#define 	CC_STATUS_CLOSING	1
+	#define 	CC_STATUS_ERROR		2
+	#define 	CC_STATUS_SIGNALED	4
+	#define 	CC_STATUS_TLS		8
+
+	pthread_t	cc_rcvthr;	/* thread for receiving messages on the connection */
+	int		cc_loop;	/* tell the thread if it loops or stops after the first message is received */
+	
+	struct fifo *	cc_incoming;	/* FIFO queue of events received on the connection, FDEVP_CNX_* */
+	struct fifo *	cc_alt;		/* alternate fifo to send FDEVP_CNX_* events to. */
+
+	/* If cc_tls == true */
+	struct {
+		DiamId_t 			 cn;		/* If not NULL, remote certif will be checked to match this Common Name */
+		int				 mode; 		/* GNUTLS_CLIENT / GNUTLS_SERVER */
+		int				 algo;		/* ALGO_HANDSHAKE_DEFAULT / ALGO_HANDSHAKE_3436 */
+		gnutls_session_t 		 session;	/* Session object (stream #0 in case of SCTP) */
+	}		cc_tls_para;
+
+	/* If cc_proto == SCTP */
+	struct	{
+		uint16_t str_out;	/* Out streams */
+		uint16_t str_in;	/* In streams */
+		uint16_t pairs;		/* max number of pairs ( = min(in, out)) */
+		uint16_t next;		/* # of stream the next message will be sent to */
+		int	 unordered;	/* boolean telling if use of streams > 0 is permitted */
+	} 		cc_sctp_para;
+
+	/* If both conditions */
+	struct {
+		struct sctp3436_ctx *array; /* an array of cc_sctp_para.pairs elements -- the #0 is special (session is outside)*/
+		struct sr_store	 *sess_store; /* Session data of the master session, to resume the children sessions */
+	} 		cc_sctp3436_data;
+};
+
+void fd_cnx_markerror(struct cnxctx * conn);
+uint32_t fd_cnx_getstate(struct cnxctx * conn);
+int  fd_cnx_teststate(struct cnxctx * conn, uint32_t flag);
+void fd_cnx_addstate(struct cnxctx * conn, uint32_t orstate);
+void fd_cnx_setstate(struct cnxctx * conn, uint32_t abstate);
+struct fifo * fd_cnx_target_queue(struct cnxctx * conn);
+
+
+/* Socket */
+ssize_t fd_cnx_s_recv(struct cnxctx * conn, void *buffer, size_t length);
+void fd_cnx_s_setto(int sock);
+
+/* TLS */
+int fd_tls_rcvthr_core(struct cnxctx * conn, gnutls_session_t session);
+int fd_tls_prepare(gnutls_session_t * session, int mode, int dtls, char * priority, void * alt_creds);
+#ifndef GNUTLS_VERSION_300
+int fd_tls_verify_credentials(gnutls_session_t session, struct cnxctx * conn, int verbose);
+#endif /* GNUTLS_VERSION_300 */
+
+/* TCP */
+int fd_tcp_create_bind_server( int * sock, sSA * sa, socklen_t salen );
+int fd_tcp_listen( int sock );
+int fd_tcp_client( int *sock, sSA * sa, socklen_t salen );
+int fd_tcp_get_local_ep(int sock, sSS * ss, socklen_t *sl);
+int fd_tcp_get_remote_ep(int sock, sSS * ss, socklen_t *sl);
+
+#ifndef DISABLE_SCTP
+/* SCTP */
+int fd_sctp_create_bind_server( int * sock, int family, struct fd_list * list, uint16_t port );
+int fd_sctp_listen( int sock );
+int fd_sctp_client( int *sock, int no_ip6, uint16_t port, struct fd_list * list );
+int fd_sctp_get_local_ep(int sock,  struct fd_list * list);
+int fd_sctp_get_remote_ep(int sock, struct fd_list * list);
+int fd_sctp_get_str_info( int sock, uint16_t *in, uint16_t *out, sSS *primary );
+ssize_t fd_sctp_sendstrv(struct cnxctx * conn, uint16_t strid, const struct iovec *iov, int iovcnt);
+int fd_sctp_recvmeta(struct cnxctx * conn, uint16_t * strid, uint8_t ** buf, size_t * len, int *event);
+
+/* TLS over SCTP (multi-stream) */
+struct sctp3436_ctx {
+	struct cnxctx 	*parent; 	/* for info such as socket, conn name, event list */
+	uint16_t	 strid;		/* Stream # of this session */
+	struct fifo	*raw_recv;	/* Raw data received on this stream, for demux */
+	struct {
+		uint8_t *buf;
+		size_t   bufsz;
+		size_t   offset;
+	} 		 partial;	/* If the pull function did not read the full content of first message in raw, it stores it here for next read call. */
+	pthread_t	 thr;		/* Thread to decrypt raw data in this pair of streams */
+	gnutls_session_t session;	/* TLS context using this pair of streams -- except if strid == 0, in that case session is outside the array */
+};
+
+int fd_sctp3436_init(struct cnxctx * conn);
+int fd_sctp3436_handshake_others(struct cnxctx * conn, char * priority, void * alt_creds);
+int fd_sctp3436_startthreads(struct cnxctx * conn, int others);
+void fd_sctp3436_bye(struct cnxctx * conn);
+void fd_sctp3436_waitthreadsterm(struct cnxctx * conn);
+void fd_sctp3436_gnutls_deinit_others(struct cnxctx * conn);
+void fd_sctp3436_stopthreads(struct cnxctx * conn);
+void fd_sctp3436_destroy(struct cnxctx * conn);
+
+#endif /* DISABLE_SCTP */
+
+#endif /* _CNXCTX_H */
+
diff --git a/libfdcore/config.c b/libfdcore/config.c
new file mode 100644
index 0000000..2a1a063
--- /dev/null
+++ b/libfdcore/config.c
@@ -0,0 +1,644 @@
+/*********************************************************************************************************
+* Software License Agreement (BSD License)                                                               *
+* Author: Sebastien Decugis <sdecugis@freediameter.net>							 *
+*													 *
+* Copyright (c) 2015, WIDE Project and NICT								 *
+* All rights reserved.											 *
+* 													 *
+* Redistribution and use of this software in source and binary forms, with or without modification, are  *
+* permitted provided that the following conditions are met:						 *
+* 													 *
+* * Redistributions of source code must retain the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer.										 *
+*    													 *
+* * Redistributions in binary form must reproduce the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer in the documentation and/or other						 *
+*   materials provided with the distribution.								 *
+* 													 *
+* * Neither the name of the WIDE Project or NICT nor the 						 *
+*   names of its contributors may be used to endorse or 						 *
+*   promote products derived from this software without 						 *
+*   specific prior written permission of WIDE Project and 						 *
+*   NICT.												 *
+* 													 *
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED *
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
+* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR *
+* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 	 *
+* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 	 *
+* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR *
+* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF   *
+* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.								 *
+*********************************************************************************************************/
+
+#include "fdcore-internal.h"
+#include <sys/stat.h>
+
+/* Configuration management */
+
+#ifndef GNUTLS_DEFAULT_PRIORITY
+# define GNUTLS_DEFAULT_PRIORITY "NORMAL"
+#endif /* GNUTLS_DEFAULT_PRIORITY */
+#ifndef GNUTLS_DEFAULT_DHBITS
+# define GNUTLS_DEFAULT_DHBITS 1024
+#endif /* GNUTLS_DEFAULT_DHBITS */
+
+/* Initialize the fd_g_config structure to default values -- it should already have been initialized to all-0 */
+int fd_conf_init()
+{
+	TRACE_ENTRY();
+	
+	fd_g_config->cnf_eyec = EYEC_CONFIG;
+	
+	fd_g_config->cnf_timer_tc = 30;
+	fd_g_config->cnf_timer_tw = 30;
+	
+	fd_g_config->cnf_port     = DIAMETER_PORT;
+	fd_g_config->cnf_port_tls = DIAMETER_SECURE_PORT;
+	fd_g_config->cnf_sctp_str = 30;
+	fd_g_config->cnf_thr_srv  = 5;
+	fd_g_config->cnf_dispthr  = 4;
+	fd_list_init(&fd_g_config->cnf_endpoints, NULL);
+	fd_list_init(&fd_g_config->cnf_apps, NULL);
+	#ifdef DISABLE_SCTP
+	fd_g_config->cnf_flags.no_sctp = 1;
+	#endif /* DISABLE_SCTP */
+	
+	fd_g_config->cnf_orstateid = (uint32_t) time(NULL);
+	
+	CHECK_FCT( fd_dict_init(&fd_g_config->cnf_dict) );
+	CHECK_FCT( fd_fifo_new(&fd_g_config->cnf_main_ev, 0) );
+	
+	/* TLS parameters */
+	CHECK_GNUTLS_DO( gnutls_certificate_allocate_credentials (&fd_g_config->cnf_sec_data.credentials), return ENOMEM );
+	CHECK_GNUTLS_DO( gnutls_dh_params_init (&fd_g_config->cnf_sec_data.dh_cache), return ENOMEM );
+#ifdef GNUTLS_VERSION_300
+	CHECK_GNUTLS_DO( gnutls_x509_trust_list_init(&fd_g_config->cnf_sec_data.trustlist, 0), return ENOMEM );
+#endif /* GNUTLS_VERSION_300 */
+
+	return 0;
+}
+
+DECLARE_FD_DUMP_PROTOTYPE(fd_conf_dump)
+{
+	FD_DUMP_HANDLE_OFFSET();
+	
+	CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "freeDiameter configuration:\n"), return NULL);	
+	CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "  Default trace level .... : %+d\n", fd_g_debug_lvl), return NULL);
+	CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "  Configuration file ..... : %s\n", fd_g_config->cnf_file), return NULL);
+	CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "  Diameter Identity ...... : %s (l:%zi)\n", fd_g_config->cnf_diamid, fd_g_config->cnf_diamid_len), return NULL);
+	CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "  Diameter Realm ......... : %s (l:%zi)\n", fd_g_config->cnf_diamrlm, fd_g_config->cnf_diamrlm_len), return NULL);
+	CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "  Tc Timer ............... : %u\n", fd_g_config->cnf_timer_tc), return NULL);
+	CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "  Tw Timer ............... : %u\n", fd_g_config->cnf_timer_tw), return NULL);
+	CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "  Local port ............. : %hu\n", fd_g_config->cnf_port), return NULL);
+	CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "  Local secure port ...... : %hu\n", fd_g_config->cnf_port_tls), return NULL);
+	if (fd_g_config->cnf_port_3436) {
+		CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "  Local SCTP TLS port .... : %hu\n", fd_g_config->cnf_port_3436), return NULL);
+	}
+	CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "  Number of SCTP streams . : %hu\n", fd_g_config->cnf_sctp_str), return NULL);
+	CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "  Number of clients thr .. : %d\n", fd_g_config->cnf_thr_srv), return NULL);
+	CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "  Number of app threads .. : %hu\n", fd_g_config->cnf_dispthr), return NULL);
+	if (FD_IS_LIST_EMPTY(&fd_g_config->cnf_endpoints)) {
+		CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "  Local endpoints ........ : Default (use all available)\n"), return NULL);
+	} else {
+		CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "  Local endpoints ........ : "), return NULL);
+		CHECK_MALLOC_DO( fd_ep_dump( FD_DUMP_STD_PARAMS, 0, 0, &fd_g_config->cnf_endpoints ), return NULL);
+	}
+	if (FD_IS_LIST_EMPTY(&fd_g_config->cnf_apps)) {
+		CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "  Local applications ..... : (none)"), return NULL);
+	} else {
+		struct fd_list * li = fd_g_config->cnf_apps.next;
+		CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "  Local applications ..... : "), return NULL);
+		while (li != &fd_g_config->cnf_apps) {
+			struct fd_app * app = (struct fd_app *)li;
+			CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "App: %u,%s%s,Vnd:%u\t", 
+					app->appid,
+					app->flags.auth ? "Au" : "--",
+					app->flags.acct ? "Ac" : "--",
+					app->vndid), return NULL);
+			li = li->next;
+		}
+	}
+	
+	CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "\n  Flags : - IP ........... : %s\n", fd_g_config->cnf_flags.no_ip4 ? "DISABLED" : "Enabled"), return NULL);
+	CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "          - IPv6 ......... : %s\n", fd_g_config->cnf_flags.no_ip6 ? "DISABLED" : "Enabled"), return NULL);
+	CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "          - Relay app .... : %s\n", fd_g_config->cnf_flags.no_fwd ? "DISABLED" : "Enabled"), return NULL);
+	CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "          - TCP .......... : %s\n", fd_g_config->cnf_flags.no_tcp ? "DISABLED" : "Enabled"), return NULL);
+	#ifdef DISABLE_SCTP
+	CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "          - SCTP ......... : DISABLED (at compilation)\n"), return NULL);
+	#else /* DISABLE_SCTP */
+	CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "          - SCTP ......... : %s\n", fd_g_config->cnf_flags.no_sctp ? "DISABLED" : "Enabled"), return NULL);
+	#endif /* DISABLE_SCTP */
+	CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "          - Pref. proto .. : %s\n", fd_g_config->cnf_flags.pr_tcp ? "TCP" : "SCTP"), return NULL);
+	CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "          - TLS method ... : %s\n", fd_g_config->cnf_flags.tls_alg ? "INBAND" : "Separate port"), return NULL);
+	
+	CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "  TLS :   - Certificate .. : %s\n", fd_g_config->cnf_sec_data.cert_file ?: "(NONE)"), return NULL);
+	CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "          - Private key .. : %s\n", fd_g_config->cnf_sec_data.key_file ?: "(NONE)"), return NULL);
+	CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "          - CA (trust) ... : %s (%d certs)\n", fd_g_config->cnf_sec_data.ca_file ?: "(none)", fd_g_config->cnf_sec_data.ca_file_nr), return NULL);
+	CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "          - CRL .......... : %s\n", fd_g_config->cnf_sec_data.crl_file ?: "(none)"), return NULL);
+	CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "          - Priority ..... : %s\n", fd_g_config->cnf_sec_data.prio_string ?: "(default: '" GNUTLS_DEFAULT_PRIORITY "')"), return NULL);
+	if (fd_g_config->cnf_sec_data.dh_file) {
+		CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "          - DH file ...... : %s\n", fd_g_config->cnf_sec_data.dh_file), return NULL);
+	} else {
+		CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "          - DH bits ...... : %d\n", fd_g_config->cnf_sec_data.dh_bits ?: GNUTLS_DEFAULT_DHBITS), return NULL);
+	}
+	
+	CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "  Origin-State-Id ........ : %u", fd_g_config->cnf_orstateid), return NULL);
+	
+	return *buf;
+}
+
+/* read contents of a file opened in "rb" mode and alloc this data into a gnutls_datum_t (must be freed afterwards) */
+int fd_conf_stream_to_gnutls_datum(FILE * pemfile, gnutls_datum_t *out)
+{
+	size_t alloc = 0;
+	
+	CHECK_PARAMS( pemfile && out );
+	memset(out, 0, sizeof(gnutls_datum_t));
+
+	do {
+		uint8_t * realloced = NULL;
+		size_t read = 0;
+
+		if (alloc < out->size + BUFSIZ + 1) {
+			alloc += alloc / 2 + BUFSIZ + 1;
+			CHECK_MALLOC_DO( realloced = realloc(out->data, alloc),
+				{
+					free(out->data);
+					return ENOMEM;
+				} )
+			out->data = realloced;
+		}
+
+		read = fread( out->data + out->size, 1, alloc - out->size - 1, pemfile );
+		out->size += read;
+
+		if (ferror(pemfile)) {
+			int err = errno;
+			TRACE_DEBUG(INFO, "An error occurred while reading file: %s", strerror(err));
+			return err; 
+		}
+	} while (!feof(pemfile));
+	
+	out->data[out->size] = '\0';
+	return 0;
+}
+
+#ifdef GNUTLS_VERSION_300
+/* inspired from GnuTLS manual */
+static int fd_conf_print_details_func (gnutls_x509_crt_t cert,
+                    gnutls_x509_crt_t issuer, gnutls_x509_crl_t crl,
+                    unsigned int verification_output)
+{
+  char name[512];
+  char issuer_name[512];
+  size_t name_size;
+  size_t issuer_name_size;
+  
+  if (!TRACE_BOOL(GNUTLS_DBG_LEVEL))
+	  return 0;
+
+  issuer_name_size = sizeof (issuer_name);
+  gnutls_x509_crt_get_issuer_dn (cert, issuer_name, &issuer_name_size);
+
+  name_size = sizeof (name);
+  gnutls_x509_crt_get_dn (cert, name, &name_size);
+
+  fd_log_debug("\tSubject: %s", name);
+  fd_log_debug("\tIssuer: %s", issuer_name);
+
+  if (issuer != NULL)
+    {
+      issuer_name_size = sizeof (issuer_name);
+      gnutls_x509_crt_get_dn (issuer, issuer_name, &issuer_name_size);
+
+      fd_log_debug("\tVerified against: %s", issuer_name);
+    }
+
+  if (crl != NULL)
+    {
+      issuer_name_size = sizeof (issuer_name);
+      gnutls_x509_crl_get_issuer_dn (crl, issuer_name, &issuer_name_size);
+
+      fd_log_debug("\tVerified against CRL of: %s", issuer_name);
+    }
+
+  fd_log_debug("\tVerification output: %x", verification_output);
+
+  return 0;
+}
+#endif /* GNUTLS_VERSION_300 */
+
+#ifndef GNUTLS_VERSION_300
+GCC_DIAG_OFF("-Wdeprecated-declarations")
+#endif /* !GNUTLS_VERSION_300 */
+/* Parse the configuration file (using the yacc parser) */
+int fd_conf_parse()
+{
+	extern FILE * fddin;
+	const char * orig = NULL;
+	
+	/* Attempt to find the configuration file */
+	if (!fd_g_config->cnf_file)
+		fd_g_config->cnf_file = FD_DEFAULT_CONF_FILENAME;
+	
+	fddin = fopen(fd_g_config->cnf_file, "r");
+	if ((fddin == NULL) && (*fd_g_config->cnf_file != '/')) {
+		char * new_cnf = NULL;
+		/* We got a relative path, attempt to add the default directory prefix */
+		orig = fd_g_config->cnf_file;
+		CHECK_MALLOC( new_cnf = malloc(strlen(orig) + strlen(DEFAULT_CONF_PATH) + 2) ); /* we will not free it, but not important */
+		sprintf( new_cnf, DEFAULT_CONF_PATH "/%s", orig );
+		fd_g_config->cnf_file = new_cnf;
+		fddin = fopen(fd_g_config->cnf_file, "r");
+	}
+	if (fddin == NULL) {
+		int ret = errno;
+		LOG_F("Unable to open configuration file for reading; tried the following locations: %s%s%s; Error: %s",
+				  orig ?: "", orig? " and " : "", fd_g_config->cnf_file, strerror(ret));
+		return ret;
+	}
+	
+	/* call yacc parser */
+	TRACE_DEBUG (FULL, "Parsing configuration file: %s", fd_g_config->cnf_file);
+	CHECK_FCT(  fddparse(fd_g_config)  );
+	
+	/* close the file */
+	fclose(fddin);
+	
+	/* Check that TLS private key was given */
+	if (! fd_g_config->cnf_sec_data.key_file) {
+		/* If TLS is not enabled, we allow empty TLS configuration */
+		if ((fd_g_config->cnf_port_tls == 0) && (fd_g_config->cnf_flags.tls_alg == 0)) {
+			LOG_N("TLS is disabled, this is *NOT* a recommended practice! Diameter protocol conveys highly sensitive information on your users.");
+			fd_g_config->cnf_sec_data.tls_disabled = 1;
+		} else {
+			LOG_F( "Missing private key configuration for TLS. Please provide the TLS_cred configuration directive.");
+			return EINVAL;
+		}
+	}
+	
+	/* Resolve hostname if not provided */
+	if (fd_g_config->cnf_diamid == NULL) {
+		char buf[HOST_NAME_MAX + 1];
+		struct addrinfo hints, *info;
+		int ret;
+		
+		/* local host name */
+		CHECK_SYS(gethostname(buf, sizeof(buf)));
+		
+		/* get FQDN */
+		memset(&hints, 0, sizeof hints);
+		hints.ai_flags = AI_CANONNAME;
+
+		ret = getaddrinfo(buf, NULL, &hints, &info);
+		if (ret != 0) {
+			TRACE_ERROR( "Error resolving local FQDN : '%s' : %s"
+					". Please provide Identity in configuration file.",
+					buf, gai_strerror(ret));
+			return EINVAL;
+		}
+		fd_g_config->cnf_diamid = info->ai_canonname;
+		CHECK_FCT( fd_os_validate_DiameterIdentity(&fd_g_config->cnf_diamid, &fd_g_config->cnf_diamid_len, 1) );
+		freeaddrinfo(info);
+	} else {
+		CHECK_FCT( fd_os_validate_DiameterIdentity(&fd_g_config->cnf_diamid, &fd_g_config->cnf_diamid_len, 0) );
+	}
+	
+	/* Handle the realm part */
+	if (fd_g_config->cnf_diamrlm == NULL) {
+		char * start = NULL;
+		
+		/* Check the diameter identity is a fqdn */
+		start = strchr(fd_g_config->cnf_diamid, '.');
+		if ((start == NULL) || (start[1] == '\0')) {
+			TRACE_ERROR( "Unable to extract realm from the Identity '%s'."
+					" Please fix your Identity setting or provide Realm.",
+					fd_g_config->cnf_diamid);
+			return EINVAL;
+		}
+		
+		fd_g_config->cnf_diamrlm = start + 1;
+		CHECK_FCT( fd_os_validate_DiameterIdentity(&fd_g_config->cnf_diamrlm, &fd_g_config->cnf_diamrlm_len, 1) );
+	} else {
+		CHECK_FCT( fd_os_validate_DiameterIdentity(&fd_g_config->cnf_diamrlm, &fd_g_config->cnf_diamrlm_len, 0) );
+	}
+	
+	/* Validate some flags */
+	if (fd_g_config->cnf_flags.no_ip4 && fd_g_config->cnf_flags.no_ip6) {
+		TRACE_ERROR( "IP and IPv6 cannot be disabled at the same time.");
+		return EINVAL;
+	}
+	if (fd_g_config->cnf_flags.no_tcp && fd_g_config->cnf_flags.no_sctp) {
+		TRACE_ERROR( "TCP and SCTP cannot be disabled at the same time.");
+		return EINVAL;
+	}
+	
+	/* Validate local endpoints */
+	if ((!FD_IS_LIST_EMPTY(&fd_g_config->cnf_endpoints)) && (fd_g_config->cnf_flags.no_ip4 || fd_g_config->cnf_flags.no_ip6)) {
+		struct fd_list * li;
+		for ( li = fd_g_config->cnf_endpoints.next; li != &fd_g_config->cnf_endpoints; li = li->next) {
+			struct fd_endpoint * ep = (struct fd_endpoint *)li;
+			if ( (fd_g_config->cnf_flags.no_ip4 && (ep->sa.sa_family == AF_INET))
+			   ||(fd_g_config->cnf_flags.no_ip6 && (ep->sa.sa_family == AF_INET6)) ) {
+				char sa_buf[sSA_DUMP_STRLEN];;
+				li = li->prev;
+				fd_list_unlink(&ep->chain);
+				fd_sa_sdump_numeric(sa_buf, &ep->sa);
+				LOG_N("Info: Removing local address conflicting with the flags no_IP / no_IP6 : %s", sa_buf);
+				free(ep);
+			}
+		}
+	}
+	
+	/* Configure TLS default parameters */
+	if ((!fd_g_config->cnf_sec_data.tls_disabled) && (!fd_g_config->cnf_sec_data.prio_string)) {
+		const char * err_pos = NULL;
+		CHECK_GNUTLS_DO( gnutls_priority_init( 
+					&fd_g_config->cnf_sec_data.prio_cache,
+					GNUTLS_DEFAULT_PRIORITY,
+					&err_pos),
+				 { TRACE_ERROR("Error in priority string at position : %s", err_pos); return EINVAL; } );
+	}
+	
+	/* Verify that our certificate is valid -- otherwise remote peers will reject it */
+	if (!fd_g_config->cnf_sec_data.tls_disabled) {
+		int ret = 0, i;
+		
+		gnutls_datum_t certfile;
+		
+		gnutls_x509_crt_t * certs = NULL;
+		unsigned int cert_max = 0;
+		
+		
+		/* Read the certificate file */
+		FILE *stream = fopen (fd_g_config->cnf_sec_data.cert_file, "rb");
+		if (!stream) {
+			int err = errno;
+			TRACE_DEBUG(INFO, "An error occurred while opening '%s': %s", fd_g_config->cnf_sec_data.cert_file, strerror(err));
+			return err; 
+		}
+		CHECK_FCT( fd_conf_stream_to_gnutls_datum(stream, &certfile) );
+		fclose(stream);
+		
+		/* Import the certificate(s) */
+		GNUTLS_TRACE( ret = gnutls_x509_crt_list_import(NULL, &cert_max, &certfile, GNUTLS_X509_FMT_PEM, GNUTLS_X509_CRT_LIST_IMPORT_FAIL_IF_EXCEED) );
+		if (ret != GNUTLS_E_SHORT_MEMORY_BUFFER) {
+			CHECK_GNUTLS_DO(ret, return EINVAL);
+		}
+		
+		CHECK_MALLOC( certs = calloc(cert_max, sizeof(gnutls_x509_crt_t)) );
+		CHECK_GNUTLS_DO( gnutls_x509_crt_list_import(certs, &cert_max, &certfile, GNUTLS_X509_FMT_PEM, 
+				#ifdef GNUTLS_VERSION_300
+				GNUTLS_X509_CRT_LIST_FAIL_IF_UNSORTED
+				#else /* GNUTLS_VERSION_300 */
+				0
+				#endif /* GNUTLS_VERSION_300 */
+				),
+			{
+				TRACE_ERROR("Failed to import the data from file '%s'", fd_g_config->cnf_sec_data.cert_file);
+				free(certfile.data);
+				return EINVAL;
+			} );
+		free(certfile.data);
+		
+		ASSERT(cert_max >= 1);
+		
+		/* Now, verify the list against the local CA and CRL */
+		
+		#ifdef GNUTLS_VERSION_300
+		
+			/* We use the trust list for this purpose */
+		{
+			unsigned int output;
+			
+			gnutls_x509_trust_list_verify_named_crt (
+						fd_g_config->cnf_sec_data.trustlist, 
+						certs[0], 
+						fd_g_config->cnf_diamid, 
+						fd_g_config->cnf_diamid_len,
+                                		0,
+                                		&output, 
+						fd_conf_print_details_func);
+
+			/* if this certificate is not explicitly trusted verify against CAs 
+			*/
+			if (output != 0)
+			{
+				gnutls_x509_trust_list_verify_crt (
+							fd_g_config->cnf_sec_data.trustlist, 
+							certs, 
+							cert_max,
+                                			0,
+                                			&output, 
+							fd_conf_print_details_func);
+			}
+			
+			if (output & GNUTLS_CERT_INVALID)
+			{
+				fd_log_debug("TLS: Local certificate chain '%s' is invalid :", fd_g_config->cnf_sec_data.cert_file);
+				if (output & GNUTLS_CERT_SIGNER_NOT_FOUND)
+					TRACE_ERROR(" - The certificate hasn't got a known issuer. Did you forget to specify TLS_CA ?");
+				if (output & GNUTLS_CERT_SIGNER_NOT_CA)
+					TRACE_ERROR(" - The certificate signer is not a CA, or uses version 1, or 3 without basic constraints.");
+				if (output & GNUTLS_CERT_NOT_ACTIVATED)
+					TRACE_ERROR(" - The certificate is not yet activated.");
+				if (output & GNUTLS_CERT_EXPIRED)
+					TRACE_ERROR(" - The certificate is expired.");
+				return EINVAL;
+			}
+			
+			/* Now check the subject matches our hostname */
+			if (!gnutls_x509_crt_check_hostname (certs[0], fd_g_config->cnf_diamid))
+			{
+				TRACE_ERROR("TLS: The certificate owner does not match the hostname '%s'", fd_g_config->cnf_diamid);
+				return EINVAL;
+			}
+			
+		}
+		
+
+		#else /* GNUTLS_VERSION_300 */ 
+		
+			/* GnuTLS 2.x way of checking certificates */
+		{
+			gnutls_x509_crt_t * CA_list;
+			int CA_list_length;
+
+			gnutls_x509_crl_t * CRL_list;
+			int CRL_list_length;
+			
+			unsigned int verify;
+			time_t now;
+			GNUTLS_TRACE( gnutls_certificate_get_x509_cas (fd_g_config->cnf_sec_data.credentials, &CA_list, (unsigned int *) &CA_list_length) );
+			GNUTLS_TRACE( gnutls_certificate_get_x509_crls (fd_g_config->cnf_sec_data.credentials, &CRL_list, (unsigned int *) &CRL_list_length) );
+			CHECK_GNUTLS_DO( gnutls_x509_crt_list_verify(certs, cert_max, CA_list, CA_list_length, CRL_list, CRL_list_length, 0, &verify),
+				{
+					TRACE_ERROR("Failed to verify the local certificate '%s' against local credentials. Please check your certificate is valid.", fd_g_config->cnf_sec_data.cert_file);
+					return EINVAL;
+				} );
+				
+			if (verify) {
+				fd_log_debug("TLS: Local certificate chain '%s' is invalid :", fd_g_config->cnf_sec_data.cert_file);
+				if (verify & GNUTLS_CERT_INVALID)
+					TRACE_ERROR(" - The certificate is not trusted (unknown CA? expired?)");
+				if (verify & GNUTLS_CERT_REVOKED)
+					TRACE_ERROR(" - The certificate has been revoked.");
+				if (verify & GNUTLS_CERT_SIGNER_NOT_FOUND)
+					TRACE_ERROR(" - The certificate hasn't got a known issuer.");
+				if (verify & GNUTLS_CERT_SIGNER_NOT_CA)
+					TRACE_ERROR(" - The certificate signer is not a CA, or uses version 1, or 3 without basic constraints.");
+				if (verify & GNUTLS_CERT_INSECURE_ALGORITHM)
+					TRACE_ERROR(" - The certificate signature uses a weak algorithm.");
+				return EINVAL;
+			}
+
+			/* Check the local Identity is valid with the certificate */
+			if (!gnutls_x509_crt_check_hostname (certs[0], fd_g_config->cnf_diamid)) {
+				TRACE_ERROR("TLS: Local certificate '%s' is invalid :", fd_g_config->cnf_sec_data.cert_file);
+				TRACE_ERROR(" - The certificate hostname does not match '%s'", fd_g_config->cnf_diamid);
+				return EINVAL;
+			}
+
+			/* Check validity of all the certificates in the chain */
+			now = time(NULL);
+			for (i = 0; i < cert_max; i++)
+			{
+				time_t deadline;
+
+				GNUTLS_TRACE( deadline = gnutls_x509_crt_get_expiration_time(certs[i]) );
+				if ((deadline != (time_t)-1) && (deadline < now)) {
+					TRACE_ERROR("TLS: Local certificate chain '%s' is invalid :", fd_g_config->cnf_sec_data.cert_file);
+					TRACE_ERROR(" - The certificate %d in the chain is expired", i);
+					return EINVAL;
+				}
+
+				GNUTLS_TRACE( deadline = gnutls_x509_crt_get_activation_time(certs[i]) );
+				if ((deadline != (time_t)-1) && (deadline > now)) {
+					TRACE_ERROR("TLS: Local certificate chain '%s' is invalid :", fd_g_config->cnf_sec_data.cert_file);
+					TRACE_ERROR(" - The certificate %d in the chain is not yet activated", i);
+					return EINVAL;
+				}
+			}
+		}
+		#endif /* GNUTLS_VERSION_300 */ 
+		
+		/* Everything checked OK, free the certificate list */
+		for (i = 0; i < cert_max; i++)
+		{
+			GNUTLS_TRACE( gnutls_x509_crt_deinit (certs[i]) );
+		}
+		free(certs);
+	
+		#ifdef GNUTLS_VERSION_300
+		/* Use certificate verification during the handshake */
+		gnutls_certificate_set_verify_function (fd_g_config->cnf_sec_data.credentials, fd_tls_verify_credentials_2);
+		#endif /* GNUTLS_VERSION_300 */
+
+	}
+	
+	/* gnutls_certificate_set_verify_limits -- so far the default values are fine... */
+	
+	/* DH */
+	if (!fd_g_config->cnf_sec_data.tls_disabled) {
+		if (fd_g_config->cnf_sec_data.dh_file) {
+			gnutls_datum_t dhparams = { NULL, 0 };
+			size_t alloc = 0;
+			FILE *stream = fopen (fd_g_config->cnf_sec_data.dh_file, "rb");
+			if (!stream) {
+				int err = errno;
+				TRACE_DEBUG(INFO, "An error occurred while opening '%s': %s", fd_g_config->cnf_sec_data.dh_file, strerror(err));
+				return err; 
+			}
+			do {
+				uint8_t * realloced = NULL;
+				size_t read = 0;
+
+				if (alloc < dhparams.size + BUFSIZ + 1) {
+					alloc += alloc / 2 + BUFSIZ + 1;
+					CHECK_MALLOC_DO( realloced = realloc(dhparams.data, alloc),
+						{
+							free(dhparams.data);
+							return ENOMEM;
+						} )
+					dhparams.data = realloced;
+				}
+
+				read = fread( dhparams.data + dhparams.size, 1, alloc - dhparams.size - 1, stream );
+				dhparams.size += read;
+
+				if (ferror(stream)) {
+					int err = errno;
+					TRACE_DEBUG(INFO, "An error occurred while reading '%s': %s", fd_g_config->cnf_sec_data.dh_file, strerror(err));
+					return err; 
+				}
+			} while (!feof(stream));
+			dhparams.data[dhparams.size] = '\0';
+			fclose(stream);
+			CHECK_GNUTLS_DO( gnutls_dh_params_import_pkcs3( 
+						fd_g_config->cnf_sec_data.dh_cache,
+						&dhparams,
+						GNUTLS_X509_FMT_PEM),
+						 { TRACE_ERROR("Error in DH bits value : %d", fd_g_config->cnf_sec_data.dh_bits ?: GNUTLS_DEFAULT_DHBITS); return EINVAL; } );
+			free(dhparams.data);
+
+		} else {
+			LOG_D( "Generating fresh Diffie-Hellman parameters of size %d (this takes some time)... ", fd_g_config->cnf_sec_data.dh_bits ?: GNUTLS_DEFAULT_DHBITS);
+			CHECK_GNUTLS_DO( gnutls_dh_params_generate2( 
+						fd_g_config->cnf_sec_data.dh_cache,
+						fd_g_config->cnf_sec_data.dh_bits ?: GNUTLS_DEFAULT_DHBITS),
+						 { TRACE_ERROR("Error in DH bits value : %d", fd_g_config->cnf_sec_data.dh_bits ?: GNUTLS_DEFAULT_DHBITS); return EINVAL; } );
+		}			
+	
+	}
+	
+	return 0;
+}
+#ifndef GNUTLS_VERSION_300
+GCC_DIAG_ON("-Wdeprecated-declarations")
+#endif /* !GNUTLS_VERSION_300 */
+
+
+/* Destroy contents of fd_g_config structure */
+int fd_conf_deinit()
+{
+	TRACE_ENTRY();
+	
+	if (!fd_g_config)
+		return 0;
+	
+	/* Free the TLS parameters */
+#ifdef GNUTLS_VERSION_300
+	gnutls_x509_trust_list_deinit(fd_g_config->cnf_sec_data.trustlist, 1);
+#endif /* GNUTLS_VERSION_300 */
+	gnutls_priority_deinit(fd_g_config->cnf_sec_data.prio_cache);
+	gnutls_dh_params_deinit(fd_g_config->cnf_sec_data.dh_cache);
+	gnutls_certificate_free_credentials(fd_g_config->cnf_sec_data.credentials);
+	
+	free(fd_g_config->cnf_sec_data.cert_file); fd_g_config->cnf_sec_data.cert_file = NULL;
+	free(fd_g_config->cnf_sec_data.key_file); fd_g_config->cnf_sec_data.key_file = NULL;
+	free(fd_g_config->cnf_sec_data.ca_file); fd_g_config->cnf_sec_data.ca_file = NULL;
+	free(fd_g_config->cnf_sec_data.crl_file); fd_g_config->cnf_sec_data.crl_file = NULL;
+	free(fd_g_config->cnf_sec_data.prio_string); fd_g_config->cnf_sec_data.prio_string = NULL;
+	free(fd_g_config->cnf_sec_data.dh_file); fd_g_config->cnf_sec_data.dh_file = NULL;
+	
+	/* Destroy dictionary */
+	CHECK_FCT_DO( fd_dict_fini(&fd_g_config->cnf_dict), );
+	
+	/* Destroy the main event queue */
+	CHECK_FCT_DO( fd_fifo_del(&fd_g_config->cnf_main_ev), );
+	
+	/* Destroy the local endpoints and applications */
+	CHECK_FCT_DO(fd_ep_filter(&fd_g_config->cnf_endpoints, 0 ), );
+	CHECK_FCT_DO(fd_app_empty(&fd_g_config->cnf_apps ), );
+	
+	/* Destroy the local identity */	
+	free(fd_g_config->cnf_diamid); fd_g_config->cnf_diamid = NULL;
+	free(fd_g_config->cnf_diamrlm); fd_g_config->cnf_diamrlm = NULL;
+	
+	return 0;
+}
+
+
diff --git a/libfdcore/core.c b/libfdcore/core.c
new file mode 100644
index 0000000..23909b7
--- /dev/null
+++ b/libfdcore/core.c
@@ -0,0 +1,373 @@
+/*********************************************************************************************************
+* Software License Agreement (BSD License)                                                               *
+* Author: Sebastien Decugis <sdecugis@freediameter.net>							 *
+*													 *
+* Copyright (c) 2013, WIDE Project and NICT								 *
+* All rights reserved.											 *
+* 													 *
+* Redistribution and use of this software in source and binary forms, with or without modification, are  *
+* permitted provided that the following conditions are met:						 *
+* 													 *
+* * Redistributions of source code must retain the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer.										 *
+*    													 *
+* * Redistributions in binary form must reproduce the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer in the documentation and/or other						 *
+*   materials provided with the distribution.								 *
+* 													 *
+* * Neither the name of the WIDE Project or NICT nor the 						 *
+*   names of its contributors may be used to endorse or 						 *
+*   promote products derived from this software without 						 *
+*   specific prior written permission of WIDE Project and 						 *
+*   NICT.												 *
+* 													 *
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED *
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
+* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR *
+* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 	 *
+* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 	 *
+* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR *
+* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF   *
+* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.								 *
+*********************************************************************************************************/
+
+#include "fdcore-internal.h"
+
+GCC_DIAG_OFF("-Wdeprecated-declarations")
+#include <gcrypt.h>
+GCC_DIAG_ON("-Wdeprecated-declarations")
+
+/* The static configuration structure */
+static struct fd_config g_conf;
+struct fd_config * fd_g_config = NULL;
+
+/* gcrypt functions to support posix threads */
+#ifndef GNUTLS_VERSION_210
+GCRY_THREAD_OPTION_PTHREAD_IMPL;
+#endif /* GNUTLS_VERSION_210 */
+
+/* Thread that process incoming events on the main queue -- and terminates the framework when requested */
+static pthread_t core_runner = (pthread_t)NULL;
+
+/* Signal extensions when the framework is completely initialized (they are waiting in fd_core_waitstartcomplete()) */
+static enum core_state {
+	CORE_NOT_INIT,	/* initial state */
+	CORE_LIBS_INIT,	/* fd_core_initialize was called */
+	CORE_CONF_READY,/* Configuration was parsed, extensions are loaded */
+	CORE_RUNNING,	/* Servers and clients are started, core_runner thread is running */
+	CORE_SHUTDOWN,	/* The framework is terminating all objects */
+	CORE_TERM	/* Shutdown complete. */	
+} core_state = CORE_NOT_INIT;
+static pthread_mutex_t core_mtx = PTHREAD_MUTEX_INITIALIZER;
+static pthread_cond_t  core_cnd = PTHREAD_COND_INITIALIZER;
+
+static enum core_state core_state_get(void)
+{
+	enum core_state cur_state;
+	CHECK_POSIX_DO( pthread_mutex_lock( &core_mtx ), );
+	cur_state = core_state;
+	CHECK_POSIX_DO( pthread_mutex_unlock( &core_mtx ), );
+	return cur_state;
+}
+
+static void core_state_set(enum core_state newstate)
+{
+	CHECK_POSIX_DO( pthread_mutex_lock( &core_mtx ), );
+	LOG_D("Core state: %d -> %d", core_state, newstate);
+	core_state = newstate;
+	CHECK_POSIX_DO( pthread_cond_broadcast( &core_cnd ), );
+	CHECK_POSIX_DO( pthread_mutex_unlock( &core_mtx ), );
+}
+
+static int core_state_wait(enum core_state waitstate)
+{
+	int ret = 0;
+	CHECK_POSIX( pthread_mutex_lock( &core_mtx ));
+	pthread_cleanup_push( fd_cleanup_mutex, &core_mtx );
+	while (waitstate > core_state) {
+		CHECK_POSIX_DO(ret = pthread_cond_wait(&core_cnd, &core_mtx), break);
+	}
+	pthread_cleanup_pop( 0 );
+	CHECK_POSIX( pthread_mutex_unlock( &core_mtx ));
+	return ret;
+}
+
+static void core_shutdown(void)
+{
+	LOG_N( FD_PROJECT_BINARY " framework is stopping...");
+	fd_log_threadname("fD Core Shutdown");
+	
+	/* cleanups */
+	CHECK_FCT_DO( fd_servers_stop(), /* Stop accepting new connections */ );
+	CHECK_FCT_DO( fd_rtdisp_cleanstop(), /* Stop dispatch thread(s) after a clean loop if possible */ );
+	CHECK_FCT_DO( fd_peer_fini(), /* Stop all connections */ );
+	CHECK_FCT_DO( fd_rtdisp_fini(), /* Stop routing threads and destroy routing queues */ );
+	
+	CHECK_FCT_DO( fd_ext_term(), /* Cleanup all extensions */ );
+	CHECK_FCT_DO( fd_rtdisp_cleanup(), /* destroy remaining handlers */ );
+	
+	GNUTLS_TRACE( gnutls_global_deinit() );
+	
+	CHECK_FCT_DO( fd_conf_deinit(), );
+	
+	CHECK_FCT_DO( fd_event_trig_fini(), );
+	
+	fd_log_debug(FD_PROJECT_BINARY " framework is terminated.");
+	
+	fd_libproto_fini();
+	
+}	
+
+
+static void * core_runner_thread(void * arg) 
+{
+	fd_log_threadname("fD Core Runner");
+	
+	core_state_wait(CORE_RUNNING);
+	
+	/* Handle events incoming on the main event queue */
+	while (1) {
+		int code; size_t sz; void * data;
+		CHECK_FCT_DO(  fd_event_get(fd_g_config->cnf_main_ev, &code, &sz, &data),  break  );
+		switch (code) {
+			case FDEV_TRIGGER:
+				{
+					int tv, *p;
+					CHECK_PARAMS_DO( sz == sizeof(int), 
+						{
+							TRACE_DEBUG(NONE, "Internal error: got FDEV_TRIGGER without trigger value!");
+							ASSERT(0);
+							goto end;
+						} );
+					p = data;
+					tv = *p;
+					free(p);
+					CHECK_FCT_DO( fd_event_trig_call_cb(tv), goto end );
+				}
+				break;
+			
+			case FDEV_TERMINATE_INT:
+				goto end;
+			
+			default:
+				TRACE_DEBUG(INFO, "Unexpected event in the main event queue (%d), ignored.", code);
+		}
+	}
+	
+end:
+	core_shutdown();
+	
+	return NULL;
+}
+
+/*********************************/
+/* Public interfaces */
+
+/* Initialize the libfdcore internals. This also initializes libfdproto */
+int fd_core_initialize(void)
+{
+	int ret;
+	
+	if (core_state_get() != CORE_NOT_INIT) {
+		fprintf(stderr, "fd_core_initialize() called more than once!\n");
+		return EINVAL;
+	}
+	
+	/* Initialize the library -- must come first since it initializes the debug facility */
+	ret = fd_libproto_init();
+	if (ret != 0) {
+		fprintf(stderr, "Unable to initialize libfdproto: %s\n", strerror(ret));
+		return ret;
+	}
+	
+	/* Name this thread */
+	fd_log_threadname("Main");
+	
+	LOG_N("libfdproto '%s' initialized.", fd_libproto_version);
+	
+	/* Initialize gcrypt and gnutls */
+	#ifndef GNUTLS_VERSION_210
+	GNUTLS_TRACE( (void) gcry_control (GCRYCTL_SET_THREAD_CBS, &gcry_threads_pthread) );
+	GNUTLS_TRACE( (void) gcry_control (GCRYCTL_ENABLE_QUICK_RANDOM, 0) );
+	#endif /* GNUTLS_VERSION_210 */
+	CHECK_GNUTLS_DO( gnutls_global_init(), return EINVAL );
+	if ( ! gnutls_check_version(GNUTLS_VERSION) ) {
+		TRACE_ERROR( "The GNUTLS library is too old; found '%s', need '" GNUTLS_VERSION "'", gnutls_check_version(NULL));
+		return EINVAL;
+	} else {
+	#ifdef GNUTLS_VERSION_210
+		TRACE_DEBUG(INFO, "libgnutls '%s' initialized.", gnutls_check_version(NULL) );
+	#else /* GNUTLS_VERSION_210 */
+		TRACE_DEBUG(INFO, "libgnutls '%s', libgcrypt '%s', initialized.", gnutls_check_version(NULL), gcry_check_version(NULL) );
+	#endif /* GNUTLS_VERSION_210 */
+	}
+	
+	/* Initialize the config with default values */
+	memset(&g_conf, 0, sizeof(struct fd_config));
+	fd_g_config = &g_conf;
+	CHECK_FCT( fd_conf_init() );
+	
+	/* Add definitions of the base protocol */
+	CHECK_FCT( fd_dict_base_protocol(fd_g_config->cnf_dict) );
+	
+	/* Initialize some modules */
+	CHECK_FCT( fd_hooks_init()  );
+	CHECK_FCT( fd_queues_init() );
+	CHECK_FCT( fd_sess_start()  );
+	CHECK_FCT( fd_p_expi_init() );
+	
+	core_state_set(CORE_LIBS_INIT);
+	
+	LOG_N("libfdcore '%s' initialized.", fd_core_version);
+	
+	
+	/* Next thing is to parse the config, leave this for a different function */
+	return 0;
+}
+
+static pthread_mutex_t core_lock = PTHREAD_MUTEX_INITIALIZER;
+
+/* Parse the freeDiameter.conf configuration file, load the extensions */
+static int fd_core_parseconf_int(const char * conffile)
+{
+	char * buf = NULL, *b;
+	size_t len = 0, offset=0;
+	
+	
+	TRACE_ENTRY("%p", conffile);
+	
+	/* Conf file */
+	if (conffile)
+		fd_g_config->cnf_file = conffile; /* otherwise, we use the default name */
+	
+	CHECK_FCT( fd_conf_parse() );
+	
+	/* The following module use data from the configuration */
+	CHECK_FCT( fd_rtdisp_init() );
+	
+	/* Now, load all dynamic extensions */
+	CHECK_FCT(  fd_ext_load()  );
+	
+	/* Display configuration */
+	b = fd_conf_dump(&buf, &len, NULL);
+	LOG_SPLIT(FD_LOG_NOTICE, NULL, b ?: "<Error during configuration dump...>", NULL);
+	
+	/* Display extensions status */
+	b = fd_ext_dump(&buf, &len, NULL);
+	LOG_SPLIT(FD_LOG_NOTICE, "Loaded extensions: ", b?:"<Error during extensions dump...>", NULL);
+	
+	/* Display registered triggers for FDEV_TRIGGER */
+	b = fd_event_trig_dump(&buf, &len, &offset);
+	if (!b || offset) {
+		LOG_N("%s", b ?: "Error during triggers dump...");
+	}
+	
+	free(buf);	
+		
+	/* Since some extensions might have modified the definitions from the dict_base_protocol, we only load the objects now */
+	CHECK_FCT( fd_msg_init()    );
+	
+	/* Ok, ready for next step */
+	core_state_set(CORE_CONF_READY);
+	
+	return 0;
+}
+
+int fd_core_parseconf(const char * conffile)
+{
+	int ret;
+	CHECK_POSIX( pthread_mutex_lock(&core_lock) );
+	ret = fd_core_parseconf_int(conffile);
+	CHECK_POSIX( pthread_mutex_unlock(&core_lock) );
+	return ret;
+}
+
+
+/* For threads that would need to wait complete start of the framework (ex: in extensions) */
+int fd_core_waitstartcomplete(void)
+{
+	TRACE_ENTRY("");
+	
+	return core_state_wait(CORE_RUNNING);
+}
+
+/* Start the server & client threads */
+static int fd_core_start_int(void)
+{
+	/* Start server threads */ 
+	CHECK_FCT( fd_servers_start() );
+	
+	/* Start the peer state machines */
+	CHECK_FCT( fd_psm_start() );
+	
+	/* Start the core runner thread that handles main events (until shutdown) */
+	CHECK_POSIX( pthread_create(&core_runner, NULL, core_runner_thread, NULL) );
+	
+	/* Unlock threads waiting into fd_core_waitstartcomplete */
+	core_state_set(CORE_RUNNING);
+	
+	/* Ok, everything is running now... */
+	return 0;
+}
+
+int fd_core_start(void)
+{
+	int ret;
+	CHECK_POSIX( pthread_mutex_lock(&core_lock) );
+	ret = fd_core_start_int();
+	CHECK_POSIX( pthread_mutex_unlock(&core_lock) );
+	return ret;
+}
+
+/* Initialize shutdown of the framework. This is not blocking. */
+int fd_core_shutdown(void)
+{
+	enum core_state cur_state = core_state_get();
+	
+	LOG_F("Initiating freeDiameter shutdown sequence (%d)", cur_state);
+		
+	if (cur_state < CORE_RUNNING) {
+		/* Calling application must make sure the initialization is not ongoing in a separate thread... */
+		if (pthread_mutex_lock(&core_lock) != 0) {
+			/* This function must not be called asynchronously from fd_core_parseconf / fd_core_start ! Please review your main app design */
+			ASSERT(0);
+			return EINVAL;
+		}
+		core_shutdown();
+		core_state_set(CORE_TERM);
+		pthread_mutex_unlock(&core_lock);
+	} else if (cur_state == CORE_RUNNING) {
+		core_state_set(CORE_SHUTDOWN);
+		CHECK_FCT( fd_event_send(fd_g_config->cnf_main_ev, FDEV_TERMINATE_INT, 0, NULL) );
+	}
+	
+	/* Other case, the framework is already shutting down */
+	
+	return 0;
+}
+
+
+/* Wait for the shutdown to be complete -- this must be called after fd_core_shutdown to reclaim some resources. */
+int fd_core_wait_shutdown_complete(void)
+{
+	enum core_state cur_state = core_state_get();
+	void * th_ret = NULL;
+	
+	CHECK_FCT(core_state_wait(CORE_SHUTDOWN));
+	
+	if (cur_state == CORE_TERM)
+		return 0;
+	
+	/* Just wait for core_runner_thread to complete and return gracefully */
+	CHECK_POSIX(pthread_join(core_runner, &th_ret));
+
+	core_state_set(CORE_TERM);
+		
+	return 0;
+}
+
+
+
+
diff --git a/libfdcore/dict_base_proto.c b/libfdcore/dict_base_proto.c
new file mode 100644
index 0000000..5c023f6
--- /dev/null
+++ b/libfdcore/dict_base_proto.c
@@ -0,0 +1,3347 @@
+/*********************************************************************************************************
+* Software License Agreement (BSD License)                                                               *
+* Author: Sebastien Decugis <sdecugis@freediameter.net>							 *
+*													 *
+* Copyright (c) 2013, WIDE Project and NICT								 *
+* All rights reserved.											 *
+* 													 *
+* Redistribution and use of this software in source and binary forms, with or without modification, are  *
+* permitted provided that the following conditions are met:						 *
+* 													 *
+* * Redistributions of source code must retain the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer.										 *
+*    													 *
+* * Redistributions in binary form must reproduce the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer in the documentation and/or other						 *
+*   materials provided with the distribution.								 *
+* 													 *
+* * Neither the name of the WIDE Project or NICT nor the 						 *
+*   names of its contributors may be used to endorse or 						 *
+*   promote products derived from this software without 						 *
+*   specific prior written permission of WIDE Project and 						 *
+*   NICT.												 *
+* 													 *
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED *
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
+* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR *
+* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 	 *
+* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 	 *
+* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR *
+* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF   *
+* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.								 *
+*********************************************************************************************************/
+
+/* Diameter Base protocol definitions.
+ */
+
+#include "fdcore-internal.h"
+
+#include <netinet/in.h>
+#include <sys/socket.h>
+
+/* The pointer for the global dictionary (initialized from main) */
+struct dictionary * fd_g_dict = NULL;
+
+
+
+#define CHECK_dict_new( _type, _data, _parent, _ref )				\
+	CHECK_FCT(  fd_dict_new( dict, (_type), (_data), (_parent), (_ref))  );
+
+#define CHECK_dict_search( _type, _criteria, _what, _result )					\
+	CHECK_FCT(  fd_dict_search( dict, (_type), (_criteria), (_what), (_result), ENOENT)  );
+
+struct local_rules_definition {
+	char 			*avp_name;
+	enum rule_position	position;
+	int 			min;
+	int			max;
+};
+
+#define RULE_ORDER( _position ) ((((_position) == RULE_FIXED_HEAD) || ((_position) == RULE_FIXED_TAIL)) ? 1 : 0 )
+
+#define PARSE_loc_rules( _rulearray, _parent) {						\
+	int __ar;									\
+	for (__ar=0; __ar < sizeof(_rulearray) / sizeof((_rulearray)[0]); __ar++) {	\
+		struct dict_rule_data __data = { NULL, 					\
+			(_rulearray)[__ar].position,					\
+			0, 								\
+			(_rulearray)[__ar].min,						\
+			(_rulearray)[__ar].max};					\
+		__data.rule_order = RULE_ORDER(__data.rule_position);			\
+		CHECK_FCT(  fd_dict_search( 						\
+			dict,								\
+			DICT_AVP, 							\
+			AVP_BY_NAME, 							\
+			(_rulearray)[__ar].avp_name, 					\
+			&__data.rule_avp, 0 ) );					\
+		if ( !__data.rule_avp ) {						\
+			TRACE_DEBUG(INFO, "AVP Not found: '%s'", (_rulearray)[__ar].avp_name );	\
+			return ENOENT;							\
+		}									\
+		CHECK_FCT_DO( fd_dict_new( dict, DICT_RULE, &__data, _parent, NULL),	\
+			{								\
+				TRACE_DEBUG(INFO, "Error on rule with AVP '%s'",	\
+					 (_rulearray)[__ar].avp_name );			\
+				return EINVAL;						\
+			} );								\
+	}										\
+}
+
+int fd_dict_base_protocol(struct dictionary * dict)
+{
+	TRACE_ENTRY("%p", dict);
+	CHECK_PARAMS(dict);
+	
+	/* Vendors section */
+	{
+		/* The base RFC has no vendor information */
+		;
+	}
+	
+	/* Applications section */
+	{
+		/* base accounting application */
+		{
+			struct dict_application_data data = {          3, "Diameter Base Accounting" 	};
+			CHECK_dict_new( DICT_APPLICATION, &data, NULL, NULL);
+		}
+		
+		/* relay application */
+		{
+			struct dict_application_data data  = { 0xffffffff, "Relay" 				};
+			#if AI_RELAY != 0xffffffff
+			#error "AI_RELAY definition mismatch"
+			#endif
+			CHECK_dict_new( DICT_APPLICATION, &data , NULL, NULL);
+		}
+	}
+	
+	/* Derived AVP types section */
+	{
+		/* Address */
+		{
+			/*
+				The Address format is derived from the OctetString AVP Base
+				Format.  It is a discriminated union, representing, for example a
+				32-bit (IPv4) [RFC791] or 128-bit (IPv6) [RFC4291] address, most
+				significant octet first.  The first two octets of the Address AVP
+				represents the AddressType, which contains an Address Family
+				defined in [IANAADFAM].  The AddressType is used to discriminate
+				the content and format of the remaining octets.
+			*/
+			struct dict_type_data data = { AVP_TYPE_OCTETSTRING,	"Address"		, fd_dictfct_Address_interpret	, fd_dictfct_Address_encode,	fd_dictfct_Address_dump	};
+			CHECK_dict_new( DICT_TYPE, &data , NULL, NULL);
+		}
+		
+		/* Time */
+		{
+			/*
+				The Time format is derived from the OctetString AVP Base Format.
+				The string MUST contain four octets, in the same format as the
+				first four bytes are in the NTP timestamp format.  The NTP
+				Timestamp format is defined in chapter 3 of [RFC4330].
+
+				This represents the number of seconds since 0h on 1 January 1900
+				with respect to the Coordinated Universal Time (UTC).
+
+				On 6h 28m 16s UTC, 7 February 2036 the time value will overflow.
+				SNTP [RFC4330] describes a procedure to extend the time to 2104.
+				This procedure MUST be supported by all DIAMETER nodes.
+			*/
+			struct dict_type_data data = { AVP_TYPE_OCTETSTRING,	"Time"			, fd_dictfct_Time_interpret	, fd_dictfct_Time_encode, 	fd_dictfct_Time_dump		};
+			CHECK_dict_new( DICT_TYPE, &data , NULL, NULL);
+		}
+		
+		/* UTF8String */
+		{
+			/*
+				The UTF8String format is derived from the OctetString AVP Base
+				Format.  This is a human readable string represented using the
+				ISO/IEC IS 10646-1 character set, encoded as an OctetString using
+				the UTF-8 [RFC3629] transformation format described in RFC 3629.
+
+				Since additional code points are added by amendments to the 10646
+				standard from time to time, implementations MUST be prepared to
+				encounter any code point from 0x00000001 to 0x7fffffff.  Byte
+				sequences that do not correspond to the valid encoding of a code
+				point into UTF-8 charset or are outside this range are prohibited.
+
+				The use of control codes SHOULD be avoided.  When it is necessary
+				to represent a new line, the control code sequence CR LF SHOULD be
+				used.
+
+				The use of leading or trailing white space SHOULD be avoided.
+
+				For code points not directly supported by user interface hardware
+				or software, an alternative means of entry and display, such as
+				hexadecimal, MAY be provided.
+
+				For information encoded in 7-bit US-ASCII, the UTF-8 charset is
+				identical to the US-ASCII charset.
+
+				UTF-8 may require multiple bytes to represent a single character /
+				code point; thus the length of an UTF8String in octets may be
+				different from the number of characters encoded.
+
+				Note that the AVP Length field of an UTF8String is measured in
+				octets, not characters.
+			*/
+			struct dict_type_data data = { AVP_TYPE_OCTETSTRING,	"UTF8String"		, NULL			, NULL	, fd_dictfct_UTF8String_dump	};
+			CHECK_dict_new( DICT_TYPE, &data , NULL, NULL);
+		}
+		
+		/* DiameterIdentity */
+		{
+			/*
+				The DiameterIdentity format is derived from the OctetString AVP
+				Base Format.
+
+                				DiameterIdentity  = FQDN
+
+
+				DiameterIdentity value is used to uniquely identify a Diameter
+				node for purposes of duplicate connection and routing loop
+				detection.
+
+				The contents of the string MUST be the FQDN of the Diameter node.
+				If multiple Diameter nodes run on the same host, each Diameter
+				node MUST be assigned a unique DiameterIdentity.  If a Diameter
+
+				node can be identified by several FQDNs, a single FQDN should be
+				picked at startup, and used as the only DiameterIdentity for that
+				node, whatever the connection it is sent on.  Note that in this
+				document, DiameterIdentity is in ASCII form in order to be
+				compatible with existing DNS infrastructure.  See Appendix D for
+				interactions between the Diameter protocol and Internationalized
+				Domain Name (IDNs).
+			*/
+			struct dict_type_data data = { AVP_TYPE_OCTETSTRING,	"DiameterIdentity"	, NULL			, NULL		, fd_dictfct_UTF8String_dump	};
+			CHECK_dict_new( DICT_TYPE, &data , NULL, NULL);
+		}
+		
+		/* DiameterURI */
+		{
+			/*
+				The DiameterURI MUST follow the Uniform Resource Identifiers (URI)
+				syntax [RFC3986] rules specified below:
+
+				 "aaa://" FQDN [ port ] [ transport ] [ protocol ]
+
+                				 ; No transport security
+
+				 "aaas://" FQDN [ port ] [ transport ] [ protocol ]
+
+                				 ; Transport security used
+
+				 FQDN               = Fully Qualified Host Name
+
+				 port               = ":" 1*DIGIT
+
+                				 ; One of the ports used to listen for
+                				 ; incoming connections.
+                				 ; If absent,
+                				 ; the default Diameter port (3868) is
+                				 ; assumed.
+
+				 transport          = ";transport=" transport-protocol
+
+                				 ; One of the transports used to listen
+                				 ; for incoming connections.  If absent,
+                				 ; the default SCTP [RFC2960] protocol is
+                				 ; assumed. UDP MUST NOT be used when
+                				 ; the aaa-protocol field is set to
+                				 ; diameter.
+
+				transport-protocol = ( "tcp" / "sctp" / "udp" )
+
+				protocol           = ";protocol=" aaa-protocol
+
+                				 ; If absent, the default AAA protocol
+                				 ; is diameter.
+
+				aaa-protocol       = ( "diameter" / "radius" / "tacacs+" )
+
+				The following are examples of valid Diameter host identities:
+
+				aaa://host.example.com;transport=tcp
+				aaa://host.example.com:6666;transport=tcp
+				aaa://host.example.com;protocol=diameter
+				aaa://host.example.com:6666;protocol=diameter
+				aaa://host.example.com:6666;transport=tcp;protocol=diameter
+				aaa://host.example.com:1813;transport=udp;protocol=radius
+			*/
+			struct dict_type_data data = { AVP_TYPE_OCTETSTRING,	"DiameterURI"		, NULL			, NULL		, fd_dictfct_UTF8String_dump	};
+			CHECK_dict_new( DICT_TYPE, &data , NULL, NULL);
+		}
+		
+		/* Enumerated */
+		{
+			/*
+				Enumerated is derived from the Integer32 AVP Base Format.  The
+				definition contains a list of valid values and their
+				interpretation and is described in the Diameter application
+				introducing the AVP.
+			*/
+			
+			/* We don't use a generic "Enumerated" type in freeDiameter. Instead, we define
+			 * types of the form "Enumerated(<avpname>)" where <avpname> is replaced 
+			 * by the name of the AVP to which the type applies.
+			 *  Example: Enumerated(Disconnect-Cause)
+			 */
+			;
+		}
+		
+		/* IPFilterRule */
+		{
+			/*
+				The IPFilterRule format is derived from the OctetString AVP Base
+				Format and uses the ASCII charset.  The rule syntax is a modified
+				subset of ipfw(8) from FreeBSD.  Packets may be filtered based on
+				the following information that is associated with it:
+
+				    Direction                          (in or out)
+				    Source and destination IP address  (possibly masked)
+				    Protocol
+				    Source and destination port        (lists or ranges)
+				    TCP flags
+				    IP fragment flag
+				    IP options
+				    ICMP types
+
+				Rules for the appropriate direction are evaluated in order, with
+				the first matched rule terminating the evaluation.  Each packet is
+				evaluated once.  If no rule matches, the packet is dropped if the
+				last rule evaluated was a permit, and passed if the last rule was
+				a deny.
+
+				IPFilterRule filters MUST follow the format:
+				
+				    action dir proto from src to dst [options]
+				
+			(...skipped loooong explanation...)
+				
+				There is one kind of packet that the access device MUST always
+				discard, that is an IP fragment with a fragment offset of one.
+				This is a valid packet, but it only has one use, to try to
+				circumvent firewalls.
+
+				An access device that is unable to interpret or apply a deny rule
+				MUST terminate the session.  An access device that is unable to
+				interpret or apply a permit rule MAY apply a more restrictive
+				rule.  An access device MAY apply deny rules of its own before the
+				supplied rules, for example to protect the access device owner's
+				infrastructure.
+			*/
+			struct dict_type_data data = { AVP_TYPE_OCTETSTRING,	"IPFilterRule"		, NULL			, NULL		, fd_dictfct_UTF8String_dump	};
+			CHECK_dict_new( DICT_TYPE, &data , NULL, NULL);
+		}
+	}
+	
+	/* AVP section */
+	{
+		struct dict_object * Address_type;
+		struct dict_object * UTF8String_type;
+		struct dict_object * DiameterIdentity_type;
+		struct dict_object * DiameterURI_type;
+		struct dict_object * Time_type;
+		
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "Address", &Address_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "UTF8String", &UTF8String_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "DiameterIdentity", &DiameterIdentity_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "DiameterURI", &DiameterURI_type);
+		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "Time", &Time_type);
+		
+		/* Vendor-Id */
+		{
+			/*
+				The Vendor-Id AVP (AVP Code 266) is of type Unsigned32 and contains
+				the IANA "SMI Network Management Private Enterprise Codes" [RFC3232]
+				value assigned to the vendor of the Diameter device.  It is
+				envisioned that the combination of the Vendor-Id, Product-Name
+				(Section 5.3.7) and the Firmware-Revision (Section 5.3.4) AVPs may
+				provide useful debugging information.
+
+				A Vendor-Id value of zero in the CER or CEA messages is reserved and
+				indicates that this field is ignored.
+			*/
+			struct dict_avp_data data = { 
+					266, 					/* Code */
+					#if AC_VENDOR_ID != 266
+					#error "AC_VENDOR_ID definition mismatch"
+					#endif
+					0, 					/* Vendor */
+					"Vendor-Id", 				/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY, 			/* Fixed flag values */
+					AVP_TYPE_UNSIGNED32 			/* base type of data */
+					};
+			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
+		}
+		
+		/* Firmware-Revision */
+		{
+			/*
+				The Firmware-Revision AVP (AVP Code 267) is of type Unsigned32 and is
+				used to inform a Diameter peer of the firmware revision of the
+				issuing device.
+
+				For devices that do not have a firmware revision (general purpose
+				computers running Diameter software modules, for instance), the
+				revision of the Diameter software module may be reported instead.
+			*/
+			struct dict_avp_data data = { 
+					267, 					/* Code */
+					#if AC_FIRMWARE_REVISION != 267
+					#error "AC_FIRMWARE_REVISION definition mismatch"
+					#endif
+					0, 					/* Vendor */
+					"Firmware-Revision", 			/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					0,		 			/* Fixed flag values */
+					AVP_TYPE_UNSIGNED32 			/* base type of data */
+					};
+			CHECK_dict_new( DICT_AVP, &data , NULL, NULL);
+		}
+		
+		/* Host-IP-Address */
+		{
+			/*
+				The Host-IP-Address AVP (AVP Code 257) is of type Address and is used
+				to inform a Diameter peer of the sender's IP address.  All source
+				addresses that a Diameter node expects to use with SCTP [RFC2960]
+				MUST be advertised in the CER and CEA messages by including a
+				Host-IP- Address AVP for each address.  This AVP MUST ONLY be used in
+				the CER and CEA messages.
+			*/
+			struct dict_avp_data data = { 
+					257, 					/* Code */
+					#if AC_HOST_IP_ADDRESS != 257
+					#error "AC_HOST_IP_ADDRESS definition mismatch"
+					#endif
+					0, 					/* Vendor */
+					"Host-IP-Address", 			/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,			/* Fixed flag values */
+					AVP_TYPE_OCTETSTRING 			/* base type of data */
+					};
+			CHECK_dict_new( DICT_AVP, &data , Address_type, NULL);
+		}
+		
+		/* Supported-Vendor-Id */
+		{
+			/*
+				The Supported-Vendor-Id AVP (AVP Code 265) is of type Unsigned32 and
+				contains the IANA "SMI Network Management Private Enterprise Codes"
+				[RFC3232] value assigned to a vendor other than the device vendor but
+				including the application vendor.  This is used in the CER and CEA
+				messages in order to inform the peer that the sender supports (a
+				subset of) the vendor-specific AVPs defined by the vendor identified
+				in this AVP.  The value of this AVP SHOULD NOT be set to zero.
+				Multiple instances of this AVP containing the same value SHOULD NOT
+				be sent.
+			*/
+			struct dict_avp_data data = { 
+					265, 					/* Code */
+					#if AC_SUPPORTED_VENDOR_ID != 265
+					#error "AC_SUPPORTED_VENDOR_ID definition mismatch"
+					#endif
+					0, 					/* Vendor */
+					"Supported-Vendor-Id", 			/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,			/* Fixed flag values */
+					AVP_TYPE_UNSIGNED32 			/* base type of data */
+					};
+			CHECK_dict_new( DICT_AVP, &data , NULL, NULL);
+		}
+		
+		/* Product-Name */
+		{
+			/*
+				The Product-Name AVP (AVP Code 269) is of type UTF8String, and
+				contains the vendor assigned name for the product.  The Product-Name
+				AVP SHOULD remain constant across firmware revisions for the same
+				product.
+			*/
+			struct dict_avp_data data = { 
+					269, 					/* Code */
+					#if AC_PRODUCT_NAME != 269
+					#error "AC_PRODUCT_NAME definition mismatch"
+					#endif
+					0, 					/* Vendor */
+					"Product-Name", 			/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					0,					/* Fixed flag values */
+					AVP_TYPE_OCTETSTRING 			/* base type of data */
+					};
+			CHECK_dict_new( DICT_AVP, &data , UTF8String_type, NULL);
+		}
+		
+		/* Disconnect-Cause */
+		{
+			/*
+				The Disconnect-Cause AVP (AVP Code 273) is of type Enumerated.  A
+				Diameter node MUST include this AVP in the Disconnect-Peer-Request
+				message to inform the peer of the reason for its intention to
+				shutdown the transport connection.  The following values are
+				supported:
+
+				REBOOTING                         0
+				A scheduled reboot is imminent. Receiver of DPR with above result
+				code MAY attempt reconnection.
+
+				BUSY                              1
+				The peer's internal resources are constrained, and it has
+				determined that the transport connection needs to be closed.
+				Receiver of DPR with above result code SHOULD NOT attempt
+				reconnection.
+
+				DO_NOT_WANT_TO_TALK_TO_YOU        2
+				The peer has determined that it does not see a need for the
+				transport connection to exist, since it does not expect any
+				messages to be exchanged in the near future. Receiver of DPR
+				with above result code SHOULD NOT attempt reconnection.
+			*/
+			struct dict_object 	* 	type;
+			struct dict_type_data 		tdata = { AVP_TYPE_INTEGER32,	"Enumerated(Disconnect-Cause)"	, NULL, NULL, NULL };
+			struct dict_enumval_data 	t_0 = { "REBOOTING", 			{ .i32 = 0 }};
+			struct dict_enumval_data 	t_1 = { "BUSY", 			{ .i32 = 1 }};
+			struct dict_enumval_data 	t_2 = { "DO_NOT_WANT_TO_TALK_TO_YOU", 	{ .i32 = 2 }};
+			struct dict_avp_data 		data = { 
+					273, 					/* Code */
+					#if AC_DISCONNECT_CAUSE != 273
+					#error "AC_DISCONNECT_CAUSE definition mismatch"
+					#endif
+					0, 					/* Vendor */
+					"Disconnect-Cause", 			/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,			/* Fixed flag values */
+					AVP_TYPE_INTEGER32 			/* base type of data */
+					};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata , NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_0 , type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1 , type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2 , type, NULL);
+			CHECK_dict_new( DICT_AVP, &data , type, NULL);
+		}
+		
+		/* Origin-Host */
+		{
+			/*
+				The Origin-Host AVP (AVP Code 264) is of type DiameterIdentity, and
+				MUST be present in all Diameter messages.  This AVP identifies the
+				endpoint that originated the Diameter message.  Relay agents MUST NOT
+				modify this AVP.
+
+				The value of the Origin-Host AVP is guaranteed to be unique within a
+				single host.
+
+				Note that the Origin-Host AVP may resolve to more than one address as
+				the Diameter peer may support more than one address.
+
+				This AVP SHOULD be placed as close to the Diameter header as
+				possible.
+			*/
+			struct dict_avp_data data = { 
+					264, 					/* Code */
+					#if AC_ORIGIN_HOST != 264
+					#error "AC_ORIGIN_HOST definition mismatch"
+					#endif
+					0, 					/* Vendor */
+					"Origin-Host", 				/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,			/* Fixed flag values */
+					AVP_TYPE_OCTETSTRING 			/* base type of data */
+					};
+			CHECK_dict_new( DICT_AVP, &data , DiameterIdentity_type, NULL);
+		}
+		
+		/* Origin-Realm */
+		{
+			/*
+				The Origin-Realm AVP (AVP Code 296) is of type DiameterIdentity.
+				This AVP contains the Realm of the originator of any Diameter message
+				and MUST be present in all messages.
+
+				This AVP SHOULD be placed as close to the Diameter header as
+				possible.
+			*/
+			struct dict_avp_data data = { 
+					296, 					/* Code */
+					#if AC_ORIGIN_REALM != 296
+					#error "AC_ORIGIN_REALM definition mismatch"
+					#endif
+					0, 					/* Vendor */
+					"Origin-Realm", 			/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,			/* Fixed flag values */
+					AVP_TYPE_OCTETSTRING 			/* base type of data */
+					};
+			CHECK_dict_new( DICT_AVP, &data , DiameterIdentity_type, NULL);
+		}
+		
+		/* Destination-Host */
+		{
+			/*
+				The Destination-Host AVP (AVP Code 293) is of type DiameterIdentity.
+				This AVP MUST be present in all unsolicited agent initiated messages,
+				MAY be present in request messages, and MUST NOT be present in Answer
+				messages.
+
+				The absence of the Destination-Host AVP will cause a message to be
+				sent to any Diameter server supporting the application within the
+				realm specified in Destination-Realm AVP.
+
+				This AVP SHOULD be placed as close to the Diameter header as
+				possible.
+			*/
+			struct dict_avp_data data = { 
+					293, 					/* Code */
+					#if AC_DESTINATION_HOST != 293
+					#error "AC_DESTINATION_HOST definition mismatch"
+					#endif
+					0, 					/* Vendor */
+					"Destination-Host", 			/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,			/* Fixed flag values */
+					AVP_TYPE_OCTETSTRING 			/* base type of data */
+					};
+			CHECK_dict_new( DICT_AVP, &data , DiameterIdentity_type, NULL);
+		}
+		
+		/* Destination-Realm */
+		{
+			/*
+				The Destination-Realm AVP (AVP Code 283) is of type DiameterIdentity,
+				and contains the realm the message is to be routed to.  The
+				Destination-Realm AVP MUST NOT be present in Answer messages.
+				Diameter Clients insert the realm portion of the User-Name AVP.
+				Diameter servers initiating a request message use the value of the
+				Origin-Realm AVP from a previous message received from the intended
+				target host (unless it is known a priori).  When present, the
+				Destination-Realm AVP is used to perform message routing decisions.
+
+				Request messages whose ABNF does not list the Destination-Realm AVP
+				as a mandatory AVP are inherently non-routable messages.
+
+				This AVP SHOULD be placed as close to the Diameter header as
+				possible.
+			*/
+			struct dict_avp_data data = { 
+					283, 					/* Code */
+					#if AC_DESTINATION_REALM != 283
+					#error "AC_DESTINATION_REALM definition mismatch"
+					#endif
+					0, 					/* Vendor */
+					"Destination-Realm", 			/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,			/* Fixed flag values */
+					AVP_TYPE_OCTETSTRING 			/* base type of data */
+					};
+			CHECK_dict_new( DICT_AVP, &data , DiameterIdentity_type, NULL);
+		}
+		
+		/* Route-Record */
+		{
+			/*
+				The Route-Record AVP (AVP Code 282) is of type DiameterIdentity.  The
+				identity added in this AVP MUST be the same as the one received in
+				the Origin-Host of the Capabilities Exchange message.
+			*/
+			struct dict_avp_data data = { 
+					282, 					/* Code */
+					#if AC_ROUTE_RECORD != 282
+					#error "AC_ROUTE_RECORD definition mismatch"
+					#endif
+					0, 					/* Vendor */
+					"Route-Record", 			/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,			/* Fixed flag values */
+					AVP_TYPE_OCTETSTRING 			/* base type of data */
+					};
+			CHECK_dict_new( DICT_AVP, &data , DiameterIdentity_type, NULL);
+		}
+		
+		/* Proxy-Host */
+		{
+			/*
+				The Proxy-Host AVP (AVP Code 280) is of type DiameterIdentity.  This
+				AVP contains the identity of the host that added the Proxy-Info AVP.
+			*/
+			struct dict_avp_data adata = { 
+					280, 					/* Code */
+					#if AC_PROXY_HOST != 280
+					#error "AC_PROXY_HOST definition mismatch"
+					#endif
+					0, 					/* Vendor */
+					"Proxy-Host", 				/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,			/* Fixed flag values */
+					AVP_TYPE_OCTETSTRING 			/* base type of data */
+					};
+			CHECK_dict_new( DICT_AVP, &adata , DiameterIdentity_type, NULL);
+		}
+		
+		/* Proxy-State */
+		{
+			/*
+				The Proxy-State AVP (AVP Code 33) is of type OctetString, and
+				contains state local information, and MUST be treated as opaque data.
+			*/
+			struct dict_avp_data adata = { 
+					33, 					/* Code */
+					#if AC_PROXY_STATE != 33
+					#error "AC_PROXY_STATE definition mismatch"
+					#endif
+					0, 					/* Vendor */
+					"Proxy-State", 				/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,			/* Fixed flag values */
+					AVP_TYPE_OCTETSTRING 			/* base type of data */
+					};
+			CHECK_dict_new( DICT_AVP, &adata , NULL, NULL);
+		}
+			
+		/* Proxy-Info */
+		{
+			/*
+				The Proxy-Info AVP (AVP Code 284) is of type Grouped.  The Grouped
+				Data field has the following ABNF grammar:
+
+				 Proxy-Info ::= < AVP Header: 284 >
+                				{ Proxy-Host }
+                				{ Proxy-State }
+        				      * [ AVP ]
+			*/
+			struct dict_object * avp;
+			struct dict_avp_data data = { 
+					284, 					/* Code */
+					#if AC_PROXY_INFO != 284
+					#error "AC_PROXY_INFO definition mismatch"
+					#endif
+					0, 					/* Vendor */
+					"Proxy-Info", 				/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,			/* Fixed flag values */
+					AVP_TYPE_GROUPED 			/* base type of data */
+					};
+			struct local_rules_definition rules[] = 
+						{ 	 {  "Proxy-Host", 			RULE_REQUIRED, -1, 1 }
+							,{  "Proxy-State",			RULE_REQUIRED, -1, 1 }
+						};
+			
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+			PARSE_loc_rules( rules, avp );
+		}
+		
+		/* Auth-Application-Id */
+		{
+			/*
+				The Auth-Application-Id AVP (AVP Code 258) is of type Unsigned32 and
+				is used in order to advertise support of the Authentication and
+				Authorization portion of an application (see Section 2.4).  If
+				present in a message other than CER and CEA, the value of the Auth-
+				Application-Id AVP MUST match the Application Id present in the
+				Diameter message header.
+			*/
+			struct dict_avp_data data = { 
+					258, 					/* Code */
+					#if AC_AUTH_APPLICATION_ID != 258
+					#error "AC_AUTH_APPLICATION_ID definition mismatch"
+					#endif
+					0, 					/* Vendor */
+					"Auth-Application-Id", 			/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,			/* Fixed flag values */
+					AVP_TYPE_UNSIGNED32 			/* base type of data */
+					};
+			CHECK_dict_new( DICT_AVP, &data , NULL, NULL);
+		}
+		
+		/* Acct-Application-Id */
+		{
+			/*
+				The Acct-Application-Id AVP (AVP Code 259) is of type Unsigned32 and
+				is used in order to advertise support of the Accounting portion of an
+				application (see Section 2.4).  If present in a message other than
+				CER and CEA, the value of the Acct-Application-Id AVP MUST match the
+				Application Id present in the Diameter message header.
+			*/
+			struct dict_avp_data data = { 
+					259, 					/* Code */
+					#if AC_ACCT_APPLICATION_ID != 259
+					#error "AC_ACCT_APPLICATION_ID definition mismatch"
+					#endif
+					0, 					/* Vendor */
+					"Acct-Application-Id", 			/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,			/* Fixed flag values */
+					AVP_TYPE_UNSIGNED32 			/* base type of data */
+					};
+			CHECK_dict_new( DICT_AVP, &data , NULL, NULL);
+		}
+		
+		/* Inband-Security-Id */
+		{
+			/*
+				The Inband-Security-Id AVP (AVP Code 299) is of type Unsigned32 and
+				is used in order to advertise support of the Security portion of the
+				application.
+
+				Currently, the following values are supported, but there is ample
+				room to add new security Ids.
+
+
+				NO_INBAND_SECURITY 0
+
+				This peer does not support TLS.  This is the default value, if the
+				AVP is omitted.
+
+				TLS 1
+
+				This node supports TLS security, as defined by [RFC4346].
+			*/
+			
+			/* Although the RFC does not specify an "Enumerated" type here, we go forward and create one.
+			 * This is the reason for the "*" in the type name
+			 */
+			
+			struct dict_object 	* 	type;
+			struct dict_type_data	 	tdata = { AVP_TYPE_UNSIGNED32,	"Enumerated(Inband-Security-Id)"	, NULL, NULL, NULL };
+			struct dict_enumval_data 	t_0 = { "NO_INBAND_SECURITY", 		{ .u32 = ACV_ISI_NO_INBAND_SECURITY }};
+			struct dict_enumval_data 	t_1 = { "TLS", 			{ .u32 = ACV_ISI_TLS }};
+			struct dict_avp_data 		data = { 
+					299, 					/* Code */
+					#if AC_INBAND_SECURITY_ID != 299
+					#error "AC_INBAND_SECURITY_ID definition mismatch"
+					#endif
+					0, 					/* Vendor */
+					"Inband-Security-Id", 			/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,			/* Fixed flag values */
+					AVP_TYPE_UNSIGNED32 			/* base type of data */
+					};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata , NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_0 , type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1 , type, NULL);
+			CHECK_dict_new( DICT_AVP, &data , type, NULL);
+		}
+		
+		/* Vendor-Specific-Application-Id */
+		{
+			/*
+				The Vendor-Specific-Application-Id AVP (AVP Code 260) is of type
+				Grouped and is used to advertise support of a vendor-specific
+				Diameter Application.  Exactly one instance of either Auth-
+				Application-Id or Acct-Application-Id AVP MUST be present.  The
+				Application Id carried by either Auth-Application-Id or Acct-
+				Application-Id AVP MUST comply with vendor specific Application Id
+				assignment described in Sec 11.3.  It MUST also match the Application
+				Id present in the diameter header except when used in a CER or CEA
+				messages.
+
+				The Vendor-Id AVP is an informational AVP pertaining to the vendor
+				who may have authorship of the vendor-specific Diameter application.
+				It MUST NOT be used as a means of defining a completely separate
+				vendor-specific Application Id space.
+
+				This AVP MUST also be present as the first AVP in all experimental
+				commands defined in the vendor-specific application.
+
+				This AVP SHOULD be placed as close to the Diameter header as
+				possible.
+
+				AVP Format
+
+				<Vendor-Specific-Application-Id> ::= < AVP Header: 260 >
+                                				   { Vendor-Id }
+                                				   [ Auth-Application-Id ]
+                                				   [ Acct-Application-Id ]
+
+				A Vendor-Specific-Application-Id AVP MUST contain exactly one of
+				either Auth-Application-Id or Acct-Application-Id.  If a Vendor-
+				Specific-Application-Id is received without any of these two AVPs,
+				then the recipient SHOULD issue an answer with a Result-Code set to
+				DIAMETER_MISSING_AVP.  The answer SHOULD also include a Failed-AVP
+				which MUST contain an example of an Auth-Application-Id AVP and an
+				Acct-Application-Id AVP.
+
+				If a Vendor-Specific-Application-Id is received that contains both
+				Auth-Application-Id and Acct-Application-Id, then the recipient
+				SHOULD issue an answer with Result-Code set to
+				DIAMETER_AVP_OCCURS_TOO_MANY_TIMES.  The answer SHOULD also include a
+				Failed-AVP which MUST contain the received Auth-Application-Id AVP
+				and Acct-Application-Id AVP.
+			*/
+			struct dict_object 	* avp;
+			struct dict_avp_data	  data = { 
+					260, 					/* Code */
+					#if AC_VENDOR_SPECIFIC_APPLICATION_ID != 260
+					#error "AC_VENDOR_SPECIFIC_APPLICATION_ID definition mismatch"
+					#endif
+					0, 					/* Vendor */
+					"Vendor-Specific-Application-Id", 	/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,			/* Fixed flag values */
+					AVP_TYPE_GROUPED 			/* base type of data */
+					};
+					
+			struct local_rules_definition rules[] = 
+						{
+#ifndef WORKAROUND_ACCEPT_INVALID_VSAI
+							/* ABNF from RFC6733 */
+						 	 {  "Vendor-Id", 			RULE_REQUIRED, -1, 1 }
+#else /* WORKAROUND_ACCEPT_INVALID_VSAI */
+							/* ABNF from RFC3588 (including erratum, because original text is nonsense) */
+						 	 {  "Vendor-Id", 			RULE_REQUIRED, -1, -1}
+#endif /* WORKAROUND_ACCEPT_INVALID_VSAI */
+							,{  "Auth-Application-Id",		RULE_OPTIONAL, -1, 1 }
+							,{  "Acct-Application-Id",		RULE_OPTIONAL, -1, 1 }
+						};
+			
+			/* Create the grouped AVP */
+			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
+			PARSE_loc_rules( rules, avp );
+			
+		}
+		
+		/* Redirect-Host */
+		{
+			/*
+				One or more of instances of this AVP MUST be present if the answer
+				message's 'E' bit is set and the Result-Code AVP is set to
+				DIAMETER_REDIRECT_INDICATION.
+
+				Upon receiving the above, the receiving Diameter node SHOULD forward
+				the request directly to one of the hosts identified in these AVPs.
+				The server contained in the selected Redirect-Host AVP SHOULD be used
+				for all messages pertaining to this session.
+			*/
+			struct dict_avp_data data = { 
+					292, 					/* Code */
+					#if AC_REDIRECT_HOST != 292
+					#error "AC_REDIRECT_HOST definition mismatch"
+					#endif
+					0, 					/* Vendor */
+					"Redirect-Host", 			/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,			/* Fixed flag values */
+					AVP_TYPE_OCTETSTRING 			/* base type of data */
+					};
+			CHECK_dict_new( DICT_AVP, &data , DiameterURI_type, NULL);
+		}
+		
+		/* Redirect-Host-Usage */
+		{
+			/*
+				The Redirect-Host-Usage AVP (AVP Code 261) is of type Enumerated.
+				This AVP MAY be present in answer messages whose 'E' bit is set and
+				the Result-Code AVP is set to DIAMETER_REDIRECT_INDICATION.
+
+				When present, this AVP dictates how the routing entry resulting from
+				the Redirect-Host is to be used.  The following values are supported:
+
+
+				DONT_CACHE 0
+
+				The host specified in the Redirect-Host AVP should not be cached.
+				This is the default value.
+
+
+				ALL_SESSION 1
+
+				All messages within the same session, as defined by the same value
+				of the Session-ID AVP MAY be sent to the host specified in the
+				Redirect-Host AVP.
+
+
+				ALL_REALM 2
+
+				All messages destined for the realm requested MAY be sent to the
+				host specified in the Redirect-Host AVP.
+
+
+				REALM_AND_APPLICATION 3
+
+				All messages for the application requested to the realm specified
+				MAY be sent to the host specified in the Redirect-Host AVP.
+
+				ALL_APPLICATION 4
+
+				All messages for the application requested MAY be sent to the host
+				specified in the Redirect-Host AVP.
+
+
+				ALL_HOST 5
+
+				All messages that would be sent to the host that generated the
+				Redirect-Host MAY be sent to the host specified in the Redirect-
+				Host AVP.
+
+
+				ALL_USER 6
+
+				All messages for the user requested MAY be sent to the host
+				specified in the Redirect-Host AVP.
+
+
+				When multiple cached routes are created by redirect indications and
+				they differ only in redirect usage and peers to forward requests to
+				(see Section 6.1.8), a precedence rule MUST be applied to the
+				redirect usage values of the cached routes during normal routing to
+				resolve contentions that may occur.  The precedence rule is the order
+				that dictate which redirect usage should be considered before any
+				other as they appear.  The order is as follows:
+
+
+				1.  ALL_SESSION
+
+				2.  ALL_USER
+
+				3.  REALM_AND_APPLICATION
+
+				4.  ALL_REALM
+
+				5.  ALL_APPLICATION
+
+				6.  ALL_HOST
+			*/
+			struct dict_object 	* 	type;
+			struct dict_type_data	 	tdata = { AVP_TYPE_INTEGER32,	"Enumerated(Redirect-Host-Usage)"	, NULL, NULL, NULL };
+			struct dict_enumval_data 	t_0 = { "DONT_CACHE", 			{ .i32 = 0 }};
+			struct dict_enumval_data 	t_1 = { "ALL_SESSION", 			{ .i32 = 1 }};
+			struct dict_enumval_data 	t_2 = { "ALL_REALM", 			{ .i32 = 2 }};
+			struct dict_enumval_data 	t_3 = { "REALM_AND_APPLICATION", 	{ .i32 = 3 }};
+			struct dict_enumval_data 	t_4 = { "ALL_APPLICATION", 		{ .i32 = 4 }};
+			struct dict_enumval_data 	t_5 = { "ALL_HOST", 			{ .i32 = 5 }};
+			struct dict_enumval_data 	t_6 = { "ALL_USER", 			{ .i32 = 6 }};
+			struct dict_avp_data 		data = { 
+					261, 					/* Code */
+					#if AC_REDIRECT_HOST_USAGE != 261
+					#error "AC_REDIRECT_HOST_USAGE definition mismatch"
+					#endif
+					0, 					/* Vendor */
+					"Redirect-Host-Usage", 			/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,			/* Fixed flag values */
+					AVP_TYPE_INTEGER32 			/* base type of data */
+					};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata , NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_0 , type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1 , type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2 , type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_3 , type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_4 , type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_5 , type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_6 , type, NULL);
+			CHECK_dict_new( DICT_AVP, &data , type, NULL);
+		}
+		
+		/* Redirect-Max-Cache-Time */
+		{
+			/*
+				The Redirect-Max-Cache-Time AVP (AVP Code 262) is of type Unsigned32.
+				This AVP MUST be present in answer messages whose 'E' bit is set, the
+				Result-Code AVP is set to DIAMETER_REDIRECT_INDICATION and the
+				Redirect-Host-Usage AVP set to a non-zero value.
+
+				This AVP contains the maximum number of seconds the peer and route
+				table entries, created as a result of the Redirect-Host, will be
+				cached.  Note that once a host created due to a redirect indication
+				is no longer reachable, any associated peer and routing table entries
+				MUST be deleted.
+			*/
+			struct dict_avp_data data = { 
+					262, 					/* Code */
+					#if AC_REDIRECT_MAX_CACHE_TIME != 262
+					#error "AC_REDIRECT_MAX_CACHE_TIME definition mismatch"
+					#endif
+					0, 					/* Vendor */
+					"Redirect-Max-Cache-Time", 		/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,			/* Fixed flag values */
+					AVP_TYPE_UNSIGNED32 			/* base type of data */
+					};
+			CHECK_dict_new( DICT_AVP, &data , NULL, NULL);
+		}
+		
+		/* Result-Code */
+		{
+			/*
+				The Result-Code AVP (AVP Code 268) is of type Unsigned32 and
+				indicates whether a particular request was completed successfully or
+				whether an error occurred.  All Diameter answer messages defined in
+				IETF applications MUST include one Result-Code AVP.  A non-successful
+				Result-Code AVP (one containing a non 2xxx value other than
+				DIAMETER_REDIRECT_INDICATION) MUST include the Error-Reporting-Host
+				AVP if the host setting the Result-Code AVP is different from the
+				identity encoded in the Origin-Host AVP.
+
+				The Result-Code data field contains an IANA-managed 32-bit address
+				space representing errors (see Section 11.4).  Diameter provides the
+				following classes of errors, all identified by the thousands digit in
+				the decimal notation:
+
+				o  1xxx (Informational)
+
+				o  2xxx (Success)
+
+				o  3xxx (Protocol Errors)
+
+				o  4xxx (Transient Failures)
+
+				o  5xxx (Permanent Failure)
+
+				A non-recognized class (one whose first digit is not defined in this
+				section) MUST be handled as a permanent failure.
+			*/
+			
+			/* Although the RFC does not specify an "Enumerated" type here, we go forward and create one.
+			 * This is the reason for the "*" in the type name
+			 */
+			struct dict_object * 	type;
+			struct dict_type_data 	tdata = { AVP_TYPE_UNSIGNED32,	"Enumerated(Result-Code)"	, NULL, NULL, NULL };
+			struct dict_avp_data 	data = { 
+					268, 					/* Code */
+					#if AC_RESULT_CODE != 268
+					#error "AC_RESULT_CODE definition mismatch"
+					#endif
+					0, 					/* Vendor */
+					"Result-Code", 				/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,			/* Fixed flag values */
+					AVP_TYPE_UNSIGNED32 			/* base type of data */
+					};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata , NULL, &type);
+			CHECK_dict_new( DICT_AVP, &data , type, NULL);
+			
+			/* Informational */
+			{
+				/* 1001 */
+				{
+					/*
+						This informational error is returned by a Diameter server to
+						inform the access device that the authentication mechanism being
+						used requires multiple round trips, and a subsequent request needs
+						to be issued in order for access to be granted.
+					*/
+					struct dict_enumval_data 	error_code = { "DIAMETER_MULTI_ROUND_AUTH", 	{ .u32 = ER_DIAMETER_MULTI_ROUND_AUTH }};
+					CHECK_dict_new( DICT_ENUMVAL, &error_code , type, NULL);
+				}
+			}
+			/* Success */
+			{
+				/* 2001 */
+				{
+					/*
+						The Request was successfully completed.
+					*/
+					struct dict_enumval_data 	error_code = { "DIAMETER_SUCCESS", 		{ .u32 = ER_DIAMETER_SUCCESS }};
+					#if ER_DIAMETER_SUCCESS != 2001
+					#error "ER_DIAMETER_SUCCESS definition mismatch"
+					#endif
+					CHECK_dict_new( DICT_ENUMVAL, &error_code , type, NULL);
+				}
+				/* 2002 */
+				{
+					/*
+						When returned, the request was successfully completed, but
+						additional processing is required by the application in order to
+						provide service to the user.
+					*/
+					struct dict_enumval_data 	error_code = { "DIAMETER_LIMITED_SUCCESS", 	{ .u32 = ER_DIAMETER_LIMITED_SUCCESS }};
+					CHECK_dict_new( DICT_ENUMVAL, &error_code , type, NULL);
+				}
+			}
+			/* Protocol Errors */
+			{
+				/* 3001 -- might be changed to 5xxx soon */
+				{
+					/*
+						The Request contained a Command-Code that the receiver did not
+						recognize or support.  This MUST be used when a Diameter node
+						receives an experimental command that it does not understand.
+					*/
+					struct dict_enumval_data 	error_code = { "DIAMETER_COMMAND_UNSUPPORTED", 	{ .u32 = ER_DIAMETER_COMMAND_UNSUPPORTED }};
+					CHECK_dict_new( DICT_ENUMVAL, &error_code , type, NULL);
+				}
+				/* 3002 */
+				{
+					/*
+						This error is given when Diameter can not deliver the message to
+						the destination, either because no host within the realm
+						supporting the required application was available to process the
+						request, or because Destination-Host AVP was given without the
+						associated Destination-Realm AVP.
+					*/
+					struct dict_enumval_data 	error_code = { "DIAMETER_UNABLE_TO_DELIVER", 	{ .u32 = ER_DIAMETER_UNABLE_TO_DELIVER }};
+					CHECK_dict_new( DICT_ENUMVAL, &error_code , type, NULL);
+				}
+				/* 3003 */
+				{
+					/*
+						The intended realm of the request is not recognized.
+					*/
+					struct dict_enumval_data 	error_code = { "DIAMETER_REALM_NOT_SERVED", 	{ .u32 = ER_DIAMETER_REALM_NOT_SERVED }};
+					CHECK_dict_new( DICT_ENUMVAL, &error_code , type, NULL);
+				}
+				/* 3004 */
+				{
+					/*
+						When returned, a Diameter node SHOULD attempt to send the message
+						to an alternate peer.  This error MUST only be used when a
+						specific server is requested, and it cannot provide the requested
+						service.
+					*/
+					struct dict_enumval_data 	error_code = { "DIAMETER_TOO_BUSY", 		{ .u32 = ER_DIAMETER_TOO_BUSY }};
+					CHECK_dict_new( DICT_ENUMVAL, &error_code , type, NULL);
+				}
+				/* 3005 */
+				{
+					/*
+						An agent detected a loop while trying to get the message to the
+						intended recipient.  The message MAY be sent to an alternate peer,
+						if one is available, but the peer reporting the error has
+						identified a configuration problem.
+					*/
+					struct dict_enumval_data 	error_code = { "DIAMETER_LOOP_DETECTED", 	{ .u32 = ER_DIAMETER_LOOP_DETECTED }};
+					CHECK_dict_new( DICT_ENUMVAL, &error_code , type, NULL);
+				}
+				/* 3006 */
+				{
+					/*
+						A redirect agent has determined that the request could not be
+						satisfied locally and the initiator of the request should direct
+						the request directly to the server, whose contact information has
+						been added to the response.  When set, the Redirect-Host AVP MUST
+						be present.
+					*/
+					struct dict_enumval_data 	error_code = { "DIAMETER_REDIRECT_INDICATION", 	{ .u32 = ER_DIAMETER_REDIRECT_INDICATION }};
+					CHECK_dict_new( DICT_ENUMVAL, &error_code , type, NULL);
+				}
+				/* 3007 */
+				{
+					/*
+						A request was sent for an application that is not supported.
+					*/
+					struct dict_enumval_data 	error_code = { "DIAMETER_APPLICATION_UNSUPPORTED",	{ .u32 = ER_DIAMETER_APPLICATION_UNSUPPORTED }};
+					CHECK_dict_new( DICT_ENUMVAL, &error_code , type, NULL);
+				}
+				/* 3008 -- will change to 5xxx soon */
+				{
+					/*
+						A request was received whose bits in the Diameter header were
+						either set to an invalid combination, or to a value that is
+						inconsistent with the command code's definition.
+					*/
+					struct dict_enumval_data 	error_code = { "DIAMETER_INVALID_HDR_BITS", 	{ .u32 = ER_DIAMETER_INVALID_HDR_BITS }};
+					CHECK_dict_new( DICT_ENUMVAL, &error_code , type, NULL);
+				}
+				/* 3009 -- will change to 5xxx soon */
+				{
+					/*
+						A request was received that included an AVP whose flag bits are
+						set to an unrecognized value, or that is inconsistent with the
+						AVP's definition.
+					*/
+					struct dict_enumval_data 	error_code = { "DIAMETER_INVALID_AVP_BITS", 	{ .u32 = ER_DIAMETER_INVALID_AVP_BITS }};
+					CHECK_dict_new( DICT_ENUMVAL, &error_code , type, NULL);
+				}
+				/* 3010  -- will change to 5xxx soon */
+				{
+					/*
+						 A CER was received from an unknown peer.
+					*/
+					struct dict_enumval_data 	error_code = { "DIAMETER_UNKNOWN_PEER", 	{ .u32 = ER_DIAMETER_UNKNOWN_PEER }};
+					CHECK_dict_new( DICT_ENUMVAL, &error_code , type, NULL);
+				}
+			}
+			/* Transient Failures */
+			{
+				/* 4001 */
+				{
+					/*
+						The authentication process for the user failed, most likely due to
+						an invalid password used by the user.  Further attempts MUST only
+						be tried after prompting the user for a new password.
+					*/
+					struct dict_enumval_data 	error_code = { "DIAMETER_AUTHENTICATION_REJECTED", 	{ .u32 = ER_DIAMETER_AUTHENTICATION_REJECTED }};
+					CHECK_dict_new( DICT_ENUMVAL, &error_code , type, NULL);
+				}
+				/* 4002 */
+				{
+					/*
+						A Diameter node received the accounting request but was unable to
+						commit it to stable storage due to a temporary lack of space.
+					*/
+					struct dict_enumval_data 	error_code = { "DIAMETER_OUT_OF_SPACE", 		{ .u32 = ER_DIAMETER_OUT_OF_SPACE }};
+					CHECK_dict_new( DICT_ENUMVAL, &error_code , type, NULL);
+				}
+				/* 4003 */
+				{
+					/*
+						The peer has determined that it has lost the election process and
+						has therefore disconnected the transport connection.
+					*/
+					struct dict_enumval_data 	error_code = { "ELECTION_LOST", 			{ .u32 = ER_ELECTION_LOST }};
+					CHECK_dict_new( DICT_ENUMVAL, &error_code , type, NULL);
+				}
+			}
+			/* Permanent Failures */
+			{
+				/* 5001 */
+				{
+					/*
+						The peer received a message that contained an AVP that is not
+						recognized or supported and was marked with the Mandatory bit.  A
+						Diameter message with this error MUST contain one or more Failed-
+						AVP AVP containing the AVPs that caused the failure.
+					*/
+					struct dict_enumval_data 	error_code = { "DIAMETER_AVP_UNSUPPORTED", 	{ .u32 = ER_DIAMETER_AVP_UNSUPPORTED }};
+					CHECK_dict_new( DICT_ENUMVAL, &error_code , type, NULL);
+				}
+				/* 5002 */
+				{
+					/*
+						The request contained an unknown Session-Id.
+					*/
+					struct dict_enumval_data 	error_code = { "DIAMETER_UNKNOWN_SESSION_ID", 	{ .u32 = ER_DIAMETER_UNKNOWN_SESSION_ID }};
+					CHECK_dict_new( DICT_ENUMVAL, &error_code , type, NULL);
+				}
+				/* 5003 */
+				{
+					/*
+						A request was received for which the user could not be authorized.
+						This error could occur if the service requested is not permitted
+						to the user.
+					*/
+					struct dict_enumval_data 	error_code = { "DIAMETER_AUTHORIZATION_REJECTED",{ .u32 = ER_DIAMETER_AUTHORIZATION_REJECTED }};
+					CHECK_dict_new( DICT_ENUMVAL, &error_code , type, NULL);
+				}
+				/* 5004 */
+				{
+					/*
+						The request contained an AVP with an invalid value in its data
+						portion.  A Diameter message indicating this error MUST include
+						the offending AVPs within a Failed-AVP AVP.
+					*/
+					struct dict_enumval_data 	error_code = { "DIAMETER_INVALID_AVP_VALUE",	{ .u32 = ER_DIAMETER_INVALID_AVP_VALUE }};
+					CHECK_dict_new( DICT_ENUMVAL, &error_code , type, NULL);
+				}
+				/* 5005 */
+				{
+					/*
+						The request did not contain an AVP that is required by the Command
+						Code definition.  If this value is sent in the Result-Code AVP, a
+						Failed-AVP AVP SHOULD be included in the message.  The Failed-AVP
+						AVP MUST contain an example of the missing AVP complete with the
+						Vendor-Id if applicable.  The value field of the missing AVP
+						should be of correct minimum length and contain zeroes.
+					*/
+					struct dict_enumval_data 	error_code = { "DIAMETER_MISSING_AVP",		{ .u32 = ER_DIAMETER_MISSING_AVP }};
+					CHECK_dict_new( DICT_ENUMVAL, &error_code , type, NULL);
+				}
+				/* 5006 */
+				{
+					/*
+						A request was received that cannot be authorized because the user
+						has already expended allowed resources.  An example of this error
+						condition is a user that is restricted to one dial-up PPP port,
+						attempts to establish a second PPP connection.
+					*/
+					struct dict_enumval_data 	error_code = { "DIAMETER_RESOURCES_EXCEEDED",	{ .u32 = ER_DIAMETER_RESOURCES_EXCEEDED }};
+					CHECK_dict_new( DICT_ENUMVAL, &error_code , type, NULL);
+				}
+				/* 5007 */
+				{
+					/*
+						The Home Diameter server has detected AVPs in the request that
+						contradicted each other, and is not willing to provide service to
+						the user.  The Failed-AVP AVPs MUST be present which contains the
+						AVPs that contradicted each other.
+					*/
+					struct dict_enumval_data 	error_code = { "DIAMETER_CONTRADICTING_AVPS",	{ .u32 = ER_DIAMETER_CONTRADICTING_AVPS }};
+					CHECK_dict_new( DICT_ENUMVAL, &error_code , type, NULL);
+				}
+				/* 5008 */
+				{
+					/*
+						A message was received with an AVP that MUST NOT be present.  The
+						Failed-AVP AVP MUST be included and contain a copy of the
+						offending AVP.
+					*/
+					struct dict_enumval_data 	error_code = { "DIAMETER_AVP_NOT_ALLOWED",	{ .u32 = ER_DIAMETER_AVP_NOT_ALLOWED }};
+					CHECK_dict_new( DICT_ENUMVAL, &error_code , type, NULL);
+				}
+				/* 5009 */
+				{
+					/*
+						A message was received that included an AVP that appeared more
+						often than permitted in the message definition.  The Failed-AVP
+						AVP MUST be included and contain a copy of the first instance of
+						the offending AVP that exceeded the maximum number of occurrences
+					*/
+					struct dict_enumval_data 	error_code = { "DIAMETER_AVP_OCCURS_TOO_MANY_TIMES",{ .u32 = ER_DIAMETER_AVP_OCCURS_TOO_MANY_TIMES }};
+					CHECK_dict_new( DICT_ENUMVAL, &error_code , type, NULL);
+				}
+				/* 5010 */
+				{
+					/*
+						This error is returned by a Diameter node that is not acting as a
+						relay when it receives a CER which advertises a set of
+						applications that it does not support.
+					*/
+					struct dict_enumval_data 	error_code = { "DIAMETER_NO_COMMON_APPLICATION",{ .u32 = ER_DIAMETER_NO_COMMON_APPLICATION }};
+					CHECK_dict_new( DICT_ENUMVAL, &error_code , type, NULL);
+				}
+				/* 5011 */
+				{
+					/*
+						This error is returned when a request was received, whose version
+						number is unsupported.
+					*/
+					struct dict_enumval_data 	error_code = { "DIAMETER_UNSUPPORTED_VERSION",	{ .u32 = ER_DIAMETER_UNSUPPORTED_VERSION }};
+					CHECK_dict_new( DICT_ENUMVAL, &error_code , type, NULL);
+				}
+				/* 5012 */
+				{
+					/*
+						This error is returned when a request is rejected for unspecified
+						reasons.
+					*/
+					struct dict_enumval_data 	error_code = { "DIAMETER_UNABLE_TO_COMPLY",	{ .u32 = ER_DIAMETER_UNABLE_TO_COMPLY }};
+					CHECK_dict_new( DICT_ENUMVAL, &error_code , type, NULL);
+				}
+				/* 5013 -- will change to 3xxx */
+				{
+					/*
+						This error is returned when an unrecognized bit in the Diameter
+						header is set to one (1).
+					*/
+					struct dict_enumval_data 	error_code = { "DIAMETER_INVALID_BIT_IN_HEADER", 	{ .u32 = ER_DIAMETER_INVALID_BIT_IN_HEADER }};
+					CHECK_dict_new( DICT_ENUMVAL, &error_code , type, NULL);
+				}
+				/* 5014 */
+				{
+					/*
+						The request contained an AVP with an invalid length.  A Diameter
+						message indicating this error MUST include the offending AVPs
+						within a Failed-AVP AVP.  In cases where the erroneous avp length
+						value exceeds the message length or is less than the minimum AVP
+						header length, it is sufficient to include the offending AVP
+						header and a zero filled payload of the minimum required length
+						for the payloads data type.  If the AVP is a grouped AVP, the
+						grouped AVP header with an empty payload would be sufficient to
+						indicate the offending AVP.  In the case where the offending AVP
+						header cannot be fully decoded when avp length is less than the
+						minimum AVP header length, it is sufficient to include an
+						offending AVP header that is formulated by padding the incomplete
+						AVP header with zero up to the minimum AVP header length.
+					*/
+					struct dict_enumval_data 	error_code = { "DIAMETER_INVALID_AVP_LENGTH",	{ .u32 = ER_DIAMETER_INVALID_AVP_LENGTH }};
+					CHECK_dict_new( DICT_ENUMVAL, &error_code , type, NULL);
+				}
+				/* 5015 -- will change to 3xxx */
+				{
+					/*
+						This error is returned when a request is received with an invalid
+						message length.
+					*/
+					struct dict_enumval_data 	error_code = { "DIAMETER_INVALID_MESSAGE_LENGTH", 	{ .u32 = ER_DIAMETER_INVALID_MESSAGE_LENGTH }};
+					CHECK_dict_new( DICT_ENUMVAL, &error_code , type, NULL);
+				}
+				/* 5016 */
+				{
+					/*
+						The request contained an AVP with which is not allowed to have the
+						given value in the AVP Flags field.  A Diameter message indicating
+						this error MUST include the offending AVPs within a Failed-AVP
+						AVP.
+					*/
+					struct dict_enumval_data 	error_code = { "DIAMETER_INVALID_AVP_BIT_COMBO", 	{ .u32 = ER_DIAMETER_INVALID_AVP_BIT_COMBO }};
+					CHECK_dict_new( DICT_ENUMVAL, &error_code , type, NULL);
+				}
+				/* 5017 */
+				{
+					/*
+						This error is returned when a CER message is received, and there
+						are no common security mechanisms supported between the peers.  A
+						Capabilities-Exchange-Answer (CEA) MUST be returned with the
+						Result-Code AVP set to DIAMETER_NO_COMMON_SECURITY.
+					*/
+					struct dict_enumval_data 	error_code = { "DIAMETER_NO_COMMON_SECURITY",	{ .u32 = ER_DIAMETER_NO_COMMON_SECURITY }};
+					CHECK_dict_new( DICT_ENUMVAL, &error_code , type, NULL);
+				}
+			}
+		}
+		
+		/* Error-Message */
+		{
+			/*
+				The Error-Message AVP (AVP Code 281) is of type UTF8String.  It MAY
+				accompany a Result-Code AVP as a human readable error message.  The
+				Error-Message AVP is not intended to be useful in real-time, and
+				SHOULD NOT be expected to be parsed by network entities.
+			*/
+			struct dict_avp_data data = { 
+					281, 					/* Code */
+					#if AC_ERROR_MESSAGE != 281
+					#error "AC_ERROR_MESSAGE definition mismatch"
+					#endif
+					0, 					/* Vendor */
+					"Error-Message", 			/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					0,					/* Fixed flag values */
+					AVP_TYPE_OCTETSTRING 			/* base type of data */
+					};
+			CHECK_dict_new( DICT_AVP, &data , UTF8String_type, NULL);
+		}
+		
+		/* Error-Reporting-Host */
+		{
+			/*
+				The Error-Reporting-Host AVP (AVP Code 294) is of type
+				DiameterIdentity.  This AVP contains the identity of the Diameter
+				host that sent the Result-Code AVP to a value other than 2001
+				(Success), only if the host setting the Result-Code is different from
+				the one encoded in the Origin-Host AVP.  This AVP is intended to be
+				used for troubleshooting purposes, and MUST be set when the Result-
+				Code AVP indicates a failure.
+			*/
+			struct dict_avp_data data = { 
+					294, 					/* Code */
+					#if AC_ERROR_REPORTING_HOST != 294
+					#error "AC_ERROR_REPORTING_HOST definition mismatch"
+					#endif
+					0, 					/* Vendor */
+					"Error-Reporting-Host", 		/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					0,					/* Fixed flag values */
+					AVP_TYPE_OCTETSTRING 			/* base type of data */
+					};
+			CHECK_dict_new( DICT_AVP, &data , DiameterIdentity_type, NULL);
+		}
+		
+		/* Failed-AVP */
+		{
+			/*
+				The Failed-AVP AVP (AVP Code 279) is of type Grouped and provides
+				debugging information in cases where a request is rejected or not
+				fully processed due to erroneous information in a specific AVP.  The
+				value of the Result-Code AVP will provide information on the reason
+				for the Failed-AVP AVP.  A Diameter message SHOULD contain only one
+				Failed-AVP that corresponds to the error indicated by the Result-Code
+				AVP.  For practical purposes, this Failed-AVP would typically refer
+				to the first AVP processing error that a Diameter node encounters.
+
+				The possible reasons for this AVP are the presence of an improperly
+				constructed AVP, an unsupported or unrecognized AVP, an invalid AVP
+				value, the omission of a required AVP, the presence of an explicitly
+				excluded AVP (see tables in Section 10), or the presence of two or
+				more occurrences of an AVP which is restricted to 0, 1, or 0-1
+				occurrences.
+
+				A Diameter message SHOULD contain one Failed-AVP AVP, containing the
+				entire AVP that could not be processed successfully.  If the failure
+				reason is omission of a required AVP, an AVP with the missing AVP
+				code, the missing vendor id, and a zero filled payload of the minimum
+				required length for the omitted AVP will be added.  If the failure
+				reason is an invalid AVP length where the reported length is less
+				than the minimum AVP header length or greater than the reported
+				message length, a copy of the offending AVP header and a zero filled
+				payload of the minimum required length SHOULD be added.
+
+				In the case where the offending AVP is embedded within a grouped AVP,
+				the Failed-AVP MAY contain the grouped AVP which in turn contains the
+				single offending AVP.  The same method MAY be employed if the grouped
+				AVP itself is embedded in yet another grouped AVP and so on.  In this
+				case, the Failed-AVP MAY contain the grouped AVP heirarchy up to the
+				single offending AVP.  This enables the recipient to detect the
+				location of the offending AVP when embedded in a group.
+
+				AVP Format
+
+				 <Failed-AVP> ::= < AVP Header: 279 >
+        				       1* {AVP}
+			*/
+			struct dict_avp_data data = { 
+					279, 					/* Code */
+					#if AC_FAILED_AVP != 279
+					#error "AC_FAILED_AVP definition mismatch"
+					#endif
+					0, 					/* Vendor */
+					"Failed-AVP", 				/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,			/* Fixed flag values */
+					AVP_TYPE_GROUPED 			/* base type of data */
+					};
+			CHECK_dict_new( DICT_AVP, &data , NULL, NULL);
+		}
+		
+		/* Experimental-Result */
+		{
+			/*
+				The Experimental-Result AVP (AVP Code 297) is of type Grouped, and
+				indicates whether a particular vendor-specific request was completed
+				successfully or whether an error occurred.  Its Data field has the
+				following ABNF grammar:
+
+				AVP Format
+
+				 Experimental-Result ::= < AVP Header: 297 >
+                        				 { Vendor-Id }
+                        				 { Experimental-Result-Code }
+
+				The Vendor-Id AVP (see Section 5.3.3) in this grouped AVP identifies
+				the vendor responsible for the assignment of the result code which
+				follows.  All Diameter answer messages defined in vendor-specific
+				applications MUST include either one Result-Code AVP or one
+				Experimental-Result AVP.
+			*/
+			struct dict_avp_data data = { 
+					297, 					/* Code */
+					0, 					/* Vendor */
+					"Experimental-Result", 			/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,			/* Fixed flag values */
+					AVP_TYPE_GROUPED 			/* base type of data */
+					};
+			CHECK_dict_new( DICT_AVP, &data , NULL, NULL);
+		}
+		
+		/* Experimental-Result-Code */
+		{
+			/*
+				The Experimental-Result-Code AVP (AVP Code 298) is of type Unsigned32
+				and contains a vendor-assigned value representing the result of
+				processing the request.
+
+				It is recommended that vendor-specific result codes follow the same
+				conventions given for the Result-Code AVP regarding the different
+				types of result codes and the handling of errors (for non 2xxx
+				values).
+			*/
+			/* Although the RFC does not specify an "Enumerated" type here, we go forward and create one.
+			 * This is the reason for the "*" in the type name. Vendors will have to define their values.
+			 */
+			struct dict_object * 	type;
+			struct dict_type_data 	tdata = { AVP_TYPE_UNSIGNED32,	"Enumerated(Experimental-Result-Code)"	, NULL, NULL, NULL };
+			struct dict_avp_data 	data = { 
+					298, 					/* Code */
+					0, 					/* Vendor */
+					"Experimental-Result-Code", 		/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,			/* Fixed flag values */
+					AVP_TYPE_UNSIGNED32 			/* base type of data */
+					};
+			
+			CHECK_dict_new( DICT_TYPE, &tdata , NULL, &type);
+			CHECK_dict_new( DICT_AVP, &data , type, NULL);
+		}
+		
+		/* Auth-Request-Type */
+		{
+			/*
+				The Auth-Request-Type AVP (AVP Code 274) is of type Enumerated and is
+				included in application-specific auth requests to inform the peers
+				whether a user is to be authenticated only, authorized only or both.
+				Note any value other than both MAY cause RADIUS interoperability
+				issues.  The following values are defined:
+
+
+				AUTHENTICATE_ONLY 1
+
+				The request being sent is for authentication only, and MUST
+				contain the relevant application specific authentication AVPs that
+				are needed by the Diameter server to authenticate the user.
+
+
+				AUTHORIZE_ONLY 2
+
+				The request being sent is for authorization only, and MUST contain
+				the application specific authorization AVPs that are necessary to
+				identify the service being requested/offered.
+
+
+				AUTHORIZE_AUTHENTICATE 3
+
+				The request contains a request for both authentication and
+				authorization.  The request MUST include both the relevant
+				application specific authentication information, and authorization
+				information necessary to identify the service being requested/
+				offered.
+			*/
+			struct dict_object 	* 	type;
+			struct dict_type_data 		tdata = { AVP_TYPE_INTEGER32,	"Enumerated(Auth-Request-Type)"	, NULL, NULL, NULL };
+			struct dict_enumval_data 	t_1 = { "AUTHENTICATE_ONLY", 		{ .i32 = 1 }};
+			struct dict_enumval_data 	t_2 = { "AUTHORIZE_ONLY", 		{ .i32 = 2 }};
+			struct dict_enumval_data 	t_3 = { "AUTHORIZE_AUTHENTICATE", 	{ .i32 = 3 }};
+			struct dict_avp_data 	data = { 
+					274, 					/* Code */
+					0, 					/* Vendor */
+					"Auth-Request-Type", 			/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,			/* Fixed flag values */
+					AVP_TYPE_INTEGER32 			/* base type of data */
+					};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata , NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1 , type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2 , type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_3 , type, NULL);
+			CHECK_dict_new( DICT_AVP, &data , type, NULL);
+		}
+		
+		/* Session-Id */
+		{
+			/*
+				The Session-Id AVP (AVP Code 263) is of type UTF8String and is used
+				to identify a specific session (see Section 8).  All messages
+				pertaining to a specific session MUST include only one Session-Id AVP
+				and the same value MUST be used throughout the life of a session.
+				When present, the Session-Id SHOULD appear immediately following the
+				Diameter Header (see Section 3).
+
+				The Session-Id MUST be globally and eternally unique, as it is meant
+				to uniquely identify a user session without reference to any other
+				information, and may be needed to correlate historical authentication
+				information with accounting information.  The Session-Id includes a
+				mandatory portion and an implementation-defined portion; a
+				recommended format for the implementation-defined portion is outlined
+				below.
+				
+				(skipped, see RFC for detail)
+			*/
+			struct dict_avp_data data = { 
+					263, 					/* Code */
+					#if AC_SESSION_ID != 263
+					#error "AC_SESSION_ID definition mismatch"
+					#endif
+					0, 					/* Vendor */
+					"Session-Id", 				/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,			/* Fixed flag values */
+					AVP_TYPE_OCTETSTRING 			/* base type of data */
+					};
+			CHECK_dict_new( DICT_AVP, &data , UTF8String_type, NULL);
+		}
+		
+		/* Authorization-Lifetime */
+		{
+			/*
+				The Authorization-Lifetime AVP (AVP Code 291) is of type Unsigned32
+				and contains the maximum number of seconds of service to be provided
+				to the user before the user is to be re-authenticated and/or re-
+				authorized.  Great care should be taken when the Authorization-
+				Lifetime value is determined, since a low, non-zero, value could
+				create significant Diameter traffic, which could congest both the
+				network and the agents.
+
+				A value of zero (0) means that immediate re-auth is necessary by the
+				access device.  This is typically used in cases where multiple
+				authentication methods are used, and a successful auth response with
+				this AVP set to zero is used to signal that the next authentication
+				method is to be immediately initiated.  The absence of this AVP, or a
+				value of all ones (meaning all bits in the 32 bit field are set to
+				one) means no re-auth is expected.
+
+				If both this AVP and the Session-Timeout AVP are present in a
+				message, the value of the latter MUST NOT be smaller than the
+				Authorization-Lifetime AVP.
+
+				An Authorization-Lifetime AVP MAY be present in re-authorization
+				messages, and contains the number of seconds the user is authorized
+				to receive service from the time the re-auth answer message is
+				received by the access device.
+
+				This AVP MAY be provided by the client as a hint of the maximum
+				lifetime that it is willing to accept.  However, the server MAY
+				return a value that is equal to, or smaller, than the one provided by
+				the client.
+			*/
+			struct dict_avp_data data = { 
+					291, 					/* Code */
+					0, 					/* Vendor */
+					"Authorization-Lifetime", 		/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,			/* Fixed flag values */
+					AVP_TYPE_UNSIGNED32 			/* base type of data */
+					};
+			CHECK_dict_new( DICT_AVP, &data , NULL, NULL);
+		}
+		
+		/* Auth-Grace-Period */
+		{
+			/*
+				The Auth-Grace-Period AVP (AVP Code 276) is of type Unsigned32 and
+				contains the number of seconds the Diameter server will wait
+				following the expiration of the Authorization-Lifetime AVP before
+				cleaning up resources for the session.
+			*/
+			struct dict_avp_data data = { 
+					276, 					/* Code */
+					0, 					/* Vendor */
+					"Auth-Grace-Period", 			/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,			/* Fixed flag values */
+					AVP_TYPE_UNSIGNED32 			/* base type of data */
+					};
+			CHECK_dict_new( DICT_AVP, &data , NULL, NULL);
+		}
+		
+		/* Auth-Session-State */
+		{
+			/*
+				The Auth-Session-State AVP (AVP Code 277) is of type Enumerated and
+				specifies whether state is maintained for a particular session.  The
+				client MAY include this AVP in requests as a hint to the server, but
+				the value in the server's answer message is binding.  The following
+				values are supported:
+
+
+				STATE_MAINTAINED 0
+
+				This value is used to specify that session state is being
+				maintained, and the access device MUST issue a session termination
+				message when service to the user is terminated.  This is the
+				default value.
+
+
+				NO_STATE_MAINTAINED 1
+
+				This value is used to specify that no session termination messages
+				will be sent by the access device upon expiration of the
+				Authorization-Lifetime.
+			*/
+			struct dict_object 	* 	type;
+			struct dict_type_data	 	tdata = { AVP_TYPE_INTEGER32,	"Enumerated(Auth-Session-State)"	, NULL, NULL, NULL };
+			struct dict_enumval_data 	t_0 = { "STATE_MAINTAINED", 		{ .i32 = 0 }};
+			struct dict_enumval_data 	t_1 = { "NO_STATE_MAINTAINED", 		{ .i32 = 1 }};
+			struct dict_avp_data	 	data = { 
+					277, 					/* Code */
+					0, 					/* Vendor */
+					"Auth-Session-State", 			/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,			/* Fixed flag values */
+					AVP_TYPE_INTEGER32 			/* base type of data */
+					};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata , NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_0 , type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1 , type, NULL);
+			CHECK_dict_new( DICT_AVP, &data , type, NULL);
+		}
+		
+		/* Re-Auth-Request-Type */
+		{
+			/*
+				The Re-Auth-Request-Type AVP (AVP Code 285) is of type Enumerated and
+				is included in application-specific auth answers to inform the client
+				of the action expected upon expiration of the Authorization-Lifetime.
+				If the answer message contains an Authorization-Lifetime AVP with a
+				positive value, the Re-Auth-Request-Type AVP MUST be present in an
+				answer message.  The following values are defined:
+
+
+				AUTHORIZE_ONLY 0
+
+				An authorization only re-auth is expected upon expiration of the
+				Authorization-Lifetime.  This is the default value if the AVP is
+				not present in answer messages that include the Authorization-
+				Lifetime.
+
+
+				AUTHORIZE_AUTHENTICATE 1
+
+				An authentication and authorization re-auth is expected upon
+				expiration of the Authorization-Lifetime.
+			*/
+			struct dict_object 	* 	type;
+			struct dict_type_data	 	tdata = { AVP_TYPE_INTEGER32,	"Enumerated(Re-Auth-Request-Type)"	, NULL, NULL, NULL };
+			struct dict_enumval_data 	t_0 = { "AUTHORIZE_ONLY", 		{ .i32 = 0 }};
+			struct dict_enumval_data 	t_1 = { "AUTHORIZE_AUTHENTICATE",	{ .i32 = 1 }};
+			struct dict_avp_data	 	data = { 
+					285, 					/* Code */
+					0, 					/* Vendor */
+					"Re-Auth-Request-Type",			/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,			/* Fixed flag values */
+					AVP_TYPE_INTEGER32 			/* base type of data */
+					};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata , NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_0 , type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1 , type, NULL);
+			CHECK_dict_new( DICT_AVP, &data , type, NULL);
+		}
+		
+		/* Session-Timeout */
+		{
+			/*
+				The Session-Timeout AVP (AVP Code 27) [RFC2865] is of type Unsigned32
+				and contains the maximum number of seconds of service to be provided
+				to the user before termination of the session.  When both the
+				Session-Timeout and the Authorization-Lifetime AVPs are present in an
+				answer message, the former MUST be equal to or greater than the value
+				of the latter.
+
+				A session that terminates on an access device due to the expiration
+				of the Session-Timeout MUST cause an STR to be issued, unless both
+				the access device and the home server had previously agreed that no
+				session termination messages would be sent (see Section 8.11).
+
+				A Session-Timeout AVP MAY be present in a re-authorization answer
+				message, and contains the remaining number of seconds from the
+				beginning of the re-auth.
+
+				A value of zero, or the absence of this AVP, means that this session
+				has an unlimited number of seconds before termination.
+
+				This AVP MAY be provided by the client as a hint of the maximum
+				timeout that it is willing to accept.  However, the server MAY return
+				a value that is equal to, or smaller, than the one provided by the
+				client.
+			*/
+			struct dict_avp_data data = { 
+					27, 					/* Code */
+					0, 					/* Vendor */
+					"Session-Timeout", 			/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,			/* Fixed flag values */
+					AVP_TYPE_UNSIGNED32 			/* base type of data */
+					};
+			CHECK_dict_new( DICT_AVP, &data , NULL, NULL);
+		}
+		
+		/* User-Name */
+		{
+			/*
+				The User-Name AVP (AVP Code 1) [RFC2865] is of type UTF8String, which
+				contains the User-Name, in a format consistent with the NAI
+				specification [RFC4282].
+			*/
+			struct dict_avp_data data = { 
+					1, 					/* Code */
+					0, 					/* Vendor */
+					"User-Name", 				/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,			/* Fixed flag values */
+					AVP_TYPE_OCTETSTRING 			/* base type of data */
+					};
+			CHECK_dict_new( DICT_AVP, &data , UTF8String_type, NULL);
+		}
+		
+		/* Termination-Cause */
+		{
+			/*
+				The Termination-Cause AVP (AVP Code 295) is of type Enumerated, and
+				is used to indicate the reason why a session was terminated on the
+				access device.  The following values are defined:
+
+
+				DIAMETER_LOGOUT 1
+
+				The user initiated a disconnect
+
+
+				DIAMETER_SERVICE_NOT_PROVIDED 2
+
+				This value is used when the user disconnected prior to the receipt
+				of the authorization answer message.
+
+
+				DIAMETER_BAD_ANSWER 3
+
+				This value indicates that the authorization answer received by the
+				access device was not processed successfully.
+
+
+				DIAMETER_ADMINISTRATIVE 4
+
+				The user was not granted access, or was disconnected, due to
+				administrative reasons, such as the receipt of a Abort-Session-
+				Request message.
+
+
+				DIAMETER_LINK_BROKEN 5
+
+				The communication to the user was abruptly disconnected.
+
+
+				DIAMETER_AUTH_EXPIRED 6
+
+				The user's access was terminated since its authorized session time
+				has expired.
+
+
+				DIAMETER_USER_MOVED 7
+
+				The user is receiving services from another access device.
+
+
+				DIAMETER_SESSION_TIMEOUT 8
+
+				The user's session has timed out, and service has been terminated.
+			*/
+			struct dict_object 	* 	type;
+			struct dict_type_data	 	tdata = { AVP_TYPE_INTEGER32,	"Enumerated(Termination-Cause)"	, NULL, NULL, NULL };
+			struct dict_enumval_data 	t_1 = { "DIAMETER_LOGOUT",			{ .i32 = 1 }};
+			struct dict_enumval_data 	t_2 = { "DIAMETER_SERVICE_NOT_PROVIDED", 	{ .i32 = 2 }};
+			struct dict_enumval_data 	t_3 = { "DIAMETER_BAD_ANSWER",			{ .i32 = 3 }};
+			struct dict_enumval_data 	t_4 = { "DIAMETER_ADMINISTRATIVE", 		{ .i32 = 4 }};
+			struct dict_enumval_data 	t_5 = { "DIAMETER_LINK_BROKEN",			{ .i32 = 5 }};
+			struct dict_enumval_data 	t_6 = { "DIAMETER_AUTH_EXPIRED", 		{ .i32 = 6 }};
+			struct dict_enumval_data 	t_7 = { "DIAMETER_USER_MOVED",			{ .i32 = 7 }};
+			struct dict_enumval_data 	t_8 = { "DIAMETER_SESSION_TIMEOUT", 		{ .i32 = 8 }};
+			struct dict_avp_data 	data = { 
+					295, 					/* Code */
+					0, 					/* Vendor */
+					"Termination-Cause",			/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,			/* Fixed flag values */
+					AVP_TYPE_INTEGER32 			/* base type of data */
+					};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata , NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1 , type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2 , type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_3 , type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_4 , type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_5 , type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_6 , type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_7 , type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_8 , type, NULL);
+			CHECK_dict_new( DICT_AVP, &data , type, NULL);
+		}
+		
+		/* Origin-State-Id */
+		{
+			/*
+				The Origin-State-Id AVP (AVP Code 278), of type Unsigned32, is a
+				monotonically increasing value that is advanced whenever a Diameter
+				entity restarts with loss of previous state, for example upon reboot.
+				Origin-State-Id MAY be included in any Diameter message, including
+				CER.
+
+				A Diameter entity issuing this AVP MUST create a higher value for
+				this AVP each time its state is reset.  A Diameter entity MAY set
+				Origin-State-Id to the time of startup, or it MAY use an incrementing
+				counter retained in non-volatile memory across restarts.
+
+				The Origin-State-Id, if present, MUST reflect the state of the entity
+				indicated by Origin-Host.  If a proxy modifies Origin-Host, it MUST
+				either remove Origin-State-Id or modify it appropriately as well.
+				Typically, Origin-State-Id is used by an access device that always
+				starts up with no active sessions; that is, any session active prior
+				to restart will have been lost.  By including Origin-State-Id in a
+				message, it allows other Diameter entities to infer that sessions
+				associated with a lower Origin-State-Id are no longer active.  If an
+				access device does not intend for such inferences to be made, it MUST
+				either not include Origin-State-Id in any message, or set its value
+				to 0.
+			*/
+			struct dict_avp_data data = { 
+					278, 					/* Code */
+					0, 					/* Vendor */
+					"Origin-State-Id", 			/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,			/* Fixed flag values */
+					AVP_TYPE_UNSIGNED32 			/* base type of data */
+					};
+			CHECK_dict_new( DICT_AVP, &data , NULL, NULL);
+		}
+		
+		/* Session-Binding */
+		{
+			/*
+				The Session-Binding AVP (AVP Code 270) is of type Unsigned32, and MAY
+				be present in application-specific authorization answer messages.  If
+				present, this AVP MAY inform the Diameter client that all future
+				application-specific re-auth messages for this session MUST be sent
+				to the same authorization server.  This AVP MAY also specify that a
+				Session-Termination-Request message for this session MUST be sent to
+				the same authorizing server.
+
+				This field is a bit mask, and the following bits have been defined:
+
+
+				RE_AUTH 1
+
+				When set, future re-auth messages for this session MUST NOT
+				include the Destination-Host AVP.  When cleared, the default
+				value, the Destination-Host AVP MUST be present in all re-auth
+				messages for this session.
+
+
+				STR 2
+
+				When set, the STR message for this session MUST NOT include the
+				Destination-Host AVP.  When cleared, the default value, the
+				Destination-Host AVP MUST be present in the STR message for this
+				session.
+
+
+				ACCOUNTING 4
+
+				When set, all accounting messages for this session MUST NOT
+				include the Destination-Host AVP.  When cleared, the default
+				value, the Destination-Host AVP, if known, MUST be present in all
+				accounting messages for this session.
+			*/
+			
+			/* Although the RFC does not specify an "Enumerated" type here, we go forward and create one.
+			 * This is the reason for the "*" in the type name
+			 * The actual values of the AVP will not always be defined here, but at least it can be used in some cases.
+			 *  ... maybe the code will be changed later to support bitfields AVP ...
+			 */
+			
+			struct dict_object 	* 	type;
+			struct dict_type_data	 	tdata = { AVP_TYPE_UNSIGNED32,	"Enumerated(Session-Binding)"	, NULL, NULL, NULL };
+			struct dict_enumval_data 	t_1 = { "RE_AUTH", 		{ .u32 = 1 }};
+			struct dict_enumval_data 	t_2 = { "STR", 			{ .u32 = 2 }};
+			struct dict_enumval_data 	t_4 = { "ACCOUNTING", 		{ .u32 = 4 }};
+			struct dict_avp_data 	data = { 
+					270, 					/* Code */
+					0, 					/* Vendor */
+					"Session-Binding", 			/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,			/* Fixed flag values */
+					AVP_TYPE_UNSIGNED32 			/* base type of data */
+					};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata , NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1 , type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2 , type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_4 , type, NULL);
+			CHECK_dict_new( DICT_AVP, &data , type, NULL);
+		}
+		
+		/* Session-Server-Failover */
+		{
+			/*
+				The Session-Server-Failover AVP (AVP Code 271) is of type Enumerated,
+				and MAY be present in application-specific authorization answer
+				messages that either do not include the Session-Binding AVP or
+				include the Session-Binding AVP with any of the bits set to a zero
+				value.  If present, this AVP MAY inform the Diameter client that if a
+				re-auth or STR message fails due to a delivery problem, the Diameter
+				client SHOULD issue a subsequent message without the Destination-Host
+				AVP.  When absent, the default value is REFUSE_SERVICE.
+
+				The following values are supported:
+
+
+				REFUSE_SERVICE 0
+
+				If either the re-auth or the STR message delivery fails, terminate
+				service with the user, and do not attempt any subsequent attempts.
+
+
+				TRY_AGAIN 1
+
+				If either the re-auth or the STR message delivery fails, resend
+				the failed message without the Destination-Host AVP present.
+
+
+				ALLOW_SERVICE 2
+
+				If re-auth message delivery fails, assume that re-authorization
+				succeeded.  If STR message delivery fails, terminate the session.
+
+
+				TRY_AGAIN_ALLOW_SERVICE 3
+
+				If either the re-auth or the STR message delivery fails, resend
+				the failed message without the Destination-Host AVP present.  If
+				the second delivery fails for re-auth, assume re-authorization
+				succeeded.  If the second delivery fails for STR, terminate the
+				session.
+			*/
+			struct dict_object  	* 	type;
+			struct dict_type_data	 	tdata = { AVP_TYPE_INTEGER32,	"Enumerated(Session-Server-Failover)"	, NULL, NULL, NULL };
+			struct dict_enumval_data 	t_0 = { "REFUSE_SERVICE", 		{ .i32 = 0 }};
+			struct dict_enumval_data 	t_1 = { "TRY_AGAIN",			{ .i32 = 1 }};
+			struct dict_enumval_data 	t_2 = { "ALLOW_SERVICE", 		{ .i32 = 2 }};
+			struct dict_enumval_data 	t_3 = { "TRY_AGAIN_ALLOW_SERVICE",	{ .i32 = 3 }};
+			struct dict_avp_data	 	data = { 
+					271, 					/* Code */
+					0, 					/* Vendor */
+					"Session-Server-Failover",		/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,			/* Fixed flag values */
+					AVP_TYPE_INTEGER32 			/* base type of data */
+					};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata , NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_0 , type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1 , type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2 , type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_3 , type, NULL);
+			CHECK_dict_new( DICT_AVP, &data , type, NULL);
+		}
+		
+		/* Multi-Round-Time-Out */
+		{
+			/*
+				The Multi-Round-Time-Out AVP (AVP Code 272) is of type Unsigned32,
+				and SHOULD be present in application-specific authorization answer
+				messages whose Result-Code AVP is set to DIAMETER_MULTI_ROUND_AUTH.
+				This AVP contains the maximum number of seconds that the access
+				device MUST provide the user in responding to an authentication
+				request.
+			*/
+			struct dict_avp_data data = { 
+					272, 					/* Code */
+					0, 					/* Vendor */
+					"Multi-Round-Time-Out", 			/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,			/* Fixed flag values */
+					AVP_TYPE_UNSIGNED32 			/* base type of data */
+					};
+			CHECK_dict_new( DICT_AVP, &data , NULL, NULL);
+		}
+		
+		/* Class */
+		{
+			/*
+				The Class AVP (AVP Code 25) is of type OctetString and is used to by
+				Diameter servers to return state information to the access device.
+				When one or more Class AVPs are present in application-specific
+				authorization answer messages, they MUST be present in subsequent re-
+				authorization, session termination and accounting messages.  Class
+				AVPs found in a re-authorization answer message override the ones
+				found in any previous authorization answer message.  Diameter server
+				implementations SHOULD NOT return Class AVPs that require more than
+				4096 bytes of storage on the Diameter client.  A Diameter client that
+				receives Class AVPs whose size exceeds local available storage MUST
+				terminate the session.
+			*/
+			struct dict_avp_data data = { 
+					25, 					/* Code */
+					0, 					/* Vendor */
+					"Class", 				/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,			/* Fixed flag values */
+					AVP_TYPE_OCTETSTRING 			/* base type of data */
+					};
+			CHECK_dict_new( DICT_AVP, &data , NULL, NULL);
+		}
+		
+		/* Event-Timestamp */
+		{
+			/*
+				The Event-Timestamp (AVP Code 55) is of type Time, and MAY be
+				included in an Accounting-Request and Accounting-Answer messages to
+				record the time that the reported event occurred, in seconds since
+				January 1, 1900 00:00 UTC.
+			*/
+			struct dict_avp_data data = { 
+					55, 					/* Code */
+					0, 					/* Vendor */
+					"Event-Timestamp", 			/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,			/* Fixed flag values */
+					AVP_TYPE_OCTETSTRING 			/* base type of data */
+					};
+			CHECK_dict_new( DICT_AVP, &data , Time_type, NULL);
+		}
+
+				
+		/* Accounting-Record-Type */
+		{
+			/*
+				The Accounting-Record-Type AVP (AVP Code 480) is of type Enumerated
+				and contains the type of accounting record being sent.  The following
+				values are currently defined for the Accounting-Record-Type AVP:
+
+
+				EVENT_RECORD 1
+
+				An Accounting Event Record is used to indicate that a one-time
+				event has occurred (meaning that the start and end of the event
+				are simultaneous).  This record contains all information relevant
+				to the service, and is the only record of the service.
+
+
+				START_RECORD 2
+
+				An Accounting Start, Interim, and Stop Records are used to
+				indicate that a service of a measurable length has been given.  An
+				Accounting Start Record is used to initiate an accounting session,
+				and contains accounting information that is relevant to the
+				initiation of the session.
+
+
+				INTERIM_RECORD 3
+
+				An Interim Accounting Record contains cumulative accounting
+				information for an existing accounting session.  Interim
+				Accounting Records SHOULD be sent every time a re-authentication
+				or re-authorization occurs.  Further, additional interim record
+				triggers MAY be defined by application-specific Diameter
+				applications.  The selection of whether to use INTERIM_RECORD
+				records is done by the Acct-Interim-Interval AVP.
+
+
+				STOP_RECORD 4
+
+				An Accounting Stop Record is sent to terminate an accounting
+				session and contains cumulative accounting information relevant to
+				the existing session.
+			*/
+			struct dict_object 	* 	type;
+			struct dict_type_data	  	tdata = { AVP_TYPE_INTEGER32,	"Enumerated(Accounting-Record-Type)"	, NULL, NULL, NULL };
+			struct dict_enumval_data 	t_1 = { "EVENT_RECORD",			{ .i32 = 1 }};
+			struct dict_enumval_data 	t_2 = { "START_RECORD", 		{ .i32 = 2 }};
+			struct dict_enumval_data 	t_3 = { "INTERIM_RECORD",		{ .i32 = 3 }};
+			struct dict_enumval_data 	t_4 = { "STOP_RECORD", 			{ .i32 = 4 }};
+			struct dict_avp_data 	data = { 
+					480, 					/* Code */
+					0, 					/* Vendor */
+					"Accounting-Record-Type",		/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,			/* Fixed flag values */
+					AVP_TYPE_INTEGER32 			/* base type of data */
+					};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata , NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1 , type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2 , type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_3 , type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_4 , type, NULL);
+			CHECK_dict_new( DICT_AVP, &data , type, NULL);
+		}
+		
+		/* Acct-Interim-Interval */
+		{
+			/*
+				The Acct-Interim-Interval AVP (AVP Code 85) is of type Unsigned32 and
+				is sent from the Diameter home authorization server to the Diameter
+				client.  The client uses information in this AVP to decide how and
+				when to produce accounting records.  With different values in this
+				AVP, service sessions can result in one, two, or two+N accounting
+				records, based on the needs of the home-organization.  The following
+				accounting record production behavior is directed by the inclusion of
+				this AVP:
+
+
+				1.  The omission of the Acct-Interim-Interval AVP or its inclusion
+				with Value field set to 0 means that EVENT_RECORD, START_RECORD,
+				and STOP_RECORD are produced, as appropriate for the service.
+
+
+				2.  The inclusion of the AVP with Value field set to a non-zero value
+				means that INTERIM_RECORD records MUST be produced between the
+				START_RECORD and STOP_RECORD records.  The Value field of this
+				AVP is the nominal interval between these records in seconds.
+
+				The Diameter node that originates the accounting information,
+				known as the client, MUST produce the first INTERIM_RECORD record
+				roughly at the time when this nominal interval has elapsed from
+				the START_RECORD, the next one again as the interval has elapsed
+				once more, and so on until the session ends and a STOP_RECORD
+				record is produced.
+
+				The client MUST ensure that the interim record production times
+				are randomized so that large accounting message storms are not
+				created either among records or around a common service start
+				time.
+			*/
+			struct dict_avp_data data = { 
+					85, 					/* Code */
+					0, 					/* Vendor */
+					"Acct-Interim-Interval", 		/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,			/* Fixed flag values */
+					AVP_TYPE_UNSIGNED32 			/* base type of data */
+					};
+			CHECK_dict_new( DICT_AVP, &data , NULL, NULL);
+		}
+		
+		/* Accounting-Record-Number */
+		{
+			/*
+				The Accounting-Record-Number AVP (AVP Code 485) is of type Unsigned32
+				and identifies this record within one session.  As Session-Id AVPs
+				are globally unique, the combination of Session-Id and Accounting-
+				Record-Number AVPs is also globally unique, and can be used in
+				matching accounting records with confirmations.  An easy way to
+				produce unique numbers is to set the value to 0 for records of type
+				EVENT_RECORD and START_RECORD, and set the value to 1 for the first
+				INTERIM_RECORD, 2 for the second, and so on until the value for
+				STOP_RECORD is one more than for the last INTERIM_RECORD.
+			*/
+			struct dict_avp_data data = { 
+					485, 					/* Code */
+					0, 					/* Vendor */
+					"Accounting-Record-Number", 		/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,			/* Fixed flag values */
+					AVP_TYPE_UNSIGNED32 			/* base type of data */
+					};
+			CHECK_dict_new( DICT_AVP, &data , NULL, NULL);
+		}
+		
+		/* Acct-Session-Id */
+		{
+			/*
+				The Acct-Session-Id AVP (AVP Code 44) is of type OctetString is only
+				used when RADIUS/Diameter translation occurs.  This AVP contains the
+				contents of the RADIUS Acct-Session-Id attribute.
+			*/
+			struct dict_avp_data data = { 
+					44, 					/* Code */
+					0, 					/* Vendor */
+					"Acct-Session-Id", 			/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,			/* Fixed flag values */
+					AVP_TYPE_OCTETSTRING 			/* base type of data */
+					};
+			CHECK_dict_new( DICT_AVP, &data , NULL, NULL);
+		}
+		
+		/* Acct-Multi-Session-Id */
+		{
+			/*
+				The Acct-Multi-Session-Id AVP (AVP Code 50) is of type UTF8String,
+				following the format specified in Section 8.8.  The Acct-Multi-
+				Session-Id AVP is used to link together multiple related accounting
+				sessions, where each session would have a unique Session-Id, but the
+				same Acct-Multi-Session-Id AVP.  This AVP MAY be returned by the
+				Diameter server in an authorization answer, and MUST be used in all
+				accounting messages for the given session.
+			*/
+			struct dict_avp_data data = { 
+					50, 					/* Code */
+					0, 					/* Vendor */
+					"Acct-Multi-Session-Id", 		/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,			/* Fixed flag values */
+					AVP_TYPE_OCTETSTRING 			/* base type of data */
+					};
+			CHECK_dict_new( DICT_AVP, &data , UTF8String_type, NULL);
+		}
+		
+		/* Accounting-Sub-Session-Id */
+		{
+			/*
+				The Accounting-Sub-Session-Id AVP (AVP Code 287) is of type
+				Unsigned64 and contains the accounting sub-session identifier.  The
+				combination of the Session-Id and this AVP MUST be unique per sub-
+				session, and the value of this AVP MUST be monotonically increased by
+				one for all new sub-sessions.  The absence of this AVP implies no
+				sub-sessions are in use, with the exception of an Accounting-Request
+				whose Accounting-Record-Type is set to STOP_RECORD.  A STOP_RECORD
+				message with no Accounting-Sub-Session-Id AVP present will signal the
+				termination of all sub-sessions for a given Session-Id.
+			*/
+			struct dict_avp_data data = { 
+					287, 					/* Code */
+					0, 					/* Vendor */
+					"Accounting-Sub-Session-Id", 		/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,			/* Fixed flag values */
+					AVP_TYPE_UNSIGNED64 			/* base type of data */
+					};
+			CHECK_dict_new( DICT_AVP, &data , NULL, NULL);
+		}
+		
+		/* Accounting-Realtime-Required */
+		{
+			/*
+				The Accounting-Realtime-Required AVP (AVP Code 483) is of type
+				Enumerated and is sent from the Diameter home authorization server to
+				the Diameter client or in the Accounting-Answer from the accounting
+				server.  The client uses information in this AVP to decide what to do
+				if the sending of accounting records to the accounting server has
+				been temporarily prevented due to, for instance, a network problem.
+
+
+				DELIVER_AND_GRANT 1
+
+				The AVP with Value field set to DELIVER_AND_GRANT means that the
+				service MUST only be granted as long as there is a connection to
+				an accounting server.  Note that the set of alternative accounting
+				servers are treated as one server in this sense.  Having to move
+				the accounting record stream to a backup server is not a reason to
+				discontinue the service to the user.
+
+
+				GRANT_AND_STORE 2
+
+				The AVP with Value field set to GRANT_AND_STORE means that service
+				SHOULD be granted if there is a connection, or as long as records
+				can still be stored as described in Section 9.4.
+
+				This is the default behavior if the AVP isn't included in the
+				reply from the authorization server.
+
+
+				GRANT_AND_LOSE 3
+
+				The AVP with Value field set to GRANT_AND_LOSE means that service
+				SHOULD be granted even if the records can not be delivered or
+				stored.
+			*/
+			struct dict_object  	* 	type;
+			struct dict_type_data	 	tdata = { AVP_TYPE_INTEGER32,	"Enumerated(Accounting-Realtime-Required)"	, NULL, NULL, NULL };
+			struct dict_enumval_data 	t_1 = { "DELIVER_AND_GRANT",		{ .i32 = 1 }};
+			struct dict_enumval_data 	t_2 = { "GRANT_AND_STORE", 		{ .i32 = 2 }};
+			struct dict_enumval_data 	t_3 = { "GRANT_AND_LOSE",		{ .i32 = 3 }};
+			struct dict_avp_data 		data = { 
+					483, 					/* Code */
+					0, 					/* Vendor */
+					"Accounting-Realtime-Required",		/* Name */
+					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
+					AVP_FLAG_MANDATORY,			/* Fixed flag values */
+					AVP_TYPE_INTEGER32 			/* base type of data */
+					};
+			/* Create the Enumerated type, and then the AVP */
+			CHECK_dict_new( DICT_TYPE, &tdata , NULL, &type);
+			CHECK_dict_new( DICT_ENUMVAL, &t_1 , type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_2 , type, NULL);
+			CHECK_dict_new( DICT_ENUMVAL, &t_3 , type, NULL);
+			CHECK_dict_new( DICT_AVP, &data , type, NULL);
+		}
+		
+	}
+	
+	/* Commands section */
+	{
+		/* To avoid defining global variables for all the AVP that we use here, we do search the dictionary in each sub-block.
+		 * This is far from optimal, but the code is clearer like this, and the time it requires at execution is not noticeable.
+		 */
+		
+		/* Generic message syntax when the 'E' bit is set */
+		{
+			/*
+				The 'E' (Error Bit) in the Diameter header is set when the request
+				caused a protocol-related error (see Section 7.1.3).  A message with
+				the 'E' bit MUST NOT be sent as a response to an answer message.
+				Note that a message with the 'E' bit set is still subjected to the
+				processing rules defined in Section 6.2.  When set, the answer
+				message will not conform to the ABNF specification for the command,
+				and will instead conform to the following ABNF:
+
+				Message Format
+
+				<answer-message> ::= < Diameter Header: code, ERR [PXY] >
+                				0*1< Session-Id >
+                				   { Origin-Host }
+                				   { Origin-Realm }
+                				   { Result-Code }
+                				   [ Origin-State-Id ]
+                				   [ Error-Message ]
+                				   [ Error-Reporting-Host ]
+                				   [ Failed-AVP ]
+                				 * [ Proxy-Info ]
+                				 * [ AVP ]
+
+				Note that the code used in the header is the same than the one found
+				in the request message, but with the 'R' bit cleared and the 'E' bit
+				set.  The 'P' bit in the header is set to the same value as the one
+				found in the request message.
+			*/
+			struct dict_object * cmd_error;
+			struct local_rules_definition rules[] = 
+						{ 	 {  "Session-Id", 			RULE_FIXED_HEAD,0, 1 }
+							,{  "Origin-Host",			RULE_REQUIRED, -1, 1 }
+							,{  "Origin-Realm",			RULE_REQUIRED, -1, 1 }
+							,{  "Result-Code",			RULE_REQUIRED, -1, 1 }
+							,{  "Origin-State-Id",			RULE_OPTIONAL, -1, 1 }
+							,{  "Error-Message",			RULE_OPTIONAL, -1, 1 }
+							,{  "Error-Reporting-Host",		RULE_OPTIONAL, -1, 1 }
+							,{  "Failed-AVP",			RULE_OPTIONAL, -1, 1 }
+							,{  "Proxy-Info",			RULE_OPTIONAL, -1,-1 }
+						};
+			CHECK_FCT( fd_dict_get_error_cmd(dict, &cmd_error) );
+			PARSE_loc_rules( rules, cmd_error );
+		}		
+		
+		/* Capabilities-Exchange-Request */
+		{
+			/*
+				The Capabilities-Exchange-Request (CER), indicated by the Command-
+				Code set to 257 and the Command Flags' 'R' bit set, is sent to
+				exchange local capabilities.  Upon detection of a transport failure,
+				this message MUST NOT be sent to an alternate peer.
+
+				When Diameter is run over SCTP [RFC2960], which allows for
+				connections to span multiple interfaces and multiple IP addresses,
+				the Capabilities-Exchange-Request message MUST contain one Host-IP-
+				Address AVP for each potential IP address that MAY be locally used
+				when transmitting Diameter messages.
+
+				Message Format
+
+				 <CER> ::= < Diameter Header: 257, REQ >
+        				   { Origin-Host }
+        				   { Origin-Realm }
+        				1* { Host-IP-Address }
+        				   { Vendor-Id }
+        				   { Product-Name }
+        				   [ Origin-State-Id ]
+        				 * [ Supported-Vendor-Id ]
+        				 * [ Auth-Application-Id ]
+        				 * [ Inband-Security-Id ]
+        				 * [ Acct-Application-Id ]
+        				 * [ Vendor-Specific-Application-Id ]
+        				   [ Firmware-Revision ]
+        				 * [ AVP ]
+			*/
+			struct dict_object * cmd;
+			struct dict_cmd_data data = { 
+					257, 					/* Code */
+					#if CC_CAPABILITIES_EXCHANGE != 257
+					#error "CC_CAPABILITIES_EXCHANGE definition mismatch"
+					#endif
+					"Capabilities-Exchange-Request", 	/* Name */
+					CMD_FLAG_REQUEST | CMD_FLAG_PROXIABLE | CMD_FLAG_RETRANSMIT | CMD_FLAG_ERROR, 	/* Fixed flags */
+					CMD_FLAG_REQUEST 			/* Fixed flag values */
+					};
+			struct local_rules_definition rules[] = 
+						{ 	 {  "Origin-Host", 			RULE_REQUIRED, -1, 1 }
+							,{  "Origin-Realm",			RULE_REQUIRED, -1, 1 }
+							,{  "Host-IP-Address",			RULE_REQUIRED, -1,-1 }
+							,{  "Vendor-Id",			RULE_REQUIRED, -1, 1 }
+							,{  "Product-Name",			RULE_REQUIRED, -1, 1 }
+							,{  "Origin-State-Id",			RULE_OPTIONAL, -1, 1 }
+							,{  "Supported-Vendor-Id",		RULE_OPTIONAL, -1,-1 }
+							,{  "Auth-Application-Id",		RULE_OPTIONAL, -1,-1 }
+							,{  "Inband-Security-Id",		RULE_OPTIONAL, -1,-1 }
+							,{  "Acct-Application-Id",		RULE_OPTIONAL, -1,-1 }
+							,{  "Vendor-Specific-Application-Id",	RULE_OPTIONAL, -1,-1 }
+							,{  "Firmware-Revision",		RULE_OPTIONAL, -1, 1 }
+						};
+			
+			CHECK_dict_new( DICT_COMMAND, &data , NULL, &cmd);
+			PARSE_loc_rules( rules, cmd );
+		}
+		
+		/* Capabilities-Exchange-Answer */
+		{
+			/*
+				The Capabilities-Exchange-Answer (CEA), indicated by the Command-Code
+				set to 257 and the Command Flags' 'R' bit cleared, is sent in
+				response to a CER message.
+
+				When Diameter is run over SCTP [RFC2960], which allows connections to
+				span multiple interfaces, hence, multiple IP addresses, the
+				Capabilities-Exchange-Answer message MUST contain one Host-IP-Address
+				AVP for each potential IP address that MAY be locally used when
+				transmitting Diameter messages.
+
+				Message Format
+
+				 <CEA> ::= < Diameter Header: 257 >
+        				   { Result-Code }
+        				   { Origin-Host }
+        				   { Origin-Realm }
+        				1* { Host-IP-Address }
+        				   { Vendor-Id }
+        				   { Product-Name }
+        				   [ Origin-State-Id ]
+        				   [ Error-Message ]
+        				   [ Failed-AVP ]
+        				 * [ Supported-Vendor-Id ]
+        				 * [ Auth-Application-Id ]
+        				 * [ Inband-Security-Id ]
+        				 * [ Acct-Application-Id ]
+        				 * [ Vendor-Specific-Application-Id ]
+        				   [ Firmware-Revision ]
+        				 * [ AVP ]
+			*/
+			struct dict_object * cmd;
+			struct dict_cmd_data data = { 
+					257, 					/* Code */
+					#if CC_CAPABILITIES_EXCHANGE != 257
+					#error "CC_CAPABILITIES_EXCHANGE definition mismatch"
+					#endif
+					"Capabilities-Exchange-Answer", 	/* Name */
+					CMD_FLAG_REQUEST | CMD_FLAG_PROXIABLE | CMD_FLAG_RETRANSMIT, 	/* Fixed flags */
+					0 					/* Fixed flag values */
+					};
+			struct local_rules_definition rules[] = 
+						{ 	 {  "Result-Code", 			RULE_REQUIRED, -1, 1 }
+						 	,{  "Origin-Host", 			RULE_REQUIRED, -1, 1 }
+							,{  "Origin-Realm",			RULE_REQUIRED, -1, 1 }
+							,{  "Host-IP-Address",			RULE_REQUIRED, -1,-1 }
+							,{  "Vendor-Id",			RULE_REQUIRED, -1, 1 }
+							,{  "Product-Name",			RULE_REQUIRED, -1, 1 }
+							,{  "Origin-State-Id",			RULE_OPTIONAL, -1, 1 }
+							,{  "Error-Message",			RULE_OPTIONAL, -1, 1 }
+							,{  "Failed-AVP",			RULE_OPTIONAL, -1, 1 }
+							,{  "Supported-Vendor-Id",		RULE_OPTIONAL, -1,-1 }
+							,{  "Auth-Application-Id",		RULE_OPTIONAL, -1,-1 }
+							,{  "Inband-Security-Id",		RULE_OPTIONAL, -1,-1 }
+							,{  "Acct-Application-Id",		RULE_OPTIONAL, -1,-1 }
+							,{  "Vendor-Specific-Application-Id",	RULE_OPTIONAL, -1,-1 }
+							,{  "Firmware-Revision",		RULE_OPTIONAL, -1, 1 }
+						};
+			
+			CHECK_dict_new( DICT_COMMAND, &data , NULL, &cmd);
+			PARSE_loc_rules( rules, cmd );
+		}
+		
+		/* Disconnect-Peer-Request */
+		{
+			/*
+				The Disconnect-Peer-Request (DPR), indicated by the Command-Code set
+				to 282 and the Command Flags' 'R' bit set, is sent to a peer to
+				inform its intentions to shutdown the transport connection.  Upon
+				detection of a transport failure, this message MUST NOT be sent to an
+				alternate peer.
+
+				Message Format
+
+				 <DPR>  ::= < Diameter Header: 282, REQ >
+        				    { Origin-Host }
+        				    { Origin-Realm }
+        				    { Disconnect-Cause }
+			*/
+			struct dict_object * cmd;
+			struct dict_cmd_data data = { 
+					282, 					/* Code */
+					#if CC_DISCONNECT_PEER != 282
+					#error "CC_DISCONNECT_PEER definition mismatch"
+					#endif
+					"Disconnect-Peer-Request", 		/* Name */
+					CMD_FLAG_REQUEST | CMD_FLAG_PROXIABLE | CMD_FLAG_RETRANSMIT | CMD_FLAG_ERROR, 	/* Fixed flags */
+					CMD_FLAG_REQUEST 			/* Fixed flag values */
+					};
+			struct local_rules_definition rules[] = 
+						{ 	 {  "Origin-Host", 			RULE_REQUIRED, -1, 1 }
+							,{  "Origin-Realm",			RULE_REQUIRED, -1, 1 }
+							,{  "Disconnect-Cause",			RULE_REQUIRED, -1, 1 }
+						};
+			
+			CHECK_dict_new( DICT_COMMAND, &data , NULL, &cmd);
+			PARSE_loc_rules( rules, cmd );
+		}
+		
+		/* Disconnect-Peer-Answer */
+		{
+			/*
+				The Disconnect-Peer-Answer (DPA), indicated by the Command-Code set
+				to 282 and the Command Flags' 'R' bit cleared, is sent as a response
+				to the Disconnect-Peer-Request message.  Upon receipt of this
+				message, the transport connection is shutdown.
+
+				Message Format
+
+				 <DPA>  ::= < Diameter Header: 282 >
+        				    { Result-Code }
+        				    { Origin-Host }
+        				    { Origin-Realm }
+        				    [ Error-Message ]
+        				    [ Failed-AVP ]
+			*/
+			struct dict_object * cmd;
+			struct dict_cmd_data data = { 
+					282, 					/* Code */
+					#if CC_DISCONNECT_PEER != 282
+					#error "CC_DISCONNECT_PEER definition mismatch"
+					#endif
+					"Disconnect-Peer-Answer", 		/* Name */
+					CMD_FLAG_REQUEST | CMD_FLAG_PROXIABLE | CMD_FLAG_RETRANSMIT, 	/* Fixed flags */
+					0 					/* Fixed flag values */
+					};
+			struct local_rules_definition rules[] = 
+						{ 	 {  "Result-Code", 			RULE_REQUIRED, -1, 1 }
+						 	,{  "Origin-Host", 			RULE_REQUIRED, -1, 1 }
+							,{  "Origin-Realm",			RULE_REQUIRED, -1, 1 }
+							,{  "Error-Message",			RULE_OPTIONAL, -1, 1 }
+							,{  "Failed-AVP",			RULE_OPTIONAL, -1, 1 }
+						};
+			
+			CHECK_dict_new( DICT_COMMAND, &data , NULL, &cmd);
+			PARSE_loc_rules( rules, cmd );
+		}
+
+		/* Device-Watchdog-Request */
+		{
+			/*
+				The Device-Watchdog-Request (DWR), indicated by the Command-Code set
+				to 280 and the Command Flags' 'R' bit set, is sent to a peer when no
+				traffic has been exchanged between two peers (see Section 5.5.3).
+				Upon detection of a transport failure, this message MUST NOT be sent
+				to an alternate peer.
+
+				Message Format
+
+				 <DWR>  ::= < Diameter Header: 280, REQ >
+        				    { Origin-Host }
+        				    { Origin-Realm }
+        				    [ Origin-State-Id ]
+			*/
+			struct dict_object * cmd;
+			struct dict_cmd_data data = { 
+					280, 					/* Code */
+					#if CC_DEVICE_WATCHDOG != 280
+					#error "CC_DEVICE_WATCHDOG definition mismatch"
+					#endif
+					"Device-Watchdog-Request", 		/* Name */
+					CMD_FLAG_REQUEST | CMD_FLAG_PROXIABLE | CMD_FLAG_RETRANSMIT | CMD_FLAG_ERROR, 	/* Fixed flags */
+					CMD_FLAG_REQUEST 			/* Fixed flag values */
+					};
+			struct local_rules_definition rules[] = 
+						{ 	 {  "Origin-Host", 			RULE_REQUIRED, -1, 1 }
+							,{  "Origin-Realm",			RULE_REQUIRED, -1, 1 }
+							,{  "Origin-State-Id",			RULE_OPTIONAL, -1, 1 }
+						};
+			
+			CHECK_dict_new( DICT_COMMAND, &data , NULL, &cmd);
+			PARSE_loc_rules( rules, cmd );
+		}
+		
+		/* Device-Watchdog-Answer */
+		{
+			/*
+				The Device-Watchdog-Answer (DWA), indicated by the Command-Code set
+				to 280 and the Command Flags' 'R' bit cleared, is sent as a response
+				to the Device-Watchdog-Request message.
+
+				Message Format
+
+				 <DWA>  ::= < Diameter Header: 280 >
+        				    { Result-Code }
+        				    { Origin-Host }
+        				    { Origin-Realm }
+        				    [ Error-Message ]
+        				    [ Failed-AVP ]
+        				    [ Origin-State-Id ]
+			*/
+			struct dict_object * cmd;
+			struct dict_cmd_data data = { 
+					280, 					/* Code */
+					#if CC_DEVICE_WATCHDOG != 280
+					#error "CC_DEVICE_WATCHDOG definition mismatch"
+					#endif
+					"Device-Watchdog-Answer", 		/* Name */
+					CMD_FLAG_REQUEST | CMD_FLAG_PROXIABLE | CMD_FLAG_RETRANSMIT, 	/* Fixed flags */
+					0 					/* Fixed flag values */
+					};
+			struct local_rules_definition rules[] = 
+						{ 	 {  "Result-Code", 			RULE_REQUIRED, -1, 1 }
+						 	,{  "Origin-Host", 			RULE_REQUIRED, -1, 1 }
+							,{  "Origin-Realm",			RULE_REQUIRED, -1, 1 }
+							,{  "Error-Message",			RULE_OPTIONAL, -1, 1 }
+							,{  "Failed-AVP",			RULE_OPTIONAL, -1, 1 }
+							,{  "Origin-State-Id",			RULE_OPTIONAL, -1, 1 }
+						};
+			
+			CHECK_dict_new( DICT_COMMAND, &data , NULL, &cmd);
+			PARSE_loc_rules( rules, cmd );
+		}
+		
+		/* Re-Auth-Request */
+		{
+			/*
+				The Re-Auth-Request (RAR), indicated by the Command-Code set to 258
+				and the message flags' 'R' bit set, may be sent by any server to the
+				access device that is providing session service, to request that the
+				user be re-authenticated and/or re-authorized.
+
+
+				Message Format
+
+				 <RAR>  ::= < Diameter Header: 258, REQ, PXY >
+        				    < Session-Id >
+        				    { Origin-Host }
+        				    { Origin-Realm }
+        				    { Destination-Realm }
+        				    { Destination-Host }
+        				    { Auth-Application-Id }
+        				    { Re-Auth-Request-Type }
+        				    [ User-Name ]
+        				    [ Origin-State-Id ]
+        				  * [ Proxy-Info ]
+        				  * [ Route-Record ]
+        				  * [ AVP ]
+			*/
+			struct dict_object * cmd;
+			struct dict_cmd_data data = { 
+					258, 					/* Code */
+					#if CC_RE_AUTH != 258
+					#error "CC_RE_AUTH definition mismatch"
+					#endif
+					"Re-Auth-Request", 			/* Name */
+					CMD_FLAG_REQUEST | CMD_FLAG_PROXIABLE | CMD_FLAG_ERROR,	/* Fixed flags */
+					CMD_FLAG_REQUEST | CMD_FLAG_PROXIABLE	/* Fixed flag values */
+					};
+			struct local_rules_definition rules[] = 
+						{ 	 {  "Session-Id", 			RULE_FIXED_HEAD, -1, 1 }
+						 	,{  "Origin-Host", 			RULE_REQUIRED,   -1, 1 }
+							,{  "Origin-Realm",			RULE_REQUIRED,   -1, 1 }
+							,{  "Destination-Realm",		RULE_REQUIRED,   -1, 1 }
+						 	,{  "Destination-Host", 		RULE_REQUIRED,   -1, 1 }
+						 	,{  "Auth-Application-Id", 		RULE_REQUIRED,   -1, 1 }
+						 	,{  "Re-Auth-Request-Type", 		RULE_REQUIRED,   -1, 1 }
+							,{  "User-Name",			RULE_OPTIONAL,   -1, 1 }
+							,{  "Origin-State-Id",			RULE_OPTIONAL,   -1, 1 }
+							,{  "Proxy-Info",			RULE_OPTIONAL,   -1,-1 }
+							,{  "Route-Record",			RULE_OPTIONAL,   -1,-1 }
+						};
+			
+			CHECK_dict_new( DICT_COMMAND, &data , NULL, &cmd);
+			PARSE_loc_rules( rules, cmd );
+		}
+		
+		/* Re-Auth-Answer */
+		{
+			/*
+				The Re-Auth-Answer (RAA), indicated by the Command-Code set to 258
+				and the message flags' 'R' bit clear, is sent in response to the RAR.
+				The Result-Code AVP MUST be present, and indicates the disposition of
+				the request.
+
+				A successful RAA message MUST be followed by an application-specific
+				authentication and/or authorization message.
+
+
+				Message Format
+
+				 <RAA>  ::= < Diameter Header: 258, PXY >
+        				    < Session-Id >
+        				    { Result-Code }
+        				    { Origin-Host }
+        				    { Origin-Realm }
+        				    [ User-Name ]
+        				    [ Origin-State-Id ]
+        				    [ Error-Message ]
+        				    [ Error-Reporting-Host ]
+        				    [ Failed-AVP ]
+        				  * [ Redirect-Host ]
+        				    [ Redirect-Host-Usage ]
+        				    [ Redirect-Max-Cache-Time ]
+        				  * [ Proxy-Info ]
+        				  * [ AVP ]
+			*/
+			struct dict_object * cmd;
+			struct dict_cmd_data data = { 
+					258, 					/* Code */
+					#if CC_RE_AUTH != 258
+					#error "CC_RE_AUTH definition mismatch"
+					#endif
+					"Re-Auth-Answer", 			/* Name */
+					CMD_FLAG_REQUEST | CMD_FLAG_PROXIABLE,	/* Fixed flags */
+							   CMD_FLAG_PROXIABLE	/* Fixed flag values */
+					};
+			struct local_rules_definition rules[] = 
+						{ 	 {  "Session-Id", 			RULE_FIXED_HEAD, -1, 1 }
+ 							,{  "Result-Code", 			RULE_REQUIRED,   -1, 1 }
+						 	,{  "Origin-Host", 			RULE_REQUIRED,   -1, 1 }
+							,{  "Origin-Realm",			RULE_REQUIRED,   -1, 1 }
+							,{  "User-Name",			RULE_OPTIONAL,   -1, 1 }
+							,{  "Origin-State-Id",			RULE_OPTIONAL,   -1, 1 }
+							,{  "Error-Message",			RULE_OPTIONAL,   -1, 1 }
+							,{  "Error-Reporting-Host",		RULE_OPTIONAL,   -1, 1 }
+							,{  "Failed-AVP",			RULE_OPTIONAL,   -1, 1 }
+							,{  "Redirect-Host",			RULE_OPTIONAL,   -1,-1 }
+							,{  "Redirect-Host-Usage",		RULE_OPTIONAL,   -1, 1 }
+							,{  "Redirect-Max-Cache-Time",		RULE_OPTIONAL,   -1, 1 }
+							,{  "Proxy-Info",			RULE_OPTIONAL,   -1,-1 }
+						};
+			
+			CHECK_dict_new( DICT_COMMAND, &data , NULL, &cmd);
+			PARSE_loc_rules( rules, cmd );
+		}
+		
+		/* Session-Termination-Request */
+		{
+			/*
+				The Session-Termination-Request (STR), indicated by the Command-Code
+				set to 275 and the Command Flags' 'R' bit set, is sent by the access
+				device to inform the Diameter Server that an authenticated and/or
+				authorized session is being terminated.
+
+
+        				   Message Format
+
+				 <STR> ::= < Diameter Header: 275, REQ, PXY >
+        				   < Session-Id >
+        				   { Origin-Host }
+        				   { Origin-Realm }
+        				   { Destination-Realm }
+        				   { Auth-Application-Id }
+        				   { Termination-Cause }
+        				   [ User-Name ]
+        				   [ Destination-Host ]
+        				 * [ Class ]
+        				   [ Origin-State-Id ]
+        				 * [ Proxy-Info ]
+        				 * [ Route-Record ]
+        				 * [ AVP ]
+			*/
+			struct dict_object * cmd;
+			struct dict_cmd_data data = { 
+					275, 					/* Code */
+					#if CC_SESSION_TERMINATION != 275
+					#error "CC_SESSION_TERMINATION definition mismatch"
+					#endif
+					"Session-Termination-Request", 		/* Name */
+					CMD_FLAG_REQUEST | CMD_FLAG_PROXIABLE | CMD_FLAG_ERROR,	/* Fixed flags */
+					CMD_FLAG_REQUEST | CMD_FLAG_PROXIABLE	/* Fixed flag values */
+					};
+			struct local_rules_definition rules[] = 
+						{ 	 {  "Session-Id", 			RULE_FIXED_HEAD, -1, 1 }
+						 	,{  "Origin-Host", 			RULE_REQUIRED,   -1, 1 }
+							,{  "Origin-Realm",			RULE_REQUIRED,   -1, 1 }
+							,{  "Destination-Realm",		RULE_REQUIRED,   -1, 1 }
+						 	,{  "Auth-Application-Id", 		RULE_REQUIRED,   -1, 1 }
+						 	,{  "Termination-Cause", 		RULE_REQUIRED,   -1, 1 }
+							,{  "User-Name",			RULE_OPTIONAL,   -1, 1 }
+							,{  "Destination-Host",			RULE_OPTIONAL,   -1, 1 }
+							,{  "Class",				RULE_OPTIONAL,   -1,-1 }
+							,{  "Origin-State-Id",			RULE_OPTIONAL,   -1, 1 }
+							,{  "Proxy-Info",			RULE_OPTIONAL,   -1,-1 }
+							,{  "Route-Record",			RULE_OPTIONAL,   -1,-1 }
+						};
+			
+			CHECK_dict_new( DICT_COMMAND, &data , NULL, &cmd);
+			PARSE_loc_rules( rules, cmd );
+		}
+		
+		/* Session-Termination-Answer */
+		{
+			/*
+				The Session-Termination-Answer (STA), indicated by the Command-Code
+				set to 275 and the message flags' 'R' bit clear, is sent by the
+				Diameter Server to acknowledge the notification that the session has
+				been terminated.  The Result-Code AVP MUST be present, and MAY
+				contain an indication that an error occurred while servicing the STR.
+
+				Upon sending or receipt of the STA, the Diameter Server MUST release
+				all resources for the session indicated by the Session-Id AVP.  Any
+				intermediate server in the Proxy-Chain MAY also release any
+				resources, if necessary.
+
+        				    Message Format
+
+				 <STA>  ::= < Diameter Header: 275, PXY >
+        				    < Session-Id >
+        				    { Result-Code }
+        				    { Origin-Host }
+        				    { Origin-Realm }
+        				    [ User-Name ]
+        				  * [ Class ]
+        				    [ Error-Message ]
+        				    [ Error-Reporting-Host ]
+        				    [ Failed-AVP ]
+        				    [ Origin-State-Id ]
+        				  * [ Redirect-Host ]
+        				    [ Redirect-Host-Usage ]
+        				    [ Redirect-Max-Cache-Time ]
+        				  * [ Proxy-Info ]
+        				  * [ AVP ]
+			*/
+			struct dict_object * cmd;
+			struct dict_cmd_data data = { 
+					275, 					/* Code */
+					#if CC_SESSION_TERMINATION != 275
+					#error "CC_SESSION_TERMINATION definition mismatch"
+					#endif
+					"Session-Termination-Answer", 		/* Name */
+					CMD_FLAG_REQUEST | CMD_FLAG_PROXIABLE,	/* Fixed flags */
+							   CMD_FLAG_PROXIABLE	/* Fixed flag values */
+					};
+			struct local_rules_definition rules[] = 
+						{ 	 {  "Session-Id", 			RULE_FIXED_HEAD, -1, 1 }
+ 							,{  "Result-Code", 			RULE_REQUIRED,   -1, 1 }
+						 	,{  "Origin-Host", 			RULE_REQUIRED,   -1, 1 }
+							,{  "Origin-Realm",			RULE_REQUIRED,   -1, 1 }
+							,{  "User-Name",			RULE_OPTIONAL,   -1, 1 }
+							,{  "Class",				RULE_OPTIONAL,   -1,-1 }
+							,{  "Error-Message",			RULE_OPTIONAL,   -1, 1 }
+							,{  "Error-Reporting-Host",		RULE_OPTIONAL,   -1, 1 }
+							,{  "Failed-AVP",			RULE_OPTIONAL,   -1, 1 }
+							,{  "Origin-State-Id",			RULE_OPTIONAL,   -1, 1 }
+							,{  "Redirect-Host",			RULE_OPTIONAL,   -1,-1 }
+							,{  "Redirect-Host-Usage",		RULE_OPTIONAL,   -1, 1 }
+							,{  "Redirect-Max-Cache-Time",		RULE_OPTIONAL,   -1, 1 }
+							,{  "Proxy-Info",			RULE_OPTIONAL,   -1,-1 }
+						};
+			
+			CHECK_dict_new( DICT_COMMAND, &data , NULL, &cmd);
+			PARSE_loc_rules( rules, cmd );
+		}
+		
+		/* Abort-Session-Request */
+		{
+			/*
+				The Abort-Session-Request (ASR), indicated by the Command-Code set to
+				274 and the message flags' 'R' bit set, may be sent by any server to
+				the access device that is providing session service, to request that
+				the session identified by the Session-Id be stopped.
+
+
+        				    Message Format
+
+				 <ASR>  ::= < Diameter Header: 274, REQ, PXY >
+        				    < Session-Id >
+        				    { Origin-Host }
+        				    { Origin-Realm }
+        				    { Destination-Realm }
+        				    { Destination-Host }
+        				    { Auth-Application-Id }
+        				    [ User-Name ]
+        				    [ Origin-State-Id ]
+        				  * [ Proxy-Info ]
+        				  * [ Route-Record ]
+        				  * [ AVP ]
+			*/
+			struct dict_object * cmd;
+			struct dict_cmd_data data = { 
+					274, 					/* Code */
+					#if CC_ABORT_SESSION != 274
+					#error "CC_ABORT_SESSION definition mismatch"
+					#endif
+					"Abort-Session-Request", 		/* Name */
+					CMD_FLAG_REQUEST | CMD_FLAG_PROXIABLE | CMD_FLAG_ERROR,	/* Fixed flags */
+					CMD_FLAG_REQUEST | CMD_FLAG_PROXIABLE	/* Fixed flag values */
+					};
+			struct local_rules_definition rules[] = 
+						{ 	 {  "Session-Id", 			RULE_FIXED_HEAD, -1, 1 }
+						 	,{  "Origin-Host", 			RULE_REQUIRED,   -1, 1 }
+							,{  "Origin-Realm",			RULE_REQUIRED,   -1, 1 }
+							,{  "Destination-Realm",		RULE_REQUIRED,   -1, 1 }
+							,{  "Destination-Host",			RULE_REQUIRED,   -1, 1 }
+						 	,{  "Auth-Application-Id", 		RULE_REQUIRED,   -1, 1 }
+							,{  "User-Name",			RULE_OPTIONAL,   -1, 1 }
+							,{  "Origin-State-Id",			RULE_OPTIONAL,   -1, 1 }
+							,{  "Proxy-Info",			RULE_OPTIONAL,   -1,-1 }
+							,{  "Route-Record",			RULE_OPTIONAL,   -1,-1 }
+						};
+			
+			CHECK_dict_new( DICT_COMMAND, &data , NULL, &cmd);
+			PARSE_loc_rules( rules, cmd );
+		}
+		
+		/* Abort-Session-Answer */
+		{
+			/*
+				The Abort-Session-Answer (ASA), indicated by the Command-Code set to
+				274 and the message flags' 'R' bit clear, is sent in response to the
+				ASR.  The Result-Code AVP MUST be present, and indicates the
+				disposition of the request.
+
+				If the session identified by Session-Id in the ASR was successfully
+				terminated, Result-Code is set to DIAMETER_SUCCESS.  If the session
+				is not currently active, Result-Code is set to
+				DIAMETER_UNKNOWN_SESSION_ID.  If the access device does not stop the
+				session for any other reason, Result-Code is set to
+				DIAMETER_UNABLE_TO_COMPLY.
+
+        				    Message Format
+
+				 <ASA>  ::= < Diameter Header: 274, PXY >
+        				    < Session-Id >
+        				    { Result-Code }
+        				    { Origin-Host }
+        				    { Origin-Realm }
+        				    [ User-Name ]
+        				    [ Origin-State-Id ]
+        				    [ Error-Message ]
+        				    [ Error-Reporting-Host ]
+        				    [ Failed-AVP ]
+        				  * [ Redirect-Host ]
+        				    [ Redirect-Host-Usage ]
+        				    [ Redirect-Max-Cache-Time ]
+        				  * [ Proxy-Info ]
+        				  * [ AVP ]
+			*/
+			struct dict_object * cmd;
+			struct dict_cmd_data data = { 
+					274, 					/* Code */
+					#if CC_ABORT_SESSION != 274
+					#error "CC_ABORT_SESSION definition mismatch"
+					#endif
+					"Abort-Session-Answer", 		/* Name */
+					CMD_FLAG_REQUEST | CMD_FLAG_PROXIABLE,	/* Fixed flags */
+							   CMD_FLAG_PROXIABLE	/* Fixed flag values */
+					};
+			struct local_rules_definition rules[] = 
+						{ 	 {  "Session-Id", 			RULE_FIXED_HEAD, -1, 1 }
+ 							,{  "Result-Code", 			RULE_REQUIRED,   -1, 1 }
+						 	,{  "Origin-Host", 			RULE_REQUIRED,   -1, 1 }
+							,{  "Origin-Realm",			RULE_REQUIRED,   -1, 1 }
+							,{  "User-Name",			RULE_OPTIONAL,   -1, 1 }
+							,{  "Origin-State-Id",			RULE_OPTIONAL,   -1, 1 }
+							,{  "Error-Message",			RULE_OPTIONAL,   -1, 1 }
+							,{  "Error-Reporting-Host",		RULE_OPTIONAL,   -1, 1 }
+							,{  "Failed-AVP",			RULE_OPTIONAL,   -1, 1 }
+							,{  "Redirect-Host",			RULE_OPTIONAL,   -1,-1 }
+							,{  "Redirect-Host-Usage",		RULE_OPTIONAL,   -1, 1 }
+							,{  "Redirect-Max-Cache-Time",		RULE_OPTIONAL,   -1, 1 }
+							,{  "Proxy-Info",			RULE_OPTIONAL,   -1,-1 }
+						};
+			
+			CHECK_dict_new( DICT_COMMAND, &data , NULL, &cmd);
+			PARSE_loc_rules( rules, cmd );
+		}
+		
+		/* Accounting-Request */
+		{
+			/*
+				The Accounting-Request (ACR) command, indicated by the Command-Code
+				field set to 271 and the Command Flags' 'R' bit set, is sent by a
+				Diameter node, acting as a client, in order to exchange accounting
+				information with a peer.
+
+				One of Acct-Application-Id and Vendor-Specific-Application-Id AVPs
+				MUST be present.  If the Vendor-Specific-Application-Id grouped AVP
+				is present, it MUST include an Acct-Application-Id AVP.
+
+				The AVP listed below SHOULD include service specific accounting AVPs,
+				as described in Section 9.3.
+
+
+				Message Format
+
+				 <ACR> ::= < Diameter Header: 271, REQ, PXY >
+        				   < Session-Id >
+        				   { Origin-Host }
+        				   { Origin-Realm }
+        				   { Destination-Realm }
+        				   { Accounting-Record-Type }
+        				   { Accounting-Record-Number }
+        				   [ Acct-Application-Id ]
+        				   [ Vendor-Specific-Application-Id ]
+        				   [ User-Name ]
+        				   [ Destination-Host ]
+        				   [ Accounting-Sub-Session-Id ]
+        				   [ Acct-Session-Id ]
+        				   [ Acct-Multi-Session-Id ]
+        				   [ Acct-Interim-Interval ]
+        				   [ Accounting-Realtime-Required ]
+        				   [ Origin-State-Id ]
+        				   [ Event-Timestamp ]
+        				 * [ Proxy-Info ]
+        				 * [ Route-Record ]
+        				 * [ AVP ]
+			*/
+			struct dict_object * cmd;
+			struct dict_cmd_data data = { 
+					271, 					/* Code */
+					#if CC_ACCOUNTING != 271
+					#error "CC_ACCOUNTING definition mismatch"
+					#endif
+					"Accounting-Request", 			/* Name */
+					CMD_FLAG_REQUEST | CMD_FLAG_PROXIABLE | CMD_FLAG_ERROR,	/* Fixed flags */
+					CMD_FLAG_REQUEST | CMD_FLAG_PROXIABLE	/* Fixed flag values */
+					};
+			struct local_rules_definition rules[] = 
+						{ 	 {  "Session-Id", 			RULE_FIXED_HEAD, -1, 1 }
+						 	,{  "Origin-Host", 			RULE_REQUIRED,   -1, 1 }
+							,{  "Origin-Realm",			RULE_REQUIRED,   -1, 1 }
+							,{  "Destination-Realm",		RULE_REQUIRED,   -1, 1 }
+							,{  "Accounting-Record-Type",		RULE_REQUIRED,   -1, 1 }
+							,{  "Accounting-Record-Number",		RULE_REQUIRED,   -1, 1 }
+							,{  "Acct-Application-Id",		RULE_OPTIONAL,   -1, 1 }
+							,{  "Vendor-Specific-Application-Id",	RULE_OPTIONAL,   -1, 1 }
+							,{  "User-Name",			RULE_OPTIONAL,   -1, 1 }
+							,{  "Destination-Host",			RULE_OPTIONAL,   -1, 1 }
+							,{  "Accounting-Sub-Session-Id",	RULE_OPTIONAL,   -1, 1 }
+							,{  "Acct-Session-Id",			RULE_OPTIONAL,   -1, 1 }
+							,{  "Acct-Multi-Session-Id",		RULE_OPTIONAL,   -1, 1 }
+							,{  "Acct-Interim-Interval",		RULE_OPTIONAL,   -1, 1 }
+							,{  "Accounting-Realtime-Required",	RULE_OPTIONAL,   -1, 1 }
+							,{  "Origin-State-Id",			RULE_OPTIONAL,   -1, 1 }
+							,{  "Event-Timestamp",			RULE_OPTIONAL,   -1, 1 }
+							,{  "Proxy-Info",			RULE_OPTIONAL,   -1,-1 }
+							,{  "Route-Record",			RULE_OPTIONAL,   -1,-1 }
+						};
+			
+			CHECK_dict_new( DICT_COMMAND, &data , NULL, &cmd);
+			PARSE_loc_rules( rules, cmd );
+		}
+		
+		/* Accounting-Answer */
+		{
+			/*
+				The Accounting-Answer (ACA) command, indicated by the Command-Code
+				field set to 271 and the Command Flags' 'R' bit cleared, is used to
+				acknowledge an Accounting-Request command.  The Accounting-Answer
+				command contains the same Session-Id as the corresponding request.
+
+				Only the target Diameter Server, known as the home Diameter Server,
+				SHOULD respond with the Accounting-Answer command.
+
+				One of Acct-Application-Id and Vendor-Specific-Application-Id AVPs
+				MUST be present.  If the Vendor-Specific-Application-Id grouped AVP
+				is present, it MUST contain an Acct-Application-Id AVP.
+
+				The AVP listed below SHOULD include service specific accounting AVPs,
+				as described in Section 9.3.
+
+
+				Message Format
+
+				 <ACA> ::= < Diameter Header: 271, PXY >
+        				   < Session-Id >
+        				   { Result-Code }
+        				   { Origin-Host }
+        				   { Origin-Realm }
+        				   { Accounting-Record-Type }
+        				   { Accounting-Record-Number }
+        				   [ Acct-Application-Id ]
+        				   [ Vendor-Specific-Application-Id ]
+        				   [ User-Name ]
+        				   [ Accounting-Sub-Session-Id ]
+        				   [ Acct-Session-Id ]
+        				   [ Acct-Multi-Session-Id ]
+        				   [ Error-Message ]
+        				   [ Error-Reporting-Host ]
+        				   [ Failed-AVP ]
+        				   [ Acct-Interim-Interval ]
+        				   [ Accounting-Realtime-Required ]
+        				   [ Origin-State-Id ]
+        				   [ Event-Timestamp ]
+        				 * [ Proxy-Info ]
+        				 * [ AVP ]
+			*/
+			struct dict_object * cmd;
+			struct dict_cmd_data data = { 
+					271, 					/* Code */
+					#if CC_ACCOUNTING != 271
+					#error "CC_ACCOUNTING definition mismatch"
+					#endif
+					"Accounting-Answer", 			/* Name */
+					CMD_FLAG_REQUEST | CMD_FLAG_PROXIABLE,	/* Fixed flags */
+							   CMD_FLAG_PROXIABLE	/* Fixed flag values */
+					};
+			struct local_rules_definition rules[] = 
+						{ 	 {  "Session-Id", 			RULE_FIXED_HEAD, -1, 1 }
+ 							,{  "Result-Code", 			RULE_REQUIRED,   -1, 1 }
+						 	,{  "Origin-Host", 			RULE_REQUIRED,   -1, 1 }
+							,{  "Origin-Realm",			RULE_REQUIRED,   -1, 1 }
+							,{  "Accounting-Record-Type",		RULE_REQUIRED,   -1, 1 }
+							,{  "Accounting-Record-Number",		RULE_REQUIRED,   -1, 1 }
+							,{  "Acct-Application-Id",		RULE_OPTIONAL,   -1, 1 }
+							,{  "Vendor-Specific-Application-Id",	RULE_OPTIONAL,   -1, 1 }
+							,{  "User-Name",			RULE_OPTIONAL,   -1, 1 }
+							,{  "Accounting-Sub-Session-Id",	RULE_OPTIONAL,   -1, 1 }
+							,{  "Acct-Session-Id",			RULE_OPTIONAL,   -1, 1 }
+							,{  "Acct-Multi-Session-Id",		RULE_OPTIONAL,   -1, 1 }
+							,{  "Error-Message",			RULE_OPTIONAL,   -1, 1 }
+							,{  "Error-Reporting-Host",		RULE_OPTIONAL,   -1, 1 }
+							,{  "Failed-AVP",			RULE_OPTIONAL,   -1, 1 }
+							,{  "Acct-Interim-Interval",		RULE_OPTIONAL,   -1, 1 }
+							,{  "Accounting-Realtime-Required",	RULE_OPTIONAL,   -1, 1 }
+							,{  "Origin-State-Id",			RULE_OPTIONAL,   -1, 1 }
+							,{  "Event-Timestamp",			RULE_OPTIONAL,   -1, 1 }
+							,{  "Proxy-Info",			RULE_OPTIONAL,   -1,-1 }
+						};
+			
+			CHECK_dict_new( DICT_COMMAND, &data , NULL, &cmd);
+			PARSE_loc_rules( rules, cmd );
+		}
+	}
+
+	return 0;
+}
diff --git a/libfdcore/endpoints.c b/libfdcore/endpoints.c
new file mode 100644
index 0000000..e80c2a3
--- /dev/null
+++ b/libfdcore/endpoints.c
@@ -0,0 +1,271 @@
+/*********************************************************************************************************
+* Software License Agreement (BSD License)                                                               *
+* Author: Sebastien Decugis <sdecugis@freediameter.net>							 *
+*													 *
+* Copyright (c) 2013, WIDE Project and NICT								 *
+* All rights reserved.											 *
+* 													 *
+* Redistribution and use of this software in source and binary forms, with or without modification, are  *
+* permitted provided that the following conditions are met:						 *
+* 													 *
+* * Redistributions of source code must retain the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer.										 *
+*    													 *
+* * Redistributions in binary form must reproduce the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer in the documentation and/or other						 *
+*   materials provided with the distribution.								 *
+* 													 *
+* * Neither the name of the WIDE Project or NICT nor the 						 *
+*   names of its contributors may be used to endorse or 						 *
+*   promote products derived from this software without 						 *
+*   specific prior written permission of WIDE Project and 						 *
+*   NICT.												 *
+* 													 *
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED *
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
+* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR *
+* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 	 *
+* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 	 *
+* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR *
+* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF   *
+* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.								 *
+*********************************************************************************************************/
+
+#include "fdcore-internal.h"
+
+
+/* Add an endpoint information in a list */
+int fd_ep_add_merge( struct fd_list * list, sSA * sa, socklen_t sl, uint32_t flags )
+{
+	struct fd_endpoint * ep;
+	struct fd_list * li;
+	union {
+		sSA * sa;
+		sSA4 *sin;
+		sSA6 *sin6;
+	} ptr;
+	in_port_t * port;
+	int cmp = -1;
+	
+	TRACE_ENTRY("%p %p %u %x", list, sa, sl, flags);
+	CHECK_PARAMS( list && sa && (sl <= sizeof(sSS)) );
+	
+	if (list->next == NULL) {
+		/* the list is not initialized yet, do it */
+		fd_list_init(list, NULL);
+	}
+	
+	ptr.sa = sa;
+	
+	/* Filter out a bunch of invalid addresses */
+	switch (sa->sa_family) {
+		case AF_INET:
+			if (! (flags & EP_ACCEPTALL)) {
+				if (IN_IS_ADDR_UNSPECIFIED(&ptr.sin->sin_addr) 
+				 || IN_IS_ADDR_LOOPBACK(&ptr.sin->sin_addr)
+				    /* the next one filters both EXPERIMENTAL, BADCLASS and MULTICAST. */
+				 || ((ntohl(ptr.sin->sin_addr.s_addr) & 0xe0000000) == 0xe0000000)
+				 || (ptr.sin->sin_addr.s_addr == INADDR_BROADCAST)) {
+					LOG_A("  DEBUG:fd_ep_add_merge  Address was ignored, not added.");
+					return 0;
+				}
+			}
+			port = &ptr.sin->sin_port;
+			break;
+
+		case AF_INET6:
+			if (! (flags & EP_ACCEPTALL)) {
+				if (IN6_IS_ADDR_UNSPECIFIED(&ptr.sin6->sin6_addr) 
+				 || IN6_IS_ADDR_LOOPBACK(&ptr.sin6->sin6_addr)
+				 || IN6_IS_ADDR_MULTICAST(&ptr.sin6->sin6_addr)
+				 || IN6_IS_ADDR_LINKLOCAL(&ptr.sin6->sin6_addr)
+				 || IN6_IS_ADDR_SITELOCAL(&ptr.sin6->sin6_addr)) {
+					LOG_A("  DEBUG:fd_ep_add_merge  Address was ignored, not added.");
+					return 0;
+				}
+			}
+			port = &ptr.sin6->sin6_port;
+			break;
+
+		default:
+			LOG_A("  DEBUG:fd_ep_add_merge  Address family was unknown, not added.");
+			return 0;
+	}
+	
+	/* remove the ACCEPTALL flag */
+	flags &= ~EP_ACCEPTALL;
+	
+	/* Search place in the list */
+	for (li = list->next; li != list; li = li->next) {
+		ep = (struct fd_endpoint *)li;
+		in_port_t * ep_port;
+		
+		/* First, compare the address family */
+		if (ep->sa.sa_family < sa->sa_family)
+			continue;
+		if (ep->sa.sa_family > sa->sa_family)
+			break;
+		
+		/* Then compare the address field */
+		switch (sa->sa_family) {
+			case AF_INET:
+				cmp = memcmp(&ep->sin.sin_addr, &ptr.sin->sin_addr, sizeof(struct in_addr));
+				ep_port = &ep->sin.sin_port;
+				break;
+			case AF_INET6:
+				cmp = memcmp(&ep->sin6.sin6_addr, &ptr.sin6->sin6_addr, sizeof(struct in6_addr));
+				ep_port = &ep->sin6.sin6_port;
+				break;
+			default:
+				ASSERT( 0 ); /* we got a different value previously in this same function */
+		}
+		if (cmp < 0)
+			continue;
+		if (cmp > 0)
+			break;
+		
+		/* Finally compare the port, only if not 0 */
+		if (*port == 0)
+			break;
+		if (*ep_port == 0) {
+			/* save the port information in the list, and break */
+			*ep_port = *port;
+			break;
+		}
+		if (*ep_port < *port) {
+			cmp = -1;
+			continue;
+		}
+		if (*ep_port > *port)
+			cmp = 1;
+		break;
+	}
+	
+	if (cmp) {
+		/* new item to be added */
+		CHECK_MALLOC( ep = malloc(sizeof(struct fd_endpoint)) );
+		memset(ep, 0, sizeof(struct fd_endpoint));
+		fd_list_init(&ep->chain, NULL);
+		memcpy(&ep->ss, sa, sl);
+		
+		/* Insert in the list */
+		fd_list_insert_before(li, &ep->chain);
+	}
+	
+	/* Merge the flags */
+	ep->flags |= flags;
+	
+	return 0;
+}
+
+/* Delete endpoints that do not have a matching flag from a list (0: delete all endpoints) */
+int fd_ep_filter( struct fd_list * list, uint32_t flags )
+{
+	struct fd_list * li;
+	
+	TRACE_ENTRY("%p %x", list, flags);
+	CHECK_PARAMS(list);
+	
+	for (li = list->next; li != list; li = li->next) {
+		struct fd_endpoint * ep = (struct fd_endpoint *)li;
+		
+		if (! (ep->flags & flags)) {
+			li = li->prev;
+			fd_list_unlink(&ep->chain);
+			free(ep);
+		}
+	}
+	
+	return 0;
+}
+
+/* Keep only endpoints of the same family as af */
+int fd_ep_filter_family( struct fd_list * list, int af )
+{
+	struct fd_list * li;
+	
+	TRACE_ENTRY("%p %d", list, af);
+	CHECK_PARAMS(list);
+	
+	for (li = list->next; li != list; li = li->next) {
+		struct fd_endpoint * ep = (struct fd_endpoint *)li;
+		
+		if (ep->sa.sa_family != af) {
+			li = li->prev;
+			fd_list_unlink(&ep->chain);
+			free(ep);
+		}
+	}
+	
+	return 0;
+}
+
+/* Reset the given flag(s) from all items in the list */
+int fd_ep_clearflags( struct fd_list * list, uint32_t flags )
+{
+	struct fd_list * li;
+	
+	TRACE_ENTRY("%p %x", list, flags);
+	CHECK_PARAMS(list);
+	
+	for (li = list->next; li != list; li = li->next) {
+		struct fd_endpoint * ep = (struct fd_endpoint *)li;
+		ep->flags &= ~flags;
+		if (ep->flags == 0) {
+			li = li->prev;
+			fd_list_unlink(&ep->chain);
+			free(ep);
+		}
+	}
+	
+	return 0;
+}
+
+DECLARE_FD_DUMP_PROTOTYPE(fd_ep_dump_one, int preamble, struct fd_endpoint * ep )
+{
+	FD_DUMP_HANDLE_OFFSET();
+	
+	if (preamble) {
+		CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "{ep}(@%p): ", ep), return NULL);
+	}
+	
+	if (!ep) {
+		CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "INVALID/NULL"), return NULL);
+		return *buf;
+	}
+	
+	CHECK_MALLOC_DO( fd_sa_dump( FD_DUMP_STD_PARAMS, &ep->sa, NI_NUMERICHOST | NI_NUMERICSERV ), return NULL);
+	CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "{%s%s%s%s%s}",
+				(ep->flags & EP_FL_CONF) 	? "C" : "-",
+				(ep->flags & EP_FL_DISC) 	? "D" : "-",
+				(ep->flags & EP_FL_ADV) 	? "A" : "-",
+				(ep->flags & EP_FL_LL) 		? "L" : "-",
+				(ep->flags & EP_FL_PRIMARY) 	? "P" : "-"), return NULL);
+	return *buf;
+}
+
+DECLARE_FD_DUMP_PROTOTYPE(fd_ep_dump, int preamble, int indent, struct fd_list * eps  )
+{
+	struct fd_list * li;
+	
+	FD_DUMP_HANDLE_OFFSET();
+	
+	if (preamble) {
+		CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "%*s{eps}(@%p):", indent, "", eps), return NULL);
+	}
+	if (eps) {
+		for (li = eps->next; li != eps; li = li->next) {
+			struct fd_endpoint * ep = (struct fd_endpoint *)li;
+			if (preamble) {
+				CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "\n%*s", indent+1, ""), return NULL);
+			} else if (li->prev != eps) {
+				CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "\t"), return NULL);
+			}
+			CHECK_MALLOC_DO( fd_ep_dump_one( FD_DUMP_STD_PARAMS, preamble, ep ), return NULL);
+		}
+	}
+	return *buf;
+}
+	
diff --git a/libfdcore/events.c b/libfdcore/events.c
new file mode 100644
index 0000000..bea5885
--- /dev/null
+++ b/libfdcore/events.c
@@ -0,0 +1,231 @@
+/*********************************************************************************************************
+* Software License Agreement (BSD License)                                                               *
+* Author: Sebastien Decugis <sdecugis@freediameter.net>							 *
+*													 *
+* Copyright (c) 2013, WIDE Project and NICT								 *
+* All rights reserved.											 *
+* 													 *
+* Redistribution and use of this software in source and binary forms, with or without modification, are  *
+* permitted provided that the following conditions are met:						 *
+* 													 *
+* * Redistributions of source code must retain the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer.										 *
+*    													 *
+* * Redistributions in binary form must reproduce the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer in the documentation and/or other						 *
+*   materials provided with the distribution.								 *
+* 													 *
+* * Neither the name of the WIDE Project or NICT nor the 						 *
+*   names of its contributors may be used to endorse or 						 *
+*   promote products derived from this software without 						 *
+*   specific prior written permission of WIDE Project and 						 *
+*   NICT.												 *
+* 													 *
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED *
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
+* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR *
+* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 	 *
+* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 	 *
+* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR *
+* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF   *
+* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.								 *
+*********************************************************************************************************/
+
+#include "fdcore-internal.h"
+
+/* Events are a subset of fifo queues, with a known type */
+
+int fd_event_send(struct fifo *queue, int code, size_t datasz, void * data)
+{
+	struct fd_event * ev;
+	CHECK_MALLOC( ev = malloc(sizeof(struct fd_event)) );
+	ev->code = code;
+	ev->size = datasz;
+	ev->data = data;
+	CHECK_FCT( fd_fifo_post(queue, &ev) );
+	return 0;
+}
+
+int fd_event_get(struct fifo *queue, int *code, size_t *datasz, void ** data)
+{
+	struct fd_event * ev;
+	CHECK_FCT( fd_fifo_get(queue, &ev) );
+	if (code)
+		*code = ev->code;
+	if (datasz)
+		*datasz = ev->size;
+	if (data)
+		*data = ev->data;
+	free(ev);
+	return 0;
+}
+
+int fd_event_timedget(struct fifo *queue, struct timespec * timeout, int timeoutcode, int *code, size_t *datasz, void ** data)
+{
+	struct fd_event * ev;
+	int ret = 0;
+	ret = fd_fifo_timedget(queue, &ev, timeout);
+	if (ret == ETIMEDOUT) {
+		if (code)
+			*code = timeoutcode;
+		if (datasz)
+			*datasz = 0;
+		if (data)
+			*data = NULL;
+	} else {
+		CHECK_FCT( ret );
+		if (code)
+			*code = ev->code;
+		if (datasz)
+			*datasz = ev->size;
+		if (data)
+			*data = ev->data;
+		free(ev);
+	}
+	return 0;
+}
+
+void fd_event_destroy(struct fifo **queue, void (*free_cb)(void * data))
+{
+	struct fd_event * ev;
+	/* Purge all events, and free the associated data if any */
+	while (fd_fifo_tryget( *queue, &ev ) == 0) {
+		(*free_cb)(ev->data);
+		free(ev);
+	}
+	CHECK_FCT_DO( fd_fifo_del(queue), /* continue */ );
+	return ;
+} 
+
+const char * fd_ev_str(int event)
+{
+	switch (event) {
+	#define case_str( _val )\
+		case _val : return #_val
+		case_str(FDEV_TERMINATE_INT);
+		case_str(FDEV_TRIGGER);
+		
+		default:
+			TRACE_DEBUG(FULL, "Unknown event : %d", event);
+			return "Unknown event";
+	}
+}
+
+/**********************************************************************/
+/* Trigged events */
+/* This allows extensions to register for / send triggers to other extensions */
+/* It is used for example for users interactions (through signals or ...) */
+
+/* Because the number of triggers is not expected to grow, we use a simple ordered chained list */
+static pthread_rwlock_t trig_rwl = PTHREAD_RWLOCK_INITIALIZER;
+static struct fd_list   trig_list = FD_LIST_INITIALIZER(trig_list); /* The list of triggers ordered by trigger value */
+struct trig_item {
+	struct fd_list 	chain;
+	int  		trig_value;
+	const char * 	trig_module;
+	void 		(*cb)(void);
+};	
+
+/* Add a new entry in the trigger list */
+int fd_event_trig_regcb(int trigger_val, const char * module, void (*cb)(void))
+{
+	struct trig_item * ti;
+	struct fd_list * li;
+	
+	TRACE_ENTRY("%d %p %p", trigger_val, module, cb);
+	CHECK_PARAMS( trigger_val && cb );
+	
+	/* Create a new trig_item */
+	CHECK_MALLOC( ti = malloc(sizeof(struct trig_item)) );
+	memset(ti, 0, sizeof(struct trig_item));
+	fd_list_init(&ti->chain, ti);
+	ti->trig_value = trigger_val;
+	ti->trig_module = module;
+	ti->cb = cb;
+	
+	/* Now insert in the list */
+	CHECK_POSIX( pthread_rwlock_wrlock(&trig_rwl) );
+	
+	for (li = trig_list.next; li != &trig_list; li = li->next) {
+		struct trig_item *t = li->o;
+		if (t->trig_value >= trigger_val)
+			break;
+	}
+	
+	fd_list_insert_before(li, &ti->chain);
+	
+	CHECK_POSIX( pthread_rwlock_unlock(&trig_rwl) );
+
+	return 0;
+}
+
+DECLARE_FD_DUMP_PROTOTYPE(fd_event_trig_dump)
+{
+	struct fd_list * li;
+	FD_DUMP_HANDLE_OFFSET();
+	
+	CHECK_POSIX_DO( pthread_rwlock_rdlock(&trig_rwl),  );
+	
+	for (li = trig_list.next; li != &trig_list; li = li->next) {
+		struct trig_item *t = li->o;
+		CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "{signal:%d}'%s'->%p ", t->trig_value, t->trig_module, t->cb), break);
+	}
+	
+	CHECK_POSIX_DO( pthread_rwlock_unlock(&trig_rwl),  );
+	return *buf;
+}
+
+static void *call_cb_detached(void * arg)
+{
+	void (*cb)(void) = arg;
+	fd_log_threadname("Trig'd callback thread");
+	TRACE_ENTRY("%p", arg);
+	(*cb)();
+	TRACE_DEBUG(ANNOYING, "Callback %p completed", cb);
+	return NULL;
+}
+
+int fd_event_trig_call_cb(int trigger_val)
+{
+	struct fd_list * li;
+	pthread_attr_t detached;
+	pthread_t th;
+	
+	CHECK_POSIX( pthread_attr_init(&detached) );
+	CHECK_POSIX( pthread_attr_setdetachstate(&detached, PTHREAD_CREATE_DETACHED) );
+	
+	CHECK_POSIX( pthread_rwlock_rdlock(&trig_rwl)  );
+	
+	for (li = trig_list.next; li != &trig_list; li = li->next) {
+		struct trig_item *t = li->o;
+		if (t->trig_value == trigger_val) {
+			TRACE_DEBUG(FULL, "Trigger %d: Calling %p in %s", t->trig_value, t->cb, t->trig_module);
+			CHECK_POSIX_DO( pthread_create( &th, &detached, call_cb_detached, t->cb ), break );
+		}
+		if (t->trig_value > trigger_val)
+			break;
+	}
+	
+	CHECK_POSIX( pthread_rwlock_unlock(&trig_rwl)  );
+	
+	return 0;
+}
+
+int fd_event_trig_fini(void) {
+	
+	TRACE_ENTRY("");
+	
+	CHECK_POSIX( pthread_rwlock_wrlock(&trig_rwl) );
+	
+	while (!FD_IS_LIST_EMPTY(&trig_list)) {
+		struct fd_list * li = trig_list.next;
+		fd_list_unlink(li);
+		free(li);
+	}
+	
+	CHECK_POSIX( pthread_rwlock_unlock(&trig_rwl) );
+	
+	return 0;
+}
diff --git a/libfdcore/extensions.c b/libfdcore/extensions.c
new file mode 100644
index 0000000..0d4fcca
--- /dev/null
+++ b/libfdcore/extensions.c
@@ -0,0 +1,299 @@
+/*********************************************************************************************************
+* Software License Agreement (BSD License)                                                               *
+* Author: Sebastien Decugis <sdecugis@freediameter.net>							 *
+*													 *
+* Copyright (c) 2013, WIDE Project and NICT								 *
+* All rights reserved.											 *
+* 													 *
+* Redistribution and use of this software in source and binary forms, with or without modification, are  *
+* permitted provided that the following conditions are met:						 *
+* 													 *
+* * Redistributions of source code must retain the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer.										 *
+*    													 *
+* * Redistributions in binary form must reproduce the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer in the documentation and/or other						 *
+*   materials provided with the distribution.								 *
+* 													 *
+* * Neither the name of the WIDE Project or NICT nor the 						 *
+*   names of its contributors may be used to endorse or 						 *
+*   promote products derived from this software without 						 *
+*   specific prior written permission of WIDE Project and 						 *
+*   NICT.												 *
+* 													 *
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED *
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
+* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR *
+* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 	 *
+* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 	 *
+* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR *
+* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF   *
+* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.								 *
+*********************************************************************************************************/
+
+#include "fdcore-internal.h"
+
+#include <dlfcn.h>	/* We may use libtool's <ltdl.h> later for better portability.... */
+#include <libgen.h>	/* for "basename" */
+
+/* plugins management */
+
+/* List of extensions to load, from the configuration parsing */
+struct fd_ext_info {
+	struct fd_list	chain;		/* link in the list */
+	char 		*filename;	/* extension filename. must be a dynamic library with fd_ext_init symbol. */
+	char 		*conffile;	/* optional configuration file name for the extension */
+	void 		*handler;	/* object returned by dlopen() */
+	const char 	**depends;	/* names of the other extensions this one depends on (if provided) */
+	char		*ext_name;	/* points to the extension name, either inside depends, or basename(filename) */
+	int		free_ext_name;	/* must be freed if it was malloc'd */
+	void		(*fini)(void);	/* optional address of the fd_ext_fini callback */
+	char		*proto_ver;
+	double		gen_date;
+};
+
+/* list of extensions */
+static struct fd_list ext_list = FD_LIST_INITIALIZER(ext_list);
+
+/* Add new extension */
+int fd_ext_add( char * filename, char * conffile )
+{
+	struct fd_ext_info * new;
+	
+	TRACE_ENTRY("%p %p", filename, conffile);
+	
+	/* Check the filename is valid */
+	CHECK_PARAMS( filename );
+	
+	/* Create a new object in the list */
+	CHECK_MALLOC(  new = malloc( sizeof(struct fd_ext_info) )  );
+	memset(new, 0, sizeof(struct fd_ext_info));
+	fd_list_init(&new->chain, NULL);
+	new->filename = filename;
+	new->conffile = conffile;
+	fd_list_insert_before( &ext_list, &new->chain );
+	TRACE_DEBUG (FULL, "Extension %s added to the list.", filename);
+	return 0;
+}
+
+/* Dump the list */
+DECLARE_FD_DUMP_PROTOTYPE(fd_ext_dump)
+{
+	struct fd_list * li;
+	FD_DUMP_HANDLE_OFFSET();
+	
+	if (FD_IS_LIST_EMPTY(&ext_list)) {
+		CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "-none-"), return NULL);
+	} else {
+		for (li = ext_list.next; li != &ext_list; li = li->next)
+		{
+			struct fd_ext_info * ext = (struct fd_ext_info *)li;
+			CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "'%s'[%s], %sloaded%s",
+						ext->filename, 
+						ext->conffile?:"(no config file)", 
+						ext->handler ? "" : "not ", (li->next == &ext_list) ? "":"\n"), return NULL);
+		}
+	}
+	return *buf;
+}
+
+/* Load the dependencies */
+static int load_dependencies(struct fd_ext_info *ext)
+{
+	TRACE_ENTRY( "%p", ext);
+	/* Attempt to resolve the dependency array */
+	ext->depends = dlsym( ext->handler, "fd_ext_depends");
+	if (!ext->depends) {
+		/* Duplicate the filename */
+		char * tmp = strdup(ext->filename);
+		ext->ext_name = strdup(basename(tmp));
+		free(tmp);
+		ext->free_ext_name = 1;
+		TRACE_DEBUG(FULL, "Old extension's [%s] API: missing dependencies (ignored)", ext->ext_name);
+		return 0;
+	}
+	
+	ext->ext_name = (char *)ext->depends[0];
+	return 0;
+
+}
+
+/* Check the dependencies. The object must have been dlopened already. */
+static int check_dependencies(struct fd_ext_info * ext)
+{
+	int i = 1;
+	TRACE_DEBUG(FULL, "Checking dependencies for '%s'...", ext->ext_name);
+	
+	while (ext->depends[i]) {
+		struct fd_list * li;
+		for (li = ext_list.next; li != &ext_list; li = li->next)
+		{
+			struct fd_ext_info * e = (struct fd_ext_info *)li;
+			if (!strcasecmp(e->ext_name, ext->depends[i])) {
+				/* the dependency was already loaded */
+				break;
+			}
+		}
+
+		if (li == &ext_list) {
+			/* the dependency was not found */
+			LOG_F("Error: extension [%s] depends on [%s] which was not loaded first. Please fix your configuration file.",
+				ext->ext_name, ext->depends[i]);
+			return ESRCH;
+		}
+		
+		i++;
+	}
+
+	/* All dependencies resolved successfully */
+	return 0;
+}
+
+/* Load all extensions in the list */
+int fd_ext_load()
+{
+	int ret;
+	int (*fd_ext_init)(int, int, char *) = NULL;
+	int (*fd_ext_init2)(int, int, char *) = NULL;
+	struct fd_list * li;
+	
+	TRACE_ENTRY();
+	
+	/* Loop on all extensions */
+	for (li = ext_list.next; li != &ext_list; li = li->next)
+	{
+		struct fd_ext_info * ext = (struct fd_ext_info *)li;
+		LOG_D( "Loading : %s", ext->filename);
+		
+		/* Load the extension */
+#ifndef DEBUG
+		ext->handler = dlopen(ext->filename, RTLD_LAZY | RTLD_GLOBAL);
+#else /* DEBUG */
+		/* We resolve symbols immediatly so it's easier to find problems in ABI */
+		ext->handler = dlopen(ext->filename, RTLD_NOW | RTLD_GLOBAL);
+#endif /* DEBUG */
+		if (ext->handler == NULL) {
+			/* An error occured */
+			LOG_F("Loading of extension %s failed: %s", ext->filename, dlerror());
+			ext->handler = dlopen(ext->filename, RTLD_LAZY | RTLD_GLOBAL);
+			if (ext->handler) {
+				if (!check_dependencies(ext)) {
+					LOG_F("In addition, not all declared dependencies are satisfied (Internal Error!)");
+				}
+			}
+			return EINVAL;
+		}
+
+		/* Resolve the entry point of the extension */
+		fd_ext_init = ( int (*) (int, int, char *) )dlsym( ext->handler, "fd_ext_init" );
+		
+		if (fd_ext_init == NULL) {
+			/* An error occured */
+			TRACE_ERROR("Unable to resolve symbol 'fd_ext_init' for extension %s: %s", ext->filename, dlerror());
+			return EINVAL;
+		}
+
+		
+		/* Resolve the exit point of the extension, which is optional for extensions */
+		ext->fini = ( void (*) (void) )dlsym( ext->handler, "fd_ext_fini" );
+		
+		if (ext->fini == NULL) {
+			/* Not provided */
+			TRACE_DEBUG (FULL, "Extension [%s] has no fd_ext_fini function.", ext->filename);
+		} else {
+			/* Provided */
+			TRACE_DEBUG (FULL, "Extension [%s] fd_ext_fini has been resolved successfully.", ext->filename);
+		}
+
+		/* Now call the entry point to initialize the extension */
+		ret = (*fd_ext_init)( FD_PROJECT_VERSION_MAJOR, FD_PROJECT_VERSION_MINOR, ext->conffile );
+		if (ret != 0) {
+			/* The extension was unable to load cleanly */
+			TRACE_ERROR("Extension %s returned an error during initialization: %s", ext->filename, strerror(ret));
+			return ret;
+		}
+		
+		/* Proceed to the next extension */
+	}
+
+	for( li = ext_list.next; li != &ext_list; li = li->next )
+        {
+		struct fd_ext_info * ext = (struct fd_ext_info *)li;
+		CHECK_FCT( load_dependencies(ext));
+	}
+
+
+	for( li = ext_list.next; li != &ext_list; li = li->next )
+	{
+		struct fd_ext_info * ext = (struct fd_ext_info *)li;
+
+		/* Check if declared dependencies are satisfied. */
+		CHECK_FCT( check_dependencies(ext) );
+
+		/* Loading methods init2 & parserules */
+		fd_ext_init2 = ( int (*) (int, int, char *) )dlsym( ext->handler, "fd_ext_init2" );
+
+		if (fd_ext_init2 == NULL) {
+			/* Old extensions do not define fd_ext_init2 */
+			LOG_N("Unable to  resolve symbol 'fd_ext_init2' for extension %s: ", ext->filename);
+		}
+		else {
+			ret = (*fd_ext_init2)( FD_PROJECT_VERSION_MAJOR, FD_PROJECT_VERSION_MINOR, ext->conffile );
+			if (ret != 0) {
+				/* The extension was unable to load cleanly */
+				TRACE_ERROR("Extension %s returned an error during parse local rules: %s", ext->filename, strerror(ret));
+				return ret;
+			}
+		}
+	}
+	
+	LOG_N("All extensions loaded.");
+	
+	/* We have finished. */
+	return 0;
+}
+
+/* Now unload the extensions and free the memory */
+int fd_ext_term( void ) 
+{
+	TRACE_ENTRY();
+	
+	/* Loop on all extensions, in FIFO order */
+	while (!FD_IS_LIST_EMPTY(&ext_list))
+	{
+		struct fd_list * li = ext_list.next;
+		struct fd_ext_info * ext = (struct fd_ext_info *)li;
+	
+		/* Unlink this element from the list */
+		fd_list_unlink(li);
+		
+		/* Call the exit point of the extension, if it was resolved */
+		if (ext->fini != NULL) {
+			TRACE_DEBUG (FULL, "Calling [%s]->fd_ext_fini function.", ext->ext_name ?: ext->filename);
+			(*ext->fini)();
+		}
+		
+#ifndef SKIP_DLCLOSE
+		/* Now unload the extension */
+		if (ext->handler) {
+			TRACE_DEBUG (FULL, "Unloading %s", ext->ext_name ?: ext->filename);
+			if ( dlclose(ext->handler) != 0 ) {
+				TRACE_DEBUG (INFO, "Unloading [%s] failed : %s", ext->ext_name ?: ext->filename, dlerror());
+			}
+		}
+#endif /* SKIP_DLCLOSE */
+		
+		/* Free the object and continue */
+		if (ext->free_ext_name)
+			free(ext->ext_name);
+		free(ext->filename);
+		free(ext->conffile);
+		free(ext);
+	}
+	
+	/* We always return 0 since we would not handle an error anyway... */
+	return 0;
+}
+
diff --git a/libfdcore/fdcore-internal.h b/libfdcore/fdcore-internal.h
new file mode 100644
index 0000000..7fac852
--- /dev/null
+++ b/libfdcore/fdcore-internal.h
@@ -0,0 +1,375 @@
+/*********************************************************************************************************
+* Software License Agreement (BSD License)                                                               *
+* Author: Sebastien Decugis <sdecugis@freediameter.net>							 *
+*													 *
+* Copyright (c) 2013, WIDE Project and NICT								 *
+* All rights reserved.											 *
+* 													 *
+* Redistribution and use of this software in source and binary forms, with or without modification, are  *
+* permitted provided that the following conditions are met:						 *
+* 													 *
+* * Redistributions of source code must retain the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer.										 *
+*    													 *
+* * Redistributions in binary form must reproduce the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer in the documentation and/or other						 *
+*   materials provided with the distribution.								 *
+* 													 *
+* * Neither the name of the WIDE Project or NICT nor the 						 *
+*   names of its contributors may be used to endorse or 						 *
+*   promote products derived from this software without 						 *
+*   specific prior written permission of WIDE Project and 						 *
+*   NICT.												 *
+* 													 *
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED *
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
+* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR *
+* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 	 *
+* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 	 *
+* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR *
+* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF   *
+* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.								 *
+*********************************************************************************************************/
+
+/* This file contains the definitions for internal use in the freeDiameter core library */
+
+#ifndef _FDCORE_INTERNAL_H
+#define _FDCORE_INTERNAL_H
+
+#include <freeDiameter/freeDiameter-host.h>
+#include <freeDiameter/libfdcore.h>
+
+#ifdef DISABLE_SCTP
+#undef IPPROTO_SCTP
+#define IPPROTO_SCTP	(2 = 4) /* some compilation error to spot the references */
+#endif /* DISABLE_SCTP */
+
+#ifndef HAVE_AI_ADDRCONFIG
+#define AI_ADDRCONFIG 0 /* ignore this flag at the moment */
+#endif /* HAVE_AI_ADDRCONFIG */
+
+/* Timeout for establishing a connection */
+#ifndef CNX_TIMEOUT
+#define  CNX_TIMEOUT	10	/* in seconds */
+#endif /* CNX_TIMEOUT */
+
+/* Timeout for receiving a CER after incoming connection is established */
+#ifndef INCNX_TIMEOUT
+#define  INCNX_TIMEOUT	 20	/* in seconds */
+#endif /* INCNX_TIMEOUT */
+
+/* Timeout for receiving a CEA after CER is sent */
+#ifndef CEA_TIMEOUT
+#define  CEA_TIMEOUT	10	/* in seconds */
+#endif /* CEA_TIMEOUT */
+
+/* The timeout value to wait for answer to a DPR */
+#ifndef DPR_TIMEOUT
+#define DPR_TIMEOUT 	15	/* in seconds */
+#endif /* DPR_TIMEOUT */
+
+/* Delay where the connection is maintained opened to allow exchanging remaining pending answers after DPR/DPA */
+#ifndef GRACE_TIMEOUT
+#define GRACE_TIMEOUT   1	/* in seconds */
+#endif /* GRACE_TIMEOUT */
+
+/* The Vendor-Id to advertise in CER/CEA */
+#ifndef MY_VENDOR_ID
+#define MY_VENDOR_ID	0 	/* Reserved value to tell it must be ignored */
+#endif /* MY_VENDOR_ID */
+
+
+
+/* Configuration */
+int fd_conf_init();
+int fd_conf_deinit();
+int fd_conf_parse();
+int fddparse(struct fd_config * conf); /* yacc generated */
+int fd_conf_stream_to_gnutls_datum(FILE * pemfile, gnutls_datum_t *out);
+
+
+/* Extensions */
+int fd_ext_add( char * filename, char * conffile );
+int fd_ext_load();
+int fd_ext_term(void);
+
+/* Messages */
+int fd_msg_init(void);
+extern struct dict_object * fd_dict_avp_OSI; /* Origin-State-Id */
+extern struct dict_object * fd_dict_cmd_CER; /* Capabilities-Exchange-Request */
+extern struct dict_object * fd_dict_cmd_DWR; /* Device-Watchdog-Request */
+extern struct dict_object * fd_dict_avp_DC;  /* Disconnect-Cause */
+extern struct dict_object * fd_dict_cmd_DPR; /* Disconnect-Peer-Request */
+
+/* Global message queues */
+extern struct fifo * fd_g_incoming; /* all messages received from other peers, except local messages (CER, ...) */
+extern struct fifo * fd_g_outgoing; /* messages to be sent to other peers on the network following routing procedure */
+extern struct fifo * fd_g_local; /* messages to be handled to local extensions */
+/* Message queues */
+int fd_queues_init(void);
+int fd_queues_fini(struct fifo ** queue);
+
+/* Trigged events */
+int fd_event_trig_call_cb(int trigger_val);
+int fd_event_trig_fini(void);
+
+/* Create all the dictionary objects defined in the Diameter base RFC. */
+int fd_dict_base_protocol(struct dictionary * dict);
+
+/* Routing */
+int fd_rtdisp_init(void);
+int fd_rtdisp_cleanstop(void);
+int fd_rtdisp_fini(void);
+int fd_rtdisp_cleanup(void);
+
+/* Sentinel for the sent requests list */
+struct sr_list {
+	struct fd_list 	srs; /* requests ordered by hop-by-hop id */
+	struct fd_list  exp; /* requests that have a timeout set, ordered by timeout */
+	long            cnt; /* number of requests in the srs list */
+	long		cnt_lost; /* number of requests that have not been answered in time. 
+				     It is decremented when an unexpected answer is received, so this may not be accurate. */
+	pthread_mutex_t	mtx; /* mutex to protect these lists */
+	pthread_cond_t  cnd; /* cond var used by the thread that handles timeouts */
+	pthread_t       thr; /* the thread that handles timeouts (expirecb called in separate forked threads) */
+};
+
+/* Peers */
+struct fd_peer { /* The "real" definition of the peer structure */
+	
+	/* The public data */
+	struct peer_hdr	 p_hdr;
+	
+	/* Eye catcher, EYEC_PEER */
+	int		 p_eyec;
+	#define EYEC_PEER	0x373C9336
+	
+	/* Origin of this peer object, for debug */
+	char		*p_dbgorig;
+	
+	/* State of the peer, and its lock */
+	enum peer_state	 p_state;
+	pthread_mutex_t  p_state_mtx;
+	
+	/* Chaining in peers sublists */
+	struct fd_list	 p_actives;	/* list of peers in the STATE_OPEN state -- used by routing */
+	struct fd_list	 p_expiry; 	/* list of expiring peers, ordered by their timeout value */
+	struct timespec	 p_exp_timer;	/* Timestamp where the peer will expire; updated each time activity is seen on the peer (except DW) */
+	
+	/* Some flags influencing the peer state machine */
+	struct {
+		unsigned pf_responder	: 1;	/* The peer has been created to handle incoming connection */
+		unsigned pf_delete	: 1;	/* Destroy the peer when the connection is terminated */
+		unsigned pf_localterm	: 1;	/* If the latest DPR/DPA was initiated from this side */
+		
+		unsigned pf_dw_pending 	: 1;	/* A DWR message was sent and not answered yet */
+		
+		unsigned pf_cnx_pb	: 1;	/* The peer was disconnected because of watchdogs; must exchange 3 watchdogs before putting back to normal */
+		unsigned pf_reopen_cnt	: 2;	/* remaining DW to be exchanged after re-established connection */
+		
+	}		 p_flags;
+	
+	/* The events queue, peer state machine thread, timer for states timeouts */
+	struct fifo	*p_events;	/* The mutex of this FIFO list protects also the state and timer information */
+	pthread_t	 p_psm;
+	struct timespec	 p_psm_timer;
+	
+	/* Outgoing message queue, and thread managing sending the messages */
+	struct fifo	*p_tosend;
+	pthread_t	 p_outthr;
+	
+	/* The next hop-by-hop id value for the link, only read & modified by p_outthr */
+	uint32_t	 p_hbh;
+	
+	/* Sent requests (for fallback), list of struct sentreq ordered by hbh */
+	struct sr_list	 p_sr;
+	struct fifo	*p_tofailover;
+	
+	/* Pending received requests not yet answered (count only) */
+	long		 p_reqin_count; /* We use p_state_mtx to protect this value */
+	
+	/* Data for transitional states before the peer is in OPEN state */
+	struct {
+		struct cnxctx * p_receiver;	/* Only used in case of election */
+		struct msg    * p_cer;		/* Only used in case of election */
+		
+		pthread_t	p_ini_thr;	/* Initiator thread for establishing a connection */
+		struct fd_list  p_connparams;	/* The list of connection attempts, see p_cnx.c */
+	};
+	
+	/* connection context: socket and related information */
+	struct cnxctx	*p_cnxctx;
+	
+	/* Callback for peer validation after the handshake */
+	int		(*p_cb2)(struct peer_info *);
+	
+	/* Callback on initial connection success / failure after the peer was added */
+	void 		(*p_cb)(struct peer_info *, void *);
+	void 		*p_cb_data;
+	
+};
+#define CHECK_PEER( _p ) \
+	(((_p) != NULL) && (((struct fd_peer *)(_p))->p_eyec == EYEC_PEER))
+
+#define fd_peer_getstate(peer)  fd_peer_get_state((struct peer_hdr *)(peer))
+
+
+/* Events codespace for struct fd_peer->p_events */
+enum {
+	/* request to terminate this peer : disconnect, requeue all messages */
+	FDEVP_TERMINATE = 1500
+	
+	/* A connection object has received a message. (data contains the buffer + padding + struct fd_msg_pmdl) */
+	,FDEVP_CNX_MSG_RECV
+			 
+	/* A connection object has encountered an error (disconnected). */
+	,FDEVP_CNX_ERROR
+	
+	/* Endpoints of a connection have been changed (multihomed SCTP). */
+	,FDEVP_CNX_EP_CHANGE
+	
+	/* The connection is being shutdown (SCTP notification). */
+	,FDEVP_CNX_SHUTDOWN
+	
+	/* A new connection (with a CER) has been received */
+	,FDEVP_CNX_INCOMING
+	
+	/* A new connection has been established to the remote peer (event data is the cnxctx object) */
+	,FDEVP_CNX_ESTABLISHED
+	
+	/* A connection attempt (initiator side) has failed */
+	,FDEVP_CNX_FAILED
+	
+	/* The PSM state is expired */
+	,FDEVP_PSM_TIMEOUT
+	
+};
+#define CHECK_PEVENT( _e ) \
+	(((int)(_e) >= FDEVP_TERMINATE) && ((int)(_e) <= FDEVP_PSM_TIMEOUT))
+/* The following macro is actually called in p_psm.c -- another solution would be to declare it static inline */
+#define DECLARE_PEV_STR()				\
+const char * fd_pev_str(int event)			\
+{							\
+	switch (event) {				\
+		case_str(FDEVP_TERMINATE);		\
+		case_str(FDEVP_CNX_MSG_RECV);		\
+		case_str(FDEVP_CNX_ERROR);		\
+		case_str(FDEVP_CNX_EP_CHANGE);		\
+		case_str(FDEVP_CNX_INCOMING);		\
+		case_str(FDEVP_CNX_ESTABLISHED);	\
+		case_str(FDEVP_CNX_FAILED);		\
+		case_str(FDEVP_PSM_TIMEOUT);		\
+	}						\
+	TRACE_DEBUG(FULL, "Unknown event : %d", event);	\
+	return "Unknown event";				\
+}
+const char * fd_pev_str(int event);
+
+/* The data structure for FDEVP_CNX_INCOMING event */
+struct cnx_incoming {
+	struct msg	* cer;		/* the CER message received on this connection */
+	struct cnxctx	* cnx;		/* The connection context */
+	int  		  validate;	/* The peer is new, it must be validated (by an extension) or error CEA to be sent */
+};
+
+/* Functions */
+int  fd_peer_fini();
+int  fd_peer_alloc(struct fd_peer ** ptr);
+int  fd_peer_free(struct fd_peer ** ptr);
+int fd_peer_handle_newCER( struct msg ** cer, struct cnxctx ** cnx );
+/* fd_peer_add declared in freeDiameter.h */
+int fd_peer_validate( struct fd_peer * peer );
+void fd_peer_failover_msg(struct fd_peer * peer);
+
+/* Peer expiry */
+int fd_p_expi_init(void);
+int fd_p_expi_fini(void);
+int fd_p_expi_update(struct fd_peer * peer );
+
+/* Peer state machine */
+int  fd_psm_start();
+int  fd_psm_begin(struct fd_peer * peer );
+int  fd_psm_terminate(struct fd_peer * peer, char * reason );
+void fd_psm_abord(struct fd_peer * peer );
+void fd_psm_next_timeout(struct fd_peer * peer, int add_random, int delay);
+int fd_psm_change_state(struct fd_peer * peer, int new_state);
+void fd_psm_cleanup(struct fd_peer * peer, int terminate);
+
+/* Peer out */
+int fd_out_send(struct msg ** msg, struct cnxctx * cnx, struct fd_peer * peer, int update_reqin_cnt);
+int fd_out_start(struct fd_peer * peer);
+int fd_out_stop(struct fd_peer * peer);
+
+/* Initiating connections */
+int fd_p_cnx_init(struct fd_peer * peer);
+void fd_p_cnx_abort(struct fd_peer * peer, int cleanup_all);
+
+/* Peer sent requests cache */
+int fd_p_sr_store(struct sr_list * srlist, struct msg **req, uint32_t *hbhloc, uint32_t hbh_restore);
+int fd_p_sr_fetch(struct sr_list * srlist, uint32_t hbh, struct msg **req);
+int fd_p_sr_start(struct sr_list * srlist);
+int fd_p_sr_stop(struct sr_list * srlist);
+void fd_p_sr_failover(struct sr_list * srlist);
+
+/* Local Link messages (CER/CEA, DWR/DWA, DPR/DPA) */
+int fd_p_ce_msgrcv(struct msg ** msg, int req, struct fd_peer * peer);
+int fd_p_ce_handle_newCER(struct msg ** msg, struct fd_peer * peer, struct cnxctx ** cnx, int valid);
+int fd_p_ce_handle_newcnx(struct fd_peer * peer, struct cnxctx * initiator);
+int fd_p_ce_process_receiver(struct fd_peer * peer);
+void fd_p_ce_clear_cnx(struct fd_peer * peer, struct cnxctx ** cnx_kept);
+int fd_p_dw_handle(struct msg ** msg, int req, struct fd_peer * peer);
+int fd_p_dw_timeout(struct fd_peer * peer);
+int fd_p_dw_reopen(struct fd_peer * peer);
+int fd_p_dp_handle(struct msg ** msg, int req, struct fd_peer * peer);
+int fd_p_dp_initiate(struct fd_peer * peer, char * reason);
+int fd_p_dp_newdelay(struct fd_peer * peer);
+
+/* Active peers -- routing process should only ever take the read lock, the write lock is managed by PSMs */
+extern struct fd_list fd_g_activ_peers;
+extern pthread_rwlock_t fd_g_activ_peers_rw; /* protect the list */
+
+
+/* Server sockets */
+int  fd_servers_start();
+int  fd_servers_stop();
+
+/* Connection contexts -- there are also definitions in cnxctx.h for the relevant files */
+struct cnxctx * fd_cnx_serv_tcp(uint16_t port, int family, struct fd_endpoint * ep);
+struct cnxctx * fd_cnx_serv_sctp(uint16_t port, struct fd_list * ep_list);
+int             fd_cnx_serv_listen(struct cnxctx * conn);
+struct cnxctx * fd_cnx_serv_accept(struct cnxctx * serv);
+struct cnxctx * fd_cnx_cli_connect_tcp(sSA * sa, socklen_t addrlen);
+struct cnxctx * fd_cnx_cli_connect_sctp(int no_ip6, uint16_t port, struct fd_list * list);
+int             fd_cnx_start_clear(struct cnxctx * conn, int loop);
+void		fd_cnx_sethostname(struct cnxctx * conn, DiamId_t hn);
+int		fd_cnx_proto_info(struct cnxctx * conn, char * buf, size_t len);
+#define ALGO_HANDSHAKE_DEFAULT	0 /* TLS for TCP, DTLS for SCTP */
+#define ALGO_HANDSHAKE_3436	1 /* For TLS for SCTP also */
+int             fd_cnx_handshake(struct cnxctx * conn, int mode, int algo, char * priority, void * alt_creds);
+char *          fd_cnx_getid(struct cnxctx * conn);
+int		fd_cnx_getproto(struct cnxctx * conn);
+int		fd_cnx_getTLS(struct cnxctx * conn);
+int		fd_cnx_is_unordered_delivery_supported(struct cnxctx * conn);
+int		fd_cnx_unordered_delivery(struct cnxctx * conn, int is_allowed);
+int             fd_cnx_getcred(struct cnxctx * conn, const gnutls_datum_t **cert_list, unsigned int *cert_list_size);
+int 		fd_cnx_get_local_eps(struct fd_list * list);
+int             fd_cnx_getremoteeps(struct cnxctx * conn, struct fd_list * eps);
+char *          fd_cnx_getremoteid(struct cnxctx * conn);
+int             fd_cnx_receive(struct cnxctx * conn, struct timespec * timeout, unsigned char **buf, size_t * len);
+int             fd_cnx_recv_setaltfifo(struct cnxctx * conn, struct fifo * alt_fifo); /* send FDEVP_CNX_MSG_RECV event to the fifo list */
+int             fd_cnx_send(struct cnxctx * conn, unsigned char * buf, size_t len);
+void            fd_cnx_destroy(struct cnxctx * conn);
+#ifdef GNUTLS_VERSION_300
+int             fd_tls_verify_credentials_2(gnutls_session_t session);
+#endif /* GNUTLS_VERSION_300 */
+
+/* Internal calls of the hook mechanism */
+void   fd_hook_call(enum fd_hook_type type, struct msg * msg, struct fd_peer * peer, void * other, struct fd_msg_pmdl * pmdl);
+void   fd_hook_associate(struct msg * msg, struct fd_msg_pmdl * pmdl);
+int    fd_hooks_init(void);
+size_t fd_msg_pmdl_sizewithoverhead(size_t datalen);
+struct fd_msg_pmdl * fd_msg_pmdl_get_inbuf(uint8_t * buf, size_t datalen); 
+
+#endif /* _FDCORE_INTERNAL_H */
diff --git a/libfdcore/fdd.l b/libfdcore/fdd.l
new file mode 100644
index 0000000..8835def
--- /dev/null
+++ b/libfdcore/fdd.l
@@ -0,0 +1,285 @@
+/*********************************************************************************************************
+* Software License Agreement (BSD License)                                                               *
+* Author: Sebastien Decugis <sdecugis@freediameter.net>							 *
+*													 *
+* Copyright (c) 2013, WIDE Project and NICT								 *
+* All rights reserved.											 *
+* 													 *
+* Redistribution and use of this software in source and binary forms, with or without modification, are  *
+* permitted provided that the following conditions are met:						 *
+* 													 *
+* * Redistributions of source code must retain the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer.										 *
+*    													 *
+* * Redistributions in binary form must reproduce the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer in the documentation and/or other						 *
+*   materials provided with the distribution.								 *
+* 													 *
+* * Neither the name of the WIDE Project or NICT nor the 						 *
+*   names of its contributors may be used to endorse or 						 *
+*   promote products derived from this software without 						 *
+*   specific prior written permission of WIDE Project and 						 *
+*   NICT.												 *
+* 													 *
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED *
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
+* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR *
+* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 	 *
+* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 	 *
+* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR *
+* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF   *
+* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.								 *
+*********************************************************************************************************/
+
+/* Lex configuration parser.
+ *
+ * This file defines the token for parsing the daemon's configuration file
+ * Note that each extension has a separate independant configuration file.
+ *
+ * Note : This module is NOT thread-safe. All processing must be done from one thread only.
+ */
+%{
+/* Include the daemon's header files */
+#include "fdcore-internal.h"
+/* Include yacc tokens definitions */
+#include "fdd.tab.h"
+
+/* Update the column information */
+#ifdef DEBUG_LEX
+#define YY_USER_ACTION { 						\
+	yylloc->first_column = yylloc->last_column + 1; 		\
+	yylloc->last_column = yylloc->first_column + yyleng - 1;	\
+	fd_log_debug(	 						\
+		"(%d:%d-%d:%d) matched rule %d, length=%d, txt='%s'",	\
+		yylloc->first_line, yylloc->first_column, 		\
+		yylloc->last_line, yylloc->last_column, 		\
+		yy_act, yyleng, yytext); 				\
+}
+#else /* DEBUG_LEX */
+#define YY_USER_ACTION { 						\
+	yylloc->first_column = yylloc->last_column + 1; 		\
+	yylloc->last_column = yylloc->first_column + yyleng - 1;	\
+}
+#endif
+
+/* %option noinput ? */
+#define YY_NO_INPUT
+
+/* Additional for files inclusion */
+#include <glob.h>
+#include <string.h>
+
+#define MAX_NESTED_CONF_FILES	5
+
+struct nested_conffiles_t {
+	YY_BUFFER_STATE parent_level_state;
+	glob_t filelist;
+	int current_file;
+} nested_conffiles[MAX_NESTED_CONF_FILES];
+
+int current_nested_level = 0;
+
+int globerrfct(const char *epath, int eerrno)
+{
+	TRACE_ERROR("Failed to scan %s: %s", epath, strerror(eerrno));
+	return 1;
+}
+
+%}
+
+%option bison-bridge bison-locations
+%option noyywrap
+%option nounput
+
+%x in_include
+
+/* Quoted string. Multilines do not match. */
+qstring		\"[^\"\n]*\"
+
+%%
+<*>\n			{ 
+				/* Update the line count */
+				yylloc->first_line++; 
+				yylloc->last_line++; 
+				yylloc->last_column=0; 
+			} 
+
+<*>([[:space:]]{-}[\n])+	; /* Eat all spaces, not new lines */
+<*>#.*$			; /* Eat all comments */
+
+
+include		BEGIN(in_include);
+	/* Following an "include" keyword */
+<in_include>{
+{qstring}	{ /* Name of the file to include. This is directly sent to glob. */
+			int globerror=0;
+			char * buf = strdup(yytext+1);
+			if (buf[yyleng-2] != '"')
+			{
+				TRACE_ERROR("Unterminated string: %s", yytext);
+				return LEX_ERROR;
+			}
+			buf[yyleng-2] = '\0';
+
+			if (current_nested_level >= MAX_NESTED_CONF_FILES)
+			{
+				TRACE_ERROR("Too many recursion levels in configuration files includes");
+				return LEX_ERROR;
+			}
+
+			/* glob the include */
+			globerror = glob(buf, GLOB_ERR, globerrfct, &nested_conffiles[current_nested_level].filelist);
+
+			if (globerror == GLOB_NOSPACE)
+			{
+				TRACE_ERROR("Not enough memory to parse include directive.");
+				return LEX_ERROR;
+			}
+			if (globerror == GLOB_ABORTED)
+			{
+				TRACE_ERROR("An error was encountered in include directive.");
+				return LEX_ERROR;
+			}
+			if (globerror == GLOB_NOMATCH)
+			{
+				globfree(&nested_conffiles[current_nested_level].filelist);
+				goto nomatch;
+			}
+			if (globerror)
+			{
+				TRACE_ERROR("Unexpected error in glob (%d).", globerror);
+				return LEX_ERROR;
+			}
+
+			/* We have a list of files to include. */
+
+			/* save the current buffer for returning when this include has been parsed */
+			nested_conffiles[current_nested_level].parent_level_state = YY_CURRENT_BUFFER;
+
+			/* Start with the first match */
+			nested_conffiles[current_nested_level].current_file = 0;
+
+			yyin = fopen( nested_conffiles[current_nested_level].filelist.gl_pathv[0], "r" );
+
+			if ( ! yyin )
+			{
+				TRACE_ERROR("Error in %s: %s", nested_conffiles[current_nested_level].filelist.gl_pathv[0], strerror(errno));
+				return LEX_ERROR;
+			}
+
+			yy_switch_to_buffer(yy_create_buffer( yyin, YY_BUF_SIZE ));
+
+			/* In case of recursive includes */
+			current_nested_level++;
+
+nomatch:
+			BEGIN(INITIAL);
+		}
+}
+
+<<EOF>>	{
+			if (current_nested_level == 0)
+			{
+			      /* We are at the end of parsing */
+			      yyterminate();
+			}
+
+			/* Otherwise we are doing an include statement */
+			--current_nested_level;
+			yy_delete_buffer(YY_CURRENT_BUFFER);
+
+			/* Go to next file, if any */
+			nested_conffiles[current_nested_level].current_file++;
+			if ( nested_conffiles[current_nested_level].filelist.gl_pathv[nested_conffiles[current_nested_level].current_file] == NULL )
+			{
+				/* We have finished with this list of includes */
+				globfree(&nested_conffiles[current_nested_level].filelist);
+				yy_switch_to_buffer(nested_conffiles[current_nested_level].parent_level_state);
+			}
+			else
+			{
+				/* Proceed to next included file */
+				yyin = fopen( nested_conffiles[current_nested_level].filelist.gl_pathv[nested_conffiles[current_nested_level].current_file], "r" );
+
+				if ( ! yyin )
+				{
+					TRACE_ERROR("Error in %s: %s", nested_conffiles[current_nested_level].filelist.gl_pathv[nested_conffiles[current_nested_level].current_file], strerror(errno));
+					return LEX_ERROR;
+				}
+
+				yy_switch_to_buffer(yy_create_buffer( yyin, YY_BUF_SIZE ));
+
+				/* In case of recursive includes */
+				current_nested_level++;
+			}
+
+}
+
+{qstring}		{
+				/* First copy the string without the quotes for use in the yacc parser */
+				CHECK_MALLOC_DO(	yylval->string = strdup(yytext+1), /* This allocates one useless tail char but... it's easier :D */ 
+							return LEX_ERROR  );/* on error, trig an error in yacc parser */
+
+				yylval->string[yyleng-2] = '\0';
+				
+				/* the yacc parser will check the string is valid */
+				return QSTRING;
+			}
+			
+[[:digit:]]+		{
+				/* Convert this to an integer value */
+				int ret = sscanf(yytext, "%i", &yylval->integer);
+				if (ret != 1) {
+					/* No matching: an error occurred */
+					TRACE_ERROR("Unable to convert the value '%s' to a valid number: %s", yytext, strerror(errno));
+					return LEX_ERROR; /* trig an error in yacc parser */
+					/* Maybe we could REJECT instead of failing here? */
+				}
+				return INTEGER;
+			}
+				
+	/* Full words tokens (keywords) */
+(?i:"Identity")		{ return IDENTITY;	}
+(?i:"Realm")		{ return REALM;   	}
+(?i:"Port")		{ return PORT;    	}
+(?i:"SecPort")		{ return SECPORT;  	}
+	/* (?i:"SctpSec3436")	{ return SEC3436;  	} */
+(?i:"No_IPv6")		{ return NOIP6;		}
+(?i:"No_IP")		{ return NOIP;		}
+(?i:"No_TCP")		{ return NOTCP;		}
+(?i:"No_SCTP")		{ return NOSCTP;	}
+(?i:"Prefer_TCP")	{ return PREFERTCP;	}
+(?i:"TLS_old_method")	{ return OLDTLS;	}
+(?i:"SCTP_streams")	{ return SCTPSTREAMS;	}
+(?i:"AppServThreads")	{ return APPSERVTHREADS;}
+(?i:"ListenOn")		{ return LISTENON;	}
+(?i:"ThreadsPerServer")	{ return THRPERSRV;	}
+(?i:"TcTimer")		{ return TCTIMER;	}
+(?i:"TwTimer")		{ return TWTIMER;	}
+(?i:"NoRelay")		{ return NORELAY;	}
+(?i:"LoadExtension")	{ return LOADEXT;	}
+(?i:"ConnectPeer")	{ return CONNPEER;	}
+(?i:"ConnectTo")	{ return CONNTO;	}
+(?i:"No_TLS")		{ return NOTLS;		}
+(?i:"TLS_Cred")		{ return TLS_CRED;	}
+(?i:"TLS_CA")		{ return TLS_CA;	}
+(?i:"TLS_CRL")		{ return TLS_CRL;	}
+(?i:"TLS_Prio")		{ return TLS_PRIO;	}
+(?i:"TLS_DH_bits")	{ return TLS_DH_BITS;	}
+(?i:"TLS_DH_file")	{ return TLS_DH_FILE;	}
+
+
+	/* Valid single characters for yyparse */
+<*>[=,:;{}]		{ return yytext[0]; }
+
+	/* Unrecognized token */
+<*>[[:alnum:]]+		|	/* This rule is only useful to print a complete token in error messages */
+	/* Unrecognized character */
+<*>.			{
+				TRACE_ERROR("Unrecognized text on line %d col %d: '%s'.", yylloc->first_line, yylloc->first_column, yytext);
+			 	return LEX_ERROR; 
+			}
+
+%%
diff --git a/libfdcore/fdd.y b/libfdcore/fdd.y
new file mode 100644
index 0000000..07707c9
--- /dev/null
+++ b/libfdcore/fdd.y
@@ -0,0 +1,667 @@
+/*********************************************************************************************************
+* Software License Agreement (BSD License)                                                               *
+* Author: Sebastien Decugis <sdecugis@freediameter.net>							 *
+*													 *
+* Copyright (c) 2015, WIDE Project and NICT								 *
+* All rights reserved.											 *
+* 													 *
+* Redistribution and use of this software in source and binary forms, with or without modification, are  *
+* permitted provided that the following conditions are met:						 *
+* 													 *
+* * Redistributions of source code must retain the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer.										 *
+*    													 *
+* * Redistributions in binary form must reproduce the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer in the documentation and/or other						 *
+*   materials provided with the distribution.								 *
+* 													 *
+* * Neither the name of the WIDE Project or NICT nor the 						 *
+*   names of its contributors may be used to endorse or 						 *
+*   promote products derived from this software without 						 *
+*   specific prior written permission of WIDE Project and 						 *
+*   NICT.												 *
+* 													 *
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED *
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
+* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR *
+* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 	 *
+* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 	 *
+* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR *
+* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF   *
+* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.								 *
+*********************************************************************************************************/
+
+/* Yacc configuration parser.
+ *
+ * This file defines the grammar of the configuration file.
+ * Note that each extension has a separate independant configuration file.
+ *
+ * Note : This module is NOT thread-safe. All processing must be done from one thread only.
+ */
+
+/* For development only : */
+%debug 
+%error-verbose
+
+%parse-param {struct fd_config * conf}
+
+/* Keep track of location */
+%locations 
+%pure-parser
+
+%{
+#include "fdcore-internal.h"
+#include "fdd.tab.h"	/* bug : bison does not define the YYLTYPE before including this bloc, so... */
+
+/* The Lex parser prototype */
+int fddlex(YYSTYPE *lvalp, YYLTYPE *llocp);
+
+/* Function to report error */
+void yyerror (YYLTYPE *ploc, struct fd_config * conf, char const *s)
+{
+	if (ploc->first_line != ploc->last_line) {
+		TRACE_ERROR("%s:%d.%d-%d.%d : %s", conf->cnf_file, ploc->first_line, ploc->first_column, ploc->last_line, ploc->last_column, s);
+	} else if (ploc->first_column != ploc->last_column) {
+		TRACE_ERROR("%s:%d.%d-%d : %s", conf->cnf_file, ploc->first_line, ploc->first_column, ploc->last_column, s);
+	} else {
+		TRACE_ERROR("%s:%d.%d : %s", conf->cnf_file, ploc->first_line, ploc->first_column, s);
+	}
+}
+
+int got_peer_noip = 0;
+int got_peer_noipv6 = 0;
+int got_peer_notcp = 0;
+int got_peer_nosctp = 0;
+
+struct peer_info fddpi;
+
+%}
+
+/* Values returned by lex for token */
+%union {
+	char 		 *string;	/* The string is allocated by strdup in lex.*/
+	int		  integer;	/* Store integer values */
+}
+
+/* In case of error in the lexical analysis */
+%token 		LEX_ERROR
+
+%token <string>	QSTRING
+%token <integer> INTEGER
+
+%type <string> 	extconf
+
+%token		IDENTITY
+%token		REALM
+%token		PORT
+%token		SECPORT
+%token		SEC3436
+%token		NOIP
+%token		NOIP6
+%token		NOTCP
+%token		NOSCTP
+%token		PREFERTCP
+%token		OLDTLS
+%token		NOTLS
+%token		SCTPSTREAMS
+%token		APPSERVTHREADS
+%token		LISTENON
+%token		THRPERSRV
+%token		TCTIMER
+%token		TWTIMER
+%token		NORELAY
+%token		LOADEXT
+%token		CONNPEER
+%token		CONNTO
+%token		TLS_CRED
+%token		TLS_CA
+%token		TLS_CRL
+%token		TLS_PRIO
+%token		TLS_DH_BITS
+%token		TLS_DH_FILE
+
+
+/* -------------------------------------- */
+%%
+
+	/* The grammar definition - Sections blocs. */
+conffile:		/* Empty is OK -- for simplicity here, we reject in daemon later */
+			| conffile identity
+			| conffile realm
+			| conffile tctimer
+			| conffile twtimer
+			| conffile port
+			| conffile secport
+			| conffile sec3436
+			| conffile sctpstreams
+			| conffile listenon
+			| conffile thrpersrv
+			| conffile norelay
+			| conffile appservthreads
+			| conffile noip
+			| conffile noip6
+			| conffile notcp
+			| conffile nosctp
+			| conffile prefertcp
+			| conffile oldtls
+			| conffile loadext
+			| conffile connpeer
+			| conffile tls_cred
+			| conffile tls_ca
+			| conffile tls_crl
+			| conffile tls_prio
+			| conffile tls_dh
+			| conffile errors
+			{
+				yyerror(&yylloc, conf, "An error occurred while parsing the configuration file");
+				return EINVAL;
+			}
+			;
+
+			/* Lexical or syntax error */
+errors:			LEX_ERROR
+			| error
+			;
+
+identity:		IDENTITY '=' QSTRING ';'
+			{
+				conf->cnf_diamid = $3;
+			}
+			;
+
+realm:			REALM '=' QSTRING ';'
+			{
+				conf->cnf_diamrlm = $3;
+			}
+			;
+
+tctimer:		TCTIMER '=' INTEGER ';'
+			{
+				CHECK_PARAMS_DO( ($3 > 0),
+					{ yyerror (&yylloc, conf, "Invalid value"); YYERROR; } );
+				conf->cnf_timer_tc = (unsigned int)$3;
+			}
+			;
+
+twtimer:		TWTIMER '=' INTEGER ';'
+			{
+				CHECK_PARAMS_DO( ($3 > 5),
+					{ yyerror (&yylloc, conf, "Invalid value"); YYERROR; } );
+				conf->cnf_timer_tw = (unsigned int)$3;
+			}
+			;
+
+port:			PORT '=' INTEGER ';'
+			{
+				CHECK_PARAMS_DO( ($3 >= 0) && ($3 < 1<<16),
+					{ yyerror (&yylloc, conf, "Invalid value"); YYERROR; } );
+				conf->cnf_port = (uint16_t)$3;
+			}
+			;
+
+secport:		SECPORT '=' INTEGER ';'
+			{
+				CHECK_PARAMS_DO( ($3 >= 0) && ($3 < 1<<16),
+					{ yyerror (&yylloc, conf, "Invalid value"); YYERROR; } );
+				conf->cnf_port_tls = (uint16_t)$3;
+			}
+			;
+
+sec3436:		SEC3436 '=' INTEGER ';'
+			{
+				CHECK_PARAMS_DO( ($3 >= 0) && ($3 < 1<<16),
+					{ yyerror (&yylloc, conf, "Invalid value"); YYERROR; } );
+				conf->cnf_port_3436 = (uint16_t)$3;
+			}
+			;
+
+sctpstreams:		SCTPSTREAMS '=' INTEGER ';'
+			{
+				CHECK_PARAMS_DO( ($3 > 0) && ($3 < 1<<16),
+					{ yyerror (&yylloc, conf, "Invalid value"); YYERROR; } );
+				conf->cnf_sctp_str = (uint16_t)$3;
+			}
+			;
+
+listenon:		LISTENON '=' QSTRING ';'
+			{
+				struct addrinfo hints, *ai;
+				int ret;
+				
+				memset(&hints, 0, sizeof(hints));
+				hints.ai_flags = AI_PASSIVE | AI_NUMERICHOST;
+				ret = getaddrinfo($3, NULL, &hints, &ai);
+				if (ret) { yyerror (&yylloc, conf, gai_strerror(ret)); YYERROR; }
+				CHECK_FCT_DO( fd_ep_add_merge( &conf->cnf_endpoints, ai->ai_addr, ai->ai_addrlen, EP_FL_CONF ), YYERROR );
+				freeaddrinfo(ai);
+				free($3);
+			}
+			;
+
+thrpersrv:		THRPERSRV '=' INTEGER ';'
+			{
+				CHECK_PARAMS_DO( ($3 > 0),
+					{ yyerror (&yylloc, conf, "Invalid value"); YYERROR; } );
+				conf->cnf_thr_srv = $3;
+			}
+			;
+
+norelay:		NORELAY ';'
+			{
+				conf->cnf_flags.no_fwd = 1;
+			}
+			;
+
+appservthreads:		APPSERVTHREADS '=' INTEGER ';'
+			{
+				CHECK_PARAMS_DO( ($3 > 0) && ($3 < 256),
+					{ yyerror (&yylloc, conf, "Invalid value"); YYERROR; } );
+				conf->cnf_dispthr = (uint16_t)$3;
+			}
+			;
+
+noip:			NOIP ';'
+			{
+				if (got_peer_noipv6) { 
+					yyerror (&yylloc, conf, "No_IP conflicts with a ConnectPeer directive No_IPv6."); 
+					YYERROR; 
+				}
+				conf->cnf_flags.no_ip4 = 1;
+			}
+			;
+
+noip6:			NOIP6 ';'
+			{
+				if (got_peer_noip) { 
+					yyerror (&yylloc, conf, "No_IP conflicts with a ConnectPeer directive No_IP."); 
+					YYERROR; 
+				}
+				conf->cnf_flags.no_ip6 = 1;
+			}
+			;
+
+notcp:			NOTCP ';'
+			{
+				#ifdef DISABLE_SCTP
+				yyerror (&yylloc, conf, "No_TCP cannot be specified for daemon compiled with DISABLE_SCTP option."); 
+				YYERROR; 
+				#endif
+				if (conf->cnf_flags.no_sctp)
+				{
+					yyerror (&yylloc, conf, "No_TCP conflicts with No_SCTP directive." ); 
+					YYERROR; 
+				}
+				if (got_peer_nosctp) { 
+					yyerror (&yylloc, conf, "No_TCP conflicts with a ConnectPeer directive No_SCTP."); 
+					YYERROR; 
+				}
+				conf->cnf_flags.no_tcp = 1;
+			}
+			;
+
+nosctp:			NOSCTP ';'
+			{
+				if (conf->cnf_flags.no_tcp)
+				{
+					yyerror (&yylloc, conf, "No_SCTP conflicts with No_TCP directive." ); 
+					YYERROR; 
+				}
+				if (got_peer_notcp) { 
+					yyerror (&yylloc, conf, "No_SCTP conflicts with a ConnectPeer directive No_TCP.");
+					YYERROR;
+				}
+				conf->cnf_flags.no_sctp = 1;
+			}
+			;
+
+prefertcp:		PREFERTCP ';'
+			{
+				conf->cnf_flags.pr_tcp = 1;
+			}
+			;
+
+oldtls:			OLDTLS ';'
+			{
+				conf->cnf_flags.tls_alg = 1;
+			}
+			;
+
+loadext:		LOADEXT '=' QSTRING extconf ';'
+			{
+				char * fname;
+				char * cfname;
+				FILE * fd;
+				
+				/* Try and open the extension file */
+				fname = $3;
+				fd = fopen(fname, "r");
+				if ((fd == NULL) && (*fname != '/')) {
+					char * bkp = fname;
+					CHECK_MALLOC_DO( fname = malloc( strlen(bkp) + strlen(DEFAULT_EXTENSIONS_PATH) + 2 ),
+						{ yyerror (&yylloc, conf, "Not enough memory"); YYERROR; } );
+					sprintf(fname, DEFAULT_EXTENSIONS_PATH "/%s", bkp);
+					fd = fopen(fname, "r");
+					if (fd == NULL) {
+						free(fname);
+						fname = bkp;
+					} else {
+						free(bkp);
+					}
+				}
+				if (fd != NULL) {
+					fclose(fd);
+				} /* otherwise, LD_LIBRARY_PATH will be tested by dl_open. 
+				This should not give any security issue, otherwise we can add an "else fail" here. */
+				
+				/* Try and open the configuration file (optional) */
+				cfname = $4;
+				if (cfname) {
+					fd = fopen(cfname, "r");
+					if ((fd == NULL) && (*cfname != '/')) {
+						char * test;
+						CHECK_MALLOC_DO( test = malloc( strlen(cfname) + strlen(DEFAULT_CONF_PATH) + 2 ),
+							{ yyerror (&yylloc, conf, "Not enough memory"); YYERROR; } );
+						sprintf(test, DEFAULT_CONF_PATH "/%s", cfname);
+						fd = fopen(test, "r");
+						if (fd) {
+							free(cfname);
+							cfname=test;
+						} else {
+							/* This is not an error, we allow an extension to wait for something else than a real conf file. */
+							free(test);
+						}
+					}
+					if (fd)
+						fclose(fd);
+				}
+				
+				CHECK_FCT_DO( fd_ext_add( fname, cfname ),
+					{ yyerror (&yylloc, conf, "Error adding extension"); YYERROR; } );
+			}
+			;
+			
+extconf:		/* empty */
+			{
+				$$ = NULL;
+			}
+			| ':' QSTRING
+			{
+				$$ = $2;
+			}
+			;
+			
+connpeer:		{
+				memset(&fddpi, 0, sizeof(fddpi));
+				fddpi.config.pic_flags.persist = PI_PRST_ALWAYS;
+				fd_list_init( &fddpi.pi_endpoints, NULL );
+			}
+			CONNPEER '=' QSTRING peerinfo ';'
+			{
+				fddpi.pi_diamid = $4;
+				CHECK_FCT_DO( fd_peer_add ( &fddpi, conf->cnf_file, NULL, NULL ),
+					{ yyerror (&yylloc, conf, "Error adding ConnectPeer information"); YYERROR; } );
+					
+				/* Now destroy any content in the structure */
+				free(fddpi.pi_diamid);
+				free(fddpi.config.pic_realm);
+				free(fddpi.config.pic_priority);
+				while (!FD_IS_LIST_EMPTY(&fddpi.pi_endpoints)) {
+					struct fd_list * li = fddpi.pi_endpoints.next;
+					fd_list_unlink(li);
+					free(li);
+				}
+			}
+			;
+			
+peerinfo:		/* empty */
+			| '{' peerparams '}'
+			;
+			
+peerparams:		/* empty */
+			| peerparams NOIP ';'
+			{
+				if ((conf->cnf_flags.no_ip6) || (fddpi.config.pic_flags.pro3 == PI_P3_IP)) { 
+					yyerror (&yylloc, conf, "No_IP conflicts with a No_IPv6 directive.");
+					YYERROR;
+				}
+				got_peer_noip++;
+				fddpi.config.pic_flags.pro3 = PI_P3_IPv6;
+			}
+			| peerparams NOIP6 ';'
+			{
+				if ((conf->cnf_flags.no_ip4) || (fddpi.config.pic_flags.pro3 == PI_P3_IPv6)) { 
+					yyerror (&yylloc, conf, "No_IPv6 conflicts with a No_IP directive.");
+					YYERROR;
+				}
+				got_peer_noipv6++;
+				fddpi.config.pic_flags.pro3 = PI_P3_IP;
+			}
+			| peerparams NOTCP ';'
+			{
+				#ifdef DISABLE_SCTP
+					yyerror (&yylloc, conf, "No_TCP cannot be specified in daemon compiled with DISABLE_SCTP option.");
+					YYERROR;
+				#endif
+				if ((conf->cnf_flags.no_sctp) || (fddpi.config.pic_flags.pro4 == PI_P4_TCP)) { 
+					yyerror (&yylloc, conf, "No_TCP conflicts with a No_SCTP directive.");
+					YYERROR;
+				}
+				got_peer_notcp++;
+				fddpi.config.pic_flags.pro4 = PI_P4_SCTP;
+			}
+			| peerparams NOSCTP ';'
+			{
+				if ((conf->cnf_flags.no_tcp) || (fddpi.config.pic_flags.pro4 == PI_P4_SCTP)) { 
+					yyerror (&yylloc, conf, "No_SCTP conflicts with a No_TCP directive.");
+					YYERROR;
+				}
+				got_peer_nosctp++;
+				fddpi.config.pic_flags.pro4 = PI_P4_TCP;
+			}
+			| peerparams PREFERTCP ';'
+			{
+				fddpi.config.pic_flags.alg = PI_ALGPREF_TCP;
+			}
+			| peerparams OLDTLS ';'
+			{
+				fddpi.config.pic_flags.sec |= PI_SEC_TLS_OLD;
+			}
+			| peerparams NOTLS ';'
+			{
+				fddpi.config.pic_flags.sec |= PI_SEC_NONE;
+			}
+			| peerparams SEC3436 ';'
+			{
+				fddpi.config.pic_flags.sctpsec |= PI_SCTPSEC_3436;
+			}
+			| peerparams REALM '=' QSTRING ';'
+			{
+				fddpi.config.pic_realm = $4;
+			}
+			| peerparams PORT '=' INTEGER ';'
+			{
+				CHECK_PARAMS_DO( ($4 > 0) && ($4 < 1<<16),
+					{ yyerror (&yylloc, conf, "Invalid port value"); YYERROR; } );
+				fddpi.config.pic_port = (uint16_t)$4;
+			}
+			| peerparams TCTIMER '=' INTEGER ';'
+			{
+				fddpi.config.pic_tctimer = $4;
+			}
+			| peerparams TWTIMER '=' INTEGER ';'
+			{
+				fddpi.config.pic_twtimer = $4;
+			}
+			| peerparams TLS_PRIO '=' QSTRING ';'
+			{
+				fddpi.config.pic_priority = $4;
+			}
+			| peerparams CONNTO '=' QSTRING ';'
+			{
+				struct addrinfo hints, *ai;
+				int ret;
+				int disc = 0;
+				
+				memset(&hints, 0, sizeof(hints));
+				hints.ai_flags = AI_ADDRCONFIG | AI_NUMERICHOST;
+				ret = getaddrinfo($4, NULL, &hints, &ai);
+				if (ret == EAI_NONAME) {
+					/* The name was maybe not numeric, try again */
+					disc = EP_FL_DISC;
+					hints.ai_flags &= ~ AI_NUMERICHOST;
+					ret = getaddrinfo($4, NULL, &hints, &ai);
+				}
+				if (ret) { yyerror (&yylloc, conf, gai_strerror(ret)); YYERROR; }
+				
+				CHECK_FCT_DO( fd_ep_add_merge( &fddpi.pi_endpoints, ai->ai_addr, ai->ai_addrlen, EP_FL_CONF | (disc ?: EP_ACCEPTALL) ), YYERROR );
+				free($4);
+				freeaddrinfo(ai);
+			}
+			;
+
+tls_cred:		TLS_CRED '=' QSTRING ',' QSTRING ';'
+			{
+				FILE * fd;
+				fd = fopen($3, "r");
+				if (fd == NULL) {
+					int ret = errno;
+					TRACE_ERROR("Unable to open certificate file %s for reading: %s", $3, strerror(ret));
+					yyerror (&yylloc, conf, "Error on file name"); 
+					YYERROR;
+				}
+				fclose(fd);
+				fd = fopen($5, "r");
+				if (fd == NULL) {
+					int ret = errno;
+					TRACE_ERROR("Unable to open private key file %s for reading: %s", $5, strerror(ret));
+					yyerror (&yylloc, conf, "Error on file name"); 
+					YYERROR;
+				}
+				fclose(fd);
+				conf->cnf_sec_data.cert_file = $3;
+				conf->cnf_sec_data.key_file = $5;
+				
+				CHECK_GNUTLS_DO( gnutls_certificate_set_x509_key_file( 
+							conf->cnf_sec_data.credentials,
+							conf->cnf_sec_data.cert_file,
+							conf->cnf_sec_data.key_file,
+							GNUTLS_X509_FMT_PEM),
+						{ yyerror (&yylloc, conf, "Error opening certificate or private key file."); YYERROR; } );
+			}
+			;
+
+tls_ca:			TLS_CA '=' QSTRING ';'
+			{
+				FILE * fd;
+				fd = fopen($3, "rb");
+				if (fd == NULL) {
+					int ret = errno;
+					TRACE_ERROR("Unable to open CA file %s for reading: %s", $3, strerror(ret));
+					yyerror (&yylloc, conf, "Error on file name"); 
+					YYERROR;
+				}
+				#ifdef GNUTLS_VERSION_300
+				{
+					/* We import these CA in the trust list */
+					gnutls_x509_crt_t * calist;
+					unsigned int cacount;
+					gnutls_datum_t cafile;
+					
+					CHECK_FCT_DO( fd_conf_stream_to_gnutls_datum(fd, &cafile), 
+							{ yyerror (&yylloc, conf, "Error reading CA file."); YYERROR; } );
+							
+					CHECK_GNUTLS_DO( gnutls_x509_crt_list_import2(&calist, &cacount, &cafile, GNUTLS_X509_FMT_PEM, 
+										GNUTLS_X509_CRT_LIST_FAIL_IF_UNSORTED),
+							{ yyerror (&yylloc, conf, "Error importing CA file."); YYERROR; } );
+					free(cafile.data);
+					
+					CHECK_GNUTLS_DO( gnutls_x509_trust_list_add_cas (fd_g_config->cnf_sec_data.trustlist, calist, cacount, 0),
+							{ yyerror (&yylloc, conf, "Error saving CA in trust list."); YYERROR; } );
+				}
+				#endif /* GNUTLS_VERSION_300 */
+				fclose(fd);
+				conf->cnf_sec_data.ca_file = $3;
+				CHECK_GNUTLS_DO( conf->cnf_sec_data.ca_file_nr += gnutls_certificate_set_x509_trust_file( 
+							conf->cnf_sec_data.credentials,
+							conf->cnf_sec_data.ca_file,
+							GNUTLS_X509_FMT_PEM),
+						{ yyerror (&yylloc, conf, "Error setting CA parameters."); YYERROR; } );
+						
+			}
+			;
+			
+tls_crl:		TLS_CRL '=' QSTRING ';'
+			{
+				FILE * fd;
+				fd = fopen($3, "rb");
+				if (fd == NULL) {
+					int ret = errno;
+					TRACE_ERROR("Unable to open CRL file %s for reading: %s", $3, strerror(ret));
+					yyerror (&yylloc, conf, "Error on file name"); 
+					YYERROR;
+				}
+				#ifdef GNUTLS_VERSION_300
+				{
+					/* We import these CRL in the trust list */
+					gnutls_x509_crl_t * crllist;
+					unsigned int crlcount;
+					gnutls_datum_t crlfile;
+					
+					CHECK_FCT_DO( fd_conf_stream_to_gnutls_datum(fd, &crlfile), 
+							{ yyerror (&yylloc, conf, "Error reading CRL file."); YYERROR; } );
+							
+					CHECK_GNUTLS_DO( gnutls_x509_crl_list_import2(&crllist, &crlcount, &crlfile, GNUTLS_X509_FMT_PEM, 0),
+							{ yyerror (&yylloc, conf, "Error importing CRL file."); YYERROR; } );
+					free(crlfile.data);
+					
+					CHECK_GNUTLS_DO( gnutls_x509_trust_list_add_crls (fd_g_config->cnf_sec_data.trustlist, crllist, crlcount, 
+									GNUTLS_TL_VERIFY_CRL,
+									0),
+							{ yyerror (&yylloc, conf, "Error importing CRL in trust list."); YYERROR; } );
+				}
+				#endif /* GNUTLS_VERSION_300 */
+				fclose(fd);
+				conf->cnf_sec_data.crl_file = $3;
+				CHECK_GNUTLS_DO( gnutls_certificate_set_x509_crl_file( 
+							conf->cnf_sec_data.credentials,
+							conf->cnf_sec_data.crl_file,
+							GNUTLS_X509_FMT_PEM),
+						{ yyerror (&yylloc, conf, "Error setting CRL parameters."); YYERROR; } );
+			}
+			;
+			
+tls_prio:		TLS_PRIO '=' QSTRING ';'
+			{
+				const char * err_pos = NULL;
+				conf->cnf_sec_data.prio_string = $3;
+				CHECK_GNUTLS_DO( gnutls_priority_init( 
+							&conf->cnf_sec_data.prio_cache,
+							conf->cnf_sec_data.prio_string,
+							&err_pos),
+						{ yyerror (&yylloc, conf, "Error setting Priority parameter.");
+						  TRACE_ERROR("Error at position : %s", err_pos);
+						  YYERROR; } );
+			}
+			;
+			
+tls_dh:			TLS_DH_BITS '=' INTEGER ';'
+			{
+				conf->cnf_sec_data.dh_bits = $3;
+			}
+			| TLS_DH_FILE '=' QSTRING ';'
+			{
+				FILE * fd;
+				free(conf->cnf_sec_data.dh_file);
+				conf->cnf_sec_data.dh_file = $3;
+				fd = fopen($3, "r");
+				if (fd == NULL) {
+					int ret = errno;
+					TRACE_ERROR("Unable to open DH file %s for reading: %s", $3, strerror(ret));
+					yyerror (&yylloc, conf, "Error on file name"); 
+					YYERROR;
+				}
+				fclose(fd);
+			}
+			;
diff --git a/libfdcore/fifo_stats.c b/libfdcore/fifo_stats.c
new file mode 100644
index 0000000..0cffa04
--- /dev/null
+++ b/libfdcore/fifo_stats.c
@@ -0,0 +1,79 @@
+/*********************************************************************************************************
+* Software License Agreement (BSD License)                                                               *
+* Author: Sebastien Decugis <sdecugis@freediameter.net>							 *
+*													 *
+* Copyright (c) 2013, WIDE Project and NICT								 *
+* All rights reserved.											 *
+* 													 *
+* Redistribution and use of this software in source and binary forms, with or without modification, are  *
+* permitted provided that the following conditions are met:						 *
+* 													 *
+* * Redistributions of source code must retain the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer.										 *
+*    													 *
+* * Redistributions in binary form must reproduce the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer in the documentation and/or other						 *
+*   materials provided with the distribution.								 *
+* 													 *
+* * Neither the name of the WIDE Project or NICT nor the 						 *
+*   names of its contributors may be used to endorse or 						 *
+*   promote products derived from this software without 						 *
+*   specific prior written permission of WIDE Project and 						 *
+*   NICT.												 *
+* 													 *
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED *
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
+* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR *
+* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 	 *
+* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 	 *
+* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR *
+* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF   *
+* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.								 *
+*********************************************************************************************************/
+
+#include "fdcore-internal.h"
+
+/* See include/freeDiameter/libfdcore.h for more information */
+int fd_stat_getstats(enum fd_stat_type stat, struct peer_hdr * peer, 
+			int * current_count, int * limit_count, int * highest_count, long long * total_count, 
+			struct timespec * total, struct timespec * blocking, struct timespec * last)
+{
+	struct fd_peer * p = (struct fd_peer *)peer;
+	TRACE_ENTRY( "%d %p %p %p %p %p %p %p %p", stat, peer, current_count, limit_count, highest_count, total_count, total, blocking, last);
+	
+	switch (stat) {
+		case STAT_G_LOCAL: {
+			CHECK_FCT( fd_fifo_getstats(fd_g_local, current_count, limit_count, highest_count, total_count, total, blocking, last) );
+		}
+		break;
+
+		case STAT_G_INCOMING: {
+			CHECK_FCT( fd_fifo_getstats(fd_g_incoming, current_count, limit_count, highest_count, total_count, total, blocking, last) );
+		}
+		break;
+
+		case STAT_G_OUTGOING: {
+			CHECK_FCT( fd_fifo_getstats(fd_g_outgoing, current_count, limit_count, highest_count, total_count, total, blocking, last) );
+		}
+		break;
+
+		case STAT_P_PSM: {
+			CHECK_PARAMS( CHECK_PEER( peer ) );
+			CHECK_FCT( fd_fifo_getstats(p->p_events, current_count, limit_count, highest_count, total_count, total, blocking, last) );
+		}
+		break;
+
+		case STAT_P_TOSEND: {
+			CHECK_PARAMS( CHECK_PEER( peer ) );
+			CHECK_FCT( fd_fifo_getstats(p->p_tosend, current_count, limit_count, highest_count, total_count, total, blocking, last) );
+		}
+		break;
+
+		default:
+			return EINVAL;
+	}
+	
+	return 0;
+}
diff --git a/libfdcore/hooks.c b/libfdcore/hooks.c
new file mode 100644
index 0000000..f035614
--- /dev/null
+++ b/libfdcore/hooks.c
@@ -0,0 +1,454 @@
+/*********************************************************************************************************
+* Software License Agreement (BSD License)                                                               *
+* Author: Sebastien Decugis <sdecugis@freediameter.net>							 *
+*													 *
+* Copyright (c) 2015, WIDE Project and NICT								 *
+* All rights reserved.											 *
+* 													 *
+* Redistribution and use of this software in source and binary forms, with or without modification, are  *
+* permitted provided that the following conditions are met:						 *
+* 													 *
+* * Redistributions of source code must retain the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer.										 *
+*    													 *
+* * Redistributions in binary form must reproduce the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer in the documentation and/or other						 *
+*   materials provided with the distribution.								 *
+* 													 *
+* * Neither the name of the WIDE Project or NICT nor the 						 *
+*   names of its contributors may be used to endorse or 						 *
+*   promote products derived from this software without 						 *
+*   specific prior written permission of WIDE Project and 						 *
+*   NICT.												 *
+* 													 *
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED *
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
+* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR *
+* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 	 *
+* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 	 *
+* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR *
+* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF   *
+* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.								 *
+*********************************************************************************************************/
+
+#include "fdcore-internal.h"
+
+/* Structures for the fd_hook_data_hdl management */
+static struct fd_hook_data_hdl {
+	size_t	pmd_size;
+	void  (*pmd_init_cb)(struct fd_hook_permsgdata *);
+	void  (*pmd_fini_cb)(struct fd_hook_permsgdata *);
+} HDH_array[FD_HOOK_HANDLE_LIMIT];
+static int max_index = 0;
+static pthread_mutex_t HDH_lock = PTHREAD_MUTEX_INITIALIZER;
+
+/* The structure linked from the msg structure list */
+struct pmd_list_item {
+	struct fd_list	chain;		/* this list is ordered by hdl */
+	struct fd_hook_data_hdl * hdl; 
+	struct fd_hook_permsgdata { } pmd; /* this data belongs to the extension; we only know the size of it */
+};
+
+#define sizeof_pmd(hdl)	(((size_t)&((struct pmd_list_item *)0)->pmd) + hdl->pmd_size)
+
+/* Now a hook registered by an extension */
+struct fd_hook_hdl {
+	struct fd_list chain[HOOK_LAST+1];
+	void (*fd_hook_cb)(enum fd_hook_type type, struct msg * msg, struct peer_hdr * peer, void * other, struct fd_hook_permsgdata *pmd, void * regdata);
+	void  *regdata;
+	struct fd_hook_data_hdl *data_hdl;
+};
+
+/* Array of those hooks */
+struct {
+	struct fd_list sentinel;
+	pthread_rwlock_t rwlock;
+} HS_array[HOOK_LAST+1];
+
+/* Initialize the array of sentinels for the hooks */
+int fd_hooks_init(void)
+{
+	int i;
+	for (i=0; i <= HOOK_LAST; i++) {
+		fd_list_init(&HS_array[i].sentinel, NULL);
+		CHECK_POSIX( pthread_rwlock_init(&HS_array[i].rwlock, NULL) );
+	}
+	return 0;
+}
+
+/* Get a slot in the array */
+int fd_hook_data_register(
+	size_t permsgdata_size,
+	void (*permsgdata_init_cb) (struct fd_hook_permsgdata *),
+        void (*permsgdata_fini_cb) (struct fd_hook_permsgdata *),
+        struct fd_hook_data_hdl **new_handle)
+{
+	int ret = ENOSPC, idx;
+	TRACE_ENTRY("%zd %p %p %p", permsgdata_size, permsgdata_init_cb, permsgdata_fini_cb, new_handle);
+	
+	CHECK_PARAMS( permsgdata_size && new_handle );
+	
+	CHECK_POSIX( pthread_mutex_lock(&HDH_lock) );
+	if (max_index < FD_HOOK_HANDLE_LIMIT) {
+		idx = max_index++;
+		ret = 0;
+	}
+	CHECK_POSIX( pthread_mutex_unlock(&HDH_lock) );
+	
+	if (ret == 0) {
+		HDH_array[idx].pmd_size = permsgdata_size;
+		HDH_array[idx].pmd_init_cb = permsgdata_init_cb;
+		HDH_array[idx].pmd_fini_cb = permsgdata_fini_cb;
+		*new_handle = &HDH_array[idx];
+	}
+	
+	return ret;
+}
+
+/* Register a new hook callback */
+int fd_hook_register (  uint32_t type_mask, 
+			void (*fd_hook_cb)(enum fd_hook_type type, struct msg * msg, struct peer_hdr * peer, void * other, struct fd_hook_permsgdata *pmd, void * regdata), 
+			void  *regdata, 
+			struct fd_hook_data_hdl *data_hdl,
+			struct fd_hook_hdl ** handler )
+{
+	struct fd_hook_hdl * newhdl = NULL;
+	int i;
+	
+	TRACE_ENTRY("%x %p %p %p %p", type_mask, fd_hook_cb, regdata, data_hdl, handler);
+	
+	CHECK_PARAMS( fd_hook_cb && handler );
+	
+	CHECK_MALLOC( newhdl = malloc(sizeof(struct fd_hook_hdl)) );
+	memset(newhdl, 0, sizeof(struct fd_hook_hdl));
+	
+	newhdl->fd_hook_cb = fd_hook_cb;
+	newhdl->regdata = regdata;
+	newhdl->data_hdl = data_hdl;
+	
+	for (i=0; i <= HOOK_LAST; i++) {
+		fd_list_init(&newhdl->chain[i], newhdl);
+		if (type_mask & (1<<i)) {
+			CHECK_POSIX( pthread_rwlock_wrlock(&HS_array[i].rwlock) );
+			fd_list_insert_before( &HS_array[i].sentinel, &newhdl->chain[i]);
+			CHECK_POSIX( pthread_rwlock_unlock(&HS_array[i].rwlock) );
+		}
+	}
+	
+	*handler = newhdl;
+	return 0;
+}
+
+/* free this hook callback */
+int fd_hook_unregister( struct fd_hook_hdl * handler )
+{
+	int i;
+	TRACE_ENTRY("%p", handler);
+	CHECK_PARAMS( handler );
+	
+	for (i=0; i <= HOOK_LAST; i++) {
+		if ( ! FD_IS_LIST_EMPTY(&handler->chain[i])) {
+			CHECK_POSIX( pthread_rwlock_wrlock(&HS_array[i].rwlock) );
+			fd_list_unlink(&handler->chain[i]);
+			CHECK_POSIX( pthread_rwlock_unlock(&HS_array[i].rwlock) );
+		}
+	}
+	
+	free(handler);
+	
+	return 0;
+}
+
+/* callback for the libfdproto to free the data associated with a message */
+static void pmdl_free(struct fd_msg_pmdl *pmdl)
+{
+	/* destroy all the items in the list */
+	while (!FD_IS_LIST_EMPTY(&pmdl->sentinel)) {
+		struct pmd_list_item * li = (struct pmd_list_item *)(pmdl->sentinel.next);
+		if (li->hdl->pmd_fini_cb) {
+			(*li->hdl->pmd_fini_cb)(&li->pmd);
+		}
+		fd_list_unlink(&li->chain);
+		free(li);
+	}
+	CHECK_POSIX_DO( pthread_mutex_destroy(&pmdl->lock), );
+	pmdl->sentinel.o = NULL;
+}
+
+/* Save the list of pmd into the message structure, as well as the callback to free this list */
+void   fd_hook_associate(struct msg * msg, struct fd_msg_pmdl * pmdl)
+{
+	struct fd_msg_pmdl * in_msg;
+	
+	CHECK_PARAMS_DO( msg && pmdl, return );
+	in_msg = fd_msg_pmdl_get(msg);
+	ASSERT(in_msg && (in_msg->sentinel.o == NULL)); /* error / already initialized ??? */
+	in_msg->sentinel.o = pmdl_free;
+	/* Now move all items from the pmdl pointer into the initialized list */
+	CHECK_POSIX_DO( pthread_mutex_lock(&pmdl->lock), );
+	fd_list_move_end(&in_msg->sentinel, &pmdl->sentinel);
+	CHECK_POSIX_DO( pthread_mutex_unlock(&pmdl->lock), );
+	pmdl_free(pmdl);
+	/* We're done */
+}
+
+/* Return the location of the permsgdata area corresponding to this handle, after eventually having created it. Return NULL in case of failure */
+static struct fd_hook_permsgdata * get_or_create_pmd(struct fd_msg_pmdl *pmdl, struct fd_hook_hdl * h) 
+{
+	struct fd_hook_permsgdata * ret = NULL;
+	struct fd_list * li;
+	
+	CHECK_POSIX_DO( pthread_mutex_lock(&pmdl->lock), );
+	
+	if (pmdl->sentinel.o == NULL) {
+		pmdl->sentinel.o = pmdl_free;
+	}
+	
+	/* Search in the list for an item with the same handle. The list is ordered by this handle */
+	for (li=pmdl->sentinel.next; li != &pmdl->sentinel; li = li->next) {
+		struct pmd_list_item * pli = (struct pmd_list_item *) li;
+		if (pli->hdl == h->data_hdl)
+			ret = &pli->pmd;
+		if (pli->hdl >= h->data_hdl)
+			break;
+	}
+	if (!ret) {
+		/* we need to create a new one and insert before li */
+		struct pmd_list_item * pli;
+		CHECK_MALLOC_DO( pli = malloc(sizeof_pmd(h->data_hdl)), );
+		if (pli) {
+			memset(pli, 0, sizeof_pmd(h->data_hdl));
+			fd_list_init(&pli->chain, pli);
+			pli->hdl = h->data_hdl;
+			ret = &pli->pmd;
+			if (h->data_hdl->pmd_init_cb) {
+				(*h->data_hdl->pmd_init_cb)(ret);
+			}
+			fd_list_insert_before(li, &pli->chain);
+		}
+	}
+	
+	CHECK_POSIX_DO( pthread_mutex_unlock(&pmdl->lock), );
+	return ret;
+}
+
+struct fd_hook_permsgdata * fd_hook_get_request_pmd(struct fd_hook_data_hdl *data_hdl, struct msg * answer)
+{
+	struct msg * qry;
+	struct fd_msg_pmdl *pmdl;
+	struct fd_hook_permsgdata * ret = NULL;
+	struct fd_list * li;
+	
+	CHECK_FCT_DO( fd_msg_answ_getq(answer, &qry), return NULL );
+	if (!qry)
+		return NULL;
+	
+	pmdl = fd_msg_pmdl_get(qry);
+	if (!pmdl)
+		return NULL;
+	
+	CHECK_POSIX_DO( pthread_mutex_lock(&pmdl->lock), );
+	/* Search in the list for an item with the same handle. The list is ordered by this handle */
+	for (li=pmdl->sentinel.next; li != &pmdl->sentinel; li = li->next) {
+		struct pmd_list_item * pli = (struct pmd_list_item *) li;
+		if (pli->hdl == data_hdl)
+			ret = &pli->pmd;
+		if (pli->hdl >= data_hdl)
+			break;
+	}
+	CHECK_POSIX_DO( pthread_mutex_unlock(&pmdl->lock), );
+	return ret;
+}
+
+/* Create a mask */
+uint32_t fd_hook_mask_helper(int dummy, ...)
+{
+	va_list ap;
+	uint32_t ret = 0;
+	int next;
+	
+	va_start(ap, dummy);
+	while ((next = va_arg(ap, int)) >= 0) {
+		if (next > HOOK_LAST)
+			break; /* invalid parameter */
+		ret |= (1<<next);
+	}
+	va_end(ap);
+
+	return ret;
+}
+
+static pthread_mutex_t hook_default_mtx = PTHREAD_MUTEX_INITIALIZER;
+static char * hook_default_buf = NULL;
+static size_t hook_default_len = 0;
+
+/* The function that does the work of calling the extension's callbacks and also managing the permessagedata structures */
+void   fd_hook_call(enum fd_hook_type type, struct msg * msg, struct fd_peer * peer, void * other, struct fd_msg_pmdl * pmdl)
+{
+	struct fd_list * li;
+	ASSERT(type <= HOOK_LAST);
+	int call_default = 0;
+	
+	/* lock the list of hooks for this type */
+	CHECK_POSIX_DO( pthread_rwlock_rdlock(&HS_array[type].rwlock), );
+	
+	pthread_cleanup_push( fd_cleanup_rwlock, &HS_array[type].rwlock );
+	
+	if (FD_IS_LIST_EMPTY(&HS_array[type].sentinel)) {
+		call_default = 1;
+	} else {
+		/* for each registered hook */
+		for (li = HS_array[type].sentinel.next; li != &HS_array[type].sentinel; li = li->next) {
+			struct fd_hook_hdl * h = (struct fd_hook_hdl *)li->o;
+			struct fd_hook_permsgdata * pmd = NULL;
+
+			/* do we need to handle pmd ? */
+			if (h->data_hdl && pmdl) {
+				pmd = get_or_create_pmd(pmdl, h);
+			}
+
+			/* Now, call this callback */
+			(*h->fd_hook_cb)(type, msg, &peer->p_hdr, other, pmd, h->regdata);
+		}
+	}
+	
+	pthread_cleanup_pop(0);
+	
+	/* done */
+	CHECK_POSIX_DO( pthread_rwlock_unlock(&HS_array[type].rwlock), );
+	
+	if (call_default) {
+		CHECK_POSIX_DO( pthread_mutex_lock(&hook_default_mtx), );
+		
+		pthread_cleanup_push( fd_cleanup_mutex, &hook_default_mtx );
+	
+		/* There was no registered handler, default behavior for this hook */
+		switch (type) {
+			case HOOK_DATA_RECEIVED: {
+				struct fd_cnx_rcvdata *rcv_data = other;
+				LOG_A("RCV: %zd bytes", rcv_data->length);
+				break;
+			}
+			
+			case HOOK_MESSAGE_RECEIVED: {
+				CHECK_MALLOC_DO(fd_msg_dump_summary(&hook_default_buf, &hook_default_len, NULL, msg, NULL, 0, 1), break);
+				LOG_D("RCV from '%s': %s", peer ? peer->p_hdr.info.pi_diamid : "<unknown>", hook_default_buf);
+				break;
+			}
+			
+			case HOOK_MESSAGE_LOCAL: {
+				CHECK_MALLOC_DO(fd_msg_dump_full(&hook_default_buf, &hook_default_len, NULL, msg, NULL, 0, 1), break);
+				LOG_A("Handled to framework for sending: %s", hook_default_buf);
+				break;
+			}
+			
+			case HOOK_MESSAGE_SENDING: {
+				LOG_A("SENDING message to '%s'", peer ? peer->p_hdr.info.pi_diamid : "<unknown>");
+				break;
+			}
+			
+			case HOOK_MESSAGE_SENT: {
+				CHECK_MALLOC_DO(fd_msg_dump_summary(&hook_default_buf, &hook_default_len, NULL, msg, NULL, 0, 1), break);
+				LOG_D("SENT to '%s': %s", peer ? peer->p_hdr.info.pi_diamid : "<unknown>", hook_default_buf);
+				break;
+			}
+			
+			case HOOK_MESSAGE_FAILOVER: {
+				CHECK_MALLOC_DO(fd_msg_dump_summary(&hook_default_buf, &hook_default_len, NULL, msg, NULL, 0, 1), break);
+				LOG_D("Failing over message sent to '%s': %s", peer ? peer->p_hdr.info.pi_diamid : "<unknown>", hook_default_buf);
+				break;
+			}
+			
+			case HOOK_MESSAGE_PARSING_ERROR: {
+				if (msg) {
+					DiamId_t id = NULL;
+					if (fd_msg_source_get( msg, &id, NULL ))
+						id = (DiamId_t)"<error getting source>";
+					
+					if (!id)
+						id = (DiamId_t)"<local>";
+					
+					CHECK_MALLOC_DO(fd_msg_dump_treeview(&hook_default_buf, &hook_default_len, NULL, msg, NULL, 0, 1), break);
+					
+					LOG_E("Parsing error: '%s' for the following message received from '%s':", (char *)other, (char *)id);
+					LOG_SPLIT(FD_LOG_ERROR, "   ", hook_default_buf, NULL);
+				} else {
+					struct fd_cnx_rcvdata *rcv_data = other;
+					CHECK_MALLOC_DO(fd_dump_extend_hexdump(&hook_default_buf, &hook_default_len, NULL, rcv_data->buffer, rcv_data->length, 0, 0), break);
+					LOG_E("Parsing error: cannot parse %zdB buffer from '%s': %s",  rcv_data->length, peer ? peer->p_hdr.info.pi_diamid : "<unknown>", hook_default_buf);
+				}
+				break;
+			}
+			
+			case HOOK_MESSAGE_PARSING_ERROR2: {
+				CHECK_MALLOC_DO(fd_msg_dump_treeview(&hook_default_buf, &hook_default_len, NULL, msg, NULL, 0, 1), break);
+
+				LOG_E("Returning following message after parsing error:");
+				LOG_SPLIT(FD_LOG_ERROR, "   ", hook_default_buf, NULL);
+				break;
+			}
+			
+			case HOOK_MESSAGE_ROUTING_ERROR: {
+				CHECK_MALLOC_DO(fd_msg_dump_treeview(&hook_default_buf, &hook_default_len, NULL, msg, NULL, 0, 1), break);
+				LOG_E("Routing error: '%s' for the following message:", (char *)other);
+				LOG_SPLIT(FD_LOG_ERROR, "   ", hook_default_buf, NULL);
+				break;
+			}
+			
+			case HOOK_MESSAGE_ROUTING_FORWARD: {
+				CHECK_MALLOC_DO(fd_msg_dump_summary(&hook_default_buf, &hook_default_len, NULL, msg, NULL, 0, 1), break);
+				LOG_D("FORWARDING: %s", hook_default_buf);
+				break;
+			}
+			
+			case HOOK_MESSAGE_ROUTING_LOCAL: {
+				CHECK_MALLOC_DO(fd_msg_dump_summary(&hook_default_buf, &hook_default_len, NULL, msg, NULL, 0, 1), break);
+				LOG_D("DISPATCHING: %s", hook_default_buf);
+				break;
+			}
+			
+			case HOOK_MESSAGE_DROPPED: {
+				CHECK_MALLOC_DO(fd_msg_dump_treeview(&hook_default_buf, &hook_default_len, NULL, msg, NULL, 0, 1), break);
+				LOG_E("Message discarded ('%s'):", (char *)other);
+				LOG_SPLIT(FD_LOG_ERROR, "   ", hook_default_buf, NULL);
+				break;
+			}
+			
+			case HOOK_PEER_CONNECT_FAILED: {
+				if (msg) {
+					CHECK_MALLOC_DO(fd_msg_dump_full(&hook_default_buf, &hook_default_len, NULL, msg, NULL, 0, 1), break);
+					LOG_N("Connection to '%s' failed: '%s'; CER/CEA dump:", peer ? peer->p_hdr.info.pi_diamid : "<unknown>", (char *)other);
+					LOG_SPLIT(FD_LOG_NOTICE, "   ", hook_default_buf, NULL);
+				} else {
+					LOG_D("Connection to '%s' failed: %s", peer ? peer->p_hdr.info.pi_diamid : "<unknown>", (char *)other);
+				}
+				break;
+			}
+			
+			case HOOK_PEER_CONNECT_SUCCESS: {
+				DiamId_t id = NULL;
+				if ((!fd_msg_source_get( msg, &id, NULL )) && (id == NULL)) { /* The CEA is locally issued */
+					fd_msg_answ_getq(msg, &msg); /* We dump the CER in that case */
+				}
+				CHECK_MALLOC_DO(fd_msg_dump_full(&hook_default_buf, &hook_default_len, NULL, msg, NULL, 0, 1), break);
+				char protobuf[40];
+				if (peer) {
+					CHECK_FCT_DO(fd_peer_cnx_proto_info(&peer->p_hdr, protobuf, sizeof(protobuf)), break );
+				} else {
+					protobuf[0] = '-';
+					protobuf[1] = '\0';
+				}
+				LOG_N("Connected to '%s' (%s), remote capabilities: ", peer ? peer->p_hdr.info.pi_diamid : "<unknown>", protobuf);
+				LOG_SPLIT(FD_LOG_NOTICE, "   ", hook_default_buf, NULL);
+				break;
+			}
+			
+		}
+		
+		pthread_cleanup_pop(0);
+		
+		CHECK_POSIX_DO( pthread_mutex_unlock(&hook_default_mtx), );
+	}
+}
diff --git a/libfdcore/messages.c b/libfdcore/messages.c
new file mode 100644
index 0000000..2242827
--- /dev/null
+++ b/libfdcore/messages.c
@@ -0,0 +1,452 @@
+/*********************************************************************************************************
+* Software License Agreement (BSD License)                                                               *
+* Author: Sebastien Decugis <sdecugis@freediameter.net>							 *
+*													 *
+* Copyright (c) 2015, WIDE Project and NICT								 *
+* All rights reserved.											 *
+* 													 *
+* Redistribution and use of this software in source and binary forms, with or without modification, are  *
+* permitted provided that the following conditions are met:						 *
+* 													 *
+* * Redistributions of source code must retain the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer.										 *
+*    													 *
+* * Redistributions in binary form must reproduce the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer in the documentation and/or other						 *
+*   materials provided with the distribution.								 *
+* 													 *
+* * Neither the name of the WIDE Project or NICT nor the 						 *
+*   names of its contributors may be used to endorse or 						 *
+*   promote products derived from this software without 						 *
+*   specific prior written permission of WIDE Project and 						 *
+*   NICT.												 *
+* 													 *
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED *
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
+* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR *
+* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 	 *
+* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 	 *
+* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR *
+* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF   *
+* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.								 *
+*********************************************************************************************************/
+
+#include "fdcore-internal.h"
+
+static struct dict_object * dict_avp_SI  = NULL; /* Session-Id */
+static struct dict_object * dict_avp_OH  = NULL; /* Origin-Host */
+static struct dict_object * dict_avp_OR  = NULL; /* Origin-Realm */
+static struct dict_object * dict_avp_EM  = NULL; /* Error-Message */
+static struct dict_object * dict_avp_ERH = NULL; /* Error-Reporting-Host */
+static struct dict_object * dict_avp_FAVP= NULL; /* Failed-AVP */
+static struct dict_object * dict_avp_RC  = NULL; /* Result-Code */
+struct dict_object * fd_dict_avp_OSI = NULL; /* Origin-State-Id */
+struct dict_object * fd_dict_cmd_CER = NULL; /* Capabilities-Exchange-Request */
+struct dict_object * fd_dict_cmd_DWR = NULL; /* Device-Watchdog-Request */
+struct dict_object * fd_dict_avp_DC  = NULL; /* Disconnect-Cause */
+struct dict_object * fd_dict_cmd_DPR = NULL; /* Disconnect-Peer-Request */
+
+/* Resolve the dictionary objects */
+int fd_msg_init(void)
+{
+	TRACE_ENTRY("");
+	
+	/* Initialize the dictionary objects that we may use frequently */
+	CHECK_FCT(  fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Session-Id", 	&dict_avp_SI , ENOENT)  );
+	CHECK_FCT(  fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Origin-Host",     	&dict_avp_OH  , ENOENT)  );
+	CHECK_FCT(  fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Origin-Realm",    	&dict_avp_OR  , ENOENT)  );
+	CHECK_FCT(  fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Origin-State-Id", 	&fd_dict_avp_OSI , ENOENT)  );
+	
+	CHECK_FCT(  fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Result-Code",     	&dict_avp_RC  , ENOENT)  );
+	CHECK_FCT(  fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Error-Message",   	&dict_avp_EM  , ENOENT)  );
+	CHECK_FCT(  fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Error-Reporting-Host", &dict_avp_ERH , ENOENT)  );
+	CHECK_FCT(  fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Failed-AVP",      	&dict_avp_FAVP, ENOENT)  );
+	
+	CHECK_FCT(  fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Disconnect-Cause", 	&fd_dict_avp_DC , ENOENT)  );
+	
+	CHECK_FCT( fd_dict_search ( fd_g_config->cnf_dict, DICT_COMMAND, CMD_BY_NAME, "Capabilities-Exchange-Request", &fd_dict_cmd_CER, ENOENT ) );
+	CHECK_FCT( fd_dict_search ( fd_g_config->cnf_dict, DICT_COMMAND, CMD_BY_NAME, "Device-Watchdog-Request", &fd_dict_cmd_DWR, ENOENT ) );
+	CHECK_FCT( fd_dict_search ( fd_g_config->cnf_dict, DICT_COMMAND, CMD_BY_NAME, "Disconnect-Peer-Request", &fd_dict_cmd_DPR, ENOENT ) );
+	
+	
+	return 0;
+}
+
+/* Add Origin-Host, Origin-Realm, Origin-State-Id AVPS at the end of the message */
+int fd_msg_add_origin ( struct msg * msg, int osi )
+{
+	union avp_value val;
+	struct avp * avp_OH  = NULL;
+	struct avp * avp_OR  = NULL;
+	struct avp * avp_OSI = NULL;
+	
+	TRACE_ENTRY("%p", msg);
+	CHECK_PARAMS(  msg  );
+	
+	/* Create the Origin-Host AVP */
+	CHECK_FCT( fd_msg_avp_new( dict_avp_OH, 0, &avp_OH ) );
+	
+	/* Set its value */
+	memset(&val, 0, sizeof(val));
+	val.os.data = (os0_t)fd_g_config->cnf_diamid;
+	val.os.len  = fd_g_config->cnf_diamid_len;
+	CHECK_FCT( fd_msg_avp_setvalue( avp_OH, &val ) );
+	
+	/* Add it to the message */
+	CHECK_FCT( fd_msg_avp_add( msg, MSG_BRW_LAST_CHILD, avp_OH ) );
+	
+	
+	/* Create the Origin-Realm AVP */
+	CHECK_FCT( fd_msg_avp_new( dict_avp_OR, 0, &avp_OR ) );
+	
+	/* Set its value */
+	memset(&val, 0, sizeof(val));
+	val.os.data = (os0_t)fd_g_config->cnf_diamrlm;
+	val.os.len  = fd_g_config->cnf_diamrlm_len;
+	CHECK_FCT( fd_msg_avp_setvalue( avp_OR, &val ) );
+	
+	/* Add it to the message */
+	CHECK_FCT( fd_msg_avp_add( msg, MSG_BRW_LAST_CHILD, avp_OR ) );
+	
+	if (osi) {
+		/* Create the Origin-State-Id AVP */
+		CHECK_FCT( fd_msg_avp_new( fd_dict_avp_OSI, 0, &avp_OSI ) );
+
+		/* Set its value */
+		memset(&val, 0, sizeof(val));
+		val.u32 = fd_g_config->cnf_orstateid;
+		CHECK_FCT( fd_msg_avp_setvalue( avp_OSI, &val ) );
+
+		/* Add it to the message */
+		CHECK_FCT( fd_msg_avp_add( msg, MSG_BRW_LAST_CHILD, avp_OSI ) );
+	}
+	
+	return 0;
+}
+
+/* Create a new Session-Id and add at the beginning of the message. */
+int fd_msg_new_session( struct msg * msg, os0_t opt, size_t optlen )
+{
+	union avp_value val;
+	struct avp * avp  = NULL;
+	struct session * sess = NULL;
+	os0_t sid;
+	size_t sidlen;
+	
+	TRACE_ENTRY("%p %p %zd", msg, opt, optlen);
+	CHECK_PARAMS(  msg  );
+	
+	/* Check there is not already a session in the message */
+	CHECK_FCT( fd_msg_sess_get(fd_g_config->cnf_dict, msg, &sess, NULL) );
+	CHECK_PARAMS( sess == NULL );
+	
+	/* Ok, now create the session */
+	CHECK_FCT( fd_sess_new ( &sess, fd_g_config->cnf_diamid, fd_g_config->cnf_diamid_len, opt, optlen ) );
+	CHECK_FCT( fd_sess_getsid( sess, &sid, &sidlen) );
+	
+	/* Create an AVP to hold it */
+	CHECK_FCT( fd_msg_avp_new( dict_avp_SI, 0, &avp ) );
+	
+	/* Set its value */
+	memset(&val, 0, sizeof(val));
+	val.os.data = sid;
+	val.os.len  = sidlen;
+	CHECK_FCT( fd_msg_avp_setvalue( avp, &val ) );
+	
+	/* Add it to the message */
+	CHECK_FCT( fd_msg_avp_add( msg, MSG_BRW_FIRST_CHILD, avp ) );
+	
+	/* Save the session associated with the message */
+	CHECK_FCT( fd_msg_sess_set( msg, sess) );
+	
+	/* Done! */
+	return 0;
+}
+
+
+/* Add Result-Code and eventually Failed-AVP, Error-Message and Error-Reporting-Host AVPs */
+int fd_msg_rescode_set( struct msg * msg, char * rescode, char * errormsg, struct avp * optavp, int type_id )
+{
+	union avp_value val;
+	struct avp * avp_RC  = NULL;
+	struct avp * avp_EM  = NULL;
+	struct avp * avp_ERH = NULL;
+	struct avp * avp_FAVP= NULL;
+	uint32_t rc_val = 0;
+	int set_e_bit=0;
+	int std_err_msg=0;
+	
+	TRACE_ENTRY("%p %s %p %p %d", msg, rescode, errormsg, optavp, type_id);
+		
+	CHECK_PARAMS(  msg && rescode  );
+	
+	/* Find the enum value corresponding to the rescode string, this will give the class of error */
+	{
+		struct dict_object * enum_obj = NULL;
+		struct dict_enumval_request req;
+		memset(&req, 0, sizeof(struct dict_enumval_request));
+		
+		/* First, get the enumerated type of the Result-Code AVP (this is fast, no need to cache the object) */
+		CHECK_FCT(  fd_dict_search( fd_g_config->cnf_dict, DICT_TYPE, TYPE_OF_AVP, dict_avp_RC, &(req.type_obj), ENOENT  )  );
+		
+		/* Now search for the value given as parameter */
+		req.search.enum_name = rescode;
+		CHECK_FCT(  fd_dict_search( fd_g_config->cnf_dict, DICT_ENUMVAL, ENUMVAL_BY_STRUCT, &req, &enum_obj, ENOTSUP)  );
+		
+		/* finally retrieve its data */
+		CHECK_FCT_DO(  fd_dict_getval( enum_obj, &(req.search) ), return EINVAL );
+		
+		/* copy the found value, we're done */
+		rc_val = req.search.enum_value.u32;
+	}
+	
+	if (type_id == 1) {
+		/* Add the Origin-Host and Origin-Realm AVP */
+		CHECK_FCT( fd_msg_add_origin ( msg, 0 ) );
+	}
+	
+	/* Create the Result-Code AVP */
+	CHECK_FCT( fd_msg_avp_new( dict_avp_RC, 0, &avp_RC ) );
+	
+	/* Set its value */
+	memset(&val, 0, sizeof(val));
+	val.u32  = rc_val;
+	CHECK_FCT( fd_msg_avp_setvalue( avp_RC, &val ) );
+	
+	/* Add it to the message */
+	CHECK_FCT( fd_msg_avp_add( msg, MSG_BRW_LAST_CHILD, avp_RC ) );
+	
+	if (type_id == 2) {
+		/* Add the Error-Reporting-Host AVP */
+		
+		CHECK_FCT( fd_msg_avp_new( dict_avp_ERH, 0, &avp_ERH ) );
+
+		/* Set its value */
+		memset(&val, 0, sizeof(val));
+		val.os.data = (uint8_t *)fd_g_config->cnf_diamid;
+		val.os.len  = fd_g_config->cnf_diamid_len;
+		CHECK_FCT( fd_msg_avp_setvalue( avp_ERH, &val ) );
+
+		/* Add it to the message */
+		CHECK_FCT( fd_msg_avp_add( msg, MSG_BRW_LAST_CHILD, avp_ERH ) );
+	
+	}
+	
+	/* Now add the optavp in a FailedAVP if provided */
+	if (optavp) {
+		struct avp * optavp_cpy = NULL;
+		struct avp_hdr *opt_hdr, *optcpy_hdr;
+		struct dict_object * opt_model = NULL;
+		int is_grouped = 0;
+		
+		/* Create the Failed-AVP AVP */
+		CHECK_FCT( fd_msg_avp_new( dict_avp_FAVP, 0, &avp_FAVP ) );
+		
+		/* Was this AVP a grouped one? Best effort only here */
+		if (!fd_msg_model ( optavp, &opt_model ) && (opt_model != NULL)) {
+			struct dict_avp_data  dictdata;
+			CHECK_FCT(  fd_dict_getval(opt_model, &dictdata)  );
+			if (dictdata.avp_basetype == AVP_TYPE_GROUPED) 
+				is_grouped = 1;
+		}
+		
+		/* Create a new AVP with a copy of the data of the invalid or missing AVP */
+		optavp_cpy = optavp;
+		
+		if (is_grouped) {
+			CHECK_FCT( fd_msg_avp_new( opt_model, 0, &optavp_cpy) );
+		} else {
+			CHECK_FCT( fd_msg_avp_new( NULL, AVPFL_SET_BLANK_VALUE | AVPFL_SET_RAWDATA_FROM_AVP, &optavp_cpy) );
+		
+			CHECK_FCT( fd_msg_avp_hdr(optavp, &opt_hdr) );
+			CHECK_FCT( fd_msg_avp_hdr(optavp_cpy, &optcpy_hdr) );
+			memcpy(optcpy_hdr, opt_hdr, sizeof(struct avp_hdr));
+		}
+		
+		/* Add the passed AVP inside it */
+		CHECK_FCT( fd_msg_avp_add( avp_FAVP, MSG_BRW_LAST_CHILD, optavp_cpy ) );
+		
+		/* And add to the message */
+		CHECK_FCT( fd_msg_avp_add( msg, MSG_BRW_LAST_CHILD, avp_FAVP ) );
+	}
+	
+	
+	/* Deal with the 'E' bit and the error message */
+	switch (rc_val / 1000) {
+		case 1:	/* Informational */
+		case 2: /* Success */
+			/* Nothing special here: no E bit, no error message unless one is specified */
+			break;
+			
+		case 3: /* Protocol Errors */
+			set_e_bit = 1;
+			std_err_msg = 1;
+			break;
+			
+		case 4: /* Transcient Failure */
+		case 5: /* Permanent Failure */
+		default:
+			std_err_msg = 1;
+			break;
+			
+	}
+	
+	{
+		struct msg_hdr * hdr = NULL;
+		
+		CHECK_FCT(  fd_msg_hdr( msg, &hdr )  );
+		
+		if (set_e_bit)
+			hdr->msg_flags |= CMD_FLAG_ERROR;
+		else
+			hdr->msg_flags &= ~ CMD_FLAG_ERROR;
+	}
+	
+	if (std_err_msg || errormsg) {
+		/* Add the Error-Message AVP */
+		
+		CHECK_FCT( fd_msg_avp_new( dict_avp_EM, 0, &avp_EM ) );
+
+		/* Set its value */
+		memset(&val, 0, sizeof(val));
+		
+		if (errormsg) {
+			val.os.data = (uint8_t *)errormsg;
+			val.os.len  = strlen(errormsg);
+		} else {
+			val.os.data = (uint8_t *)rescode;
+			val.os.len  = strlen(rescode);
+		}
+		CHECK_FCT( fd_msg_avp_setvalue( avp_EM, &val ) );
+
+		/* Add it to the message */
+		CHECK_FCT( fd_msg_avp_add( msg, MSG_BRW_LAST_CHILD, avp_EM ) );
+	}
+	
+	return 0;
+}
+
+static int fd_msg_send_int( struct msg ** pmsg, void (*anscb)(void *, struct msg **), void * data, void (*expirecb)(void *, DiamId_t, size_t, struct msg **), const struct timespec *timeout )
+{
+	struct msg_hdr *hdr;
+	DiamId_t diamid;
+	
+	/* Save the callback in the message, with the timeout */
+	CHECK_FCT(  fd_msg_anscb_associate( *pmsg, anscb, data, expirecb, timeout )  );
+	
+	/* If this is a new request, call the HOOK_MESSAGE_LOCAL hook */
+	if ( (fd_msg_hdr(*pmsg, &hdr) == 0)
+	 &&  (hdr->msg_flags & CMD_FLAG_REQUEST)
+	 &&  (fd_msg_source_get(*pmsg, &diamid, NULL) == 0)
+	 &&  (diamid == NULL)) {
+		fd_hook_call(HOOK_MESSAGE_LOCAL, *pmsg, NULL, NULL, fd_msg_pmdl_get(*pmsg));
+	}
+		
+	/* Post the message in the outgoing queue */
+	CHECK_FCT( fd_fifo_post(fd_g_outgoing, pmsg) );
+	
+	return 0;
+}
+
+/* Send a message and optionally register a callback for an answer */
+int fd_msg_send ( struct msg ** pmsg, void (*anscb)(void *, struct msg **), void * data )
+{
+	TRACE_ENTRY("%p %p %p", pmsg, anscb, data);
+	CHECK_PARAMS( pmsg );
+	
+	return fd_msg_send_int(pmsg, anscb, data, NULL, NULL);
+}
+
+/* The variation of the same function with a timeout callback */
+int fd_msg_send_timeout ( struct msg ** pmsg, void (*anscb)(void *, struct msg **), void * data, void (*expirecb)(void *, DiamId_t, size_t, struct msg **), const struct timespec *timeout )
+{
+	TRACE_ENTRY("%p %p %p %p %p", pmsg, anscb, data, expirecb, timeout);
+	CHECK_PARAMS( pmsg && expirecb && timeout );
+	
+	return fd_msg_send_int(pmsg, anscb, data, expirecb, timeout);
+}
+
+
+/* Parse a message against our dictionary, and in case of error log and eventually build the error reply -- returns the parsing status */
+int fd_msg_parse_or_error( struct msg ** msg, struct msg **error)
+{
+	int ret = 0;
+	struct msg * m;
+	struct msg_hdr * hdr = NULL;
+	struct fd_pei	pei;
+	
+	TRACE_ENTRY("%p", msg);
+	
+	CHECK_PARAMS(msg && *msg && error);
+	m = *msg;
+	*error = NULL;
+	
+	/* Parse the message against our dictionary */
+	ret = fd_msg_parse_rules ( m, fd_g_config->cnf_dict, &pei);
+	if 	((ret != EBADMSG) 	/* Parsing grouped AVP failed / Conflicting rule found */
+		&& (ret != ENOTSUP))	/* Command is not supported / Mandatory AVP is not supported */
+		return ret; /* 0 or another error */
+	
+	/* Log */
+	fd_hook_call(HOOK_MESSAGE_PARSING_ERROR, m, NULL, pei.pei_message ?: pei.pei_errcode, fd_msg_pmdl_get(m));
+	
+	CHECK_FCT( fd_msg_hdr(m, &hdr) );
+	
+	/* Now create an answer error if the message is a query */
+	if (hdr->msg_flags & CMD_FLAG_REQUEST) {
+		
+		/* Create the error message */
+		CHECK_FCT( fd_msg_new_answer_from_req ( fd_g_config->cnf_dict, &m, pei.pei_protoerr ? MSGFL_ANSW_ERROR : 0 ) );
+		
+		/* Set the error code */
+		CHECK_FCT( fd_msg_rescode_set(m, pei.pei_errcode, pei.pei_message, pei.pei_avp, 1 ) );
+		
+		/* free the pei AVP to avoid memory leak */
+		if (pei.pei_avp_free) {
+			fd_msg_free(pei.pei_avp);
+		}
+		
+		*msg = NULL;
+		*error = m;
+		
+	} else {
+		do { /* Rescue error messages */
+			struct avp * avp;
+			union avp_value * rc = NULL;
+			
+			/* Search the Result-Code AVP */
+			CHECK_FCT_DO(  fd_msg_browse(*msg, MSG_BRW_FIRST_CHILD, &avp, NULL), break  );
+			while (avp) {
+				struct avp_hdr * ahdr;
+				CHECK_FCT_DO(  fd_msg_avp_hdr( avp, &ahdr ), break  );
+				
+				if ((ahdr->avp_code == AC_RESULT_CODE) && (! (ahdr->avp_flags & AVP_FLAG_VENDOR)) ) {
+					/* Parse this AVP */
+					ASSERT( ahdr->avp_value );
+					rc = ahdr->avp_value;
+					break;
+				}
+				
+				/* Go to next AVP */
+				CHECK_FCT_DO(  fd_msg_browse(avp, MSG_BRW_NEXT, &avp, NULL), break  );
+			}
+			
+			if (rc) {
+				switch (rc->u32 / 1000) {
+					case 1:	/* 1xxx : Informational */
+					case 2:	/* 2xxx : Sucess */
+						/* In these cases, we want the message to validate the ABNF, so we will discard the bad message */
+						break;
+						
+					default: /* Other errors */
+						/* We let the application decide what to do with the message, we rescue it */
+						*error = m;
+				}
+			}
+		} while (0);
+	}
+	
+	return EBADMSG; /* We convert ENOTSUP to EBADMSG as well */
+}
diff --git a/libfdcore/p_ce.c b/libfdcore/p_ce.c
new file mode 100644
index 0000000..1b4cd13
--- /dev/null
+++ b/libfdcore/p_ce.c
@@ -0,0 +1,1103 @@
+/*********************************************************************************************************
+* Software License Agreement (BSD License)                                                               *
+* Author: Sebastien Decugis <sdecugis@freediameter.net>							 *
+*													 *
+* Copyright (c) 2015, WIDE Project and NICT								 *
+* All rights reserved.											 *
+* 													 *
+* Redistribution and use of this software in source and binary forms, with or without modification, are  *
+* permitted provided that the following conditions are met:						 *
+* 													 *
+* * Redistributions of source code must retain the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer.										 *
+*    													 *
+* * Redistributions in binary form must reproduce the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer in the documentation and/or other						 *
+*   materials provided with the distribution.								 *
+* 													 *
+* * Neither the name of the WIDE Project or NICT nor the 						 *
+*   names of its contributors may be used to endorse or 						 *
+*   promote products derived from this software without 						 *
+*   specific prior written permission of WIDE Project and 						 *
+*   NICT.												 *
+* 													 *
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED *
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
+* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR *
+* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 	 *
+* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 	 *
+* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR *
+* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF   *
+* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.								 *
+*********************************************************************************************************/
+
+#include "fdcore-internal.h"
+
+/* This file contains code to handle Capabilities Exchange messages (CER and CEA) and election process */
+
+/* Save a connection as peer's principal */
+static int set_peer_cnx(struct fd_peer * peer, struct cnxctx **cnx)
+{
+	CHECK_PARAMS( peer->p_cnxctx == NULL );
+	
+	/* Save the connection in peer */
+	peer->p_cnxctx = *cnx;
+	*cnx = NULL;
+	
+	/* Set the events to be sent to the PSM */
+	CHECK_FCT( fd_cnx_recv_setaltfifo(peer->p_cnxctx, peer->p_events) );
+	
+	/* Read the credentials if possible */
+	if (fd_cnx_getTLS(peer->p_cnxctx)) {
+		CHECK_FCT( fd_cnx_getcred(peer->p_cnxctx, &peer->p_hdr.info.runtime.pir_cert_list, &peer->p_hdr.info.runtime.pir_cert_list_size) );
+	}
+	
+	/* Read the endpoints, maybe used to reconnect to the peer later */
+	CHECK_FCT( fd_cnx_getremoteeps(peer->p_cnxctx, &peer->p_hdr.info.pi_endpoints) );
+	
+	/* Read the protocol */
+	peer->p_hdr.info.runtime.pir_proto = fd_cnx_getproto(peer->p_cnxctx);
+	
+	return 0;
+}
+
+/* Delete the peer connection, and cleanup associated information */
+void fd_p_ce_clear_cnx(struct fd_peer * peer, struct cnxctx ** cnx_kept)
+{
+	peer->p_hdr.info.runtime.pir_cert_list = NULL;
+	peer->p_hdr.info.runtime.pir_cert_list_size = 0;
+	peer->p_hdr.info.runtime.pir_proto = 0;
+	
+	if (peer->p_cnxctx) {
+		if (cnx_kept != NULL) {
+			*cnx_kept = peer->p_cnxctx;
+		} else {
+			fd_cnx_destroy(peer->p_cnxctx);
+		}
+		peer->p_cnxctx = NULL;
+	}
+}
+
+/* Election: compare the Diameter Ids by lexical order, return true if the election is won */
+static __inline__ int election_result(struct fd_peer * peer)
+{
+	int ret = (strcasecmp(peer->p_hdr.info.pi_diamid, fd_g_config->cnf_diamid) < 0);
+	if (ret) {
+		TRACE_DEBUG(INFO, "Election WON against peer '%s'", peer->p_hdr.info.pi_diamid);
+	} else {
+		TRACE_DEBUG(INFO, "Election LOST against peer '%s'", peer->p_hdr.info.pi_diamid);
+	}
+	return ret;
+}
+
+/* Add AVPs about local information in a CER or CEA */
+static int add_CE_info(struct msg *msg, struct cnxctx * cnx, int isi_tls, int isi_none)
+{
+	struct dict_object * dictobj = NULL;
+	struct avp * avp = NULL;
+	union avp_value val;
+	struct fd_list *li;
+	
+	/* Add the Origin-* AVPs */
+	CHECK_FCT( fd_msg_add_origin ( msg, 1 ) );
+	
+	/* Find the model for Host-IP-Address AVP */
+	CHECK_FCT(  fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Host-IP-Address", &dictobj, ENOENT )  );
+		
+	/* Add the AVP(s) -- not sure what is the purpose... We could probably only add the primary one ? */
+	for (li = fd_g_config->cnf_endpoints.next; li != &fd_g_config->cnf_endpoints; li = li->next) {
+		struct fd_endpoint * ep = (struct fd_endpoint *)li;
+		CHECK_FCT( fd_msg_avp_new ( dictobj, 0, &avp ) );
+		CHECK_FCT( fd_msg_avp_value_encode ( &ep->ss, avp ) );
+		CHECK_FCT( fd_msg_avp_add( msg, MSG_BRW_LAST_CHILD, avp ) );
+	}
+	
+	/* Vendor-Id, Product-Name, and Firmware-Revision AVPs */
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Vendor-Id", &dictobj, ENOENT )  );
+	CHECK_FCT( fd_msg_avp_new ( dictobj, 0, &avp ) );
+	val.u32 = MY_VENDOR_ID;
+	CHECK_FCT( fd_msg_avp_setvalue( avp, &val ) );
+	CHECK_FCT( fd_msg_avp_add( msg, MSG_BRW_LAST_CHILD, avp ) );
+	
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Product-Name", &dictobj, ENOENT )  );
+	CHECK_FCT( fd_msg_avp_new ( dictobj, 0, &avp ) );
+	val.os.data = (unsigned char *)FD_PROJECT_NAME;
+	val.os.len = strlen(FD_PROJECT_NAME);
+	CHECK_FCT( fd_msg_avp_setvalue( avp, &val ) );
+	CHECK_FCT( fd_msg_avp_add( msg, MSG_BRW_LAST_CHILD, avp ) );
+	
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Firmware-Revision", &dictobj, ENOENT )  );
+	CHECK_FCT( fd_msg_avp_new ( dictobj, 0, &avp ) );
+	val.u32 = (uint32_t)(FD_PROJECT_VERSION_MAJOR * 10000 + FD_PROJECT_VERSION_MINOR * 100 + FD_PROJECT_VERSION_REV);
+	CHECK_FCT( fd_msg_avp_setvalue( avp, &val ) );
+	CHECK_FCT( fd_msg_avp_add( msg, MSG_BRW_LAST_CHILD, avp ) );
+	
+	
+	/* Add the Inband-Security-Id AVP if needed */
+	if (isi_tls || isi_none) {
+		CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Inband-Security-Id", &dictobj, ENOENT )  );
+		
+		if (isi_none) {
+			CHECK_FCT( fd_msg_avp_new ( dictobj, 0, &avp ) );
+			val.u32 = ACV_ISI_NO_INBAND_SECURITY;
+			CHECK_FCT( fd_msg_avp_setvalue( avp, &val ) );
+			CHECK_FCT( fd_msg_avp_add( msg, MSG_BRW_LAST_CHILD, avp ) );
+		}
+		
+		if (isi_tls) {
+			CHECK_FCT( fd_msg_avp_new ( dictobj, 0, &avp ) );
+			val.u32 = ACV_ISI_TLS;
+			CHECK_FCT( fd_msg_avp_setvalue( avp, &val ) );
+			CHECK_FCT( fd_msg_avp_add( msg, MSG_BRW_LAST_CHILD, avp ) );
+		}
+	}
+	
+	/* List of local applications */
+	{
+		struct dict_object * dictobj_auth = NULL;
+		struct dict_object * dictobj_acct = NULL;
+		struct dict_object * dictobj_vid = NULL;
+		
+		CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Vendor-Specific-Application-Id", &dictobj, ENOENT )  );
+		CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Vendor-Id", &dictobj_vid, ENOENT )  );
+		CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Auth-Application-Id", &dictobj_auth, ENOENT )  );
+		CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Acct-Application-Id", &dictobj_acct, ENOENT )  );
+		
+		for (li = fd_g_config->cnf_apps.next; li != &fd_g_config->cnf_apps; li = li->next) {
+			struct fd_app * a = (struct fd_app *)(li);
+
+			if (a->flags.auth) {
+				CHECK_FCT( fd_msg_avp_new ( dictobj_auth, 0, &avp ) );
+				val.u32 = a->appid;
+				CHECK_FCT( fd_msg_avp_setvalue( avp, &val ) );
+				if (a->vndid != 0) {
+					struct avp * avp2 = NULL;
+					CHECK_FCT( fd_msg_avp_new ( dictobj, 0, &avp2 ) );
+					CHECK_FCT( fd_msg_avp_add( avp2, MSG_BRW_LAST_CHILD, avp ) );
+					avp = avp2;
+					CHECK_FCT( fd_msg_avp_new ( dictobj_vid, 0, &avp2 ) );
+					val.u32 = a->vndid;
+					CHECK_FCT( fd_msg_avp_setvalue( avp2, &val ) );
+					CHECK_FCT( fd_msg_avp_add( avp, MSG_BRW_LAST_CHILD, avp2 ) );
+				}
+				CHECK_FCT( fd_msg_avp_add( msg, MSG_BRW_LAST_CHILD, avp ) );
+			}
+			if (a->flags.acct) {
+				CHECK_FCT( fd_msg_avp_new ( dictobj_acct, 0, &avp ) );
+				val.u32 = a->appid;
+				CHECK_FCT( fd_msg_avp_setvalue( avp, &val ) );
+				if (a->vndid != 0) {
+					struct avp * avp2 = NULL;
+					CHECK_FCT( fd_msg_avp_new ( dictobj, 0, &avp2 ) );
+					CHECK_FCT( fd_msg_avp_add( avp2, MSG_BRW_LAST_CHILD, avp ) );
+					avp = avp2;
+					CHECK_FCT( fd_msg_avp_new ( dictobj_vid, 0, &avp2 ) );
+					val.u32 = a->vndid;
+					CHECK_FCT( fd_msg_avp_setvalue( avp2, &val ) );
+					CHECK_FCT( fd_msg_avp_add( avp, MSG_BRW_LAST_CHILD, avp2 ) );
+				}
+				CHECK_FCT( fd_msg_avp_add( msg, MSG_BRW_LAST_CHILD, avp ) );
+			}
+		}
+		
+		/* do not forget the relay application */
+		if (! fd_g_config->cnf_flags.no_fwd) {
+			CHECK_FCT( fd_msg_avp_new ( dictobj_auth, 0, &avp ) );
+			val.u32 = AI_RELAY;
+			CHECK_FCT( fd_msg_avp_setvalue( avp, &val ) );
+			CHECK_FCT( fd_msg_avp_add( msg, MSG_BRW_LAST_CHILD, avp ) );
+		}
+	}
+	
+	/* Add the list of supported vendors */
+	{
+		uint32_t * array = fd_dict_get_vendorid_list(fd_g_config->cnf_dict);
+		if (array) {
+			int i = 0;
+			CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Supported-Vendor-Id", &dictobj, ENOENT )  );
+			
+			while (array[i] != 0) {
+				CHECK_FCT( fd_msg_avp_new ( dictobj, 0, &avp ) );
+				val.u32 = array[i];
+				CHECK_FCT( fd_msg_avp_setvalue( avp, &val ) );
+				CHECK_FCT( fd_msg_avp_add( msg, MSG_BRW_LAST_CHILD, avp ) );
+				i++;
+			}
+			
+			free(array);
+		}
+	}
+	
+	return 0;
+}
+
+/* Remove any information saved from a previous CER/CEA exchange */
+static void cleanup_remote_CE_info(struct fd_peer * peer)
+{
+	/* free linked information */
+	free(peer->p_hdr.info.runtime.pir_realm);
+	free(peer->p_hdr.info.runtime.pir_prodname);
+	while (!FD_IS_LIST_EMPTY(&peer->p_hdr.info.runtime.pir_apps)) {
+		struct fd_list * li = peer->p_hdr.info.runtime.pir_apps.next;
+		fd_list_unlink(li);
+		free(li);
+	}
+	/* note: pir_cert_list needs not be freed (belongs to gnutls) */
+	
+	/* cleanup the area */
+	memset(&peer->p_hdr.info.runtime, 0, sizeof(peer->p_hdr.info.runtime));
+	
+	/* reinit the list */
+	fd_list_init(&peer->p_hdr.info.runtime.pir_apps, peer);
+
+	/* Remove previously advertised endpoints */
+	fd_ep_clearflags( &peer->p_hdr.info.pi_endpoints, EP_FL_ADV );
+}
+
+/* Extract information sent by the remote peer and save it in our peer structure */
+static int save_remote_CE_info(struct msg * msg, struct fd_peer * peer, struct fd_pei * error, uint32_t *rc)
+{
+	struct avp * avp = NULL;
+	
+	cleanup_remote_CE_info(peer);
+	
+	CHECK_FCT( fd_msg_browse( msg, MSG_BRW_FIRST_CHILD, &avp, NULL) );
+	
+	/* Loop on all AVPs and save what we are interrested into */
+	while (avp) {
+		struct avp_hdr * hdr;
+
+		CHECK_FCT(  fd_msg_avp_hdr( avp, &hdr )  );
+
+		if (hdr->avp_flags & AVP_FLAG_VENDOR) {
+			/* Ignore all vendor-specific AVPs in CER/CEA because we don't support any currently */
+			LOG_A("Ignored a vendor-specific AVP in CER / CEA");
+			goto next;
+		}
+
+		switch (hdr->avp_code) {
+			case AC_RESULT_CODE: /* Result-Code */
+				if (hdr->avp_value == NULL) {
+					/* This is a sanity check */
+					LOG_F("Ignored an AVP (code %x) with unset value in CER/CEA", hdr->avp_code);
+					ASSERT(0); /* To check if this really happens, and understand why... */
+					goto next;
+				}
+				
+				if (rc)
+					*rc = hdr->avp_value->u32;
+				break;
+		
+			case AC_ORIGIN_HOST: /* Origin-Host */
+				if (hdr->avp_value == NULL) {
+					/* This is a sanity check */
+					LOG_F("Ignored an AVP (code %x) with unset value in CER/CEA", hdr->avp_code);
+					ASSERT(0); /* To check if this really happens, and understand why... */
+					goto next;
+				}
+				
+				/* We check that the value matches what we know, otherwise disconnect the peer */
+				if (fd_os_almostcasesrch(hdr->avp_value->os.data, hdr->avp_value->os.len, 
+							peer->p_hdr.info.pi_diamid, peer->p_hdr.info.pi_diamidlen, NULL)) {
+					TRACE_DEBUG(INFO, "Received a message with Origin-Host set to '%.*s' while expecting '%s'", 
+							(int)hdr->avp_value->os.len, hdr->avp_value->os.data, peer->p_hdr.info.pi_diamid);
+					error->pei_errcode = "DIAMETER_AVP_NOT_ALLOWED";
+					error->pei_message = "Your Origin-Host value does not match my configuration.";
+					error->pei_avp = avp;
+					return EINVAL;
+				}
+
+				break;
+		
+			case AC_ORIGIN_REALM: /* Origin-Realm */
+				if (hdr->avp_value == NULL) {
+					/* This is a sanity check */
+					LOG_F("Ignored an AVP (code %x) with unset value in CER/CEA", hdr->avp_code);
+					ASSERT(0); /* To check if this really happens, and understand why... */
+					goto next;
+				}
+				
+				/* In case of multiple AVPs */
+				if (peer->p_hdr.info.runtime.pir_realm) {
+					TRACE_DEBUG(INFO, "Multiple instances of the Origin-Realm AVP");
+					error->pei_errcode = "DIAMETER_AVP_OCCURS_TOO_MANY_TIMES";
+					error->pei_message = "I found several Origin-Realm AVPs";
+					error->pei_avp = avp;
+					return EINVAL;
+				}
+				
+				/* If the octet string contains a \0 */
+				if (!fd_os_is_valid_DiameterIdentity(hdr->avp_value->os.data, hdr->avp_value->os.len)) {
+					error->pei_errcode = "DIAMETER_INVALID_AVP_VALUE";
+					error->pei_message = "Your Origin-Realm contains invalid characters.";
+					error->pei_avp = avp;
+					return EINVAL;
+				}
+				
+				/* Save the value */
+				CHECK_MALLOC(  peer->p_hdr.info.runtime.pir_realm = os0dup( hdr->avp_value->os.data, hdr->avp_value->os.len )  );
+				peer->p_hdr.info.runtime.pir_realmlen = hdr->avp_value->os.len;
+				break;
+
+			case AC_HOST_IP_ADDRESS: /* Host-IP-Address */
+				if (hdr->avp_value == NULL) {
+					/* This is a sanity check */
+					LOG_F("Ignored an AVP (code %x) with unset value in CER/CEA", hdr->avp_code);
+					ASSERT(0); /* To check if this really happens, and understand why... */
+					goto next;
+				}
+				{
+					sSS	ss;
+
+					/* Get the sockaddr value */
+					memset(&ss, 0, sizeof(ss));
+					CHECK_FCT_DO( fd_msg_avp_value_interpret( avp, &ss),
+						{
+							/* in case of error, assume the AVP value was wrong */
+							error->pei_errcode = "DIAMETER_INVALID_AVP_VALUE";
+							error->pei_avp = avp;
+							return EINVAL;
+						} );
+
+					/* Save this endpoint in the list as advertized */
+					CHECK_FCT( fd_ep_add_merge( &peer->p_hdr.info.pi_endpoints, (sSA *)&ss, sizeof(sSS), EP_FL_ADV ) );
+				}
+				break;
+
+			case AC_VENDOR_ID: /* Vendor-Id */
+				if (hdr->avp_value == NULL) {
+					/* This is a sanity check */
+					LOG_F("Ignored an AVP (code %x) with unset value in CER/CEA", hdr->avp_code);
+					ASSERT(0); /* To check if this really happens, and understand why... */
+					goto next;
+				}
+				
+				/* In case of multiple AVPs */
+				if (peer->p_hdr.info.runtime.pir_vendorid) {
+					TRACE_DEBUG(INFO, "Multiple instances of the Vendor-Id AVP");
+					error->pei_errcode = "DIAMETER_AVP_OCCURS_TOO_MANY_TIMES";
+					error->pei_message = "I found several Vendor-Id AVPs";
+					error->pei_avp = avp;
+					return EINVAL;
+				}
+				
+				peer->p_hdr.info.runtime.pir_vendorid = hdr->avp_value->u32;
+				break;
+
+			case AC_PRODUCT_NAME: /* Product-Name */
+				if (hdr->avp_value == NULL) {
+					/* This is a sanity check */
+					LOG_F("Ignored an AVP (code %x) with unset value in CER/CEA", hdr->avp_code);
+					ASSERT(0); /* To check if this really happens, and understand why... */
+					goto next;
+				}
+				
+				/* In case of multiple AVPs */
+				if (peer->p_hdr.info.runtime.pir_prodname) {
+					TRACE_DEBUG(INFO, "Multiple instances of the Product-Name AVP");
+					error->pei_errcode = "DIAMETER_AVP_OCCURS_TOO_MANY_TIMES";
+					error->pei_message = "I found several Product-Name AVPs";
+					error->pei_avp = avp;
+					return EINVAL;
+				}
+
+				CHECK_MALLOC( peer->p_hdr.info.runtime.pir_prodname = calloc( hdr->avp_value->os.len + 1, 1 )  );
+				memcpy(peer->p_hdr.info.runtime.pir_prodname, hdr->avp_value->os.data, hdr->avp_value->os.len);
+				break;
+
+			case AC_ORIGIN_STATE_ID: /* Origin-State-Id */
+				if (hdr->avp_value == NULL) {
+					/* This is a sanity check */
+					LOG_F("Ignored an AVP (code %x) with unset value in CER/CEA", hdr->avp_code);
+					ASSERT(0); /* To check if this really happens, and understand why... */
+					goto next;
+				}
+				
+				/* In case of multiple AVPs */
+				if (peer->p_hdr.info.runtime.pir_orstate) {
+					TRACE_DEBUG(INFO, "Multiple instances of the Origin-State-Id AVP");
+					error->pei_errcode = "DIAMETER_AVP_OCCURS_TOO_MANY_TIMES";
+					error->pei_message = "I found several Origin-State-Id AVPs";
+					error->pei_avp = avp;
+					return EINVAL;
+				}
+				
+				peer->p_hdr.info.runtime.pir_orstate = hdr->avp_value->u32;
+				break;
+
+			case AC_SUPPORTED_VENDOR_ID: /* Supported-Vendor-Id */
+				if (hdr->avp_value == NULL) {
+					/* This is a sanity check */
+					LOG_F("Ignored an AVP (code %x) with unset value in CER/CEA", hdr->avp_code);
+					ASSERT(0); /* To check if this really happens, and understand why... */
+					goto next;
+				}
+				
+				TRACE_DEBUG(FULL, "'%s' claims support for a subset of vendor %d features.", peer->p_hdr.info.pi_diamid, hdr->avp_value->u32);
+				/* not that it makes a difference for us... 
+				 -- if an application actually needs this info, we could save it somewhere.
+				*/
+				break;
+
+			case AC_VENDOR_SPECIFIC_APPLICATION_ID: /* Vendor-Specific-Application-Id (grouped)*/
+				{
+					struct avp * inavp = NULL;
+					vendor_id_t vid = 0;
+					application_id_t auth_aid = 0;
+					application_id_t acct_aid = 0;
+					int invalid=0;
+
+					/* get the first child AVP */
+					CHECK_FCT(  fd_msg_browse(avp, MSG_BRW_FIRST_CHILD, &inavp, NULL)  );
+
+					while (inavp) {
+						struct avp_hdr * inhdr;
+						CHECK_FCT(  fd_msg_avp_hdr( inavp, &inhdr )  );
+
+						if (inhdr->avp_flags & AVP_FLAG_VENDOR) {
+							LOG_A("Ignored a vendor AVP inside Vendor-Specific-Application-Id AVP");
+							goto innext;
+						}
+
+						if (inhdr->avp_value == NULL) {
+							/* This is a sanity check */
+							LOG_F("Ignored an AVP (code %x) with unset value in CER/CEA", hdr->avp_code);
+							ASSERT(0); /* To check if this really happens, and understand why... */
+							goto innext;
+						}
+						switch (inhdr->avp_code) {
+							case AC_VENDOR_ID: /* Vendor-Id */
+#ifndef WORKAROUND_ACCEPT_INVALID_VSAI
+								if (vid != 0)
+									invalid++; /* We already had one such AVP. This is invalid according to RFC6733 but not RFC3588 (but there is an erratum) */
+#endif /* WORKAROUND_ACCEPT_INVALID_VSAI */
+								vid = inhdr->avp_value->u32;
+								break;
+							case AC_AUTH_APPLICATION_ID: /* Auth-Application-Id */
+								if (auth_aid != 0)
+									invalid++; /* We already had one such AVP */
+#ifndef WORKAROUND_ACCEPT_INVALID_VSAI
+								if (acct_aid != 0)
+									invalid++; /* Only 1 *-Application-Id AVP is allowed */
+#endif /* WORKAROUND_ACCEPT_INVALID_VSAI */
+								auth_aid = inhdr->avp_value->u32;
+								break;
+							case AC_ACCT_APPLICATION_ID: /* Acct-Application-Id */
+								if (acct_aid != 0)
+									invalid++; /* We already had one such AVP */
+#ifndef WORKAROUND_ACCEPT_INVALID_VSAI
+								if (auth_aid != 0)
+									invalid++; /* Only 1 *-Application-Id AVP is allowed */
+#endif /* WORKAROUND_ACCEPT_INVALID_VSAI */
+								acct_aid = inhdr->avp_value->u32;
+								break;
+							/* ignore other AVPs */
+						}
+						
+						if (invalid) {
+							TRACE_DEBUG(FULL, "Invalid Vendor-Specific-Application-Id AVP received");
+							error->pei_errcode = "DIAMETER_INVALID_AVP_VALUE";
+							error->pei_avp = avp;
+							return EINVAL;
+						}
+
+					innext:			
+						/* Go to next in AVP */
+						CHECK_FCT( fd_msg_browse(inavp, MSG_BRW_NEXT, &inavp, NULL) );
+					}
+					
+					/* Add entry in the list */
+					if (auth_aid) {
+						CHECK_FCT( fd_app_merge(&peer->p_hdr.info.runtime.pir_apps, auth_aid, vid, 1, 0) );
+					}
+					if (acct_aid) {
+						CHECK_FCT( fd_app_merge(&peer->p_hdr.info.runtime.pir_apps, acct_aid, vid, 0, 1) );
+					}
+				}
+				break;
+
+			case AC_AUTH_APPLICATION_ID: /* Auth-Application-Id */
+				if (hdr->avp_value == NULL) {
+					/* This is a sanity check */
+					LOG_F("Ignored an AVP (code %x) with unset value in CER/CEA", hdr->avp_code);
+					ASSERT(0); /* To check if this really happens, and understand why... */
+					goto next;
+				}
+				
+				if (hdr->avp_value->u32 == AI_RELAY) {
+					peer->p_hdr.info.runtime.pir_relay = 1;
+				} else {
+					CHECK_FCT( fd_app_merge(&peer->p_hdr.info.runtime.pir_apps, hdr->avp_value->u32, 0, 1, 0) );
+				}
+				break;
+
+			case AC_ACCT_APPLICATION_ID: /* Acct-Application-Id */
+				if (hdr->avp_value == NULL) {
+					/* This is a sanity check */
+					LOG_F("Ignored an AVP (code %x) with unset value in CER/CEA", hdr->avp_code);
+					ASSERT(0); /* To check if this really happens, and understand why... */
+					goto next;
+				}
+				
+				if (hdr->avp_value->u32 == AI_RELAY) {
+					/* Not clear if the relay application can be inside this AVP... */
+					peer->p_hdr.info.runtime.pir_relay = 1;
+				} else {
+					CHECK_FCT( fd_app_merge(&peer->p_hdr.info.runtime.pir_apps, hdr->avp_value->u32, 0, 0, 1) );
+				}
+				break;
+
+			case AC_FIRMWARE_REVISION: /* Firmware-Revision */
+				if (hdr->avp_value == NULL) {
+					/* This is a sanity check */
+					LOG_F("Ignored an AVP (code %x) with unset value in CER/CEA", hdr->avp_code);
+					ASSERT(0); /* To check if this really happens, and understand why... */
+					goto next;
+				}
+				
+				peer->p_hdr.info.runtime.pir_firmrev = hdr->avp_value->u32;
+				break;
+
+			case AC_INBAND_SECURITY_ID: /* Inband-Security-Id */
+				if (hdr->avp_value == NULL) {
+					/* This is a sanity check */
+					LOG_F("Ignored an AVP (code %x) with unset value in CER/CEA", hdr->avp_code);
+					ASSERT(0); /* To check if this really happens, and understand why... */
+					goto next;
+				}
+				if (hdr->avp_value->u32 >= 32 ) {
+					error->pei_errcode = "DIAMETER_INVALID_AVP_VALUE";
+					error->pei_message = "I don't support this Inband-Security-Id value (yet).";
+					error->pei_avp = avp;
+					return EINVAL;
+				}
+				peer->p_hdr.info.runtime.pir_isi |= (1 << hdr->avp_value->u32);
+				break;
+		}
+
+next:			
+		/* Go to next AVP */
+		CHECK_FCT( fd_msg_browse(avp, MSG_BRW_NEXT, &avp, NULL) );
+	}
+	
+	return 0;
+}
+
+/* Create a CER message for sending */ 
+static int create_CER(struct fd_peer * peer, struct cnxctx * cnx, struct msg ** cer)
+{
+	int isi_tls = 0;
+	int isi_none = 0;
+	
+	/* Find CER dictionary object and create an instance */
+	CHECK_FCT( fd_msg_new ( fd_dict_cmd_CER, MSGFL_ALLOC_ETEID, cer ) );
+	
+	/* Do we need Inband-Security-Id AVPs ? If we're already using TLS, we don't... */
+	if (!fd_cnx_getTLS(cnx)) {
+		isi_none = peer->p_hdr.info.config.pic_flags.sec & PI_SEC_NONE; /* we add it even if the peer does not use the old mechanism, it is impossible to distinguish */
+
+		if (peer->p_hdr.info.config.pic_flags.sec & PI_SEC_TLS_OLD) {
+			if (fd_g_config->cnf_sec_data.tls_disabled) {
+				LOG_N("TLS disabled locally, so Inband-Security-Id (TLS) not included for peer %s", peer->p_hdr.info.pi_diamid);
+			} else {
+				isi_tls  = 1;
+			}
+		}
+	}
+	
+	/* Add the information about the local peer */
+	CHECK_FCT( add_CE_info(*cer, cnx, isi_tls, isi_none) );
+	
+	/* Done! */
+	return 0;
+}
+
+
+/* Continue with the initiator side */
+static int to_waitcea(struct fd_peer * peer, struct cnxctx * cnx)
+{
+	/* We sent a CER on the connection, set the event queue so that we receive the CEA */
+	CHECK_FCT( set_peer_cnx(peer, &cnx) );
+	
+	/* Change state and reset the timer */
+	CHECK_FCT( fd_psm_change_state(peer, STATE_WAITCEA) );
+	fd_psm_next_timeout(peer, 0, CEA_TIMEOUT);
+	
+	return 0;
+}
+
+/* Reject an incoming connection attempt */
+static void receiver_reject(struct cnxctx ** recv_cnx, struct msg ** cer, struct fd_pei * error)
+{
+	struct msg_hdr * hdr = NULL;
+	
+	/* Create and send the CEA with appropriate error code */
+	CHECK_FCT_DO( fd_msg_new_answer_from_req ( fd_g_config->cnf_dict, cer, MSGFL_ANSW_ERROR ), goto destroy );
+	CHECK_FCT_DO( fd_msg_rescode_set(*cer, error->pei_errcode, error->pei_message, error->pei_avp, 0 ), goto destroy );
+	CHECK_FCT_DO(  fd_msg_hdr( *cer, &hdr ), goto destroy  );
+	if (hdr->msg_flags & CMD_FLAG_ERROR) {
+		/* Generic error format, just add the origin AVPs */
+		CHECK_FCT_DO( fd_msg_add_origin ( *cer, 1 ), goto destroy );
+	} else {
+		/* Add other AVPs to be compliant with the ABNF */
+		CHECK_FCT_DO( add_CE_info(*cer, *recv_cnx, 0, 0), goto destroy );
+	}
+	CHECK_FCT_DO( fd_out_send(cer, *recv_cnx, NULL, 0), goto destroy );
+	
+	if (error->pei_avp_free) {
+		fd_msg_free(error->pei_avp);
+	}
+	
+	/* And now destroy this connection */
+destroy:
+	fd_cnx_destroy(*recv_cnx);
+	*recv_cnx = NULL;
+	if (*cer) {
+		fd_hook_call(HOOK_MESSAGE_DROPPED, *cer, NULL, "An error occurred while rejecting this CER.", fd_msg_pmdl_get(*cer));
+		fd_msg_free(*cer);
+		*cer = NULL;
+	}
+}
+
+/* We have established a new connection to the remote peer, send CER and eventually process the election */
+int fd_p_ce_handle_newcnx(struct fd_peer * peer, struct cnxctx * initiator)
+{
+	struct msg * cer = NULL;
+	
+	/* Send CER on the new connection */
+	CHECK_FCT( create_CER(peer, initiator, &cer) );
+	CHECK_FCT( fd_out_send(&cer, initiator, peer, 0) );
+	
+	/* Are we doing an election ? */
+	if (fd_peer_getstate(peer) == STATE_WAITCNXACK_ELEC) {
+		if (election_result(peer)) {
+			/* Close initiator connection */
+			fd_cnx_destroy(initiator);
+
+			LOG_D("%s: Election lost on outgoing connection, closing and answering CEA on incoming connection.", peer->p_hdr.info.pi_diamid);
+			
+			/* Process with the receiver side */
+			CHECK_FCT( fd_p_ce_process_receiver(peer) );
+
+		} else {
+			struct fd_pei pei;
+			memset(&pei, 0, sizeof(pei));
+			pei.pei_errcode = "ELECTION_LOST";
+			pei.pei_message = "Please answer my CER instead, you won the election.";
+			LOG_D("%s: Election lost on incoming connection, closing and waiting for CEA on outgoing connection.", peer->p_hdr.info.pi_diamid);
+
+			/* Answer an ELECTION LOST to the receiver side */
+			receiver_reject(&peer->p_receiver, &peer->p_cer, &pei);
+			CHECK_FCT( to_waitcea(peer, initiator) );
+		}
+	} else {
+		/* No election (yet) */
+		CHECK_FCT( to_waitcea(peer, initiator) );
+	}
+	
+	return 0;
+}
+
+/* We have received a Capabilities Exchange message on the peer connection */
+int fd_p_ce_msgrcv(struct msg ** msg, int req, struct fd_peer * peer)
+{
+	uint32_t rc = 0;
+	int st;
+	struct fd_pei pei;
+	
+	TRACE_ENTRY("%p %p", msg, peer);
+	CHECK_PARAMS( msg && *msg && CHECK_PEER(peer) );
+	
+	/* The only valid situation where we are called is in WAITCEA and we receive a CEA (we may have won an election) */
+	
+	/* Note : to implement Capabilities Update, we would need to change here */
+	
+	/* If it is a CER, just reply an error */
+	if (req) {
+		/* Create the error message */
+		CHECK_FCT( fd_msg_new_answer_from_req ( fd_g_config->cnf_dict, msg, MSGFL_ANSW_ERROR ) );
+		
+		/* Set the error code */
+		CHECK_FCT( fd_msg_rescode_set(*msg, "DIAMETER_UNABLE_TO_COMPLY", "No CER allowed in current state", NULL, 1 ) );
+
+		/* msg now contains an answer message to send back */
+		CHECK_FCT_DO( fd_out_send(msg, NULL, peer, 0), /* In case of error the message has already been dumped */ );
+	}
+	
+	/* If the state is not WAITCEA, just discard the message */
+	if (req || ((st = fd_peer_getstate(peer)) != STATE_WAITCEA)) {
+		if (*msg) {
+			/* In such case, just discard the message */
+			char buf[128];
+			snprintf(buf, sizeof(buf), "Received while peer state machine was in state %s.", STATE_STR(st));
+			fd_hook_call(HOOK_MESSAGE_DROPPED, *msg, peer, buf, fd_msg_pmdl_get(*msg));
+
+			CHECK_FCT_DO( fd_msg_free(*msg), /* continue */);
+			*msg = NULL;
+		}
+		
+		return 0;
+	}
+	
+	memset(&pei, 0, sizeof(pei));
+	
+	/* Save info from the CEA into the peer */
+	CHECK_FCT_DO( save_remote_CE_info(*msg, peer, &pei, &rc), 
+		{
+			fd_hook_call(HOOK_PEER_CONNECT_FAILED, *msg, peer, "An error occurred while processing incoming CEA.", NULL);
+			goto cleanup;
+		} );
+	
+	/* Check the Result-Code */
+	switch (rc) {
+		case ER_DIAMETER_SUCCESS:
+			/* Log success */
+			fd_hook_call(HOOK_PEER_CONNECT_SUCCESS, *msg, peer, NULL, NULL);
+			
+			/* Dispose of the message, we don't need it anymore */
+			CHECK_FCT_DO( fd_msg_free(*msg), /* continue */ );
+			*msg = NULL;
+			
+			/* No problem, we can continue */
+			break;
+			
+		case ER_DIAMETER_TOO_BUSY:
+			/* Retry later */
+			fd_hook_call(HOOK_PEER_CONNECT_FAILED, *msg, peer, "Remote peer is too busy", NULL);
+			fd_psm_cleanup(peer, 0);
+			fd_psm_next_timeout(peer, 0, 300);
+			return 0;
+		
+		case ER_ELECTION_LOST:
+			/* Ok, just wait for a little while for the CER to be processed on the other connection. */
+			TRACE_DEBUG(FULL, "Peer %s replied a CEA with Result-Code AVP ELECTION_LOST, waiting for events.", peer->p_hdr.info.pi_diamid);
+			return 0;
+		
+		default:
+			/* In any other case, we abort all attempts to connect to this peer */
+			fd_hook_call(HOOK_PEER_CONNECT_FAILED, *msg, peer, "CEA with unexpected error code", NULL);
+			return EINVAL;
+	}
+	
+	
+	/* Handshake if needed, start clear otherwise */
+	if ( ! fd_cnx_getTLS(peer->p_cnxctx) ) {
+		int todo = peer->p_hdr.info.config.pic_flags.sec & peer->p_hdr.info.runtime.pir_isi ;
+		/* Special case: if the peer did not send a ISI AVP */
+		if (peer->p_hdr.info.runtime.pir_isi == 0)
+			todo = peer->p_hdr.info.config.pic_flags.sec;
+		
+		if (todo == PI_SEC_NONE) {
+			/* Ok for clear connection */
+			TRACE_DEBUG(INFO, "No TLS protection negotiated with peer '%s'.", peer->p_hdr.info.pi_diamid);
+			CHECK_FCT( fd_cnx_start_clear(peer->p_cnxctx, 1) );
+			
+		} else if (fd_g_config->cnf_sec_data.tls_disabled) {
+			LOG_E("Clear connection with remote peer '%s' is not (explicitly) allowed, and TLS is disabled. Giving up...", peer->p_hdr.info.pi_diamid);
+			fd_hook_call(HOOK_PEER_CONNECT_FAILED, NULL, peer, "TLS is disabled and peer is not configured for IPsec", NULL);
+			goto cleanup;
+			
+		} else {
+			fd_psm_change_state(peer, STATE_OPEN_HANDSHAKE);
+			CHECK_FCT_DO( fd_cnx_handshake(peer->p_cnxctx, GNUTLS_CLIENT, ALGO_HANDSHAKE_3436, peer->p_hdr.info.config.pic_priority, NULL),
+				{
+					/* Handshake failed ...  */
+					fd_hook_call(HOOK_PEER_CONNECT_FAILED, NULL, peer, "TLS handshake failed after CER/CEA exchange", NULL);
+					goto cleanup;
+				} );
+
+			/* Retrieve the credentials */
+			CHECK_FCT( fd_cnx_getcred(peer->p_cnxctx, &peer->p_hdr.info.runtime.pir_cert_list, &peer->p_hdr.info.runtime.pir_cert_list_size) );
+		}
+	}
+	
+	/* Move to next state */
+	if (peer->p_flags.pf_cnx_pb) {
+		fd_psm_change_state(peer, STATE_REOPEN );
+		CHECK_FCT( fd_p_dw_reopen(peer) );
+	} else {
+		fd_psm_change_state(peer, STATE_OPEN );
+		fd_psm_next_timeout(peer, 1, peer->p_hdr.info.config.pic_twtimer ?: fd_g_config->cnf_timer_tw);
+	}
+	
+	return 0;
+	
+cleanup:
+	fd_p_ce_clear_cnx(peer, NULL);
+
+	/* Send the error to the peer */
+	CHECK_FCT( fd_event_send(peer->p_events, FDEVP_CNX_ERROR, 0, NULL) );
+
+	return 0;
+}
+
+/* Handle the receiver side to go to OPEN or OPEN_NEW state (any election is resolved) */
+int fd_p_ce_process_receiver(struct fd_peer * peer)
+{
+	struct fd_pei pei;
+	struct msg * msg = NULL;
+	int isi = 0;
+	int fatal = 0;
+	int tls_sync=0;
+	
+	TRACE_ENTRY("%p", peer);
+	
+	CHECK_FCT_DO( set_peer_cnx(peer, &peer->p_receiver),
+		{
+			fd_hook_call(HOOK_PEER_CONNECT_FAILED, NULL, peer, "Error saving the incoming connection in the peer structure", NULL);
+			return __ret__;
+		} );
+	msg = peer->p_cer;
+	peer->p_cer = NULL;
+	
+	memset(&pei, 0, sizeof(pei));
+	
+	/* Parse the content of the received CER */
+	CHECK_FCT_DO( save_remote_CE_info(msg, peer, &pei, NULL), goto error_abort );
+	
+	/* Validate the realm if needed */
+	if (peer->p_hdr.info.config.pic_realm) {
+		size_t len = strlen(peer->p_hdr.info.config.pic_realm);
+		if (fd_os_almostcasesrch(peer->p_hdr.info.config.pic_realm, len, peer->p_hdr.info.runtime.pir_realm, peer->p_hdr.info.runtime.pir_realmlen, NULL)) {
+			TRACE_DEBUG(INFO, "Rejected CER from peer '%s', realm mismatch with configured value (returning DIAMETER_UNKNOWN_PEER).", peer->p_hdr.info.pi_diamid);
+			pei.pei_errcode = "DIAMETER_UNKNOWN_PEER"; /* maybe AVP_NOT_ALLOWED would be better fit? */
+			goto error_abort;
+		}
+	}
+	
+	/* Save the credentials if handshake already occurred */
+	if ( fd_cnx_getTLS(peer->p_cnxctx) ) {
+		CHECK_FCT( fd_cnx_getcred(peer->p_cnxctx, &peer->p_hdr.info.runtime.pir_cert_list, &peer->p_hdr.info.runtime.pir_cert_list_size) );
+	}
+	
+	/* Validate the peer if needed */
+	if (peer->p_flags.pf_responder) {
+		int res = fd_peer_validate( peer );
+		if (res < 0) {
+			TRACE_DEBUG(INFO, "Rejected CER from peer '%s', validation failed (returning DIAMETER_UNKNOWN_PEER).", peer->p_hdr.info.pi_diamid);
+			pei.pei_errcode = "DIAMETER_UNKNOWN_PEER";
+			goto error_abort;
+		}
+		CHECK_FCT( res );
+	}
+	
+	/* Check if we have common applications */
+	if ( fd_g_config->cnf_flags.no_fwd && (! peer->p_hdr.info.runtime.pir_relay) ) {
+		int got_common;
+		CHECK_FCT( fd_app_check_common( &fd_g_config->cnf_apps, &peer->p_hdr.info.runtime.pir_apps, &got_common) );
+		if (!got_common) {
+			TRACE_DEBUG(INFO, "No common application with peer '%s', sending DIAMETER_NO_COMMON_APPLICATION", peer->p_hdr.info.pi_diamid);
+			pei.pei_errcode = "DIAMETER_NO_COMMON_APPLICATION";
+			fatal = 1;
+			goto error_abort;
+		}
+	}
+	
+	/* Do we agree on ISI ? */
+	if ( ! fd_cnx_getTLS(peer->p_cnxctx) ) {
+		
+		/* In case of responder, the validate callback must have set the config.pic_flags.sec value already */
+	
+		/* First case: we are not using old mechanism: ISI are deprecated, we ignore it. */
+		if ( ! (peer->p_hdr.info.config.pic_flags.sec & PI_SEC_TLS_OLD)) {
+			/* Just check then that the peer configuration allows for IPsec protection */
+			if (peer->p_hdr.info.config.pic_flags.sec & PI_SEC_NONE) {
+				isi = PI_SEC_NONE;
+			} else {
+				/* otherwise, we should have already been protected. Reject */
+				TRACE_DEBUG(INFO, "Non TLS-protected CER/CEA exchanges are not allowed with this peer, rejecting.");
+			}
+		} else {
+			/* The old mechanism is allowed with this peer. Now, look into the ISI AVP values */
+			
+			/* In case no ISI was present anyway: */
+			if (!peer->p_hdr.info.runtime.pir_isi) {
+				TRACE_DEBUG(INFO, "Inband-Security-Id AVP is missing in received CER.");
+				if (peer->p_hdr.info.config.pic_flags.sec & PI_SEC_NONE) {
+					isi = PI_SEC_NONE;
+					TRACE_DEBUG(INFO, "IPsec protection allowed by configuration, allowing this mechanism to be used.");
+				} else {
+					/* otherwise, we should have already been protected. Reject */
+					TRACE_DEBUG(INFO, "Rejecting the peer connection (please allow IPsec here or configure TLS in the remote peer).");
+				}
+			} else {
+				/* OK, the remote peer did send the ISI AVP. */
+				if ((peer->p_hdr.info.config.pic_flags.sec & PI_SEC_NONE) && (peer->p_hdr.info.runtime.pir_isi & PI_SEC_NONE)) {
+					/* We have allowed IPsec */
+					isi = PI_SEC_NONE;
+				} else if (fd_g_config->cnf_sec_data.tls_disabled) {
+					/* We can agree on TLS */
+					TRACE_DEBUG(INFO, "Remote peer is not allowed for IPsec and TLS is disabled.");;
+				} else if (peer->p_hdr.info.runtime.pir_isi & PI_SEC_TLS_OLD) {
+					/* We can agree on TLS */
+					isi = PI_SEC_TLS_OLD;
+				} else {
+					TRACE_DEBUG(INFO, "Remote peer requested IPsec protection, but local configuration forbids it.");
+				}
+			}
+		}
+	
+		/* If we did not find an agreement */
+		if (!isi) {
+			TRACE_DEBUG(INFO, "No common security mechanism with '%s', sending DIAMETER_NO_COMMON_SECURITY", peer->p_hdr.info.pi_diamid);
+			pei.pei_errcode = "DIAMETER_NO_COMMON_SECURITY";
+			fatal = 1;
+			goto error_abort;
+		}
+		
+		/* Do not send the ISI IPsec if we are using the new mechanism */
+		if ((isi == PI_SEC_NONE) && (! (peer->p_hdr.info.config.pic_flags.sec & PI_SEC_TLS_OLD)))
+			isi = 0;
+	} else if (peer->p_hdr.info.runtime.pir_isi & PI_SEC_TLS_OLD) {
+		/* Seem some weird peers are sending the Inband-Security-Id AVP on the secure port... No harm */
+		isi = PI_SEC_TLS_OLD;
+	}
+	
+	/* Reply a CEA */
+	CHECK_FCT( fd_msg_new_answer_from_req ( fd_g_config->cnf_dict, &msg, 0 ) );
+	CHECK_FCT( fd_msg_rescode_set(msg, "DIAMETER_SUCCESS", NULL, NULL, 0 ) );
+	CHECK_FCT( add_CE_info(msg, peer->p_cnxctx, isi & PI_SEC_TLS_OLD, isi & PI_SEC_NONE) );
+	
+	/* The connection is complete, but we may still need TLS handshake */
+	fd_hook_call(HOOK_PEER_CONNECT_SUCCESS, msg, peer, NULL, NULL);
+	
+	CHECK_FCT( fd_out_send(&msg, peer->p_cnxctx, peer, 0 ) );
+	
+	/* Handshake if needed */
+	if (isi & PI_SEC_TLS_OLD) {
+		fd_psm_change_state(peer, STATE_OPEN_HANDSHAKE);
+		CHECK_FCT_DO( fd_cnx_handshake(peer->p_cnxctx, GNUTLS_SERVER, ALGO_HANDSHAKE_3436, peer->p_hdr.info.config.pic_priority, NULL),
+			{
+				/* Handshake failed ...  */
+				fd_hook_call(HOOK_PEER_CONNECT_FAILED, NULL, peer, "TLS handshake failed after CER/CEA exchange", NULL);
+				goto cleanup;
+			} );
+		
+		/* Retrieve the credentials */
+		CHECK_FCT_DO( fd_cnx_getcred(peer->p_cnxctx, &peer->p_hdr.info.runtime.pir_cert_list, &peer->p_hdr.info.runtime.pir_cert_list_size),
+			{
+				/* Error ...  */
+				fd_hook_call(HOOK_PEER_CONNECT_FAILED, NULL, peer, "Unable to retrieve remote credentials after TLS handshake", NULL);
+				goto cleanup;
+			} );
+		
+		
+		/* Call second validation callback if needed */
+		if (peer->p_cb2) {
+			TRACE_DEBUG(FULL, "Calling second validation callback for %s", peer->p_hdr.info.pi_diamid);
+			CHECK_FCT_DO( (*peer->p_cb2)( &peer->p_hdr.info ),
+				{
+					fd_hook_call(HOOK_PEER_CONNECT_FAILED, NULL, peer, "Validation callback rejected the peer after handshake", NULL);
+					CHECK_FCT( fd_psm_terminate( peer, "DO_NOT_WANT_TO_TALK_TO_YOU" ) );
+					return 0;
+				}  );
+		}
+		tls_sync = 1;
+	} else {
+		if ( ! fd_cnx_getTLS(peer->p_cnxctx) ) {
+			TRACE_DEBUG(INFO, "No TLS protection negotiated with peer '%s'.", peer->p_hdr.info.pi_diamid);
+			CHECK_FCT( fd_cnx_start_clear(peer->p_cnxctx, 1) );
+		}
+	}
+		
+	/* Move to OPEN or REOPEN state */
+	if (peer->p_flags.pf_cnx_pb) {
+		fd_psm_change_state(peer, STATE_REOPEN );
+		CHECK_FCT( fd_p_dw_reopen(peer) );
+	} else {
+		if ((!tls_sync) && (fd_cnx_is_unordered_delivery_supported(peer->p_cnxctx))) {
+			fd_psm_change_state(peer, STATE_OPEN_NEW );
+			/* send DWR */
+			CHECK_FCT( fd_p_dw_timeout(peer) );
+		} else {
+
+			fd_psm_change_state(peer, STATE_OPEN );
+			fd_psm_next_timeout(peer, 1, peer->p_hdr.info.config.pic_twtimer ?: fd_g_config->cnf_timer_tw);
+		}
+	}
+	
+	return 0;
+
+error_abort:
+	if (pei.pei_errcode) {
+		/* Send the error */
+		fd_hook_call(HOOK_PEER_CONNECT_FAILED, msg, peer, pei.pei_message ?: pei.pei_errcode, NULL);
+		receiver_reject(&peer->p_cnxctx, &msg, &pei);
+	} else {
+		char buf[1024];
+		snprintf(buf, sizeof(buf), "Unexpected error occurred while processing incoming connection from '%s'.", peer->p_hdr.info.pi_diamid);
+		fd_hook_call(HOOK_PEER_CONNECT_FAILED, msg, peer, buf, NULL);
+	}
+	
+cleanup:
+	if (msg) {
+		fd_msg_free(msg);
+	}
+	fd_p_ce_clear_cnx(peer, NULL);
+
+	/* Send the error to the peer */
+	CHECK_FCT( fd_event_send(peer->p_events, fatal ? FDEVP_TERMINATE : FDEVP_CNX_ERROR, 0, NULL) );
+
+	return 0;
+}
+
+/* We have received a CER on a new connection for this peer */
+int fd_p_ce_handle_newCER(struct msg ** msg, struct fd_peer * peer, struct cnxctx ** cnx, int valid)
+{
+	struct fd_pei pei;
+	int cur_state = fd_peer_getstate(peer);
+	memset(&pei, 0, sizeof(pei));
+	
+	switch (cur_state) {
+		case STATE_CLOSED:
+			peer->p_receiver = *cnx;
+			*cnx = NULL;
+			peer->p_cer = *msg;
+			*msg = NULL;
+			CHECK_FCT( fd_p_ce_process_receiver(peer) );
+			break;
+
+		case STATE_WAITCNXACK:
+			/* Save the parameters in the peer, move to STATE_WAITCNXACK_ELEC */
+			peer->p_receiver = *cnx;
+			*cnx = NULL;
+			peer->p_cer = *msg;
+			*msg = NULL;
+			CHECK_FCT( fd_psm_change_state(peer, STATE_WAITCNXACK_ELEC) );
+			break;
+			
+		case STATE_WAITCEA:
+			if (election_result(peer)) {
+				
+				/* Close initiator connection (was already set as principal) */
+				LOG_D("%s: Election lost on outgoing connection, closing and answering CEA on incoming connection.", peer->p_hdr.info.pi_diamid);
+				fd_p_ce_clear_cnx(peer, NULL);
+				
+				/* and go on with the receiver side */
+				peer->p_receiver = *cnx;
+				*cnx = NULL;
+				peer->p_cer = *msg;
+				*msg = NULL;
+				CHECK_FCT( fd_p_ce_process_receiver(peer) );
+
+			} else {
+
+				/* Answer an ELECTION LOST to the receiver side and continue */
+				pei.pei_errcode = "ELECTION_LOST";
+				pei.pei_message = "Please answer my CER instead, you won the election.";
+				LOG_D("%s: Election lost on incoming connection, closing and waiting for CEA on outgoing connection.", peer->p_hdr.info.pi_diamid);
+				receiver_reject(cnx, msg, &pei);
+			}
+			break;
+
+		default:
+			pei.pei_errcode = "DIAMETER_UNABLE_TO_COMPLY"; /* INVALID COMMAND? in case of Capabilities-Updates? */
+			pei.pei_message = "Invalid state to receive a new connection attempt.";
+			LOG_E("%s: Rejecting new connection attempt while our state machine is in state '%s'", peer->p_hdr.info.pi_diamid, STATE_STR(cur_state));
+			receiver_reject(cnx, msg, &pei);
+	}
+				
+	return 0;
+}
diff --git a/libfdcore/p_cnx.c b/libfdcore/p_cnx.c
new file mode 100644
index 0000000..9dc2a03
--- /dev/null
+++ b/libfdcore/p_cnx.c
@@ -0,0 +1,357 @@
+/*********************************************************************************************************
+* Software License Agreement (BSD License)                                                               *
+* Author: Sebastien Decugis <sdecugis@freediameter.net>							 *
+*													 *
+* Copyright (c) 2013, WIDE Project and NICT								 *
+* All rights reserved.											 *
+* 													 *
+* Redistribution and use of this software in source and binary forms, with or without modification, are  *
+* permitted provided that the following conditions are met:						 *
+* 													 *
+* * Redistributions of source code must retain the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer.										 *
+*    													 *
+* * Redistributions in binary form must reproduce the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer in the documentation and/or other						 *
+*   materials provided with the distribution.								 *
+* 													 *
+* * Neither the name of the WIDE Project or NICT nor the 						 *
+*   names of its contributors may be used to endorse or 						 *
+*   promote products derived from this software without 						 *
+*   specific prior written permission of WIDE Project and 						 *
+*   NICT.												 *
+* 													 *
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED *
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
+* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR *
+* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 	 *
+* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 	 *
+* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR *
+* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF   *
+* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.								 *
+*********************************************************************************************************/
+
+#include "fdcore-internal.h"
+
+
+/* TODO: change the behavior to handle properly forced ordering at beginning & end of OPEN state */
+
+/* This file contains code used by a peer state machine to initiate a connection to remote peer */
+
+struct next_conn {
+	struct fd_list	chain;
+	int		proto;	/* Protocol of the next attempt */
+	union {
+		sSS	ss;	/* The address, only for TCP */
+		sSA4	sin;
+		sSA6	sin6;
+	};
+	uint16_t	port;	/* The port, for SCTP (included in ss for TCP) */
+	int		dotls;	/* Handshake TLS after connection ? */
+};
+
+static __inline__ void failed_connection_attempt(struct fd_peer * peer)
+{
+	/* Simply remove the first item in the list if not empty */
+	if (! FD_IS_LIST_EMPTY(&peer->p_connparams) ) {
+		struct fd_list * li = peer->p_connparams.next;
+		fd_list_unlink(li);
+		free(li);
+	}
+}
+
+static void empty_connection_list(struct fd_peer * peer)
+{
+	/* Remove all items */
+	while (!FD_IS_LIST_EMPTY(&peer->p_connparams)) {
+		failed_connection_attempt(peer);
+	}
+}
+
+static int prepare_connection_list(struct fd_peer * peer)
+{
+	struct fd_list * li, *last_prio;
+	struct next_conn   * new; 
+	
+	uint16_t	port_no; /* network order */
+	int		dotls_immediate;
+	int count = 0;
+	
+	TRACE_ENTRY("%p", peer);
+	 
+	/* Resolve peer address(es) if needed */
+	if (FD_IS_LIST_EMPTY(&peer->p_hdr.info.pi_endpoints)) {
+		struct addrinfo hints, *ai, *aip;
+		int ret;
+
+		memset(&hints, 0, sizeof(hints));
+		hints.ai_flags = AI_ADDRCONFIG;
+		ret = getaddrinfo(peer->p_hdr.info.pi_diamid, NULL, &hints, &ai);
+		if (ret) {
+			TRACE_DEBUG(INFO, "Unable to resolve address for peer '%s' (%s), aborting", peer->p_hdr.info.pi_diamid, gai_strerror(ret));
+			if (ret != EAI_AGAIN)
+				fd_psm_terminate( peer, NULL );
+			return 0;
+		}
+		
+		for (aip = ai; aip != NULL; aip = aip->ai_next) {
+			CHECK_FCT( fd_ep_add_merge( &peer->p_hdr.info.pi_endpoints, aip->ai_addr, aip->ai_addrlen, EP_FL_DISC ) );
+		}
+		freeaddrinfo(ai);
+	}
+	
+	/* Remove addresses from unwanted family */
+	if (peer->p_hdr.info.config.pic_flags.pro3) {
+		CHECK_FCT( fd_ep_filter_family(
+					&peer->p_hdr.info.pi_endpoints, 
+					(peer->p_hdr.info.config.pic_flags.pro3 == PI_P3_IP) ? 
+						AF_INET 
+						: AF_INET6));
+	}
+	if (fd_g_config->cnf_flags.no_ip4) {
+		CHECK_FCT( fd_ep_filter_family(
+					&peer->p_hdr.info.pi_endpoints, 
+					AF_INET6));
+	}
+	if (fd_g_config->cnf_flags.no_ip6) {
+		CHECK_FCT( fd_ep_filter_family(
+					&peer->p_hdr.info.pi_endpoints, 
+					AF_INET));
+	}
+	
+	/* We don't use the alternate addresses that were sent by the remote peer */
+	CHECK_FCT( fd_ep_clearflags(&peer->p_hdr.info.pi_endpoints, EP_FL_ADV) );
+	
+	
+	/* Now check we have at least one address to attempt */
+	if (FD_IS_LIST_EMPTY(&peer->p_hdr.info.pi_endpoints)) {
+		TRACE_DEBUG(INFO, "No address %savailable to connect to peer '%s', aborting", 
+					peer->p_hdr.info.config.pic_flags.pro3 ? "in the configured family " : "", peer->p_hdr.info.pi_diamid);
+		fd_psm_terminate( peer, NULL );
+		return 0;
+	}
+	
+	/* Check if we are able to communicate with this peer */
+	if (fd_g_config->cnf_sec_data.tls_disabled && ( peer->p_hdr.info.config.pic_flags.sec != PI_SEC_NONE)) {
+		LOG_E("Peer '%s' not configured for No_TLS and TLS is locally disabled; giving up connection attempts", 
+					peer->p_hdr.info.pi_diamid);
+		fd_psm_terminate( peer, NULL );
+		return 0;
+	}
+	
+	/* Cleanup any previous list */
+	empty_connection_list(peer);
+	
+	/* Prepare the parameters */
+	if ((peer->p_hdr.info.config.pic_flags.sec != PI_SEC_DEFAULT) || (fd_g_config->cnf_flags.tls_alg)) {
+		dotls_immediate = 0;
+		port_no = htons(peer->p_hdr.info.config.pic_port ?: DIAMETER_PORT);
+	} else {
+		dotls_immediate = 1;
+		port_no = htons(peer->p_hdr.info.config.pic_port ?: DIAMETER_SECURE_PORT);
+	}
+	
+	last_prio = &peer->p_connparams;
+	
+	/* Create TCP parameters unless specified otherwise */
+	if ((!fd_g_config->cnf_flags.no_tcp) && (peer->p_hdr.info.config.pic_flags.pro4 != PI_P4_SCTP)) {
+		for (li = peer->p_hdr.info.pi_endpoints.next; li != &peer->p_hdr.info.pi_endpoints; li = li->next) {
+			struct fd_endpoint * ep = (struct fd_endpoint *)li;
+			
+			CHECK_MALLOC( new = malloc(sizeof(struct next_conn)) );
+			memset(new, 0, sizeof(struct next_conn));
+			fd_list_init(&new->chain, new);
+			
+			new->proto = IPPROTO_TCP;
+			
+			memcpy( &new->ss, &ep->ss, sizeof(sSS) );
+			switch (new->ss.ss_family) {
+				case AF_INET:
+					new->sin.sin_port = port_no;
+					break;
+				case AF_INET6:
+					new->sin6.sin6_port = port_no;
+					break;
+				default:
+					free(new);
+					continue; /* Move to the next endpoint */
+			}
+			
+			new->dotls = dotls_immediate;
+			
+			/* Add the new entry to the appropriate position (conf and disc go first) */
+			if (ep->flags & (EP_FL_CONF | EP_FL_DISC)) {
+				fd_list_insert_after(last_prio, &new->chain);
+				last_prio = &new->chain;
+			} else {
+				fd_list_insert_before(&peer->p_connparams, &new->chain);
+			}
+			count++;
+		}
+	}
+	
+	/* Now, add the SCTP entry, if not disabled */
+#ifndef DISABLE_SCTP
+	if ((!fd_g_config->cnf_flags.no_sctp) && (peer->p_hdr.info.config.pic_flags.pro4 != PI_P4_TCP)) {
+		struct next_conn   * new;
+		
+		CHECK_MALLOC( new = malloc(sizeof(struct next_conn)) );
+		memset(new, 0, sizeof(struct next_conn));
+		fd_list_init(&new->chain, new);
+
+		new->proto = IPPROTO_SCTP;
+		new->port  = ntohs(port_no); /* back to host byte order... */
+		new->dotls = dotls_immediate;
+
+		/* Add the new entry to the appropriate position (depending on preferences) */
+		if ((fd_g_config->cnf_flags.pr_tcp) || (peer->p_hdr.info.config.pic_flags.alg == PI_ALGPREF_TCP)) {
+			fd_list_insert_after(last_prio, &new->chain);
+		} else {
+			fd_list_insert_after(&peer->p_connparams, &new->chain); /* very first position */
+		}
+		count++;
+	}
+#endif /* DISABLE_SCTP */
+	
+	LOG_D("Prepared %d sets of connection parameters to peer %s", count, peer->p_hdr.info.pi_diamid);
+	
+	return 0;
+}
+
+
+/* The thread that attempts the connection */
+static void * connect_thr(void * arg)
+{
+	struct fd_peer * peer = arg;
+	struct cnxctx * cnx = NULL;
+	struct next_conn * nc = NULL;
+	int rebuilt = 0;
+	int fatal_error=0;
+	
+	TRACE_ENTRY("%p", arg);
+	CHECK_PARAMS_DO( CHECK_PEER(peer), return NULL );
+
+	/* Set the thread name */
+	{
+		char buf[48];
+		snprintf(buf, sizeof(buf), "ConnTo:%s", peer->p_hdr.info.pi_diamid);
+		fd_log_threadname ( buf );
+	}
+	
+	do {
+		/* Rebuild the list if needed, if it is empty -- but at most once */
+		if (FD_IS_LIST_EMPTY(&peer->p_connparams)) {
+			if (! rebuilt) {
+				CHECK_FCT_DO( fatal_error = prepare_connection_list(peer), goto out );
+				rebuilt ++;
+			}
+			if (FD_IS_LIST_EMPTY(&peer->p_connparams)) {
+				/* We encountered an error or we have looped over all the addresses of the peer. */
+				fd_hook_call(HOOK_PEER_CONNECT_FAILED, NULL, peer, "All connection attempts failed, will retry later", NULL);
+				
+				CHECK_FCT_DO( fatal_error = fd_event_send(peer->p_events, FDEVP_CNX_FAILED, 0, NULL), goto out );
+				return NULL;
+			}
+		}
+		
+		/* Attempt connection to the first entry */
+		nc = (struct next_conn *)(peer->p_connparams.next);
+		
+		switch (nc->proto) {
+			case IPPROTO_TCP:
+				cnx = fd_cnx_cli_connect_tcp((sSA *)&nc->ss, sSAlen(&nc->ss));
+				break;
+#ifndef DISABLE_SCTP			
+			case IPPROTO_SCTP:
+				cnx = fd_cnx_cli_connect_sctp((peer->p_hdr.info.config.pic_flags.pro3 == PI_P3_IP) ? 1 : fd_g_config->cnf_flags.no_ip6, 
+							nc->port, &peer->p_hdr.info.pi_endpoints);
+				break;
+#endif /* DISABLE_SCTP */
+		}
+		
+		if (cnx)
+			break;
+		
+		/* Pop these parameters and continue */
+		failed_connection_attempt(peer);
+		
+		pthread_testcancel();
+		
+	} while (!cnx); /* and until cancellation or all addresses attempted without success */
+	
+	/* Now, we have an established connection in cnx */
+	
+	pthread_cleanup_push((void *)fd_cnx_destroy, cnx);
+	
+	/* Set the hostname in the connection, so that handshake verifies the remote identity */
+	fd_cnx_sethostname(cnx,peer->p_hdr.info.pi_diamid);
+	
+	/* Handshake if needed (secure port) */
+	if (nc->dotls) {
+		CHECK_FCT_DO( fd_cnx_handshake(cnx, GNUTLS_CLIENT, 
+						ALGO_HANDSHAKE_3436,
+						peer->p_hdr.info.config.pic_priority, NULL),
+			{
+				/* Handshake failed ...  */
+				fd_hook_call(HOOK_PEER_CONNECT_FAILED, NULL, peer, "TLS Handshake failed", NULL);
+				fd_cnx_destroy(cnx);
+				empty_connection_list(peer);
+				fd_ep_filter(&peer->p_hdr.info.pi_endpoints, EP_FL_CONF);
+				goto out_pop;
+			} );
+		LOG_A("%s: TLS handshake successful.", peer->p_hdr.info.pi_diamid);
+	} else {
+		/* Prepare to receive the next message */
+		CHECK_FCT_DO( fatal_error = fd_cnx_start_clear(cnx, 0), goto out_pop );
+	}
+	
+	/* Upon success, generate FDEVP_CNX_ESTABLISHED */
+	CHECK_FCT_DO( fatal_error = fd_event_send(peer->p_events, FDEVP_CNX_ESTABLISHED, 0, cnx),  );
+out_pop:
+	;	
+	pthread_cleanup_pop(0);
+	
+out:
+	
+	if (fatal_error) {
+	
+		/* Cleanup the connection */
+		if (cnx)
+			fd_cnx_destroy(cnx);
+
+		/* Generate a termination event */
+		CHECK_FCT_DO(fd_core_shutdown(), );
+	}
+	
+	return NULL;
+}
+
+
+/* Initiate a connection attempt to a remote peer */
+int fd_p_cnx_init(struct fd_peer * peer)
+{
+	TRACE_ENTRY("%p", peer);
+	
+	/* Start the connect thread */
+	CHECK_FCT( pthread_create(&peer->p_ini_thr, NULL, connect_thr, peer) );
+	return 0;
+}
+
+/* Cancel a connection attempt */
+void fd_p_cnx_abort(struct fd_peer * peer, int cleanup_all)
+{
+	TRACE_ENTRY("%p %d", peer, cleanup_all);
+	CHECK_PARAMS_DO( CHECK_PEER(peer), return );
+	
+	if (peer->p_ini_thr != (pthread_t)NULL) {
+		CHECK_FCT_DO( fd_thr_term(&peer->p_ini_thr), /* continue */);
+		failed_connection_attempt(peer);
+	}
+	
+	if (cleanup_all) {
+		empty_connection_list(peer);
+	}
+}
+
diff --git a/libfdcore/p_dp.c b/libfdcore/p_dp.c
new file mode 100644
index 0000000..2cd39d5
--- /dev/null
+++ b/libfdcore/p_dp.c
@@ -0,0 +1,207 @@
+/*********************************************************************************************************
+* Software License Agreement (BSD License)                                                               *
+* Author: Sebastien Decugis <sdecugis@freediameter.net>							 *
+*													 *
+* Copyright (c) 2013, WIDE Project and NICT								 *
+* All rights reserved.											 *
+* 													 *
+* Redistribution and use of this software in source and binary forms, with or without modification, are  *
+* permitted provided that the following conditions are met:						 *
+* 													 *
+* * Redistributions of source code must retain the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer.										 *
+*    													 *
+* * Redistributions in binary form must reproduce the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer in the documentation and/or other						 *
+*   materials provided with the distribution.								 *
+* 													 *
+* * Neither the name of the WIDE Project or NICT nor the 						 *
+*   names of its contributors may be used to endorse or 						 *
+*   promote products derived from this software without 						 *
+*   specific prior written permission of WIDE Project and 						 *
+*   NICT.												 *
+* 													 *
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED *
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
+* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR *
+* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 	 *
+* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 	 *
+* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR *
+* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF   *
+* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.								 *
+*********************************************************************************************************/
+
+#include "fdcore-internal.h"
+
+/* This file contains code to handle Disconnect Peer messages (DPR and DPA) */
+
+/* Delay to use before next reconnect attempt */
+int fd_p_dp_newdelay(struct fd_peer * peer) 
+{
+	int delay = peer->p_hdr.info.config.pic_tctimer ?: fd_g_config->cnf_timer_tc;
+	
+	switch (peer->p_hdr.info.runtime.pir_lastDC) {
+		case ACV_DC_REBOOTING:
+		default:
+			/* We use TcTimer to attempt reconnection */
+			break;
+		case ACV_DC_BUSY:
+			/* No need to hammer the overloaded peer */
+			delay *= 10;
+			break;
+		case ACV_DC_NOT_FRIEND:
+			/* He does not want to speak to us... let's retry a *lot* later maybe */
+			delay *= 200;
+			break;
+	}
+	return delay;
+}
+
+/* Handle a received message */
+int fd_p_dp_handle(struct msg ** msg, int req, struct fd_peer * peer)
+{
+	long to_receive, to_send;
+	TRACE_ENTRY("%p %d %p", msg, req, peer);
+	
+	if (req) {
+		/* We received a DPR, save the Disconnect-Cause and go to CLOSING_GRACE or terminate the connection */
+		struct avp * dc;
+		
+		CHECK_FCT( fd_msg_search_avp ( *msg, fd_dict_avp_DC, &dc ));
+		if (dc) {
+			struct avp_hdr * hdr;
+			CHECK_FCT(  fd_msg_avp_hdr( dc, &hdr )  );
+			if (hdr->avp_value == NULL) {
+				/* This is a sanity check */
+				LOG_F("BUG: Unset value in Disconnect-Cause in DPR");
+				ASSERT(0); /* To check if this really happens, and understand why... */
+			}
+
+			/* save the cause */
+			peer->p_hdr.info.runtime.pir_lastDC = hdr->avp_value->u32;
+		}
+		if (TRACE_BOOL(INFO)) {
+			if (dc) {
+				struct dict_object * dictobj;
+				struct dict_enumval_request er;
+				memset(&er, 0, sizeof(er));
+				
+				/* prepare the request */
+				CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_TYPE, TYPE_OF_AVP, fd_dict_avp_DC, &er.type_obj, ENOENT )  );
+				er.search.enum_value.u32 = peer->p_hdr.info.runtime.pir_lastDC;
+				
+				/* Search the enum value */
+				CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_ENUMVAL, ENUMVAL_BY_STRUCT, &er, &dictobj, 0 )  );
+				if (dictobj) {
+					CHECK_FCT( fd_dict_getval( dictobj, &er.search ) );
+					TRACE_DEBUG(INFO, "Peer '%s' sent a DPR with cause: %s", peer->p_hdr.info.pi_diamid, er.search.enum_name);
+				} else {
+					TRACE_DEBUG(INFO, "Peer '%s' sent a DPR with unknown cause: %u", peer->p_hdr.info.pi_diamid, peer->p_hdr.info.runtime.pir_lastDC);
+				}
+			} else {
+				TRACE_DEBUG(INFO, "Peer '%s' sent a DPR without Disconnect-Cause AVP", peer->p_hdr.info.pi_diamid);
+			}
+		}
+		
+		/* Now reply with a DPA */
+		CHECK_FCT( fd_msg_new_answer_from_req ( fd_g_config->cnf_dict, msg, 0 ) );
+		CHECK_FCT( fd_msg_rescode_set( *msg, "DIAMETER_SUCCESS", NULL, NULL, 1 ) );
+		
+		/* Do we have pending exchanges with this peer? */
+		CHECK_FCT( fd_peer_get_load_pending(&peer->p_hdr, &to_receive, &to_send) );
+		
+		if ((to_receive == 0) && (to_send == 0)) {
+			/* No pending exchange, move to CLOSING directly */
+			CHECK_FCT( fd_psm_change_state(peer, STATE_CLOSING) );
+		
+			/* Now send the DPA */
+			CHECK_FCT( fd_out_send( msg, NULL, peer, 0) );
+			
+			/* and move to CLOSED */
+			fd_psm_cleanup(peer, 0);
+
+			/* Reset the timer for next connection attempt -- we'll retry sooner or later depending on the disconnection cause */
+			fd_psm_next_timeout(peer, 1, fd_p_dp_newdelay(peer));
+		} else {
+			/* We have pending exchanges, we move to CLOSING_GRACE which allows exchanges of answers but
+			not new requests */
+			CHECK_FCT( fd_psm_change_state(peer, STATE_CLOSING_GRACE) );
+			fd_psm_next_timeout(peer, 0, GRACE_TIMEOUT);
+			
+			/* Now send the DPA */
+			CHECK_FCT( fd_out_send( msg, NULL, peer, 0) );
+		}
+	} else {
+		/* We received a DPA */
+		int curstate = fd_peer_getstate(peer);
+		if (curstate != STATE_CLOSING_GRACE) {
+			TRACE_DEBUG(INFO, "Ignoring DPA received in state %s", STATE_STR(curstate));
+		}
+			
+		/* In theory, we should control the Result-Code AVP. But since we will not go back to OPEN state here anyway, let's skip it */
+		
+		/* TODO("Control Result-Code in the DPA") */
+		CHECK_FCT_DO( fd_msg_free( *msg ), /* continue */ );
+		*msg = NULL;
+		
+		/* Do we still have pending exchanges with this peer? */
+		CHECK_FCT( fd_peer_get_load_pending(&peer->p_hdr, &to_receive, &to_send) );
+		if ((to_receive != 0) || (to_send != 0)) {
+			TRACE_DEBUG(INFO, "Received DPA but pending load: [%ld, %ld], giving grace delay before closing", to_receive, to_send);
+			fd_psm_next_timeout(peer, 0, GRACE_TIMEOUT);
+			peer->p_flags.pf_localterm = 1;
+		} else {
+			/* otherwise, go to CLOSING state, the psm will handle terminating the connection */
+			CHECK_FCT( fd_psm_change_state(peer, STATE_CLOSING) );
+		}
+	}
+	
+	return 0;
+}
+
+/* Start disconnection of a peer: send DPR */
+int fd_p_dp_initiate(struct fd_peer * peer, char * reason)
+{
+	struct msg * msg = NULL;
+	struct dict_object * dictobj = NULL;
+	struct avp * avp = NULL;
+	struct dict_enumval_request er;
+	union avp_value val;
+	
+	TRACE_ENTRY("%p %p", peer, reason);
+	
+	/* Create a new DWR instance */
+	CHECK_FCT( fd_msg_new ( fd_dict_cmd_DPR, MSGFL_ALLOC_ETEID, &msg ) );
+	
+	/* Add the Origin information */
+	CHECK_FCT( fd_msg_add_origin ( msg, 0 ) );
+	
+	/* Add the Disconnect-Cause */
+	CHECK_FCT( fd_msg_avp_new ( fd_dict_avp_DC, 0, &avp ) );
+	
+	/* Search the value in the dictionary */
+	memset(&er, 0, sizeof(er));
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_TYPE, TYPE_OF_AVP, fd_dict_avp_DC, &er.type_obj, ENOENT )  );
+	er.search.enum_name = reason ?: "REBOOTING";
+	CHECK_FCT_DO( fd_dict_search( fd_g_config->cnf_dict, DICT_ENUMVAL, ENUMVAL_BY_STRUCT, &er, &dictobj, ENOENT ), { ASSERT(0); /* internal error: unknown reason */ }  );
+	CHECK_FCT( fd_dict_getval( dictobj, &er.search ) );
+	
+	/* Set the value in the AVP */
+	val.u32 = er.search.enum_value.u32;
+	CHECK_FCT( fd_msg_avp_setvalue( avp, &val ) );
+	CHECK_FCT( fd_msg_avp_add( msg, MSG_BRW_LAST_CHILD, avp ) );
+	
+	/* Save the value also in the peer */
+	peer->p_hdr.info.runtime.pir_lastDC = val.u32;
+	
+	/* Update the peer state and timer */
+	CHECK_FCT( fd_psm_change_state(peer, STATE_CLOSING_GRACE) );
+	fd_psm_next_timeout(peer, 0, DPR_TIMEOUT);
+	
+	/* Now send the DPR message */
+	CHECK_FCT_DO( fd_out_send(&msg, NULL, peer, 0), /* ignore since we are on timeout anyway */ );
+	
+	return 0;
+}
diff --git a/libfdcore/p_dw.c b/libfdcore/p_dw.c
new file mode 100644
index 0000000..dc87f8d
--- /dev/null
+++ b/libfdcore/p_dw.c
@@ -0,0 +1,177 @@
+/*********************************************************************************************************
+* Software License Agreement (BSD License)                                                               *
+* Author: Sebastien Decugis <sdecugis@freediameter.net>							 *
+*													 *
+* Copyright (c) 2013, WIDE Project and NICT								 *
+* All rights reserved.											 *
+* 													 *
+* Redistribution and use of this software in source and binary forms, with or without modification, are  *
+* permitted provided that the following conditions are met:						 *
+* 													 *
+* * Redistributions of source code must retain the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer.										 *
+*    													 *
+* * Redistributions in binary form must reproduce the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer in the documentation and/or other						 *
+*   materials provided with the distribution.								 *
+* 													 *
+* * Neither the name of the WIDE Project or NICT nor the 						 *
+*   names of its contributors may be used to endorse or 						 *
+*   promote products derived from this software without 						 *
+*   specific prior written permission of WIDE Project and 						 *
+*   NICT.												 *
+* 													 *
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED *
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
+* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR *
+* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 	 *
+* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 	 *
+* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR *
+* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF   *
+* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.								 *
+*********************************************************************************************************/
+
+#include "fdcore-internal.h"
+
+/* This file contains code to handle Device Watchdog messages (DWR and DWA) */
+
+/* Check the value of Origin-State-Id is consistent in a DWR or DWA -- we return an error otherwise */
+static int check_state_id(struct msg * msg, struct fd_peer * peer)
+{
+	struct avp * osi;
+	
+	/* Check if the request contains the Origin-State-Id */
+	CHECK_FCT( fd_msg_search_avp ( msg, fd_dict_avp_OSI, &osi ) );
+	if (osi) {
+		/* Check the value is consistent with the saved one */
+		struct avp_hdr * hdr;
+		CHECK_FCT(  fd_msg_avp_hdr( osi, &hdr )  );
+		if (hdr->avp_value == NULL) {
+			/* This is a sanity check */
+			LOG_F("Ignored an Origin-State-Id AVP with unset value in DWR/DWA");
+			ASSERT(0); /* To check if this really happens, and understand why... */
+		}
+
+		if (! peer->p_hdr.info.runtime.pir_orstate) {
+			/* It was not already received in CER/CEA, save it now */
+			peer->p_hdr.info.runtime.pir_orstate = hdr->avp_value->u32;
+		}
+
+		if (peer->p_hdr.info.runtime.pir_orstate != hdr->avp_value->u32) {
+			TRACE_DEBUG(INFO, "Received a new Origin-State-Id from peer '%s'! (%x -> %x); resetting the connection.", 
+				peer->p_hdr.info.pi_diamid, 
+				peer->p_hdr.info.runtime.pir_orstate,
+				hdr->avp_value->u32 );
+			return EINVAL;
+		}
+	}
+	return 0;
+}
+
+/* Create and send a DWR */
+static int send_DWR(struct fd_peer * peer)
+{
+	struct msg * msg = NULL;
+	
+	/* Create a new DWR instance */
+	CHECK_FCT( fd_msg_new ( fd_dict_cmd_DWR, MSGFL_ALLOC_ETEID, &msg ) );
+	
+	/* Add the content of the message (only the origin) */
+	CHECK_FCT( fd_msg_add_origin ( msg, 1 ) );
+	
+	/* Now send this message */
+	CHECK_FCT( fd_out_send(&msg, NULL, peer, 0) );
+	
+	/* And mark the pending DW */
+	peer->p_flags.pf_dw_pending = 1;
+	
+	return 0;
+}
+
+/* Handle an incoming message */
+int fd_p_dw_handle(struct msg ** msg, int req, struct fd_peer * peer)
+{
+	int reset_tmr = 0;
+	
+	TRACE_ENTRY("%p %d %p", msg, req, peer);
+	
+	/* Check the value of OSI for information */
+	CHECK_FCT( check_state_id(*msg, peer) );
+	
+	if (req) {
+		/* If we receive a DWR, send back a DWA */
+		CHECK_FCT( fd_msg_new_answer_from_req ( fd_g_config->cnf_dict, msg, 0 ) );
+		CHECK_FCT( fd_msg_rescode_set( *msg, "DIAMETER_SUCCESS", NULL, NULL, 0 ) );
+		CHECK_FCT( fd_msg_add_origin ( *msg, 1 ) );
+		CHECK_FCT( fd_out_send( msg, peer->p_cnxctx, peer, 0) );
+		
+	} else {
+		/* Discard the DWA */
+		CHECK_FCT_DO( fd_msg_free(*msg), /* continue */ );
+		*msg = NULL;
+		
+		/* And clear the pending DW flag */
+		peer->p_flags.pf_dw_pending = 0;
+	}
+	
+	/* Now update timeout */
+	if (req) {
+		/* Update timeout only if we did not already send a DWR ourselves */
+		reset_tmr = !peer->p_flags.pf_dw_pending;
+	} else {
+		/* Reset the timer */
+		reset_tmr = 1;
+	}
+	if (reset_tmr) {
+		fd_psm_next_timeout(peer, 1, peer->p_hdr.info.config.pic_twtimer ?: fd_g_config->cnf_timer_tw);
+	}
+	
+	/* If we are in REOPEN state, increment the counter */
+	if (fd_peer_getstate(peer) == STATE_REOPEN) {
+		peer->p_flags.pf_reopen_cnt += 1;
+		
+		if (peer->p_flags.pf_reopen_cnt) {
+			/* Send a new DWR */
+			CHECK_FCT( send_DWR(peer) );
+		} else {
+			/* Move to OPEN state */
+			CHECK_FCT( fd_psm_change_state(peer, STATE_OPEN) );
+		}
+	}
+		
+	return 0;
+}
+
+/* Handle a timeout in the PSM (OPEN or REOPEN state only) */
+int fd_p_dw_timeout(struct fd_peer * peer)
+{
+	TRACE_ENTRY("%p", peer);
+
+	if (peer->p_flags.pf_dw_pending) {
+		/* We have sent a DWR and received no answer during TwTimer */
+		CHECK_FCT( fd_psm_change_state(peer, STATE_SUSPECT) );
+		fd_psm_next_timeout(peer, 0, 2 * (peer->p_hdr.info.config.pic_twtimer ?: fd_g_config->cnf_timer_tw) );
+	} else {
+		/* The timeout has expired, send a DWR */
+		CHECK_FCT( send_DWR(peer) );
+		fd_psm_next_timeout(peer, 0, peer->p_hdr.info.config.pic_twtimer ?: fd_g_config->cnf_timer_tw );
+	}
+	
+	return 0;
+}
+
+/* Handle DW exchanges after the peer has come alive again */
+int fd_p_dw_reopen(struct fd_peer * peer)
+{
+	TRACE_ENTRY("%p", peer);
+
+	peer->p_flags.pf_reopen_cnt = 1;
+	peer->p_flags.pf_cnx_pb = 0;
+	CHECK_FCT( send_DWR(peer) );
+	
+	return 0;
+}
+
+
diff --git a/libfdcore/p_expiry.c b/libfdcore/p_expiry.c
new file mode 100644
index 0000000..c51f9d8
--- /dev/null
+++ b/libfdcore/p_expiry.c
@@ -0,0 +1,205 @@
+/*********************************************************************************************************
+* Software License Agreement (BSD License)                                                               *
+* Author: Sebastien Decugis <sdecugis@freediameter.net>							 *
+*													 *
+* Copyright (c) 2013, WIDE Project and NICT								 *
+* All rights reserved.											 *
+* 													 *
+* Redistribution and use of this software in source and binary forms, with or without modification, are  *
+* permitted provided that the following conditions are met:						 *
+* 													 *
+* * Redistributions of source code must retain the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer.										 *
+*    													 *
+* * Redistributions in binary form must reproduce the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer in the documentation and/or other						 *
+*   materials provided with the distribution.								 *
+* 													 *
+* * Neither the name of the WIDE Project or NICT nor the 						 *
+*   names of its contributors may be used to endorse or 						 *
+*   promote products derived from this software without 						 *
+*   specific prior written permission of WIDE Project and 						 *
+*   NICT.												 *
+* 													 *
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED *
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
+* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR *
+* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 	 *
+* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 	 *
+* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR *
+* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF   *
+* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.								 *
+*********************************************************************************************************/
+
+#include "fdcore-internal.h"
+
+/* Delay for garbage collection of expired peers, in seconds */
+#define GC_TIME		120
+
+static pthread_t       exp_thr = (pthread_t)NULL;
+static pthread_t       gc_thr  = (pthread_t)NULL;
+static struct fd_list  exp_list = FD_LIST_INITIALIZER( exp_list );
+static pthread_cond_t  exp_cnd  = PTHREAD_COND_INITIALIZER;
+static pthread_mutex_t exp_mtx  = PTHREAD_MUTEX_INITIALIZER;
+
+static void * gc_th_fct(void * arg)
+{
+	fd_log_threadname ( "Peers/garb. col." );
+	TRACE_ENTRY( "%p", arg );
+	
+	do {
+		struct fd_list * li, purge = FD_LIST_INITIALIZER(purge);
+		
+		sleep(GC_TIME);	/* sleep is a cancellation point */
+		
+		/* Now check in the peers list if any peer can be deleted */
+		CHECK_FCT_DO( pthread_rwlock_wrlock(&fd_g_peers_rw), goto error );
+		
+		for (li = fd_g_peers.next; li != &fd_g_peers; li = li->next) {
+			struct fd_peer * peer = (struct fd_peer *)li->o;
+			
+			if (fd_peer_getstate(peer) != STATE_ZOMBIE)
+				continue;
+			
+			if (peer->p_hdr.info.config.pic_flags.persist == PI_PRST_ALWAYS)
+				continue; /* This peer was not supposed to terminate, keep it in the list for debug */
+			
+			/* Ok, the peer was expired, let's remove it */
+			li = li->prev; /* to avoid breaking the loop */
+			fd_list_unlink(&peer->p_hdr.chain);
+			fd_list_insert_before(&purge, &peer->p_hdr.chain);
+		}
+
+		CHECK_FCT_DO( pthread_rwlock_unlock(&fd_g_peers_rw), goto error );
+		
+		/* Now delete peers that are in the purge list */
+		while (!FD_IS_LIST_EMPTY(&purge)) {
+			struct fd_peer * peer = (struct fd_peer *)(purge.next->o);
+			fd_list_unlink(&peer->p_hdr.chain);
+			TRACE_DEBUG(INFO, "Garbage Collect: delete zombie peer '%s'", peer->p_hdr.info.pi_diamid);
+			CHECK_FCT_DO( fd_peer_free(&peer), /* Continue... what else to do ? */ );
+		}
+	} while (1);
+	
+error:
+	TRACE_DEBUG(INFO, "An error occurred in peers module! GC thread is terminating...");
+	ASSERT(0);
+	CHECK_FCT_DO(fd_core_shutdown(), );
+	return NULL;
+}
+
+
+static void * exp_th_fct(void * arg)
+{
+	fd_log_threadname ( "Peers/expire" );
+	TRACE_ENTRY( "%p", arg );
+	
+	CHECK_POSIX_DO( pthread_mutex_lock(&exp_mtx), { ASSERT(0); } );
+	pthread_cleanup_push( fd_cleanup_mutex, &exp_mtx );
+	
+	do {
+		struct timespec	now;
+		struct fd_peer * first;
+		
+		/* Check if there are expiring peers available */
+		if (FD_IS_LIST_EMPTY(&exp_list)) {
+			/* Just wait for a change or cancelation */
+			CHECK_POSIX_DO( pthread_cond_wait( &exp_cnd, &exp_mtx ), { ASSERT(0); } );
+			/* Restart the loop on wakeup */
+			continue;
+		}
+		
+		/* Get the pointer to the peer that expires first */
+		first = (struct fd_peer *)(exp_list.next->o);
+		ASSERT( CHECK_PEER(first) );
+		
+		/* Get the current time */
+		CHECK_SYS_DO(  clock_gettime(CLOCK_REALTIME, &now),  { ASSERT(0); }  );
+
+		/* If first peer is not expired, we just wait until it happens */
+		if ( TS_IS_INFERIOR( &now, &first->p_exp_timer ) ) {
+			
+			CHECK_POSIX_DO2(  pthread_cond_timedwait( &exp_cnd, &exp_mtx, &first->p_exp_timer ),  
+					ETIMEDOUT, /* ETIMEDOUT is a normal return value, continue */,
+					/* on other error, */ { ASSERT(0); } );
+	
+			/* on wakeup, loop */
+			continue;
+		}
+		
+		/* Now, the first peer in the list is expired; signal it */
+		fd_list_unlink( &first->p_expiry );
+		CHECK_FCT_DO( fd_event_send(first->p_events, FDEVP_TERMINATE, 0, "DO_NOT_WANT_TO_TALK_TO_YOU"), break );
+		
+	} while (1);
+	
+	pthread_cleanup_pop( 1 );
+
+	TRACE_DEBUG(INFO, "An error occurred in peers module! Expiry thread is terminating...");
+	CHECK_FCT_DO(fd_core_shutdown(), );
+	return NULL;
+}
+
+/* Initialize peers expiry mechanism */
+int fd_p_expi_init(void)
+{
+	TRACE_ENTRY();
+	CHECK_FCT( pthread_create( &exp_thr, NULL, exp_th_fct, NULL ) );
+	CHECK_FCT( pthread_create( &gc_thr,  NULL, gc_th_fct,  NULL ) );
+	return 0;
+}
+
+/* Finish peers expiry mechanism */
+int fd_p_expi_fini(void)
+{
+	CHECK_FCT_DO( fd_thr_term(&exp_thr), );
+	CHECK_POSIX( pthread_mutex_lock(&exp_mtx) );
+	while (!FD_IS_LIST_EMPTY(&exp_list)) {
+		struct fd_peer * peer = (struct fd_peer *)(exp_list.next->o);
+		fd_list_unlink(&peer->p_expiry );
+	}
+	CHECK_POSIX( pthread_mutex_unlock(&exp_mtx) );
+	
+	CHECK_FCT_DO( fd_thr_term(&gc_thr), );
+	return 0;
+}
+
+/* Add / requeue a peer in the expiry list */
+int fd_p_expi_update(struct fd_peer * peer )
+{
+	TRACE_ENTRY("%p", peer);
+	CHECK_PARAMS( CHECK_PEER(peer) );
+	
+	CHECK_POSIX( pthread_mutex_lock(&exp_mtx) );
+	
+	fd_list_unlink(&peer->p_expiry );
+	
+	/* if peer expires */
+	if (peer->p_hdr.info.config.pic_flags.exp) {
+		struct fd_list * li;
+		
+		/* update the p_exp_timer value */
+		CHECK_SYS_DO(  clock_gettime(CLOCK_REALTIME, &peer->p_exp_timer), { ASSERT(0); }  );
+		peer->p_exp_timer.tv_sec += peer->p_hdr.info.config.pic_lft;
+		
+		/* add to the expiry list in appropriate position (probably around the end) */
+		for (li = exp_list.prev; li != &exp_list; li = li->prev) {
+			struct fd_peer * p = (struct fd_peer *)(li->o);
+			if (TS_IS_INFERIOR( &p->p_exp_timer, &peer->p_exp_timer ) )
+				break;
+		}
+		
+		fd_list_insert_after(li, &peer->p_expiry);
+		
+		/* signal the expiry thread if we added in first position */
+		if (li == &exp_list) {
+			CHECK_POSIX( pthread_cond_signal(&exp_cnd) );
+		}
+	}
+	
+	CHECK_POSIX( pthread_mutex_unlock(&exp_mtx) );
+	return 0;
+}
+
diff --git a/libfdcore/p_out.c b/libfdcore/p_out.c
new file mode 100644
index 0000000..b410f11
--- /dev/null
+++ b/libfdcore/p_out.c
@@ -0,0 +1,237 @@
+/*********************************************************************************************************
+* Software License Agreement (BSD License)                                                               *
+* Author: Sebastien Decugis <sdecugis@freediameter.net>							 *
+*													 *
+* Copyright (c) 2015, WIDE Project and NICT								 *
+* All rights reserved.											 *
+* 													 *
+* Redistribution and use of this software in source and binary forms, with or without modification, are  *
+* permitted provided that the following conditions are met:						 *
+* 													 *
+* * Redistributions of source code must retain the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer.										 *
+*    													 *
+* * Redistributions in binary form must reproduce the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer in the documentation and/or other						 *
+*   materials provided with the distribution.								 *
+* 													 *
+* * Neither the name of the WIDE Project or NICT nor the 						 *
+*   names of its contributors may be used to endorse or 						 *
+*   promote products derived from this software without 						 *
+*   specific prior written permission of WIDE Project and 						 *
+*   NICT.												 *
+* 													 *
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED *
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
+* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR *
+* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 	 *
+* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 	 *
+* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR *
+* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF   *
+* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.								 *
+*********************************************************************************************************/
+
+#include "fdcore-internal.h"
+
+/* Alloc a new hbh for requests, bufferize the message and send on the connection, save in sentreq if provided */
+static int do_send(struct msg ** msg, struct cnxctx * cnx, uint32_t * hbh, struct fd_peer * peer)
+{
+	struct msg_hdr * hdr;
+	int msg_is_a_req;
+	uint8_t * buf;
+	size_t sz;
+	int ret;
+	uint32_t bkp_hbh = 0;
+	struct msg *cpy_for_logs_only;
+	
+	TRACE_ENTRY("%p %p %p %p", msg, cnx, hbh, peer);
+	
+	/* Retrieve the message header */
+	CHECK_FCT( fd_msg_hdr(*msg, &hdr) );
+	
+	msg_is_a_req = (hdr->msg_flags & CMD_FLAG_REQUEST);
+	if (msg_is_a_req) {
+		CHECK_PARAMS(hbh && peer);
+		/* Alloc the hop-by-hop id and increment the value for next message */
+		bkp_hbh = hdr->msg_hbhid;
+		hdr->msg_hbhid = *hbh;
+		*hbh = hdr->msg_hbhid + 1;
+	}
+	
+	/* Create the message buffer */
+	CHECK_FCT(fd_msg_bufferize( *msg, &buf, &sz ));
+	pthread_cleanup_push( free, buf );
+	
+	cpy_for_logs_only = *msg;
+	
+	/* Save a request before sending so that there is no race condition with the answer */
+	if (msg_is_a_req) {
+		CHECK_FCT_DO( ret = fd_p_sr_store(&peer->p_sr, msg, &hdr->msg_hbhid, bkp_hbh), goto out );
+	}
+	
+	/* Log the message */
+	fd_hook_call(HOOK_MESSAGE_SENT, cpy_for_logs_only, peer, NULL, fd_msg_pmdl_get(cpy_for_logs_only));
+	
+	pthread_cleanup_push((void *)fd_msg_free, *msg /* might be NULL, no problem */);
+	
+	/* Send the message */
+	CHECK_FCT_DO( ret = fd_cnx_send(cnx, buf, sz), );
+	
+	pthread_cleanup_pop(0);
+	
+out:
+	;	
+	pthread_cleanup_pop(1);
+	
+	if (ret)
+		return ret;
+	
+	/* Free remaining messages (i.e. answers) */
+	if (*msg) {
+		CHECK_FCT( fd_msg_free(*msg) );
+		*msg = NULL;
+	}
+	
+	return 0;
+}
+
+/* The code of the "out" thread */
+static void * out_thr(void * arg)
+{
+	struct fd_peer * peer = arg;
+	int stop = 0;
+	struct msg * msg;
+	ASSERT( CHECK_PEER(peer) );
+	
+	/* Set the thread name */
+	{
+		char buf[48];
+		snprintf(buf, sizeof(buf), "OUT/%s", peer->p_hdr.info.pi_diamid);
+		fd_log_threadname ( buf );
+	}
+	
+	/* Loop until cancelation */
+	while (!stop) {
+		int ret;
+		
+		/* Retrieve next message to send */
+		CHECK_FCT_DO( fd_fifo_get(peer->p_tosend, &msg), goto error );
+		
+		/* Send the message, log any error */
+		CHECK_FCT_DO( ret = do_send(&msg, peer->p_cnxctx, &peer->p_hbh, peer),
+			{
+				if (msg) {
+					char buf[256];
+					snprintf(buf, sizeof(buf), "Error while sending this message: %s", strerror(ret));
+					fd_hook_call(HOOK_MESSAGE_DROPPED, msg, NULL, buf, fd_msg_pmdl_get(msg));
+					fd_msg_free(msg);
+				}
+				stop = 1;
+			} );
+			
+	}
+	
+	/* If we're here it means there was an error on the socket. We need to continue to purge the fifo & until we are canceled */
+	CHECK_FCT_DO( fd_event_send(peer->p_events, FDEVP_CNX_ERROR, 0, NULL), /* What do we do if it fails? */ );
+	
+	/* Requeue all routable messages in the global "out" queue, until we are canceled once the PSM deals with the CNX_ERROR sent above */
+	while ( fd_fifo_get(peer->p_tosend, &msg) == 0 ) {
+		if (fd_msg_is_routable(msg)) {
+			CHECK_FCT_DO(fd_fifo_post_noblock(peer->p_tofailover, (void *)&msg), 
+				{
+					/* fallback: destroy the message */
+					fd_hook_call(HOOK_MESSAGE_DROPPED, msg, NULL, "Internal error: unable to requeue this message during failover process", fd_msg_pmdl_get(msg));
+					CHECK_FCT_DO(fd_msg_free(msg), /* What can we do more? */)
+				} );
+		} else {
+			/* Just free it */
+			/* fd_hook_call(HOOK_MESSAGE_DROPPED, m, NULL, "Non-routable message freed during handover", fd_msg_pmdl_get(m)); */
+			CHECK_FCT_DO(fd_msg_free(msg), /* What can we do more? */)
+		}
+	}
+
+error:
+	/* It is not really a connection error, but the effect is the same, we are not able to send anymore message */
+	CHECK_FCT_DO( fd_event_send(peer->p_events, FDEVP_CNX_ERROR, 0, NULL), /* What do we do if it fails? */ );
+	return NULL;
+}
+
+/* Wrapper to sending a message either by out thread (peer in OPEN state) or directly; cnx or peer must be provided. Flags are valid only for direct sending, not through thread (unused) */
+int fd_out_send(struct msg ** msg, struct cnxctx * cnx, struct fd_peer * peer, int update_reqin_cnt)
+{
+	struct msg_hdr * hdr;
+	
+	TRACE_ENTRY("%p %p %p", msg, cnx, peer);
+	CHECK_PARAMS( msg && *msg && (cnx || (peer && peer->p_cnxctx)));
+
+	fd_hook_call(HOOK_MESSAGE_SENDING, *msg, peer, NULL, fd_msg_pmdl_get(*msg));
+	
+	if (update_reqin_cnt && peer) {
+		CHECK_FCT( fd_msg_hdr(*msg, &hdr) );
+		if (!(hdr->msg_flags & CMD_FLAG_REQUEST)) {
+			/* Update the count of pending answers to send */
+			CHECK_POSIX( pthread_mutex_lock(&peer->p_state_mtx) );
+			peer->p_reqin_count--;
+			CHECK_POSIX( pthread_mutex_unlock(&peer->p_state_mtx) );			
+		}
+	}
+	
+	if (fd_peer_getstate(peer) == STATE_OPEN) {
+		/* Normal case: just queue for the out thread to pick it up */
+		CHECK_FCT( fd_fifo_post(peer->p_tosend, msg) );
+		
+	} else {
+		int ret;
+		uint32_t *hbh = NULL;
+		
+		/* In other cases, the thread is not running, so we handle the sending directly */
+		if (peer)
+			hbh = &peer->p_hbh;
+
+		if (!cnx)
+			cnx = peer->p_cnxctx;
+
+		/* Do send the message */
+		CHECK_FCT_DO( ret = do_send(msg, cnx, hbh, peer),
+			{
+				if (msg) {
+					char buf[256];
+					snprintf(buf, sizeof(buf), "Error while sending this message: %s", strerror(ret));
+					fd_hook_call(HOOK_MESSAGE_DROPPED, *msg, NULL, buf, fd_msg_pmdl_get(*msg));
+					fd_msg_free(*msg);
+					*msg = NULL;
+				}
+			} );
+	}
+	
+	return 0;
+}
+
+/* Start the "out" thread that picks messages in p_tosend and send them on p_cnxctx */
+int fd_out_start(struct fd_peer * peer)
+{
+	TRACE_ENTRY("%p", peer);
+	CHECK_PARAMS( CHECK_PEER(peer) && (peer->p_outthr == (pthread_t)NULL) );
+	
+	CHECK_POSIX( pthread_create(&peer->p_outthr, NULL, out_thr, peer) );
+	
+	CHECK_FCT( fd_cnx_unordered_delivery(peer->p_cnxctx, 1) );
+	
+	return 0;
+}
+
+/* Stop that thread */
+int fd_out_stop(struct fd_peer * peer)
+{
+	TRACE_ENTRY("%p", peer);
+	CHECK_PARAMS( CHECK_PEER(peer) );
+	
+	CHECK_FCT( fd_cnx_unordered_delivery(peer->p_cnxctx, 0) );
+	
+	CHECK_FCT( fd_thr_term(&peer->p_outthr) );
+	
+	return 0;
+}
+		
diff --git a/libfdcore/p_psm.c b/libfdcore/p_psm.c
new file mode 100644
index 0000000..2a30c5c
--- /dev/null
+++ b/libfdcore/p_psm.c
@@ -0,0 +1,952 @@
+/*********************************************************************************************************
+* Software License Agreement (BSD License)                                                               *
+* Author: Sebastien Decugis <sdecugis@freediameter.net>							 *
+*													 *
+* Copyright (c) 2013, WIDE Project and NICT								 *
+* All rights reserved.											 *
+* 													 *
+* Redistribution and use of this software in source and binary forms, with or without modification, are  *
+* permitted provided that the following conditions are met:						 *
+* 													 *
+* * Redistributions of source code must retain the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer.										 *
+*    													 *
+* * Redistributions in binary form must reproduce the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer in the documentation and/or other						 *
+*   materials provided with the distribution.								 *
+* 													 *
+* * Neither the name of the WIDE Project or NICT nor the 						 *
+*   names of its contributors may be used to endorse or 						 *
+*   promote products derived from this software without 						 *
+*   specific prior written permission of WIDE Project and 						 *
+*   NICT.												 *
+* 													 *
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED *
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
+* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR *
+* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 	 *
+* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 	 *
+* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR *
+* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF   *
+* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.								 *
+*********************************************************************************************************/
+
+#include "fdcore-internal.h"
+
+/*
+This file implement a Peer State Machine which is a mix of:
+ - the state machine described in rfc3588bis
+ - the state machine described in rfc3539#section-3.4
+ - the following observations.
+ 
+The delivery of Diameter messages must not always be unordered: order is important at
+begining and end of a connection lifetime. It means we need agility to
+switch between "ordering enforced" and "ordering not enforced to counter
+Head of the Line Blocking" modes of operation.
+
+The connection state machine represented in RFC3588 (and RFC6733) is
+incomplete, because it lacks the SUSPECT state and the 3 DWR/DWA
+exchanges (section 5.1) when the peer recovers from this state.
+Personnally I don't see the rationale for exchanging 3 messages (why 3?)
+but, if we require at least 1 DWR/DWA exchange to be always performed
+after the CER/CEA exchange (and initiated by the peer that sent the
+CEA), we have a simple way to deal with our ordering problem, as resumed
+below. Peers are: [i]nitiator, [r]esponder.
+ (1) [i] SCTP connection attempt.
+ (2) [r] accept the connection.
+ (3) [i,r] (if secure port) DTLS handshake, close on failure.
+ (4) [i] Send CER
+ (5) [r] Receive CER, send CEA using stream 0, flag "unordered" cleared.
+       [r] Immediately send a DWR after the CEA, also using stream 0,
+flag "unordered" cleared.
+       [r] Move to STATE_OPEN_NEW state -- equivalent to OPEN except
+that all messages are sent ordered at the moment.
+ (6) [i] receive CEA, move to OPEN state. All messages can be sent
+unordered in OPEN state.
+       [i] As per normal operation, reply with DWA to the DWR.
+ (7) [r] Upon reception of the DWA, move to OPEN state, messages can be
+sent unordered from this point.
+
+Note about (5) and (6): if the Diameter Identity received in CER or CEA
+does not match the credentials from the certificate presented during
+TLS handshake, we may need to specify a path of clean disconnection
+(not blocking the remote peer waiting for something).
+
+This proposed mechanism removes the problem of application messages
+received before the CEA by the initiator. Note that if the "old" inband
+TLS handshake is used, this handshake plays the same synchronization
+role than the new DWR/DWA, which becomes useless.
+
+
+The other time where ordering is important is by the end of connection
+lifetime, when one peer is shutting down the link for some reason
+(reboot, overload, no activity, etc...). In case of unordered delivery,
+we may have:
+- peer A sends an application message followed by a DPR. Peer B receives
+the DPR first and tears down the connection. Application message is lost.
+- Peer B sends an application message, then receives a DPR and answers a
+DPA. Peer A receives the DPA before the application message. The
+application message is lost.
+
+This situation is actually happening easily because DPR/DPA messages are
+very short, while application messages can be quite large. Therefore,
+they require much more time to deliver.
+
+I really cannot see a way to counter this effect by using the ordering
+of the messages, except by applying a timer (state STATE_CLOSING_GRACE).
+This timer can be also useful when we detect that some messages has not 
+yet received an answer on this link, to give time to the application to 
+complete the exchange ongoing.
+
+However, this problem must be balanced with the fact that the message
+that is lost will be in many cases sent again as the failover mechanism
+specifies.
+*/
+
+/* The actual declaration of peer_state_str */
+DECLARE_STATE_STR();
+
+/* Helper for next macro */
+#define case_str( _val )		\
+	case _val : return #_val
+
+DECLARE_PEV_STR();
+
+/************************************************************************/
+/*                      Delayed startup                                 */
+/************************************************************************/
+static int started = 0;
+static pthread_mutex_t  started_mtx = PTHREAD_MUTEX_INITIALIZER;
+static pthread_cond_t   started_cnd = PTHREAD_COND_INITIALIZER;
+
+/* Wait for start signal */
+static int fd_psm_waitstart()
+{
+	int ret = 0;
+	TRACE_ENTRY("");
+	CHECK_POSIX( pthread_mutex_lock(&started_mtx) );
+awake:	
+	if (!ret && !started) {
+		pthread_cleanup_push( fd_cleanup_mutex, &started_mtx );
+		CHECK_POSIX_DO( ret = pthread_cond_wait(&started_cnd, &started_mtx), );
+		pthread_cleanup_pop( 0 );
+		goto awake;
+	}
+	CHECK_POSIX( pthread_mutex_unlock(&started_mtx) );
+	return ret;
+}
+
+/* Allow the state machines to start */
+int fd_psm_start()
+{
+	TRACE_ENTRY("");
+	CHECK_POSIX( pthread_mutex_lock(&started_mtx) );
+	started = 1;
+	CHECK_POSIX( pthread_cond_broadcast(&started_cnd) );
+	CHECK_POSIX( pthread_mutex_unlock(&started_mtx) );
+	return 0;
+}
+
+
+/************************************************************************/
+/*                 Manage the list of active peers                      */
+/************************************************************************/
+
+/* Enter/leave OPEN state */
+static int enter_open_state(struct fd_peer * peer)
+{
+	struct fd_list * li;
+	CHECK_PARAMS( FD_IS_LIST_EMPTY(&peer->p_actives) );
+	
+	/* Callback registered by the credential validator (fd_peer_validate_register) */
+	if (peer->p_cb2) {
+		CHECK_FCT_DO( (*peer->p_cb2)(&peer->p_hdr.info),
+			{
+				TRACE_DEBUG(FULL, "Validation failed, terminating the connection");
+				fd_psm_terminate(peer, "DO_NOT_WANT_TO_TALK_TO_YOU" );
+			} );
+		peer->p_cb2 = NULL;
+		return 0;
+	}
+	
+	/* Insert in the active peers list */
+	CHECK_POSIX( pthread_rwlock_wrlock(&fd_g_activ_peers_rw) );
+	for (li = fd_g_activ_peers.next; li != &fd_g_activ_peers; li = li->next) {
+		struct fd_peer * next_p = (struct fd_peer *)li->o;
+		int cmp = fd_os_cmp(peer->p_hdr.info.pi_diamid, peer->p_hdr.info.pi_diamidlen, 
+					next_p->p_hdr.info.pi_diamid, next_p->p_hdr.info.pi_diamidlen);
+		if (cmp < 0)
+			break;
+	}
+	fd_list_insert_before(li, &peer->p_actives);
+	CHECK_POSIX( pthread_rwlock_unlock(&fd_g_activ_peers_rw) );
+	
+	/* Callback registered when the peer was added, by fd_peer_add */
+	if (peer->p_cb) {
+		TRACE_DEBUG(FULL, "Calling add callback for peer %s", peer->p_hdr.info.pi_diamid);
+		(*peer->p_cb)(&peer->p_hdr.info, peer->p_cb_data); /* TODO: do this in a separate detached thread? */
+		peer->p_cb = NULL;
+		peer->p_cb_data = NULL;
+	}
+	
+	/* Start the thread to handle outgoing messages */
+	CHECK_FCT( fd_out_start(peer) );
+	
+	/* Update the expiry timer now */
+	CHECK_FCT( fd_p_expi_update(peer) );
+	
+	return 0;
+}
+static int leave_open_state(struct fd_peer * peer, int skip_failover)
+{
+	/* Remove from active peers list */
+	CHECK_POSIX( pthread_rwlock_wrlock(&fd_g_activ_peers_rw) );
+	fd_list_unlink( &peer->p_actives );
+	CHECK_POSIX( pthread_rwlock_unlock(&fd_g_activ_peers_rw) );
+	
+	/* Stop the "out" thread */
+	CHECK_FCT( fd_out_stop(peer) );
+	
+	/* Failover the messages */
+	if (!skip_failover) {
+		fd_peer_failover_msg(peer);
+	}
+	
+	return 0;
+}
+
+
+/************************************************************************/
+/*                      Helpers for state changes                       */
+/************************************************************************/
+
+/* Cleanup pending events in the peer */
+void fd_psm_events_free(struct fd_peer * peer)
+{
+	struct fd_event * ev;
+	/* Purge all events, and free the associated data if any */
+	while (fd_fifo_tryget( peer->p_events, &ev ) == 0) {
+		switch (ev->code) {
+			case FDEVP_CNX_ESTABLISHED: {
+				fd_cnx_destroy(ev->data);
+			}
+			break;
+			
+			case FDEVP_TERMINATE:
+				/* Do not free the string since it is a constant */
+			break;
+			
+			case FDEVP_CNX_INCOMING: {
+				struct cnx_incoming * evd = ev->data;
+				fd_hook_call(HOOK_MESSAGE_DROPPED, evd->cer, NULL, "Message discarded while cleaning peer state machine queue.", fd_msg_pmdl_get(evd->cer));
+				CHECK_FCT_DO( fd_msg_free(evd->cer), /* continue */);
+				fd_cnx_destroy(evd->cnx);
+			}
+			default:
+				free(ev->data);
+		}
+		free(ev);
+	}
+}
+
+/* Read state */
+int fd_peer_get_state(struct peer_hdr *peer)
+{
+	int ret;
+	
+	struct fd_peer * p = (struct fd_peer *)peer;
+	
+	if (!CHECK_PEER(p))
+		return -1;
+	
+	CHECK_POSIX_DO( pthread_mutex_lock(&p->p_state_mtx), return -1 );
+	ret = p->p_state;
+	CHECK_POSIX_DO( pthread_mutex_unlock(&p->p_state_mtx), return -1 );
+	
+	return ret;
+}
+
+
+/* Change state */
+int fd_psm_change_state(struct fd_peer * peer, int new_state)
+{
+	int old;
+	
+	TRACE_ENTRY("%p %d(%s)", peer, new_state, STATE_STR(new_state));
+	CHECK_PARAMS( CHECK_PEER(peer) );
+	
+	old = fd_peer_getstate(peer);
+	if (old == new_state)
+		return 0;
+	
+	LOG(((old == STATE_OPEN) || (new_state == STATE_OPEN)) ? FD_LOG_NOTICE : FD_LOG_DEBUG, "'%s'\t-> '%s'\t'%s'",
+			STATE_STR(old),
+			STATE_STR(new_state),
+			peer->p_hdr.info.pi_diamid);
+	
+	
+	CHECK_POSIX( pthread_mutex_lock(&peer->p_state_mtx) );
+	peer->p_state = new_state;
+	CHECK_POSIX( pthread_mutex_unlock(&peer->p_state_mtx) );
+	
+	if (old == STATE_OPEN) {
+		CHECK_FCT( leave_open_state(peer, new_state == STATE_CLOSING_GRACE) );
+	}
+	if (old == STATE_CLOSING_GRACE) {
+		fd_peer_failover_msg(peer);
+	}
+
+	if (new_state == STATE_OPEN) {
+		CHECK_FCT( enter_open_state(peer) );
+	}
+	
+	if (new_state == STATE_CLOSED) {
+		/* Purge event list */
+		fd_psm_events_free(peer);
+		
+		/* Reset the counter of pending anwers to send */
+		peer->p_reqin_count = 0;
+		
+		/* If the peer is not persistant, we destroy it */
+		if (peer->p_hdr.info.config.pic_flags.persist == PI_PRST_NONE) {
+			CHECK_FCT( fd_event_send(peer->p_events, FDEVP_TERMINATE, 0, NULL) );
+		}
+	}
+	
+	return 0;
+}
+
+/* Set timeout timer of next event */
+void fd_psm_next_timeout(struct fd_peer * peer, int add_random, int delay)
+{
+	TRACE_DEBUG(FULL, "Peer timeout reset to %d seconds%s", delay, add_random ? " (+/- 2)" : "" );
+	
+	/* Initialize the timer */
+	CHECK_POSIX_DO(  clock_gettime( CLOCK_REALTIME,  &peer->p_psm_timer ), ASSERT(0) );
+	
+	if (add_random) {
+		if (delay > 2)
+			delay -= 2;
+		else
+			delay = 0;
+
+		/* Add a random value between 0 and 4sec */
+		peer->p_psm_timer.tv_sec += random() % 4;
+		peer->p_psm_timer.tv_nsec+= random() % 1000000000L;
+		if (peer->p_psm_timer.tv_nsec >= 1000000000L) {
+			peer->p_psm_timer.tv_nsec -= 1000000000L;
+			peer->p_psm_timer.tv_sec ++;
+		}
+	}
+	
+	peer->p_psm_timer.tv_sec += delay;
+	
+#ifdef SLOW_PSM
+	/* temporary for debug */
+	peer->p_psm_timer.tv_sec += 10;
+#endif
+}
+
+/* Cleanup the peer */
+void fd_psm_cleanup(struct fd_peer * peer, int terminate)
+{
+	/* Move to CLOSED state: failover messages, stop OUT thread, unlink peer from active list */
+	if (fd_peer_getstate(peer) != STATE_ZOMBIE) {
+		CHECK_FCT_DO( fd_psm_change_state(peer, STATE_CLOSED), /* continue */ );
+	}
+	
+	fd_p_cnx_abort(peer, terminate);
+	
+	fd_p_ce_clear_cnx(peer, NULL);
+	
+	if (peer->p_receiver) {
+		fd_cnx_destroy(peer->p_receiver);
+		peer->p_receiver = NULL;
+	}
+	
+	if (terminate) {
+		fd_psm_events_free(peer);
+		CHECK_FCT_DO( fd_fifo_del(&peer->p_events), /* continue */ );
+	}
+	
+}
+
+
+/************************************************************************/
+/*                      The PSM thread                                  */
+/************************************************************************/
+/* Cancelation cleanup : set ZOMBIE state in the peer */
+void cleanup_setstate(void * arg) 
+{
+	struct fd_peer * peer = (struct fd_peer *)arg;
+	CHECK_PARAMS_DO( CHECK_PEER(peer), return );
+	CHECK_POSIX_DO( pthread_mutex_lock(&peer->p_state_mtx), );
+	peer->p_state = STATE_ZOMBIE;
+	CHECK_POSIX_DO( pthread_mutex_unlock(&peer->p_state_mtx), );
+	return;
+}
+
+/* The state machine thread (controler) */
+static void * p_psm_th( void * arg )
+{
+	struct fd_peer * peer = (struct fd_peer *)arg;
+	int created_started = started ? 1 : 0;
+	int event;
+	size_t ev_sz;
+	void * ev_data;
+	int cur_state;
+	
+	CHECK_PARAMS_DO( CHECK_PEER(peer), ASSERT(0) );
+	
+	pthread_cleanup_push( cleanup_setstate, arg );
+	
+	/* Set the thread name */
+	{
+		char buf[48];
+		snprintf(buf, sizeof(buf), "PSM/%s", peer->p_hdr.info.pi_diamid);
+		fd_log_threadname ( buf );
+	}
+	
+	/* The state machine starts in CLOSED state */
+	CHECK_POSIX_DO( pthread_mutex_lock(&peer->p_state_mtx), goto psm_end );
+	peer->p_state = STATE_CLOSED;
+	CHECK_POSIX_DO( pthread_mutex_unlock(&peer->p_state_mtx), goto psm_end );
+
+	/* Wait that the PSM are authorized to start in the daemon */
+	CHECK_FCT_DO( fd_psm_waitstart(), goto psm_end );
+	
+	/* Initialize the timer */
+	if (peer->p_flags.pf_responder) {
+		fd_psm_next_timeout(peer, 0, INCNX_TIMEOUT);
+	} else {
+		fd_psm_next_timeout(peer, created_started, 0);
+	}
+	
+psm_loop:
+	/* Get next event */
+	TRACE_DEBUG(FULL, "'%s' in state '%s' waiting for next event.",
+			peer->p_hdr.info.pi_diamid, STATE_STR(fd_peer_getstate(peer)));
+	CHECK_FCT_DO( fd_event_timedget(peer->p_events, &peer->p_psm_timer, FDEVP_PSM_TIMEOUT, &event, &ev_sz, &ev_data), goto psm_end );
+	
+	cur_state = fd_peer_getstate(peer);
+	if (cur_state == -1)
+		goto psm_end;
+	
+	TRACE_DEBUG(FULL, "'%s'\t<-- '%s'\t(%p,%zd)\t'%s'",
+			STATE_STR(cur_state),
+			fd_pev_str(event), ev_data, ev_sz,
+			peer->p_hdr.info.pi_diamid);
+
+	/* Now, the action depends on the current state and the incoming event */
+
+	/* The following states are impossible */
+	ASSERT( cur_state != STATE_NEW );
+	ASSERT( cur_state != STATE_ZOMBIE );
+	ASSERT( cur_state != STATE_OPEN_HANDSHAKE ); /* because it should exist only between two loops */
+
+	/* Purge invalid events */
+	if (!CHECK_PEVENT(event)) {
+		TRACE_DEBUG(INFO, "Invalid event received in PSM '%s' : %d", peer->p_hdr.info.pi_diamid, event);
+		ASSERT(0); /* we should investigate this situation */
+		goto psm_loop;
+	}
+
+	/* Requests to terminate the peer object */
+	if (event == FDEVP_TERMINATE) {
+		switch (cur_state) {
+			case STATE_OPEN:
+			case STATE_OPEN_NEW:
+			case STATE_REOPEN:
+				/* We cannot just close the connection, we have to send a DPR first */
+				CHECK_FCT_DO( fd_p_dp_initiate(peer, ev_data), goto psm_end );
+				goto psm_loop;
+			
+			/*	
+			case STATE_CLOSING:
+			case STATE_CLOSING_GRACE:
+			case STATE_WAITCNXACK:
+			case STATE_WAITCNXACK_ELEC:
+			case STATE_WAITCEA:
+			case STATE_SUSPECT:
+			case STATE_CLOSED:
+			*/
+			default:
+				/* In these cases, we just cleanup the peer object (if needed) and terminate */
+				goto psm_end;
+		}
+	}
+	
+	/* A message was received */
+	if (event == FDEVP_CNX_MSG_RECV) {
+		struct msg * msg = NULL;
+		struct msg_hdr * hdr;
+		struct fd_cnx_rcvdata rcv_data;
+		struct fd_msg_pmdl * pmdl = NULL;
+		
+		rcv_data.buffer = ev_data;
+		rcv_data.length = ev_sz;
+		pmdl = fd_msg_pmdl_get_inbuf(rcv_data.buffer, rcv_data.length);
+		
+		/* Parse the received buffer */
+		CHECK_FCT_DO( fd_msg_parse_buffer( (void *)&ev_data, ev_sz, &msg), 
+			{
+				fd_hook_call(HOOK_MESSAGE_PARSING_ERROR, NULL, peer, &rcv_data, pmdl );
+				free(ev_data);
+				CHECK_FCT_DO( fd_event_send(peer->p_events, FDEVP_CNX_ERROR, 0, NULL), goto psm_reset );
+				goto psm_loop;
+			} );
+			
+		fd_hook_associate(msg, pmdl);
+		CHECK_FCT_DO( fd_msg_source_set( msg, peer->p_hdr.info.pi_diamid, peer->p_hdr.info.pi_diamidlen), goto psm_end);
+	
+		/* If the current state does not allow receiving messages, just drop it */
+		if (cur_state == STATE_CLOSED) {
+			/* In such case, just discard the message */
+			fd_hook_call(HOOK_MESSAGE_DROPPED, msg, peer, "Message purged from queue, peer in CLOSED state", fd_msg_pmdl_get(msg));
+			fd_msg_free(msg);
+			goto psm_loop;
+		}
+		
+		/* Extract the header */
+		CHECK_FCT_DO( fd_msg_hdr(msg, &hdr), goto psm_end );
+		
+		/* If it is an answer, associate with the request or drop */
+		if (!(hdr->msg_flags & CMD_FLAG_REQUEST)) {
+			struct msg * req;
+			/* Search matching request (same hbhid) */
+			CHECK_FCT_DO( fd_p_sr_fetch(&peer->p_sr, hdr->msg_hbhid, &req), goto psm_end );
+			if (req == NULL) {
+				fd_hook_call(HOOK_MESSAGE_DROPPED, msg, peer, "Answer received with no corresponding sent request.", fd_msg_pmdl_get(msg));
+				fd_msg_free(msg);
+				goto psm_loop;
+			}
+			
+			/* Associate */
+			CHECK_FCT_DO( fd_msg_answ_associate( msg, req ), goto psm_end );
+			
+		}
+		
+		/* Log incoming message */
+		fd_hook_call(HOOK_MESSAGE_RECEIVED, msg, peer, NULL, fd_msg_pmdl_get(msg));
+		
+		if (cur_state == STATE_OPEN_NEW) {
+			/* OK, we have received something, so the connection is supposedly now in OPEN state at the remote site */
+			fd_psm_change_state(peer, STATE_OPEN );
+		}
+		
+		/* Now handle non-link-local messages */
+		if (fd_msg_is_routable(msg)) {
+			switch (cur_state) {
+				/* To maximize compatibility -- should not be a security issue here */
+				case STATE_REOPEN:
+				case STATE_SUSPECT:
+				case STATE_CLOSING:
+				case STATE_CLOSING_GRACE:
+					TRACE_DEBUG(FULL, "Accepted a message while not in OPEN state... ");
+				/* The standard situation : */
+				case STATE_OPEN_NEW:
+				case STATE_OPEN:
+					/* We received a valid routable message, update the expiry timer */
+					CHECK_FCT_DO( fd_p_expi_update(peer), goto psm_end );
+
+					/* Set the message source and add the Route-Record */
+					CHECK_FCT_DO( fd_msg_source_setrr( msg, peer->p_hdr.info.pi_diamid, peer->p_hdr.info.pi_diamidlen, fd_g_config->cnf_dict ), goto psm_end);
+
+					if ((hdr->msg_flags & CMD_FLAG_REQUEST)) {
+						/* Mark the incoming request so that we know we have pending answers for this peer */
+						CHECK_POSIX_DO( pthread_mutex_lock(&peer->p_state_mtx), goto psm_end  );
+						peer->p_reqin_count++;
+						CHECK_POSIX_DO( pthread_mutex_unlock(&peer->p_state_mtx), goto psm_end  );
+					}
+						
+					/* Requeue to the global incoming queue */
+					CHECK_FCT_DO(fd_fifo_post(fd_g_incoming, &msg), goto psm_end );
+
+					/* Update the peer timer (only in OPEN state) */
+					if ((cur_state == STATE_OPEN) && (!peer->p_flags.pf_dw_pending)) {
+						fd_psm_next_timeout(peer, 1, peer->p_hdr.info.config.pic_twtimer ?: fd_g_config->cnf_timer_tw);
+					}
+					break;
+					
+				/* In other states, we discard the message, it is either old or invalid to send it for the remote peer */
+				case STATE_WAITCNXACK:
+				case STATE_WAITCNXACK_ELEC:
+				case STATE_WAITCEA:
+				case STATE_CLOSED:
+				default: {
+					/* In such case, just discard the message */
+					char buf[128];
+					snprintf(buf, sizeof(buf), "Received while peer state machine was in state %s.", STATE_STR(cur_state));
+					fd_hook_call(HOOK_MESSAGE_DROPPED, msg, peer, buf, fd_msg_pmdl_get(msg));
+					fd_msg_free(msg);
+				}
+			}
+			goto psm_loop;
+		}
+		
+		/* Link-local message: They must be understood by our dictionary, otherwise we return an error */
+		{
+			struct msg * error = NULL;
+			int ret = fd_msg_parse_or_error( &msg, &error );
+			if (ret != EBADMSG) {
+				CHECK_FCT_DO( ret, 
+					{
+						char buf[256];
+						snprintf(buf, sizeof(buf), "%s: An unexpected error occurred while parsing a link-local message", peer->p_hdr.info.pi_diamid); 
+						fd_hook_call(HOOK_MESSAGE_DROPPED, msg, peer, buf, fd_msg_pmdl_get(msg));
+						fd_msg_free(msg); 
+						goto psm_end; 
+					} );
+			} else {
+				if (msg == NULL) {
+					/* Send the error back to the peer */
+					CHECK_FCT_DO( ret = fd_out_send(&error, NULL, peer, 0),  );
+					if (error) {
+						char buf[256];
+						/* Only if an error occurred & the message was not saved / dumped */
+						snprintf(buf, sizeof(buf), "%s: error sending a message", peer->p_hdr.info.pi_diamid); 
+						fd_hook_call(HOOK_MESSAGE_DROPPED, error, peer, buf, fd_msg_pmdl_get(error));
+						CHECK_FCT_DO( fd_msg_free(error), goto psm_end);
+					}
+				} else {
+					char buf[256];
+					/* We received an invalid answer, let's disconnect */
+					snprintf(buf, sizeof(buf), "%s: Received invalid answer to Base protocol message, disconnecting...", peer->p_hdr.info.pi_diamid);
+					fd_hook_call(HOOK_MESSAGE_DROPPED, msg, peer, buf, fd_msg_pmdl_get(msg));
+					CHECK_FCT_DO( fd_msg_free(msg), goto psm_end);
+					CHECK_FCT_DO( fd_event_send(peer->p_events, FDEVP_CNX_ERROR, 0, NULL), goto psm_reset );
+				}
+				goto psm_loop;
+			}
+		}
+		
+		/* Handle the LL message and update the expiry timer appropriately */
+		switch (hdr->msg_code) {
+			case CC_CAPABILITIES_EXCHANGE:
+				CHECK_FCT_DO( fd_p_ce_msgrcv(&msg, (hdr->msg_flags & CMD_FLAG_REQUEST), peer), 
+					{
+						if (msg)
+							CHECK_FCT_DO( fd_msg_free(msg), );
+						goto psm_reset;
+					} );
+				break;
+			
+			case CC_DISCONNECT_PEER:
+				CHECK_FCT_DO( fd_p_dp_handle(&msg, (hdr->msg_flags & CMD_FLAG_REQUEST), peer), goto psm_reset );
+				if (fd_peer_getstate(peer) == STATE_CLOSING)
+					goto psm_end;
+
+				break;
+			
+			case CC_DEVICE_WATCHDOG:
+				CHECK_FCT_DO( fd_p_dw_handle(&msg, (hdr->msg_flags & CMD_FLAG_REQUEST), peer), goto psm_reset );
+				break;
+			
+			default:
+				/* Unknown / unexpected / invalid message -- but validated by our dictionary */
+				TRACE_DEBUG(INFO, "Invalid non-routable command received: %u.", hdr->msg_code);
+				if (hdr->msg_flags & CMD_FLAG_REQUEST) {
+					do {
+						/* Reply with an error code */
+						CHECK_FCT_DO( fd_msg_new_answer_from_req ( fd_g_config->cnf_dict, &msg, MSGFL_ANSW_ERROR ), break );
+
+						/* Set the error code */
+						CHECK_FCT_DO( fd_msg_rescode_set(msg, "DIAMETER_COMMAND_UNSUPPORTED", "Or maybe the P-bit or application Id are erroneous.", NULL, 1 ), break );
+
+						/* Send the answer */
+						CHECK_FCT_DO( fd_out_send(&msg, peer->p_cnxctx, peer, 0), break );
+					} while (0);
+				} else {
+					/* We did ASK for it ??? */
+					TRACE_DEBUG(INFO, "Received answer with erroneous 'is_routable' result...");
+				}
+				
+				/* Cleanup the message if not done */
+				if (msg) {
+					char buf[256];
+					snprintf(buf, sizeof(buf), "Received un-handled non-routable command from peer '%s'.", peer->p_hdr.info.pi_diamid);
+					fd_hook_call(HOOK_MESSAGE_DROPPED, msg, NULL, buf, fd_msg_pmdl_get(msg));
+					CHECK_FCT_DO( fd_msg_free(msg), /* continue */);
+					msg = NULL;
+				}
+		};
+		
+		/* At this point the message must have been fully handled already */
+		if (msg) {
+			char buf[256];
+			snprintf(buf, sizeof(buf), "Internal error ('%s'): unhandled message.", peer->p_hdr.info.pi_diamid);
+			fd_hook_call(HOOK_MESSAGE_DROPPED, msg, NULL, buf, fd_msg_pmdl_get(msg));
+			fd_msg_free(msg);
+		}
+		
+		goto psm_loop;
+	}
+	
+	/* The connection object is broken */
+	if (event == FDEVP_CNX_ERROR) {
+		switch (cur_state) {
+			case STATE_WAITCNXACK_ELEC:
+				/* Abort the initiating side */
+				fd_p_cnx_abort(peer, 0);
+				/* Process the receiver side */
+				CHECK_FCT_DO( fd_p_ce_process_receiver(peer), goto psm_end );
+				break;
+			
+			case STATE_WAITCEA:
+			case STATE_OPEN:
+			case STATE_OPEN_NEW:
+			case STATE_REOPEN:
+			case STATE_WAITCNXACK:
+			case STATE_SUSPECT:
+			default:
+				/* Mark the connection problem */
+				peer->p_flags.pf_cnx_pb = 1;
+			
+				fd_hook_call(HOOK_PEER_CONNECT_FAILED, NULL, peer, "The connection was broken", NULL);
+				
+				/* Destroy the connection, restart the timer to a new connection attempt */
+				fd_psm_next_timeout(peer, 1, peer->p_hdr.info.config.pic_tctimer ?: fd_g_config->cnf_timer_tc);
+				
+			case STATE_CLOSED:
+				goto psm_reset;
+				
+			case STATE_CLOSING:
+				/* We sent a DPR so we are terminating, do not wait for DPA */
+				goto psm_end;
+				
+			case STATE_CLOSING_GRACE:
+				if (peer->p_flags.pf_localterm) /* initiated here */
+					goto psm_end;
+				
+				fd_psm_cleanup(peer, 0);
+				
+				/* Reset the timer for next connection attempt */
+				fd_psm_next_timeout(peer, 1, fd_p_dp_newdelay(peer));
+				goto psm_loop;
+		}
+		goto psm_loop;
+	}
+	
+	/* The connection notified a change in endpoints */
+	if (event == FDEVP_CNX_EP_CHANGE) {
+		/* We actually don't care if we are in OPEN state here... */
+		
+		/* Cleanup the remote LL and primary addresses */
+		CHECK_FCT_DO( fd_ep_filter( &peer->p_hdr.info.pi_endpoints, EP_FL_CONF | EP_FL_DISC | EP_FL_ADV ), /* ignore the error */);
+		CHECK_FCT_DO( fd_ep_clearflags( &peer->p_hdr.info.pi_endpoints, EP_FL_PRIMARY ), /* ignore the error */);
+		
+		/* Get the new ones */
+		CHECK_FCT_DO( fd_cnx_getremoteeps(peer->p_cnxctx, &peer->p_hdr.info.pi_endpoints), /* ignore the error */);
+		
+		/* We do not support local endpoints change currently, but it could be added here if needed (refresh fd_g_config->cnf_endpoints) */
+		{
+			char * buf = NULL;
+			size_t len = 0;
+			LOG_D("Got low layer notification (IGNORED): remote endpoint(s) changed: %s",  fd_ep_dump(&buf, &len, NULL, 0, 0, &peer->p_hdr.info.pi_endpoints) ?: "error");
+			free(buf);
+		}
+		
+		/* Done */
+		goto psm_loop;
+	}
+	
+	/* A new connection was established and CER containing this peer id was received */
+	if (event == FDEVP_CNX_INCOMING) {
+		struct cnx_incoming * params = ev_data;
+		ASSERT(params);
+		
+		/* Handle the message */
+		CHECK_FCT_DO( fd_p_ce_handle_newCER(&params->cer, peer, &params->cnx, params->validate), goto psm_end );
+		
+		/* Cleanup if needed */
+		if (params->cnx) {
+			fd_cnx_destroy(params->cnx);
+			params->cnx = NULL;
+		}
+		if (params->cer) {
+			CHECK_FCT_DO( fd_msg_free(params->cer), );
+			params->cer = NULL;
+		}
+		
+		/* Loop */
+		free(ev_data);
+		goto psm_loop;
+	}
+	
+	/* A new connection has been established with the remote peer */
+	if (event == FDEVP_CNX_ESTABLISHED) {
+		struct cnxctx * cnx = ev_data;
+		
+		/* Release the resources of the connecting thread */
+		CHECK_POSIX_DO( pthread_join( peer->p_ini_thr, NULL), /* ignore, it is not a big deal */);
+		peer->p_ini_thr = (pthread_t)NULL;
+		
+		switch (cur_state) {
+			case STATE_WAITCNXACK_ELEC:
+			case STATE_WAITCNXACK:
+				LOG_D("%s: Connection established, %s", peer->p_hdr.info.pi_diamid, fd_cnx_getid(cnx));
+				fd_p_ce_handle_newcnx(peer, cnx);
+				break;
+				
+			default:
+				/* Just abort the attempt and continue */
+				TRACE_DEBUG(FULL, "Connection attempt successful but current state is %s, closing... (too slow?)", STATE_STR(cur_state));
+				fd_cnx_destroy(cnx);
+		}
+		
+		goto psm_loop;
+	}
+	
+	/* A new connection has not been established with the remote peer */
+	if (event == FDEVP_CNX_FAILED) {
+		
+		/* Release the resources of the connecting thread */
+		CHECK_POSIX_DO( pthread_join( peer->p_ini_thr, NULL), /* ignore, it is not a big deal */);
+		peer->p_ini_thr = (pthread_t)NULL;
+		
+		switch (cur_state) {
+			case STATE_WAITCNXACK_ELEC:
+				/* Abort the initiating side */
+				fd_p_cnx_abort(peer, 0);
+				/* Process the receiver side */
+				CHECK_FCT_DO( fd_p_ce_process_receiver(peer), goto psm_end );
+				break;
+				
+			case STATE_WAITCNXACK:
+				/* Go back to CLOSE */
+				fd_psm_next_timeout(peer, 1, peer->p_hdr.info.config.pic_tctimer ?: fd_g_config->cnf_timer_tc);
+				goto psm_reset;
+				
+			default:
+				/* Just ignore */
+				TRACE_DEBUG(FULL, "Connection attempt failed but current state is %s, ignoring...", STATE_STR(cur_state));
+		}
+		
+		goto psm_loop;
+	}
+	
+	/* The timeout for the current state has been reached */
+	if (event == FDEVP_PSM_TIMEOUT) {
+		switch (cur_state) {
+			case STATE_OPEN:
+			case STATE_REOPEN:
+			case STATE_OPEN_NEW:
+				CHECK_FCT_DO( fd_p_dw_timeout(peer), goto psm_end );
+				goto psm_loop;
+				
+			case STATE_CLOSED:
+				LOG_D("%s: Connecting...", peer->p_hdr.info.pi_diamid);
+				CHECK_FCT_DO( fd_psm_change_state(peer, STATE_WAITCNXACK), goto psm_end );
+				fd_psm_next_timeout(peer, 0, CNX_TIMEOUT);
+				CHECK_FCT_DO( fd_p_cnx_init(peer), goto psm_end );
+				goto psm_loop;
+				
+			case STATE_SUSPECT:
+				/* Mark the connection problem */
+				peer->p_flags.pf_cnx_pb = 1;
+			case STATE_WAITCNXACK:
+			case STATE_WAITCEA:
+				fd_hook_call(HOOK_PEER_CONNECT_FAILED, NULL, peer, "Timeout while waiting for remote peer", NULL);
+			case STATE_CLOSING:
+				/* Destroy the connection, restart the timer to a new connection attempt */
+				fd_psm_next_timeout(peer, 1, peer->p_hdr.info.config.pic_tctimer ?: fd_g_config->cnf_timer_tc);
+				goto psm_reset;
+				
+			case STATE_CLOSING_GRACE:
+				/* The grace period is completed, now close */
+				if (peer->p_flags.pf_localterm)
+					goto psm_end;
+				
+				fd_psm_cleanup(peer, 0);
+				/* Reset the timer for next connection attempt */
+				fd_psm_next_timeout(peer, 1, fd_p_dp_newdelay(peer));
+				goto psm_loop;
+				
+			case STATE_WAITCNXACK_ELEC:
+				/* Abort the initiating side */
+				fd_p_cnx_abort(peer, 0);
+				/* Process the receiver side */
+				CHECK_FCT_DO( fd_p_ce_process_receiver(peer), goto psm_end );
+				goto psm_loop;
+			
+			default:
+				ASSERT(0); /* implementation problem, we did not foresee this case? */
+		}
+	}
+	
+	/* Default action : the handling has not yet been implemented. [for debug only] */
+	TRACE_DEBUG(INFO, "Missing handler in PSM for '%s'\t<-- '%s'", STATE_STR(cur_state), fd_pev_str(event));
+psm_reset:
+	if (peer->p_flags.pf_delete)
+		goto psm_end;
+	fd_psm_cleanup(peer, 0);
+	goto psm_loop;
+	
+psm_end:
+	LOG_E("%s: Going to ZOMBIE state (no more activity)", peer->p_hdr.info.pi_diamid);
+	fd_psm_cleanup(peer, 1);
+	TRACE_DEBUG(INFO, "'%s'\t-> 'STATE_ZOMBIE' (terminated)\t'%s'",
+			STATE_STR(fd_peer_getstate(peer)),
+			peer->p_hdr.info.pi_diamid);
+	pthread_cleanup_pop(1); /* set STATE_ZOMBIE */
+	peer->p_psm = (pthread_t)NULL;
+	pthread_detach(pthread_self());
+	return NULL;
+}
+
+
+/************************************************************************/
+/*                      Functions to control the PSM                    */
+/************************************************************************/
+/* Create the PSM thread of one peer structure */
+int fd_psm_begin(struct fd_peer * peer )
+{
+	TRACE_ENTRY("%p", peer);
+	
+	/* Check the peer and state are OK */
+	CHECK_PARAMS( fd_peer_getstate(peer) == STATE_NEW );
+	
+	/* Create the FIFO for events */
+	CHECK_FCT( fd_fifo_new(&peer->p_events, 0) );
+	
+	/* Create the PSM controler thread */
+	CHECK_POSIX( pthread_create( &peer->p_psm, NULL, p_psm_th, peer ) );
+	
+	/* We're done */
+	return 0;
+}
+
+/* End the PSM (clean ending) */
+int fd_psm_terminate(struct fd_peer * peer, char * reason )
+{
+	TRACE_ENTRY("%p", peer);
+	CHECK_PARAMS( CHECK_PEER(peer) );
+	
+	if (fd_peer_getstate(peer) != STATE_ZOMBIE) {
+		CHECK_FCT( fd_event_send(peer->p_events, FDEVP_TERMINATE, 0, reason) );
+	} else {
+		TRACE_DEBUG(FULL, "Peer '%s' was already terminated", peer->p_hdr.info.pi_diamid);
+	}
+	return 0;
+}
+
+/* End the PSM & cleanup the peer structure */
+void fd_psm_abord(struct fd_peer * peer )
+{
+	TRACE_ENTRY("%p", peer);
+	
+	/* Cancel PSM thread */
+	CHECK_FCT_DO( fd_thr_term(&peer->p_psm), /* continue */ );
+	
+	/* Cleanup the data */
+	fd_psm_cleanup(peer, 1);
+	
+	/* Destroy the event list */
+	CHECK_FCT_DO( fd_fifo_del(&peer->p_events), /* continue */ );
+	
+	/* Remaining cleanups are performed in fd_peer_free */
+	return;
+}
+
diff --git a/libfdcore/p_sr.c b/libfdcore/p_sr.c
new file mode 100644
index 0000000..36b5a55
--- /dev/null
+++ b/libfdcore/p_sr.c
@@ -0,0 +1,350 @@
+/*********************************************************************************************************
+* Software License Agreement (BSD License)                                                               *
+* Author: Sebastien Decugis <sdecugis@freediameter.net>							 *
+*													 *
+* Copyright (c) 2013, WIDE Project and NICT								 *
+* All rights reserved.											 *
+* 													 *
+* Redistribution and use of this software in source and binary forms, with or without modification, are  *
+* permitted provided that the following conditions are met:						 *
+* 													 *
+* * Redistributions of source code must retain the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer.										 *
+*    													 *
+* * Redistributions in binary form must reproduce the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer in the documentation and/or other						 *
+*   materials provided with the distribution.								 *
+* 													 *
+* * Neither the name of the WIDE Project or NICT nor the 						 *
+*   names of its contributors may be used to endorse or 						 *
+*   promote products derived from this software without 						 *
+*   specific prior written permission of WIDE Project and 						 *
+*   NICT.												 *
+* 													 *
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED *
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
+* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR *
+* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 	 *
+* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 	 *
+* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR *
+* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF   *
+* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.								 *
+*********************************************************************************************************/
+
+#include "fdcore-internal.h"
+
+/* Structure to store a sent request */
+struct sentreq {
+	struct fd_list	chain; 	/* the "o" field points directly to the (new) hop-by-hop of the request (uint32_t *)  */
+	struct msg	*req;	/* A request that was sent and not yet answered. */
+	uint32_t	prevhbh;/* The value to set back in the hbh header when the message is retrieved */
+	struct fd_list  expire; /* the list of expiring requests */
+	struct timespec timeout; /* Cache the expire date of the request so that the timeout thread does not need to get it each time. */
+	struct timespec added_on; /* the time the request was added */
+};
+
+/* Find an element in the hbh list, or the following one */
+static struct fd_list * find_or_next(struct fd_list * srlist, uint32_t hbh, int * match)
+{
+	struct fd_list * li;
+	*match = 0;
+	for (li = srlist->next; li != srlist; li = li->next) {
+		uint32_t * nexthbh = li->o;
+		if (*nexthbh < hbh)
+			continue;
+		if (*nexthbh == hbh)
+			*match = 1;
+		break;
+	}
+	return li;
+}
+
+/* Similar but start from the end, since we add requests in growing hbh order usually */
+static struct fd_list * find_or_prev(struct fd_list * srlist, uint32_t hbh, int * match)
+{
+	struct fd_list * li;
+	*match = 0;
+	for (li = srlist->prev; li != srlist; li = li->prev) {
+		uint32_t * prevhbh = li->o;
+		if (*prevhbh > hbh)
+			continue;
+		if (*prevhbh == hbh)
+			*match = 1;
+		break;
+	}
+	return li;
+}
+
+static void srl_dump(const char * text, struct fd_list * srlist)
+{
+	struct fd_list * li;
+	struct timespec now;
+	
+	LOG_D("%sSentReq list @%p:", text, srlist);
+	
+	CHECK_SYS_DO( clock_gettime(CLOCK_REALTIME, &now), );
+	
+	for (li = srlist->next; li != srlist; li = li->next) {
+		struct sentreq * sr = (struct sentreq *)li;
+		uint32_t * nexthbh = li->o;
+		
+		LOG_D(" - Next req (hbh:0x%x, prev:0x%x): [since %ld.%06ld sec]", *nexthbh, sr->prevhbh,
+			(long)((now.tv_nsec >= sr->added_on.tv_nsec) ? (now.tv_sec - sr->added_on.tv_sec) : (now.tv_sec - sr->added_on.tv_sec - 1)),
+			(long)((now.tv_nsec >= sr->added_on.tv_nsec) ? ((now.tv_nsec - sr->added_on.tv_nsec) / 1000) : ((now.tv_nsec - sr->added_on.tv_nsec + 1000000000) / 1000)));
+	}
+}
+
+/* thread that handles messages expiring. The thread is started only when needed */
+static void * sr_expiry_th(void * arg) {
+	struct sr_list * srlist = arg;
+	
+	TRACE_ENTRY("%p", arg);
+	CHECK_PARAMS_DO( arg, return NULL );
+	
+	/* Set the thread name */
+	{
+		char buf[48];
+		snprintf(buf, sizeof(buf), "ReqExp/%s", ((struct fd_peer *)(srlist->exp.o))->p_hdr.info.pi_diamid);
+		fd_log_threadname ( buf );
+	}
+	
+	do {
+		struct timespec	now;
+		struct sentreq * first;
+		struct msg * request;
+		struct fd_peer * sentto;
+		void (*expirecb)(void *, DiamId_t, size_t, struct msg **);
+		void * data;
+		int no_error;
+
+		CHECK_POSIX_DO( pthread_mutex_lock(&srlist->mtx),  return NULL );
+		pthread_cleanup_push( fd_cleanup_mutex, &srlist->mtx );
+
+loop:	
+		no_error = 0;
+
+		/* Check if there are expiring requests available */
+		if (FD_IS_LIST_EMPTY(&srlist->exp)) {
+			/* Just wait for a change or cancelation */
+			CHECK_POSIX_DO( pthread_cond_wait( &srlist->cnd, &srlist->mtx ), goto unlock );
+			/* Restart the loop on wakeup */
+			goto loop;
+		}
+		
+		/* Get the pointer to the request that expires first */
+		first = (struct sentreq *)(srlist->exp.next->o);
+		
+		/* Get the current time */
+		CHECK_SYS_DO(  clock_gettime(CLOCK_REALTIME, &now),  goto unlock  );
+
+		/* If first request is not expired, we just wait until it happens */
+		if ( TS_IS_INFERIOR( &now, &first->timeout ) ) {
+			
+			CHECK_POSIX_DO2(  pthread_cond_timedwait( &srlist->cnd, &srlist->mtx, &first->timeout ),  
+					ETIMEDOUT, /* ETIMEDOUT is a normal return value, continue */,
+					/* on other error, */ goto unlock );
+	
+			/* on wakeup, loop */
+			goto loop;
+		}
+		
+		/* Now, the first request in the list is expired; remove it and call the expirecb for it */
+		request = first->req;
+		sentto = first->chain.head->o;
+		
+		TRACE_DEBUG(FULL, "Request %x was not answered by %s within the timer delay", *((uint32_t *)first->chain.o), sentto->p_hdr.info.pi_diamid);
+		
+		/* Restore the hbhid */
+		*((uint32_t *)first->chain.o) = first->prevhbh; 
+		
+		/* Free the sentreq information */
+		fd_list_unlink(&first->chain);
+		srlist->cnt--;
+		srlist->cnt_lost++; /* We are not waiting for this answer anymore, but the remote peer may still be processing it. */
+		fd_list_unlink(&first->expire);
+		free(first);
+		
+		no_error = 1;
+unlock:
+		; /* pthread_cleanup_pop sometimes expands as "} ..." and the label before this cause some compilers to complain... */
+		pthread_cleanup_pop( 1 ); /* unlock the mutex */
+		if (!no_error)
+			break;
+
+		
+		/* Retrieve callback in the message */
+		CHECK_FCT_DO( fd_msg_anscb_get( request, NULL, &expirecb, &data ), break);
+		ASSERT(expirecb);
+	
+		/* Clean up this expirecb from the message */
+		CHECK_FCT_DO( fd_msg_anscb_reset( request, 0, 1 ), break);
+
+		/* Call it */
+		(*expirecb)(data, sentto->p_hdr.info.pi_diamid, sentto->p_hdr.info.pi_diamidlen, &request);
+	
+		/* If the callback did not dispose of the message, do it now */
+		if (request) {
+			fd_hook_call(HOOK_MESSAGE_DROPPED, request, NULL, "Expiration period completed without an answer, and the expiry callback did not dispose of the message.", fd_msg_pmdl_get(request));
+			CHECK_FCT_DO( fd_msg_free(request), /* ignore */ );
+		}
+	
+	} while (1);
+	
+	ASSERT(0); /* we have encountered a problem, maybe time to signal the framework to terminate? */
+	return NULL;
+}
+
+
+/* Store a new sent request */
+int fd_p_sr_store(struct sr_list * srlist, struct msg **req, uint32_t *hbhloc, uint32_t hbh_restore)
+{
+	struct sentreq * sr;
+	struct fd_list * prev;
+	int match;
+	struct timespec * ts;
+	
+	TRACE_ENTRY("%p %p %p %x", srlist, req, hbhloc, hbh_restore);
+	CHECK_PARAMS(srlist && req && *req && hbhloc);
+	
+	CHECK_MALLOC( sr = malloc(sizeof(struct sentreq)) );
+	memset(sr, 0, sizeof(struct sentreq));
+	fd_list_init(&sr->chain, hbhloc);
+	sr->req = *req;
+	sr->prevhbh = hbh_restore;
+	fd_list_init(&sr->expire, sr);
+	CHECK_SYS( clock_gettime(CLOCK_REALTIME, &sr->added_on) );
+	
+	/* Search the place in the list */
+	CHECK_POSIX( pthread_mutex_lock(&srlist->mtx) );
+	prev = find_or_prev(&srlist->srs, *hbhloc, &match);
+	if (match) {
+		TRACE_DEBUG(INFO, "A request with the same hop-by-hop Id (0x%x) was already sent: error", *hbhloc);
+		free(sr);
+		srl_dump("Current list of SR: ", &srlist->srs);
+		CHECK_POSIX_DO( pthread_mutex_unlock(&srlist->mtx), /* ignore */ );
+		return EINVAL;
+	}
+	
+	/* Save in the list */
+	*req = NULL;
+	fd_list_insert_after(prev, &sr->chain);
+	srlist->cnt++;
+	
+	/* In case of request with a timeout, also store in the timeout list */
+	ts = fd_msg_anscb_gettimeout( sr->req );
+	if (ts) {
+		struct fd_list * li;
+		
+		memcpy(&sr->timeout, ts, sizeof(struct timespec));
+		
+		/* browse srlist->exp from the end */
+		for (li = srlist->exp.prev; li != &srlist->exp; li = li->prev) {
+			struct sentreq * s = (struct sentreq *)(li->o);
+			if (TS_IS_INFERIOR(&s->timeout, ts))
+				break;
+		}
+		
+		fd_list_insert_after(li, &sr->expire);
+	
+		/* if the thread does not exist yet, create it */
+		if (srlist->thr == (pthread_t)NULL) {
+			CHECK_POSIX_DO( pthread_create(&srlist->thr, NULL, sr_expiry_th, srlist), /* continue anyway */);
+		} else {
+			/* or, if added in first position, signal the condvar to update the sleep time of the thread */
+			if (li == &srlist->exp) {
+				CHECK_POSIX_DO( pthread_cond_signal(&srlist->cnd), /* continue anyway */);
+			}
+		}
+	}
+	
+	CHECK_POSIX( pthread_mutex_unlock(&srlist->mtx) );
+	return 0;
+}
+
+/* Fetch a request by hbh */
+int fd_p_sr_fetch(struct sr_list * srlist, uint32_t hbh, struct msg **req)
+{
+	struct sentreq * sr;
+	int match;
+	
+	TRACE_ENTRY("%p %x %p", srlist, hbh, req);
+	CHECK_PARAMS(srlist && req);
+	
+	/* Search the request in the list */
+	CHECK_POSIX( pthread_mutex_lock(&srlist->mtx) );
+	sr = (struct sentreq *)find_or_next(&srlist->srs, hbh, &match);
+	if (!match) {
+		TRACE_DEBUG(INFO, "There is no saved request with this hop-by-hop id (%x)", hbh);
+		srl_dump("Current list of SR: ", &srlist->srs);
+		*req = NULL;
+		if (srlist->cnt_lost > 0) {
+			srlist->cnt_lost--; /* This is probably an answer for a request we already timedout. */
+		} /* else, probably a bug in the remote peer */
+	} else {
+		/* Restore hop-by-hop id */
+		*((uint32_t *)sr->chain.o) = sr->prevhbh;
+		/* Unlink */
+		fd_list_unlink(&sr->chain);
+		srlist->cnt--;
+		fd_list_unlink(&sr->expire);
+		*req = sr->req;
+		free(sr);
+	}
+	CHECK_POSIX( pthread_mutex_unlock(&srlist->mtx) );
+	
+	/* do not stop the expire thread here, it might cause creating/destroying it very often otherwise */
+
+	/* Done */
+	return 0;
+}
+
+/* Failover requests (free or requeue routables) */
+void fd_p_sr_failover(struct sr_list * srlist)
+{
+	CHECK_POSIX_DO( pthread_mutex_lock(&srlist->mtx), /* continue anyway */ );
+	while (!FD_IS_LIST_EMPTY(&srlist->srs)) {
+		struct sentreq * sr = (struct sentreq *)(srlist->srs.next);
+		fd_list_unlink(&sr->chain);
+		srlist->cnt--;
+		fd_list_unlink(&sr->expire);
+		if (fd_msg_is_routable(sr->req)) {
+			struct msg_hdr * hdr = NULL;
+			int ret;
+			
+			/* Set the 'T' flag */
+			CHECK_FCT_DO(fd_msg_hdr(sr->req, &hdr), /* continue */);
+			if (hdr)
+				hdr->msg_flags |= CMD_FLAG_RETRANSMIT;
+			
+			/* Restore the original hop-by-hop id of the request */
+			*((uint32_t *)sr->chain.o) = sr->prevhbh;
+			
+			fd_hook_call(HOOK_MESSAGE_FAILOVER, sr->req, (struct fd_peer *)srlist->srs.o, NULL, fd_msg_pmdl_get(sr->req));
+			
+			/* Requeue for sending to another peer */
+			CHECK_FCT_DO( ret = fd_fifo_post_noblock(fd_g_outgoing, (void *)&sr->req),
+				{
+					char buf[256];
+					snprintf(buf, sizeof(buf), "Internal error: error while requeuing during failover: %s", strerror(ret));
+					fd_hook_call(HOOK_MESSAGE_DROPPED, sr->req, NULL, buf, fd_msg_pmdl_get(sr->req));
+					CHECK_FCT_DO(fd_msg_free(sr->req), /* What can we do more? */)
+				});
+		} else {
+			/* Just free the request. */
+			/* fd_hook_call(HOOK_MESSAGE_DROPPED, sr->req, NULL, "Sent & unanswered local message discarded during failover.", fd_msg_pmdl_get(sr->req)); */
+			CHECK_FCT_DO(fd_msg_free(sr->req), /* Ignore */);
+		}
+		free(sr);
+	}
+	/* The list of expiring requests must be empty now */
+	ASSERT( FD_IS_LIST_EMPTY(&srlist->exp) );
+	ASSERT( srlist->cnt == 0 ); /* debug the counter management if needed */
+	
+	CHECK_POSIX_DO( pthread_mutex_unlock(&srlist->mtx), /* continue anyway */ );
+	
+	/* Terminate the expiry thread (must be done when the lock can be taken) */
+	CHECK_FCT_DO( fd_thr_term(&srlist->thr), /* ignore error */ );
+}
+
diff --git a/libfdcore/peers.c b/libfdcore/peers.c
new file mode 100644
index 0000000..98f1921
--- /dev/null
+++ b/libfdcore/peers.c
@@ -0,0 +1,693 @@
+/*********************************************************************************************************
+* Software License Agreement (BSD License)                                                               *
+* Author: Sebastien Decugis <sdecugis@freediameter.net>							 *
+*													 *
+* Copyright (c) 2013, WIDE Project and NICT								 *
+* All rights reserved.											 *
+* 													 *
+* Redistribution and use of this software in source and binary forms, with or without modification, are  *
+* permitted provided that the following conditions are met:						 *
+* 													 *
+* * Redistributions of source code must retain the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer.										 *
+*    													 *
+* * Redistributions in binary form must reproduce the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer in the documentation and/or other						 *
+*   materials provided with the distribution.								 *
+* 													 *
+* * Neither the name of the WIDE Project or NICT nor the 						 *
+*   names of its contributors may be used to endorse or 						 *
+*   promote products derived from this software without 						 *
+*   specific prior written permission of WIDE Project and 						 *
+*   NICT.												 *
+* 													 *
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED *
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
+* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR *
+* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 	 *
+* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 	 *
+* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR *
+* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF   *
+* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.								 *
+*********************************************************************************************************/
+
+#include "fdcore-internal.h"
+
+/* Global list of peers */
+struct fd_list   fd_g_peers = FD_LIST_INITIALIZER(fd_g_peers);
+pthread_rwlock_t fd_g_peers_rw = PTHREAD_RWLOCK_INITIALIZER;
+
+/* List of active peers */
+struct fd_list   fd_g_activ_peers = FD_LIST_INITIALIZER(fd_g_activ_peers);	/* peers linked by their p_actives oredered by p_diamid */
+pthread_rwlock_t fd_g_activ_peers_rw = PTHREAD_RWLOCK_INITIALIZER;
+
+/* List of validation callbacks (registered with fd_peer_validate_register) */
+static struct fd_list validators = FD_LIST_INITIALIZER(validators);	/* list items are simple fd_list with "o" pointing to the callback */
+static pthread_rwlock_t validators_rw = PTHREAD_RWLOCK_INITIALIZER;
+
+
+/* Alloc / reinit a peer structure. if *ptr is not NULL, it must already point to a valid struct fd_peer. */
+int fd_peer_alloc(struct fd_peer ** ptr)
+{
+	struct fd_peer *p;
+	
+	TRACE_ENTRY("%p", ptr);
+	CHECK_PARAMS(ptr);
+	
+	if (*ptr) {
+		p = *ptr;
+	} else {
+		CHECK_MALLOC( p = malloc(sizeof(struct fd_peer)) );
+		*ptr = p;
+	}
+	
+	/* Now initialize the content */
+	memset(p, 0, sizeof(struct fd_peer));
+	
+	fd_list_init(&p->p_hdr.chain, p);
+	
+	fd_list_init(&p->p_hdr.info.pi_endpoints, p);
+	fd_list_init(&p->p_hdr.info.runtime.pir_apps, p);
+	
+	p->p_eyec = EYEC_PEER;
+	CHECK_POSIX( pthread_mutex_init(&p->p_state_mtx, NULL) );
+	
+	fd_list_init(&p->p_actives, p);
+	fd_list_init(&p->p_expiry, p);
+	CHECK_FCT( fd_fifo_new(&p->p_tosend, 5) );
+	CHECK_FCT( fd_fifo_new(&p->p_tofailover, 0) );
+	p->p_hbh = lrand48();
+	
+	fd_list_init(&p->p_sr.srs, p);
+	fd_list_init(&p->p_sr.exp, p);
+	CHECK_POSIX( pthread_mutex_init(&p->p_sr.mtx, NULL) );
+	CHECK_POSIX( pthread_cond_init(&p->p_sr.cnd, NULL) );
+	
+	fd_list_init(&p->p_connparams, p);
+	
+	return 0;
+}
+
+/* Add a new peer entry */
+int fd_peer_add ( struct peer_info * info, const char * orig_dbg, void (*cb)(struct peer_info *, void *), void * cb_data )
+{
+	struct fd_peer *p = NULL;
+	struct fd_list * li, *li_inf;
+	int ret = 0;
+	
+	TRACE_ENTRY("%p %p %p %p", info, orig_dbg, cb, cb_data);
+	CHECK_PARAMS(info && info->pi_diamid);
+	
+	if (info->config.pic_realm) {
+		if (!fd_os_is_valid_DiameterIdentity((os0_t)info->config.pic_realm, strlen(info->config.pic_realm))) {
+			TRACE_DEBUG(INFO, "'%s' is not a valid DiameterIdentity.", info->config.pic_realm);
+			return EINVAL;
+		}
+	}
+	
+	/* Create a structure to contain the new peer information */
+	CHECK_FCT( fd_peer_alloc(&p) );
+	
+	/* Copy the informations from the parameters received */
+	p->p_hdr.info.pi_diamid = info->pi_diamid;
+	CHECK_FCT( fd_os_validate_DiameterIdentity(&p->p_hdr.info.pi_diamid, &p->p_hdr.info.pi_diamidlen, 1) );
+	
+	memcpy( &p->p_hdr.info.config, &info->config, sizeof(p->p_hdr.info.config) );
+	
+	/* Duplicate the strings if provided */
+	if (info->config.pic_realm) {
+		CHECK_MALLOC( p->p_hdr.info.config.pic_realm = strdup(info->config.pic_realm) );
+	}
+	if (info->config.pic_priority) {
+		CHECK_MALLOC( p->p_hdr.info.config.pic_priority = strdup(info->config.pic_priority) );
+	}
+	
+	/* Move the list of endpoints into the peer */
+	if (info->pi_endpoints.next)
+		while (!FD_IS_LIST_EMPTY( &info->pi_endpoints ) ) {
+			li = info->pi_endpoints.next;
+			fd_list_unlink(li);
+			fd_list_insert_before(&p->p_hdr.info.pi_endpoints, li);
+		}
+	
+	/* The internal data */
+	if (orig_dbg) {
+		CHECK_MALLOC( p->p_dbgorig = strdup(orig_dbg) );
+	} else {
+		CHECK_MALLOC( p->p_dbgorig = strdup("unspecified") );
+	}
+	p->p_cb = cb;
+	p->p_cb_data = cb_data;
+	
+	/* Ok, now check if we don't already have an entry with the same Diameter Id, and insert this one */
+	CHECK_POSIX( pthread_rwlock_wrlock(&fd_g_peers_rw) );
+	li_inf = &fd_g_peers;
+	for (li = fd_g_peers.next; li != &fd_g_peers; li = li->next) {
+		struct fd_peer * next = (struct fd_peer *)li;
+		int cont;
+		int cmp = fd_os_almostcasesrch( p->p_hdr.info.pi_diamid, p->p_hdr.info.pi_diamidlen, 
+						next->p_hdr.info.pi_diamid, next->p_hdr.info.pi_diamidlen,
+						&cont );
+		if (cmp > 0)
+			li_inf = li; /* it will come after this element, for sure */
+		
+		if (cmp == 0) {
+			ret = EEXIST; /* we have a duplicate */
+			break;
+		}
+		if (!cont)
+			break;
+	}
+	
+	/* We can insert the new peer object */
+	if (! ret)
+		do {
+			/* Update expiry list */
+			CHECK_FCT_DO( ret = fd_p_expi_update( p ), break );
+
+			/* Insert the new element in the list */
+			fd_list_insert_after( li_inf, &p->p_hdr.chain );
+		} while (0);
+
+	CHECK_POSIX( pthread_rwlock_unlock(&fd_g_peers_rw) );
+	if (ret) {
+		CHECK_FCT( fd_peer_free(&p) );
+	} else {
+		CHECK_FCT( fd_psm_begin(p) );
+	}
+	return ret;
+}
+
+/* Search for a peer */
+int fd_peer_getbyid( DiamId_t diamid, size_t diamidlen, int igncase, struct peer_hdr ** peer )
+{
+	struct fd_list * li;
+	TRACE_ENTRY("%p %zd %d %p", diamid, diamidlen, igncase, peer);
+	CHECK_PARAMS( diamid && diamidlen && peer );
+	
+	*peer = NULL;
+	
+	/* Search in the list */
+	CHECK_POSIX( pthread_rwlock_rdlock(&fd_g_peers_rw) );
+	if (igncase) {
+		for (li = fd_g_peers.next; li != &fd_g_peers; li = li->next) {
+			struct fd_peer * next = (struct fd_peer *)li;
+			int cmp, cont;
+			cmp = fd_os_almostcasesrch( diamid, diamidlen, next->p_hdr.info.pi_diamid, next->p_hdr.info.pi_diamidlen, &cont );
+			if (cmp == 0) {
+				*peer = &next->p_hdr;
+				break;
+			}
+			if (!cont)
+				break;
+		}
+	} else {
+		for (li = fd_g_peers.next; li != &fd_g_peers; li = li->next) {
+			struct fd_peer * next = (struct fd_peer *)li;
+			int cmp = fd_os_cmp( diamid, diamidlen, next->p_hdr.info.pi_diamid, next->p_hdr.info.pi_diamidlen );
+			if (cmp > 0)
+				continue;
+			if (cmp == 0)
+				*peer = &next->p_hdr;
+			break;
+		}
+	}
+	CHECK_POSIX( pthread_rwlock_unlock(&fd_g_peers_rw) );
+	
+	return 0;
+}
+
+
+#define free_null( _v ) 	\
+	if (_v) {		\
+		free(_v);	\
+		(_v) = NULL;	\
+	}
+	
+#define free_list( _l ) 						\
+	while (!FD_IS_LIST_EMPTY(_l)) {					\
+		struct fd_list * __li = ((struct fd_list *)(_l))->next;	\
+		fd_list_unlink(__li);					\
+		free(__li);						\
+	}
+
+/* Empty the lists of p_tosend, p_failover, and p_sentreq messages */
+void fd_peer_failover_msg(struct fd_peer * peer)
+{
+	struct msg *m;
+	TRACE_ENTRY("%p", peer);
+	CHECK_PARAMS_DO(CHECK_PEER(peer), return);
+	
+	/* Requeue all messages in the "out" queue */
+	while ( fd_fifo_tryget(peer->p_tosend, &m) == 0 ) {
+		/* but only if they are routable */
+		if (fd_msg_is_routable(m)) {
+			fd_hook_call(HOOK_MESSAGE_FAILOVER, m, peer, NULL, fd_msg_pmdl_get(m));
+			CHECK_FCT_DO(fd_fifo_post_noblock(fd_g_outgoing, (void *)&m), 
+				{
+					/* fallback: destroy the message */
+					fd_hook_call(HOOK_MESSAGE_DROPPED, m, NULL, "Internal error: unable to requeue this message during failover process", fd_msg_pmdl_get(m));
+					CHECK_FCT_DO(fd_msg_free(m), /* What can we do more? */)
+				} );
+		} else {
+			/* Just free it */
+			/* fd_hook_call(HOOK_MESSAGE_DROPPED, m, NULL, "Non-routable message freed during handover", fd_msg_pmdl_get(m)); */
+			CHECK_FCT_DO(fd_msg_free(m), /* What can we do more? */)
+		}
+	}
+	
+	/* Requeue all messages in the "failover" queue */
+	while ( fd_fifo_tryget(peer->p_tofailover, &m) == 0 ) {
+		fd_hook_call(HOOK_MESSAGE_FAILOVER, m, peer, NULL, fd_msg_pmdl_get(m));
+		CHECK_FCT_DO(fd_fifo_post_noblock(fd_g_outgoing, (void *)&m), 
+			{
+				/* fallback: destroy the message */
+				fd_hook_call(HOOK_MESSAGE_DROPPED, m, NULL, "Internal error: unable to requeue this message during failover process", fd_msg_pmdl_get(m));
+				CHECK_FCT_DO(fd_msg_free(m), /* What can we do more? */)
+			} );
+	}
+	
+	/* Requeue all routable sent requests */
+	fd_p_sr_failover(&peer->p_sr);
+	
+	/* Done */
+	return;
+}
+
+/* Describe the current connection */
+int fd_peer_cnx_proto_info(struct peer_hdr *peer, char * buf, size_t len)
+{
+	struct fd_peer * p = (struct fd_peer *)peer;
+	TRACE_ENTRY("%p %p %zd", peer, buf, len);
+	CHECK_PARAMS(CHECK_PEER(peer) && buf && len);
+	
+	if (p->p_cnxctx) {
+		CHECK_FCT(fd_cnx_proto_info(p->p_cnxctx, buf, len));
+	} else if (p->p_receiver) {
+		CHECK_FCT(fd_cnx_proto_info(p->p_receiver, buf, len));
+	} else {
+		snprintf(buf, len, "Not Connected");
+	}
+	
+	return 0;
+}
+
+/* Return the value of srlist->cnt */
+int fd_peer_get_load_pending(struct peer_hdr *peer, long * to_receive, long * to_send)
+{
+	struct fd_peer * p = (struct fd_peer *)peer;
+	TRACE_ENTRY("%p %p %p", peer, to_receive, to_send);
+	CHECK_PARAMS(CHECK_PEER(peer));
+	
+	if (to_receive) {
+		CHECK_POSIX( pthread_mutex_lock(&p->p_sr.mtx) );
+		*to_receive = p->p_sr.cnt;
+		CHECK_POSIX( pthread_mutex_unlock(&p->p_sr.mtx) );
+	}
+	if (to_send) {
+		CHECK_POSIX( pthread_mutex_lock(&p->p_state_mtx) );
+		*to_send = p->p_reqin_count;
+		CHECK_POSIX( pthread_mutex_unlock(&p->p_state_mtx) );
+	}
+	
+	return 0;
+}
+
+
+/* Destroy a structure once cleanups have been performed (fd_psm_abord, ...) */
+int fd_peer_free(struct fd_peer ** ptr)
+{
+	struct fd_peer *p;
+	
+	TRACE_ENTRY("%p", ptr);
+	CHECK_PARAMS(ptr);
+	p = *ptr;
+	*ptr = NULL;
+	CHECK_PARAMS(p);
+	
+	CHECK_PARAMS( FD_IS_LIST_EMPTY(&p->p_hdr.chain) );
+	
+	free_null(p->p_hdr.info.pi_diamid);
+	
+	free_null(p->p_hdr.info.config.pic_realm); 
+	free_null(p->p_hdr.info.config.pic_priority); 
+	
+	free_null(p->p_hdr.info.runtime.pir_realm);
+	free_null(p->p_hdr.info.runtime.pir_prodname);
+	free_list( &p->p_hdr.info.runtime.pir_apps );
+	
+	free_list( &p->p_hdr.info.pi_endpoints );
+	
+	free_null(p->p_dbgorig);
+	
+	fd_list_unlink(&p->p_expiry);
+	fd_list_unlink(&p->p_actives);
+	
+	CHECK_FCT_DO( fd_fifo_del(&p->p_tosend), /* continue */ );
+	CHECK_FCT_DO( fd_fifo_del(&p->p_tofailover), /* continue */ );
+	CHECK_POSIX_DO( pthread_mutex_destroy(&p->p_state_mtx), /* continue */);
+	CHECK_POSIX_DO( pthread_mutex_destroy(&p->p_sr.mtx), /* continue */);
+	CHECK_POSIX_DO( pthread_cond_destroy(&p->p_sr.cnd), /* continue */);
+	
+	/* If the callback is still around... */
+	if (p->p_cb)
+		(*p->p_cb)(NULL, p->p_cb_data);
+	
+	/* Free the structure */
+	free(p);
+	return 0;
+}
+
+/* Terminate peer module (destroy all peers, first gently, then violently) */
+int fd_peer_fini()
+{
+	struct fd_list * li;
+	struct fd_list purge = FD_LIST_INITIALIZER(purge); /* Store zombie peers here */
+	int list_empty;
+	struct timespec	wait_until, now;
+	
+	TRACE_ENTRY();
+	
+	CHECK_FCT_DO(fd_p_expi_fini(), /* continue */);
+	
+	TRACE_DEBUG(INFO, "Sending terminate signal to all peer connections");
+	
+	CHECK_FCT_DO( pthread_rwlock_wrlock(&fd_g_peers_rw), /* continue */ );
+	for (li = fd_g_peers.next; li != &fd_g_peers; li = li->next) {
+		struct fd_peer * peer = (struct fd_peer *)li->o;
+		
+		if (fd_peer_getstate(peer) != STATE_ZOMBIE) {
+			CHECK_FCT_DO( fd_psm_terminate(peer, "REBOOTING"), /* continue */ );
+		} else {
+			li = li->prev; /* to avoid breaking the loop */
+			fd_list_unlink(&peer->p_hdr.chain);
+			fd_list_insert_before(&purge, &peer->p_hdr.chain);
+		}
+	}
+	list_empty = FD_IS_LIST_EMPTY(&fd_g_peers);
+	CHECK_FCT_DO( pthread_rwlock_unlock(&fd_g_peers_rw), /* continue */ );
+	
+	if (!list_empty) {
+		CHECK_SYS(  clock_gettime(CLOCK_REALTIME, &now)  );
+		fd_psm_start(); /* just in case */
+		TRACE_DEBUG(INFO, "Waiting for connections shutdown... (%d sec max)", DPR_TIMEOUT + 1);
+		wait_until.tv_sec  = now.tv_sec + DPR_TIMEOUT + 1;
+		wait_until.tv_nsec = now.tv_nsec;
+	}
+	
+	while ((!list_empty) && (TS_IS_INFERIOR(&now, &wait_until))) {
+		
+		/* Allow the PSM(s) to execute */
+		usleep(100000);
+		
+		/* Remove zombie peers */
+		CHECK_FCT_DO( pthread_rwlock_wrlock(&fd_g_peers_rw), /* continue */ );
+		for (li = fd_g_peers.next; li != &fd_g_peers; li = li->next) {
+			struct fd_peer * peer = (struct fd_peer *)li->o;
+			if (fd_peer_getstate(peer) == STATE_ZOMBIE) {
+				li = li->prev; /* to avoid breaking the loop */
+				fd_list_unlink(&peer->p_hdr.chain);
+				fd_list_insert_before(&purge, &peer->p_hdr.chain);
+			}
+		}
+		list_empty = FD_IS_LIST_EMPTY(&fd_g_peers);
+		CHECK_FCT_DO( pthread_rwlock_unlock(&fd_g_peers_rw), /* continue */ );
+		CHECK_SYS(  clock_gettime(CLOCK_REALTIME, &now)  );
+	}
+	
+	if (!list_empty) {
+		TRACE_DEBUG(INFO, "Forcing connections shutdown");
+		CHECK_FCT_DO( pthread_rwlock_wrlock(&fd_g_peers_rw), /* continue */ );
+		while (!FD_IS_LIST_EMPTY(&fd_g_peers)) {
+			struct fd_peer * peer = (struct fd_peer *)(fd_g_peers.next->o);
+			fd_psm_abord(peer);
+			fd_list_unlink(&peer->p_hdr.chain);
+			fd_list_insert_before(&purge, &peer->p_hdr.chain);
+		}
+		CHECK_FCT_DO( pthread_rwlock_unlock(&fd_g_peers_rw), /* continue */ );
+	}
+	
+	/* Free memory objects of all peers */
+	while (!FD_IS_LIST_EMPTY(&purge)) {
+		struct fd_peer * peer = (struct fd_peer *)(purge.next->o);
+		fd_list_unlink(&peer->p_hdr.chain);
+		fd_peer_free(&peer);
+	}
+	
+	/* Now empty the validators list */
+	CHECK_FCT_DO( pthread_rwlock_wrlock(&validators_rw), /* continue */ );
+	while (!FD_IS_LIST_EMPTY( &validators )) {
+		struct fd_list * v = validators.next;
+		fd_list_unlink(v);
+		free(v);
+	}
+	CHECK_FCT_DO( pthread_rwlock_unlock(&validators_rw), /* continue */ );
+	
+	return 0;
+}
+
+/* Dump info of one peer */
+DECLARE_FD_DUMP_PROTOTYPE(fd_peer_dump, struct peer_hdr * p, int details)
+{
+	FD_DUMP_HANDLE_OFFSET();
+	
+	CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "{peer}(@%p): ", p), return NULL);
+	
+	if (!CHECK_PEER(p)) {
+		CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "INVALID/NULL"), return NULL);
+	} else {
+		struct fd_peer * peer = (struct fd_peer *)p;
+		
+		CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "%s [%s, cnt:%ldsr,%ldpa]", peer->p_hdr.info.pi_diamid, STATE_STR(fd_peer_getstate(peer)), peer->p_sr.cnt, peer->p_reqin_count), return NULL);
+		if (details > 0) {
+			CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, " rlm:%s", peer->p_hdr.info.runtime.pir_realm ?: "<unknown>"), return NULL);
+			if (peer->p_hdr.info.runtime.pir_prodname) {
+				CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, " ['%s' %u]", peer->p_hdr.info.runtime.pir_prodname, peer->p_hdr.info.runtime.pir_firmrev), return NULL);
+			}
+		}
+		if (details > 1) {
+			CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, " [from:%s] flags:%s%s%s%s%s%s%s%s lft:%ds", 
+				peer->p_dbgorig ?: "unset",
+				peer->p_hdr.info.config.pic_flags.pro3 == PI_P3_DEFAULT ? "-" :
+					(peer->p_hdr.info.config.pic_flags.pro3 == PI_P3_IP ? "4" : "6"),
+				peer->p_hdr.info.config.pic_flags.pro4 == PI_P4_DEFAULT ? "-" :
+					(peer->p_hdr.info.config.pic_flags.pro4 == PI_P4_TCP ? "T" : "S"),
+				peer->p_hdr.info.config.pic_flags.alg ? "P" : "-",
+				peer->p_hdr.info.config.pic_flags.sec & PI_SEC_NONE ? "N" :"-",
+				peer->p_hdr.info.config.pic_flags.sec & PI_SEC_TLS_OLD ? "O" :"-",
+				peer->p_hdr.info.config.pic_flags.sctpsec & PI_SCTPSEC_3436 ? "3" :"-",
+				peer->p_hdr.info.config.pic_flags.exp ? "E" : "-",
+				peer->p_hdr.info.config.pic_flags.persist ? "P" : "-",
+				peer->p_hdr.info.config.pic_lft), return NULL);
+		}
+	
+	}
+	
+	return *buf;
+}
+
+/* Dump the list of peers */
+DECLARE_FD_DUMP_PROTOTYPE(fd_peer_dump_list, int details)
+{
+	struct fd_list * li;
+	FD_DUMP_HANDLE_OFFSET();
+	
+	CHECK_FCT_DO( pthread_rwlock_rdlock(&fd_g_peers_rw), /* continue */ );
+	
+	for (li = fd_g_peers.next; li != &fd_g_peers; li = li->next) {
+		CHECK_MALLOC_DO( fd_peer_dump(FD_DUMP_STD_PARAMS, (struct peer_hdr *)li->o, details), break);
+		if (li->next != &fd_g_peers) {
+			CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "\n"), break);
+		}
+	}
+	
+	CHECK_FCT_DO( pthread_rwlock_unlock(&fd_g_peers_rw), /* continue */ );
+	return *buf;
+}
+
+static struct dict_object *avp_oh_model = NULL;
+static pthread_mutex_t cache_avp_lock = PTHREAD_MUTEX_INITIALIZER;
+
+/* Handle an incoming CER request on a new connection */
+int fd_peer_handle_newCER( struct msg ** cer, struct cnxctx ** cnx )
+{
+	struct msg * msg;
+	struct avp *avp_oh;
+	struct avp_hdr * avp_hdr;
+	struct fd_list * li, *li_inf;
+	int found = 0;
+	int ret = 0;
+	struct fd_peer * peer;
+	struct cnx_incoming * ev_data;
+	
+	TRACE_ENTRY("%p %p", cer, cnx);
+	CHECK_PARAMS(cer && *cer && cnx && *cnx);
+	
+	msg = *cer; 
+	
+	/* If needed, resolve the dictionary model for Origin-Host */
+	CHECK_POSIX( pthread_mutex_lock(&cache_avp_lock) );
+	if (!avp_oh_model) {
+		avp_code_t code = AC_ORIGIN_HOST;
+		CHECK_FCT_DO( fd_dict_search ( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_CODE, &code, &avp_oh_model, ENOENT),
+			{ LOG_E("Cannot find Origin-Host AVP definition in the dictionary!"); (void) pthread_mutex_unlock(&cache_avp_lock); return __ret__; } );
+	}
+	CHECK_POSIX( pthread_mutex_unlock(&cache_avp_lock) );
+	
+	/* Find the Diameter Identity of the remote peer in the message */
+	CHECK_FCT( fd_msg_search_avp ( msg, avp_oh_model, &avp_oh ) );
+	ASSERT(avp_oh); /* otherwise it should not have passed rules validation, right? */
+	CHECK_FCT( fd_msg_avp_hdr ( avp_oh, &avp_hdr ) );
+	
+	/* First, check if the Origin-Host value is valid */
+	if (!fd_os_is_valid_DiameterIdentity(avp_hdr->avp_value->os.data, avp_hdr->avp_value->os.len)) {
+		CHECK_FCT( fd_msg_new_answer_from_req ( fd_g_config->cnf_dict, cer, MSGFL_ANSW_ERROR ) );
+		CHECK_FCT( fd_msg_rescode_set(*cer, "DIAMETER_INVALID_AVP_VALUE", 
+							"Your Origin-Host contains invalid characters.", avp_oh, 1 ) );
+		
+		fd_hook_call(HOOK_PEER_CONNECT_FAILED, *cer, NULL, "Received CER with invalid Origin-Host AVP", NULL);
+		
+		CHECK_FCT( fd_out_send(cer, *cnx, NULL, 0) );
+		return EINVAL;
+	}
+	
+	/* Search if we already have this peer id in our list. We take directly the write lock so that we don't need to upgrade if it is a new peer.
+	 * There is space for a small optimization here if needed.
+	 */
+	CHECK_POSIX( pthread_rwlock_wrlock(&fd_g_peers_rw) );
+	
+	li_inf = &fd_g_peers;
+	for (li = fd_g_peers.next; li != &fd_g_peers; li = li->next) {
+		int cmp, cont;
+		peer = (struct fd_peer *)li;
+		cmp = fd_os_almostcasesrch( avp_hdr->avp_value->os.data, avp_hdr->avp_value->os.len, peer->p_hdr.info.pi_diamid, peer->p_hdr.info.pi_diamidlen, &cont );
+		if (cmp > 0) {
+			li_inf = li;
+		}
+		if (cmp == 0) {
+			found = 1;
+			break;
+		}
+		if (!cont)
+			break;
+	}
+	
+	if (!found) {
+		/* Create a new peer entry for this new remote peer */
+		peer = NULL;
+		CHECK_FCT_DO( ret = fd_peer_alloc(&peer), goto out );
+		
+		/* Set the peer Diameter Id and the responder flag parameters */
+		CHECK_MALLOC_DO( peer->p_hdr.info.pi_diamid = os0dup(avp_hdr->avp_value->os.data, avp_hdr->avp_value->os.len), 
+			{ ret = ENOMEM; goto out; } );
+		peer->p_hdr.info.pi_diamidlen = avp_hdr->avp_value->os.len;
+		CHECK_MALLOC_DO( peer->p_dbgorig = strdup(fd_cnx_getid(*cnx)), { ret = ENOMEM; goto out; } );
+		peer->p_flags.pf_responder = 1;
+		peer->p_flags.pf_delete = 1;
+		
+		LOG_D("Created new peer object for incoming CER: %s", peer->p_hdr.info.pi_diamid);
+		
+#ifndef DISABLE_PEER_EXPIRY
+		/* Set this peer to expire on inactivity */
+		peer->p_hdr.info.config.pic_flags.exp 	= PI_EXP_INACTIVE;
+		peer->p_hdr.info.config.pic_lft		= 3600;	/* 1 hour without any message 
+		-- RFC3539 states that this must not be inferior to BRINGDOWN_INTERVAL = 5 minutes */
+		
+		CHECK_FCT_DO( ret = fd_p_expi_update( peer ), goto out );
+#endif /* DISABLE_PEER_EXPIRY */
+		
+		/* Insert the new peer in the list (the PSM will take care of setting the expiry after validation) */
+		fd_list_insert_after( li_inf, &peer->p_hdr.chain );
+		
+		/* Start the PSM, which will receive the event below */
+		CHECK_FCT_DO( ret = fd_psm_begin(peer), goto out );
+	} else {
+		/* Check if the peer is in zombie state */
+		if (fd_peer_getstate(peer) == STATE_ZOMBIE) {
+			/* Re-activate the peer */
+			if (peer->p_hdr.info.config.pic_flags.exp)
+				peer->p_flags.pf_responder = 1;
+			CHECK_POSIX_DO( pthread_mutex_lock(&peer->p_state_mtx), );
+			peer->p_state = STATE_NEW;
+			CHECK_POSIX_DO( pthread_mutex_unlock(&peer->p_state_mtx), );
+			peer->p_flags.pf_localterm = 0;
+			CHECK_FCT_DO( ret = fd_psm_begin(peer), goto out );
+		}
+	}
+	
+	/* Send the new connection event to the PSM */
+	CHECK_MALLOC_DO( ev_data = malloc(sizeof(struct cnx_incoming)), { ret = ENOMEM; goto out; } );
+	memset(ev_data, 0, sizeof(*ev_data));
+	
+	ev_data->cer = msg;
+	ev_data->cnx = *cnx;
+	ev_data->validate = !found;
+	
+	CHECK_FCT_DO( ret = fd_event_send(peer->p_events, FDEVP_CNX_INCOMING, sizeof(*ev_data), ev_data), goto out );
+	
+out:	
+	CHECK_POSIX( pthread_rwlock_unlock(&fd_g_peers_rw) );
+
+	if (ret == 0) {
+		/* Reset the "out" parameters, so that they are not cleanup on function return. */
+		*cer = NULL;
+		*cnx = NULL;
+	} else {
+		char buf[1024];
+		snprintf(buf, sizeof(buf), "An error occurred while processing new incoming CER: %s", strerror(ret));
+		fd_hook_call(HOOK_PEER_CONNECT_FAILED, *cer, NULL, buf, NULL);
+	}
+	
+	return ret;
+}
+
+/* Save a callback to accept / reject incoming unknown peers */
+int fd_peer_validate_register ( int (*peer_validate)(struct peer_info * /* info */, int * /* auth */, int (**cb2)(struct peer_info *)) )
+{
+	struct fd_list * v;
+	
+	TRACE_ENTRY("%p", peer_validate);
+	CHECK_PARAMS(peer_validate);
+	
+	/* Alloc a new entry */
+	CHECK_MALLOC( v = malloc(sizeof(struct fd_list)) );
+	fd_list_init( v, peer_validate );
+	
+	/* Add at the beginning of the list */
+	CHECK_FCT( pthread_rwlock_wrlock(&validators_rw) );
+	fd_list_insert_after(&validators, v);
+	CHECK_FCT( pthread_rwlock_unlock(&validators_rw));
+	
+	/* Done! */
+	return 0;
+}
+
+/* Validate a peer by calling the callbacks in turn -- return 0 if the peer is validated, ! 0 in case of error (>0) or if the peer is rejected (-1) */
+int fd_peer_validate( struct fd_peer * peer )
+{
+	int ret = 0;
+	struct fd_list * v;
+	
+	CHECK_FCT( pthread_rwlock_rdlock(&validators_rw) );
+	for (v = validators.next; v != &validators; v = v->next) {
+		int auth = 0;
+		pthread_cleanup_push(fd_cleanup_rwlock, &validators_rw);
+		CHECK_FCT_DO( ret = ((int(*)(struct peer_info *, int *, int (**)(struct peer_info *)))(v->o)) (&peer->p_hdr.info, &auth, &peer->p_cb2),  );
+		pthread_cleanup_pop(0);
+		if (ret)
+			goto out;
+		if (auth) {
+			ret = (auth > 0) ? 0 : -1;
+			goto out;
+		}
+		peer->p_cb2 = NULL;
+	}
+	
+	/* No callback has given a firm result, the default is to reject */
+	ret = -1;
+out:
+	CHECK_FCT( pthread_rwlock_unlock(&validators_rw));
+	return ret;
+}
diff --git a/libfdcore/queues.c b/libfdcore/queues.c
new file mode 100644
index 0000000..b317d34
--- /dev/null
+++ b/libfdcore/queues.c
@@ -0,0 +1,84 @@
+/*********************************************************************************************************
+* Software License Agreement (BSD License)                                                               *
+* Author: Sebastien Decugis <sdecugis@freediameter.net>							 *
+*													 *
+* Copyright (c) 2013, WIDE Project and NICT								 *
+* All rights reserved.											 *
+* 													 *
+* Redistribution and use of this software in source and binary forms, with or without modification, are  *
+* permitted provided that the following conditions are met:						 *
+* 													 *
+* * Redistributions of source code must retain the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer.										 *
+*    													 *
+* * Redistributions in binary form must reproduce the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer in the documentation and/or other						 *
+*   materials provided with the distribution.								 *
+* 													 *
+* * Neither the name of the WIDE Project or NICT nor the 						 *
+*   names of its contributors may be used to endorse or 						 *
+*   promote products derived from this software without 						 *
+*   specific prior written permission of WIDE Project and 						 *
+*   NICT.												 *
+* 													 *
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED *
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
+* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR *
+* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 	 *
+* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 	 *
+* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR *
+* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF   *
+* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.								 *
+*********************************************************************************************************/
+
+#include "fdcore-internal.h"
+
+/* The global message queues */
+struct fifo * fd_g_incoming = NULL;
+struct fifo * fd_g_outgoing = NULL;
+struct fifo * fd_g_local = NULL;
+
+/* Initialize the message queues. */
+int fd_queues_init(void)
+{
+	TRACE_ENTRY();
+	CHECK_FCT( fd_fifo_new ( &fd_g_incoming, 20 ) );
+	CHECK_FCT( fd_fifo_new ( &fd_g_outgoing, 30 ) );
+	CHECK_FCT( fd_fifo_new ( &fd_g_local, 25 ) );
+	return 0;
+}
+
+/* Destroy a queue after emptying it (and dumping the content) */
+int fd_queues_fini(struct fifo ** queue)
+{
+	struct msg * msg;
+	int ret = 0;
+	
+	TRACE_ENTRY("%p", queue);
+	
+	/* Note : the threads that post into this queue should already been stopped before this !!! */
+	
+	CHECK_PARAMS(queue);
+	if (*queue == NULL)
+		return 0; /* the queue was not already initialized */
+
+	/* Empty all contents */
+	while (1) {
+		/* Check if there is a message in the queue */
+		ret = fd_fifo_tryget(*queue, &msg);
+		if (ret == EWOULDBLOCK)
+			break;
+		CHECK_FCT(ret);
+		
+		/* We got one! */
+		fd_hook_call(HOOK_MESSAGE_DROPPED, msg, NULL, "Message lost because framework is terminating.", fd_msg_pmdl_get(msg));
+		fd_msg_free(msg);
+	}
+	
+	/* Now, delete the empty queue */
+	CHECK_FCT( fd_fifo_del ( queue ) );
+	
+	return 0;
+}
diff --git a/libfdcore/routing_dispatch.c b/libfdcore/routing_dispatch.c
new file mode 100644
index 0000000..93df065
--- /dev/null
+++ b/libfdcore/routing_dispatch.c
@@ -0,0 +1,1328 @@
+/*********************************************************************************************************
+* Software License Agreement (BSD License)                                                               *
+* Author: Sebastien Decugis <sdecugis@freediameter.net>							 *
+*													 *
+* Copyright (c) 2015, WIDE Project and NICT								 *
+* All rights reserved.											 *
+* 													 *
+* Redistribution and use of this software in source and binary forms, with or without modification, are  *
+* permitted provided that the following conditions are met:						 *
+* 													 *
+* * Redistributions of source code must retain the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer.										 *
+*    													 *
+* * Redistributions in binary form must reproduce the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer in the documentation and/or other						 *
+*   materials provided with the distribution.								 *
+* 													 *
+* * Neither the name of the WIDE Project or NICT nor the 						 *
+*   names of its contributors may be used to endorse or 						 *
+*   promote products derived from this software without 						 *
+*   specific prior written permission of WIDE Project and 						 *
+*   NICT.												 *
+* 													 *
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED *
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
+* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR *
+* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 	 *
+* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 	 *
+* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR *
+* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF   *
+* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.								 *
+*********************************************************************************************************/
+
+#include "fdcore-internal.h"
+
+/********************************************************************************/
+/*              First part : handling the extensions callbacks                  */
+/********************************************************************************/
+
+/* Lists of the callbacks, and locks to protect them */
+static pthread_rwlock_t rt_fwd_lock = PTHREAD_RWLOCK_INITIALIZER;
+static struct fd_list 	rt_fwd_list = FD_LIST_INITIALIZER_O(rt_fwd_list, &rt_fwd_lock);
+
+static pthread_rwlock_t rt_out_lock = PTHREAD_RWLOCK_INITIALIZER;
+static struct fd_list 	rt_out_list = FD_LIST_INITIALIZER_O(rt_out_list, &rt_out_lock);
+
+/* Items in the lists are the same */
+struct rt_hdl {
+	struct fd_list	chain;	/* link in the rt_fwd_list or rt_out_list */
+	void *		cbdata;	/* the registered data */
+	union {
+		int	order;	/* This value is used to sort the list */
+		int 	dir;	/* It is the direction for FWD handlers */
+		int	prio;	/* and the priority for OUT handlers */
+	};
+	union {
+		int (*rt_fwd_cb)(void * cbdata, struct msg ** msg);
+		int (*rt_out_cb)(void * cbdata, struct msg ** msg, struct fd_list * candidates);
+	};
+};	
+
+/* Add a new entry in the list */
+static int add_ordered(struct rt_hdl * new, struct fd_list * list)
+{
+	/* The list is ordered by prio parameter */
+	struct fd_list * li;
+	
+	CHECK_POSIX( pthread_rwlock_wrlock(list->o) );
+	
+	for (li = list->next; li != list; li = li->next) {
+		struct rt_hdl * h = (struct rt_hdl *) li;
+		if (new->order <= h->order)
+			break;
+	}
+	
+	fd_list_insert_before(li, &new->chain);
+	
+	CHECK_POSIX( pthread_rwlock_unlock(list->o) );
+	
+	return 0;
+}
+
+/* Register a new FWD callback */
+int fd_rt_fwd_register ( int (*rt_fwd_cb)(void * cbdata, struct msg ** msg), void * cbdata, enum fd_rt_fwd_dir dir, struct fd_rt_fwd_hdl ** handler )
+{
+	struct rt_hdl * new;
+	
+	TRACE_ENTRY("%p %p %d %p", rt_fwd_cb, cbdata, dir, handler);
+	CHECK_PARAMS( rt_fwd_cb );
+	CHECK_PARAMS( (dir >= RT_FWD_REQ) && ( dir <= RT_FWD_ANS) );
+	
+	/* Create a new container */
+	CHECK_MALLOC(new = malloc(sizeof(struct rt_hdl)));
+	memset(new, 0, sizeof(struct rt_hdl));
+	
+	/* Write the content */
+	fd_list_init(&new->chain, NULL);
+	new->cbdata 	= cbdata;
+	new->dir    	= dir;
+	new->rt_fwd_cb 	= rt_fwd_cb;
+	
+	/* Save this in the list */
+	CHECK_FCT( add_ordered(new, &rt_fwd_list) );
+	
+	/* Give it back to the extension if needed */
+	if (handler)
+		*handler = (void *)new;
+	
+	return 0;
+}
+
+/* Remove it */
+int fd_rt_fwd_unregister ( struct fd_rt_fwd_hdl * handler, void ** cbdata )
+{
+	struct rt_hdl * del;
+	TRACE_ENTRY( "%p %p", handler, cbdata);
+	CHECK_PARAMS( handler );
+	
+	del = (struct rt_hdl *)handler;
+	CHECK_PARAMS( del->chain.head == &rt_fwd_list );
+	
+	/* Unlink */
+	CHECK_POSIX( pthread_rwlock_wrlock(&rt_fwd_lock) );
+	fd_list_unlink(&del->chain);
+	CHECK_POSIX( pthread_rwlock_unlock(&rt_fwd_lock) );
+	
+	if (cbdata)
+		*cbdata = del->cbdata;
+	
+	free(del);
+	return 0;
+}
+
+/* Register a new OUT callback */
+int fd_rt_out_register ( int (*rt_out_cb)(void * cbdata, struct msg ** pmsg, struct fd_list * candidates), void * cbdata, int priority, struct fd_rt_out_hdl ** handler )
+{
+	struct rt_hdl * new;
+	
+	TRACE_ENTRY("%p %p %d %p", rt_out_cb, cbdata, priority, handler);
+	CHECK_PARAMS( rt_out_cb );
+	
+	/* Create a new container */
+	CHECK_MALLOC(new = malloc(sizeof(struct rt_hdl)));
+	memset(new, 0, sizeof(struct rt_hdl));
+	
+	/* Write the content */
+	fd_list_init(&new->chain, NULL);
+	new->cbdata 	= cbdata;
+	new->prio    	= priority;
+	new->rt_out_cb 	= rt_out_cb;
+	
+	/* Save this in the list */
+	CHECK_FCT( add_ordered(new, &rt_out_list) );
+	
+	/* Give it back to the extension if needed */
+	if (handler)
+		*handler = (void *)new;
+	
+	return 0;
+}
+
+/* Remove it */
+int fd_rt_out_unregister ( struct fd_rt_out_hdl * handler, void ** cbdata )
+{
+	struct rt_hdl * del;
+	TRACE_ENTRY( "%p %p", handler, cbdata);
+	CHECK_PARAMS( handler );
+	
+	del = (struct rt_hdl *)handler;
+	CHECK_PARAMS( del->chain.head == &rt_out_list );
+	
+	/* Unlink */
+	CHECK_POSIX( pthread_rwlock_wrlock(&rt_out_lock) );
+	fd_list_unlink(&del->chain);
+	CHECK_POSIX( pthread_rwlock_unlock(&rt_out_lock) );
+	
+	if (cbdata)
+		*cbdata = del->cbdata;
+	
+	free(del);
+	return 0;
+}
+
+/********************************************************************************/
+/*                      Some default OUT routing callbacks                      */
+/********************************************************************************/
+
+/* Prevent sending to peers that do not support the message application */
+static int dont_send_if_no_common_app(void * cbdata, struct msg ** pmsg, struct fd_list * candidates)
+{
+	struct msg * msg = *pmsg;
+	struct fd_list * li;
+	struct msg_hdr * hdr;
+	
+	TRACE_ENTRY("%p %p %p", cbdata, msg, candidates);
+	CHECK_PARAMS(msg && candidates);
+	
+	CHECK_FCT( fd_msg_hdr(msg, &hdr) );
+	
+	/* For Base Diameter Protocol, every peer is supposed to support it, so skip */
+	if (hdr->msg_appl == 0)
+		return 0;
+	
+	/* Otherwise, check that the peers support the application */
+	for (li = candidates->next; li != candidates; li = li->next) {
+		struct rtd_candidate *c = (struct rtd_candidate *) li;
+		struct fd_peer * peer;
+		struct fd_app *found;
+		CHECK_FCT( fd_peer_getbyid( c->diamid, c->diamidlen, 0, (void *)&peer ) );
+		if (peer && !peer->p_hdr.info.runtime.pir_relay) {
+			/* Check if the remote peer advertised the message's appli */
+			CHECK_FCT( fd_app_check(&peer->p_hdr.info.runtime.pir_apps, hdr->msg_appl, &found) );
+			if (!found)
+				c->score += FD_SCORE_NO_DELIVERY;
+		}
+	}
+
+	return 0;
+}
+
+/* Detect if the Destination-Host and Destination-Realm match the peer */
+static int score_destination_avp(void * cbdata, struct msg ** pmsg, struct fd_list * candidates)
+{
+	struct msg * msg = *pmsg;
+	struct fd_list * li;
+	struct avp * avp;
+	union avp_value *dh = NULL, *dr = NULL;
+	
+	TRACE_ENTRY("%p %p %p", cbdata, msg, candidates);
+	CHECK_PARAMS(msg && candidates);
+	
+	/* Search the Destination-Host and Destination-Realm AVPs -- we could also use fd_msg_search_avp here, but this one is slightly more efficient */
+	CHECK_FCT(  fd_msg_browse(msg, MSG_BRW_FIRST_CHILD, &avp, NULL) );
+	while (avp) {
+		struct avp_hdr * ahdr;
+		CHECK_FCT(  fd_msg_avp_hdr( avp, &ahdr ) );
+
+		if (! (ahdr->avp_flags & AVP_FLAG_VENDOR)) {
+			switch (ahdr->avp_code) {
+				case AC_DESTINATION_HOST:
+					/* Parse this AVP */
+					CHECK_FCT( fd_msg_parse_dict ( avp, fd_g_config->cnf_dict, NULL ) );
+					ASSERT( ahdr->avp_value );
+					dh = ahdr->avp_value;
+					break;
+
+				case AC_DESTINATION_REALM:
+					/* Parse this AVP */
+					CHECK_FCT( fd_msg_parse_dict ( avp, fd_g_config->cnf_dict, NULL ) );
+					ASSERT( ahdr->avp_value );
+					dr = ahdr->avp_value;
+					break;
+			}
+		}
+
+		if (dh && dr)
+			break;
+
+		/* Go to next AVP */
+		CHECK_FCT(  fd_msg_browse(avp, MSG_BRW_NEXT, &avp, NULL) );
+	}
+	
+	/* Now, check each candidate against these AVP values */
+	for (li = candidates->next; li != candidates; li = li->next) {
+		struct rtd_candidate *c = (struct rtd_candidate *) li;
+		
+	    #if 0 /* this is actually useless since the sending process will also ensure that the peer is still available */
+		struct fd_peer * peer;
+		/* Since the candidates list comes from the peers list, we do not have any issue with upper/lower case to find the peer object */
+		CHECK_FCT( fd_peer_getbyid( c->diamid, c->diamidlen, 0, (void *)&peer ) );
+		if (!peer)
+			continue; /* it has been deleted since the candidate list was generated; avoid sending to this one in that case. */
+	    #endif /* 0 */
+		
+		/* In the AVPs, the value comes from the network, so let's be case permissive */
+		if (dh && !fd_os_almostcasesrch(dh->os.data, dh->os.len, c->diamid, c->diamidlen, NULL) ) {
+			/* The candidate is the Destination-Host */
+			c->score += FD_SCORE_FINALDEST;
+		} else {
+			if (dr && !fd_os_almostcasesrch(dr->os.data, dr->os.len, c->realm, c->realmlen, NULL) ) {
+				/* The candidate's realm matchs the Destination-Realm */
+				c->score += FD_SCORE_REALM;
+			}
+		}
+	}
+
+	return 0;
+}
+
+/********************************************************************************/
+/*                        Helper functions                                      */
+/********************************************************************************/
+
+/* Find (first) '!' and '@' positions in a UTF-8 encoded string (User-Name AVP value) */
+static void nai_get_indexes(union avp_value * un, int * excl_idx, int * at_idx)
+{
+	int i;
+	
+	TRACE_ENTRY("%p %p %p", un, excl_idx, at_idx);
+	CHECK_PARAMS_DO( un && excl_idx && at_idx, return );
+	
+	*excl_idx = 0;
+	*at_idx = 0;
+	
+	/* Search if there is a '!' before any '@' -- do we need to check it contains a '.' ? */
+	for (i = 0; i < un->os.len; i++) {
+		/* The '!' marks the decorated NAI */
+		if ( un->os.data[i] == (unsigned char) '!' ) {
+			if (!*excl_idx)
+				*excl_idx = i;
+			continue;
+		}
+		/* If we reach the realm part, we can stop */
+		if ( un->os.data[i] == (unsigned char) '@' ) {
+			*at_idx = i;
+			break;
+		}
+		/* Stop if we find a \0 in the middle */
+		if ( un->os.data[i] == 0 ) {
+			return;
+		}
+		/* Skip escaped characters */
+		if ( un->os.data[i] == (unsigned char) '\\' ) {
+			i++;
+			continue;
+		}
+	}
+	
+	return;
+}	
+
+/* Test if a User-Name AVP contains a Decorated NAI -- RFC4282, RFC5729 */
+/* Create new User-Name and Destination-Realm values */
+static int process_decorated_NAI(int * was_nai, union avp_value * un, union avp_value * dr)
+{
+	int at_idx, sep_idx;
+	unsigned char * old_un;
+	TRACE_ENTRY("%p %p %p", was_nai, un, dr);
+	CHECK_PARAMS(was_nai && un && dr);
+	
+	/* Save the decorated User-Name, for example 'homerealm.example.net!user@otherrealm.example.net' */
+	old_un = un->os.data;
+	
+	/* Search the positions of the first '!' and the '@' in the string */
+	nai_get_indexes(un, &sep_idx, &at_idx);
+	if ((!sep_idx) || (sep_idx > at_idx) || !fd_os_is_valid_DiameterIdentity(old_un, sep_idx /* this is the new realm part */)) {
+		*was_nai = 0;
+		return 0;
+	}
+	
+	*was_nai = 1;
+	
+	/* Create the new User-Name value */
+	CHECK_MALLOC( un->os.data = malloc( at_idx ) );
+	memcpy( un->os.data, old_un + sep_idx + 1, at_idx - sep_idx ); /* user@ */
+	memcpy( un->os.data + at_idx - sep_idx, old_un, sep_idx ); /* homerealm.example.net */
+	
+	/* Create the new Destination-Realm value */
+	CHECK_MALLOC( dr->os.data = realloc(dr->os.data, sep_idx) );
+	memcpy( dr->os.data, old_un, sep_idx );
+	dr->os.len = sep_idx;
+	
+	TRACE_DEBUG(FULL, "Processed Decorated NAI : '%.*s' became '%.*s' (%.*s)",
+				(int)un->os.len, old_un,
+				(int)at_idx, un->os.data,
+				(int)dr->os.len, dr->os.data);
+	
+	un->os.len = at_idx;
+	free(old_un);
+	
+	return 0;
+}
+
+
+/* Function to return an error to an incoming request */
+static int return_error(struct msg ** pmsg, char * error_code, char * error_message, struct avp * failedavp)
+{
+	struct fd_peer * peer;
+	int is_loc = 0;
+
+	/* Get the source of the message */
+	{
+		DiamId_t id;
+		size_t   idlen;
+		CHECK_FCT( fd_msg_source_get( *pmsg, &id, &idlen ) );
+		
+		if (id == NULL) {
+			is_loc = 1; /* The message was issued locally */
+		} else {
+		
+			/* Search the peer with this id */
+			CHECK_FCT( fd_peer_getbyid( id, idlen, 0, (void *)&peer ) );
+
+			if (!peer) {
+				char buf[256];
+				snprintf(buf, sizeof(buf), "Unable to send error '%s' to deleted peer '%s' in reply to this message.", error_code, id);
+				fd_hook_call(HOOK_MESSAGE_DROPPED, *pmsg, NULL, buf, fd_msg_pmdl_get(*pmsg));
+				fd_msg_free(*pmsg);
+				*pmsg = NULL;
+				return 0;
+			}
+		}
+	}
+	
+	/* Create the error message */
+	CHECK_FCT( fd_msg_new_answer_from_req ( fd_g_config->cnf_dict, pmsg, MSGFL_ANSW_ERROR ) );
+
+	/* Set the error code */
+	CHECK_FCT( fd_msg_rescode_set(*pmsg, error_code, error_message, failedavp, 1 ) );
+
+	/* Send the answer */
+	if (is_loc) {
+		CHECK_FCT( fd_fifo_post(fd_g_incoming, pmsg) );
+	} else {
+		CHECK_FCT( fd_out_send(pmsg, NULL, peer, 1) );
+	}
+	
+	/* Done */
+	return 0;
+}
+
+
+/****************************************************************************/
+/*         Second part : threads moving messages in the daemon              */
+/****************************************************************************/
+
+/* The DISPATCH message processing */
+static int msg_dispatch(struct msg * msg)
+{
+	struct msg_hdr * hdr;
+	int is_req = 0;
+	struct session * sess;
+	enum disp_action action;
+	char * ec = NULL;
+	char * em = NULL;
+	struct msg *msgptr = msg, *error = NULL;
+
+	/* Read the message header */
+	CHECK_FCT( fd_msg_hdr(msg, &hdr) );
+	is_req = hdr->msg_flags & CMD_FLAG_REQUEST;
+	
+	/* Note: if the message is for local delivery, we should test for duplicate
+	  (draft-asveren-dime-dupcons-00). This may conflict with path validation decisions, no clear answer yet */
+
+	/* At this point, we need to understand the message content, so parse it */
+	CHECK_FCT_DO( fd_msg_parse_or_error( &msgptr, &error ),
+		{
+			int rescue = 0;
+			if (__ret__ != EBADMSG) {
+				fd_hook_call(HOOK_MESSAGE_DROPPED, msgptr, NULL, "Error while parsing received answer", fd_msg_pmdl_get(msgptr));
+				fd_msg_free(msgptr);
+			} else {
+				if (!msgptr) {
+					fd_hook_call(HOOK_MESSAGE_PARSING_ERROR2, error, NULL, NULL, fd_msg_pmdl_get(error));
+					/* error now contains the answer message to send back */
+					CHECK_FCT( fd_fifo_post(fd_g_outgoing, &error) );
+				} else if (!error) {
+					/* We have received an invalid answer to our query */
+					fd_hook_call(HOOK_MESSAGE_DROPPED, msgptr, NULL, "Received answer failed the dictionary / rules parsing", fd_msg_pmdl_get(msgptr));
+					fd_msg_free(msgptr);
+				} else {
+					/* We will pass the invalid received error to the application */
+					rescue = 1;
+				}
+			}
+			if (!rescue)
+				return 0; /* We are done with this message, go to the next */
+		} );
+
+	/* First, if the original request was registered with a callback and we receive the answer, call it. */
+	if ( ! is_req ) {
+		struct msg * qry;
+		void (*anscb)(void *, struct msg **) = NULL;
+		void * data = NULL;
+
+		/* Retrieve the corresponding query */
+		CHECK_FCT( fd_msg_answ_getq( msgptr, &qry ) );
+
+		/* Retrieve any registered handler */
+		CHECK_FCT( fd_msg_anscb_get( qry, &anscb, NULL, &data ) );
+
+		/* If a callback was registered, pass the message to it */
+		if (anscb != NULL) {
+
+			TRACE_DEBUG(FULL, "Calling callback registered when query was sent (%p, %p)", anscb, data);
+			(*anscb)(data, &msgptr);
+			
+			/* If the message is processed, we're done */
+			if (msgptr == NULL) {
+				return 0;
+			}
+			
+			/* otherwise continue the dispatching --hoping that the anscb callback did not mess with our message :) */
+		}
+	}
+	
+	/* Retrieve the session of the message */
+	CHECK_FCT( fd_msg_sess_get(fd_g_config->cnf_dict, msgptr, &sess, NULL) );
+
+	/* Now, call any callback registered for the message */
+	CHECK_FCT( fd_msg_dispatch ( &msgptr, sess, &action, &ec, &em, &error) );
+
+	/* Now, act depending on msg and action and ec */
+	if (msgptr) {
+		switch ( action ) {
+			case DISP_ACT_CONT:
+				/* No callback has handled the message, let's reply with a generic error or relay it */
+				if (!fd_g_config->cnf_flags.no_fwd) {
+					/* requeue to fd_g_outgoing */
+					fd_hook_call(HOOK_MESSAGE_ROUTING_FORWARD, msgptr, NULL, NULL, fd_msg_pmdl_get(msgptr));
+					CHECK_FCT( fd_fifo_post(fd_g_outgoing, &msgptr) );
+					break;
+				}
+				/* We don't relay => reply error */
+				em = "The message was not handled by any extension callback";
+				ec = "DIAMETER_COMMAND_UNSUPPORTED";
+				/* and continue as if an error occurred... */
+			case DISP_ACT_ERROR:
+				/* We have a problem with delivering the message */
+				if (ec == NULL) {
+					ec = "DIAMETER_UNABLE_TO_COMPLY";
+				}
+				
+				if (!is_req) {
+					fd_hook_call(HOOK_MESSAGE_DROPPED, msgptr, NULL, "Internal error: Answer received to locally issued request, but not handled by any handler.", fd_msg_pmdl_get(msgptr));
+					fd_msg_free(msgptr);
+					break;
+				}
+				
+				/* Create an answer with the error code and message */
+				CHECK_FCT( fd_msg_new_answer_from_req ( fd_g_config->cnf_dict, &msgptr, 0 ) );
+				CHECK_FCT( fd_msg_rescode_set(msgptr, ec, em, NULL, 1 ) );
+				
+			case DISP_ACT_SEND:
+				/* Now, send the message */
+				CHECK_FCT( fd_fifo_post(fd_g_outgoing, &msgptr) );
+		}
+	} else if (em) {
+		fd_hook_call(HOOK_MESSAGE_DROPPED, error, NULL, em, fd_msg_pmdl_get(error));
+		fd_msg_free(error);
+	}
+	
+	/* We're done with dispatching this message */
+	return 0;
+}
+
+/* The ROUTING-IN message processing */
+static int msg_rt_in(struct msg * msg)
+{
+	struct msg_hdr * hdr;
+	int is_req = 0;
+	int is_err = 0;
+	DiamId_t qry_src = NULL;
+	struct msg *msgptr = msg;
+
+	/* Read the message header */
+	CHECK_FCT( fd_msg_hdr(msg, &hdr) );
+	is_req = hdr->msg_flags & CMD_FLAG_REQUEST;
+	is_err = hdr->msg_flags & CMD_FLAG_ERROR;
+
+	/* Handle incorrect bits */
+	if (is_req && is_err) {
+		fd_hook_call(HOOK_MESSAGE_PARSING_ERROR, msgptr, NULL, "R & E bits were set", fd_msg_pmdl_get(msgptr));
+		CHECK_FCT( return_error( &msgptr, "DIAMETER_INVALID_HDR_BITS", "R & E bits were set", NULL) );
+		return 0;
+	}
+	
+	/* If it is a request, we must analyze its content to decide what we do with it */
+	if (is_req) {
+		struct avp * avp, *un = NULL;
+		union avp_value * un_val = NULL, *dr_val = NULL;
+		enum status { UNKNOWN, YES, NO };
+		/* Are we Destination-Host? */
+		enum status is_dest_host = UNKNOWN;
+		/* Are we Destination-Realm? */
+		enum status is_dest_realm = UNKNOWN;
+		/* Do we support the application of the message? */
+		enum status is_local_app = UNKNOWN;
+
+		/* Check if we have local support for the message application */
+		if ( (hdr->msg_appl == 0) || (hdr->msg_appl == AI_RELAY) ) {
+			fd_hook_call(HOOK_MESSAGE_PARSING_ERROR, msgptr, NULL, "Received a routable message with application id 0 or " _stringize(AI_RELAY) " (relay)", fd_msg_pmdl_get(msgptr));
+			CHECK_FCT( return_error( &msgptr, "DIAMETER_APPLICATION_UNSUPPORTED", "Routable message with application id 0 or relay", NULL) );
+			return 0;
+		} else {
+			struct fd_app * app;
+			CHECK_FCT( fd_app_check(&fd_g_config->cnf_apps, hdr->msg_appl, &app) );
+			is_local_app = (app ? YES : NO);
+		}
+
+		/* Parse the message for Dest-Host, Dest-Realm, and Route-Record */
+		CHECK_FCT(  fd_msg_browse(msgptr, MSG_BRW_FIRST_CHILD, &avp, NULL)  );
+		while (avp) {
+			struct avp_hdr * ahdr;
+			struct fd_pei error_info;
+			int ret;
+			
+			memset(&error_info, 0, sizeof(struct fd_pei)); 
+			
+			CHECK_FCT(  fd_msg_avp_hdr( avp, &ahdr )  );
+
+			if (! (ahdr->avp_flags & AVP_FLAG_VENDOR)) {
+				switch (ahdr->avp_code) {
+					case AC_DESTINATION_HOST:
+						/* Parse this AVP */
+						CHECK_FCT_DO( ret = fd_msg_parse_dict ( avp, fd_g_config->cnf_dict, &error_info ),
+							{
+								if (error_info.pei_errcode) {
+									fd_hook_call(HOOK_MESSAGE_PARSING_ERROR, msgptr, NULL, error_info.pei_message ?: error_info.pei_errcode, fd_msg_pmdl_get(msgptr));
+									CHECK_FCT( return_error( &msgptr, error_info.pei_errcode, error_info.pei_message, error_info.pei_avp) );
+									if (error_info.pei_avp_free) { fd_msg_free(error_info.pei_avp); }
+									return 0;
+								} else {
+									fd_hook_call(HOOK_MESSAGE_PARSING_ERROR, msgptr, NULL, "Unspecified error while parsing Destination-Host AVP", fd_msg_pmdl_get(msgptr));
+									return ret;
+								}
+							} );
+						ASSERT( ahdr->avp_value );
+						/* Compare the Destination-Host AVP of the message with our identity */
+						if (!fd_os_almostcasesrch(ahdr->avp_value->os.data, ahdr->avp_value->os.len, fd_g_config->cnf_diamid, fd_g_config->cnf_diamid_len, NULL)) {
+							is_dest_host = YES;
+						} else {
+							is_dest_host = NO;
+						}
+						break;
+
+					case AC_DESTINATION_REALM:
+						/* Parse this AVP */
+						CHECK_FCT_DO( ret = fd_msg_parse_dict ( avp, fd_g_config->cnf_dict, &error_info ),
+							{
+								if (error_info.pei_errcode) {
+									fd_hook_call(HOOK_MESSAGE_PARSING_ERROR, msgptr, NULL, error_info.pei_message ?: error_info.pei_errcode, fd_msg_pmdl_get(msgptr));
+									CHECK_FCT( return_error( &msgptr, error_info.pei_errcode, error_info.pei_message, error_info.pei_avp) );
+									if (error_info.pei_avp_free) { fd_msg_free(error_info.pei_avp); }
+									return 0;
+								} else {
+									fd_hook_call(HOOK_MESSAGE_PARSING_ERROR, msgptr, NULL, "Unspecified error while parsing Destination-Realm AVP", fd_msg_pmdl_get(msgptr));
+									return ret;
+								}
+							} );
+						ASSERT( ahdr->avp_value );
+						dr_val = ahdr->avp_value;
+						/* Compare the Destination-Realm AVP of the message with our identity */
+						if (!fd_os_almostcasesrch(dr_val->os.data, dr_val->os.len, fd_g_config->cnf_diamrlm, fd_g_config->cnf_diamrlm_len, NULL)) {
+							is_dest_realm = YES;
+						} else {
+							is_dest_realm = NO;
+						}
+						break;
+
+					/* we also use User-Name for decorated NAI */
+					case AC_USER_NAME:
+						/* Parse this AVP */
+						CHECK_FCT_DO( ret = fd_msg_parse_dict ( avp, fd_g_config->cnf_dict, &error_info ),
+							{
+								if (error_info.pei_errcode) {
+									fd_hook_call(HOOK_MESSAGE_PARSING_ERROR, msgptr, NULL, error_info.pei_message ?: error_info.pei_errcode, fd_msg_pmdl_get(msgptr));
+									CHECK_FCT( return_error( &msgptr, error_info.pei_errcode, error_info.pei_message, error_info.pei_avp) );
+									if (error_info.pei_avp_free) { fd_msg_free(error_info.pei_avp); }
+									return 0;
+								} else {
+									fd_hook_call(HOOK_MESSAGE_PARSING_ERROR, msgptr, NULL, "Unspecified error while parsing User-Name AVP", fd_msg_pmdl_get(msgptr));
+									return ret;
+								}
+							} );
+						ASSERT( ahdr->avp_value );
+						un = avp;
+						un_val = ahdr->avp_value;
+						break;
+						
+					case AC_ROUTE_RECORD:
+						/* Parse this AVP */
+						CHECK_FCT_DO( ret = fd_msg_parse_dict ( avp, fd_g_config->cnf_dict, &error_info ),
+							{
+								if (error_info.pei_errcode) {
+									fd_hook_call(HOOK_MESSAGE_PARSING_ERROR, msgptr, NULL, error_info.pei_message ?: error_info.pei_errcode, fd_msg_pmdl_get(msgptr));
+									CHECK_FCT( return_error( &msgptr, error_info.pei_errcode, error_info.pei_message, error_info.pei_avp) );
+									if (error_info.pei_avp_free) { fd_msg_free(error_info.pei_avp); }
+									return 0;
+								} else {
+									fd_hook_call(HOOK_MESSAGE_PARSING_ERROR, msgptr, NULL, "Unspecified error while parsing Route-Record AVP", fd_msg_pmdl_get(msgptr));
+									return ret;
+								}
+							} );
+						ASSERT( ahdr->avp_value );
+						/* Is this our own name ? */
+						if (!fd_os_almostcasesrch(ahdr->avp_value->os.data, ahdr->avp_value->os.len, fd_g_config->cnf_diamid, fd_g_config->cnf_diamid_len, NULL)) {
+							/* Yes: then we must return DIAMETER_LOOP_DETECTED according to Diameter RFC */
+							char * error = "DIAMETER_LOOP_DETECTED";
+							fd_hook_call(HOOK_MESSAGE_PARSING_ERROR, msgptr, NULL, error, fd_msg_pmdl_get(msgptr));
+							CHECK_FCT( return_error( &msgptr, error, NULL, NULL) );
+							return 0;
+						}
+						break;
+						
+					
+				}
+			}
+
+			/* Stop when we found all 3 AVPs -- they are supposed to be at the beginning of the message, so this should be fast */
+			if ((is_dest_host != UNKNOWN) && (is_dest_realm != UNKNOWN) && un)
+				break;
+
+			/* Go to next AVP */
+			CHECK_FCT(  fd_msg_browse(avp, MSG_BRW_NEXT, &avp, NULL)  );
+		}
+
+		/* OK, now decide what we do with the request */
+
+		/* Handle the missing routing AVPs first */
+		if ( is_dest_realm == UNKNOWN ) {
+			fd_hook_call(HOOK_MESSAGE_PARSING_ERROR, msgptr, NULL, "Non-routable message not supported (invalid bit ? missing Destination-Realm ?)", fd_msg_pmdl_get(msgptr));
+			CHECK_FCT( return_error( &msgptr, "DIAMETER_COMMAND_UNSUPPORTED", "Non-routable message not supported (invalid bit ? missing Destination-Realm ?)", NULL) );
+			return 0;
+		}
+
+		/* If we are listed as Destination-Host */
+		if (is_dest_host == YES) {
+			if (is_local_app == YES) {
+				/* Ok, give the message to the dispatch thread */
+				fd_hook_call(HOOK_MESSAGE_ROUTING_LOCAL, msgptr, NULL, NULL, fd_msg_pmdl_get(msgptr));
+				CHECK_FCT( fd_fifo_post(fd_g_local, &msgptr) );
+			} else {
+				/* We don't support the application, reply an error */
+				fd_hook_call(HOOK_MESSAGE_PARSING_ERROR, msgptr, NULL, "Application unsupported", fd_msg_pmdl_get(msgptr));
+				CHECK_FCT( return_error( &msgptr, "DIAMETER_APPLICATION_UNSUPPORTED", NULL, NULL) );
+			}
+			return 0;
+		}
+
+		/* If the message is explicitely for someone else */
+		if ((is_dest_host == NO) || (is_dest_realm == NO)) {
+			if (fd_g_config->cnf_flags.no_fwd) {
+				fd_hook_call(HOOK_MESSAGE_ROUTING_ERROR, msgptr, NULL, "Message for another realm/host", fd_msg_pmdl_get(msgptr));
+				CHECK_FCT( return_error( &msgptr, "DIAMETER_UNABLE_TO_DELIVER", "I am not a Diameter agent", NULL) );
+				return 0;
+			}
+		} else {
+		/* Destination-Host was not set, and Destination-Realm is matching : we may handle or pass to a fellow peer */
+			int is_nai = 0;
+
+			/* test for decorated NAI  (RFC5729 section 4.4) */
+			/* Handle the decorated NAI */
+			if (un_val) {
+				CHECK_FCT_DO( process_decorated_NAI(&is_nai, un_val, dr_val),
+					{
+						/* If the process failed, we assume it is because of the AVP format */
+						fd_hook_call(HOOK_MESSAGE_PARSING_ERROR, msgptr, NULL, "Failed to process decorated NAI", fd_msg_pmdl_get(msgptr));
+						CHECK_FCT( return_error( &msgptr, "DIAMETER_INVALID_AVP_VALUE", "Failed to process decorated NAI", un) );
+						return 0;
+					} );
+			}
+				
+			if (is_nai) {
+				/* We have transformed the AVP, now submit it again in the queue */
+				CHECK_FCT(fd_fifo_post(fd_g_incoming, &msgptr) );
+				return 0;
+			}
+
+			if (is_local_app == YES) {
+				/* Handle localy since we are able to */
+				fd_hook_call(HOOK_MESSAGE_ROUTING_LOCAL, msgptr, NULL, NULL, fd_msg_pmdl_get(msgptr));
+				CHECK_FCT(fd_fifo_post(fd_g_local, &msgptr) );
+				return 0;
+			}
+
+			if (fd_g_config->cnf_flags.no_fwd) {
+				/* We return an error */
+				fd_hook_call(HOOK_MESSAGE_ROUTING_ERROR, msgptr, NULL, "Application unsupported", fd_msg_pmdl_get(msgptr));
+				CHECK_FCT( return_error( &msgptr, "DIAMETER_APPLICATION_UNSUPPORTED", NULL, NULL) );
+				return 0;
+			}
+		}
+
+		/* From that point, for requests, we will call the registered callbacks, then forward to another peer */
+
+	} else {
+		/* The message is an answer */
+		struct msg * qry;
+
+		/* Retrieve the corresponding query and its origin */
+		CHECK_FCT( fd_msg_answ_getq( msgptr, &qry ) );
+		CHECK_FCT( fd_msg_source_get( qry, &qry_src, NULL ) );
+
+		if ((!qry_src) && (!is_err)) {
+			/* The message is a normal answer to a request issued localy, we do not call the callbacks chain on it. */
+			fd_hook_call(HOOK_MESSAGE_ROUTING_LOCAL, msgptr, NULL, NULL, fd_msg_pmdl_get(msgptr));
+			CHECK_FCT(fd_fifo_post(fd_g_local, &msgptr) );
+			return 0;
+		}
+		
+		/* From that point, for answers, we will call the registered callbacks, then pass it to the dispatch module or forward it */
+	}
+
+	/* Call all registered callbacks for this message */
+	{
+		struct fd_list * li;
+
+		CHECK_FCT( pthread_rwlock_rdlock( &rt_fwd_lock ) );
+		pthread_cleanup_push( fd_cleanup_rwlock, &rt_fwd_lock );
+
+		/* requests: dir = 1 & 2 => in order; answers = 3 & 2 => in reverse order */
+		for (	li = (is_req ? rt_fwd_list.next : rt_fwd_list.prev) ; msgptr && (li != &rt_fwd_list) ; li = (is_req ? li->next : li->prev) ) {
+			struct rt_hdl * rh = (struct rt_hdl *)li;
+			int ret;
+
+			if (is_req && (rh->dir > RT_FWD_ALL))
+				break;
+			if ((!is_req) && (rh->dir < RT_FWD_ALL))
+				break;
+
+			/* Ok, call this cb */
+			TRACE_DEBUG(ANNOYING, "Calling next FWD callback on %p : %p", msgptr, rh->rt_fwd_cb);
+			CHECK_FCT_DO( ret = (*rh->rt_fwd_cb)(rh->cbdata, &msgptr),
+				{
+					char buf[256];
+					snprintf(buf, sizeof(buf), "A FWD routing callback returned an error: %s", strerror(ret));
+					fd_hook_call(HOOK_MESSAGE_ROUTING_ERROR, msgptr, NULL, buf, fd_msg_pmdl_get(msgptr));
+					fd_hook_call(HOOK_MESSAGE_DROPPED, msgptr, NULL, buf, fd_msg_pmdl_get(msgptr));
+					fd_msg_free(msgptr);
+					msgptr = NULL;
+					break;
+				} );
+		}
+
+		pthread_cleanup_pop(0);
+		CHECK_FCT( pthread_rwlock_unlock( &rt_fwd_lock ) );
+
+		/* If a callback has handled the message, we stop now */
+		if (!msgptr)
+			return 0;
+	}
+
+	/* Now pass the message to the next step: either forward to another peer, or dispatch to local extensions */
+	if (is_req || qry_src) {
+		fd_hook_call(HOOK_MESSAGE_ROUTING_FORWARD, msgptr, NULL, NULL, fd_msg_pmdl_get(msgptr));
+		CHECK_FCT(fd_fifo_post(fd_g_outgoing, &msgptr) );
+	} else {
+		fd_hook_call(HOOK_MESSAGE_ROUTING_LOCAL, msgptr, NULL, NULL, fd_msg_pmdl_get(msgptr));
+		CHECK_FCT(fd_fifo_post(fd_g_local, &msgptr) );
+	}
+
+	/* We're done with this message */
+	return 0;
+}
+		
+
+/* The ROUTING-OUT message processing */
+static int msg_rt_out(struct msg * msg)
+{
+	struct rt_data * rtd = NULL;
+	struct msg_hdr * hdr;
+	int is_req = 0;
+	int ret;
+	struct fd_list * li, *candidates;
+	struct avp * avp;
+	struct rtd_candidate * c;
+	struct msg *msgptr = msg;
+	DiamId_t qry_src = NULL;
+	size_t qry_src_len = 0;
+	
+	/* Read the message header */
+	CHECK_FCT( fd_msg_hdr(msgptr, &hdr) );
+	is_req = hdr->msg_flags & CMD_FLAG_REQUEST;
+	
+	/* For answers, the routing is very easy */
+	if ( ! is_req ) {
+		struct msg * qry;
+		struct msg_hdr * qry_hdr;
+		struct fd_peer * peer = NULL;
+
+		/* Retrieve the corresponding query and its origin */
+		CHECK_FCT( fd_msg_answ_getq( msgptr, &qry ) );
+		CHECK_FCT( fd_msg_source_get( qry, &qry_src, &qry_src_len ) );
+
+		ASSERT( qry_src ); /* if it is NULL, the message should have been in the LOCAL queue! */
+
+		/* Find the peer corresponding to this name */
+		CHECK_FCT( fd_peer_getbyid( qry_src, qry_src_len, 0, (void *) &peer ) );
+		if (fd_peer_getstate(peer) != STATE_OPEN && fd_peer_getstate(peer) != STATE_CLOSING_GRACE) {
+			char buf[128];
+			snprintf(buf, sizeof(buf), "Unable to forward answer to deleted / closed peer '%s'.", qry_src);
+			fd_hook_call(HOOK_MESSAGE_ROUTING_ERROR, msgptr, NULL, buf, fd_msg_pmdl_get(msgptr));
+			fd_hook_call(HOOK_MESSAGE_DROPPED, msgptr, NULL, buf, fd_msg_pmdl_get(msgptr));
+			fd_msg_free(msgptr);
+			return 0;
+		}
+
+		/* We must restore the hop-by-hop id */
+		CHECK_FCT( fd_msg_hdr(qry, &qry_hdr) );
+		hdr->msg_hbhid = qry_hdr->msg_hbhid;
+
+		/* Push the message into this peer */
+		CHECK_FCT( fd_out_send(&msgptr, NULL, peer, 1) );
+
+		/* We're done with this answer */
+		return 0;
+	}
+	
+	/* From that point, the message is a request */
+	CHECK_FCT( fd_msg_source_get( msgptr, &qry_src, &qry_src_len ) );
+	/* if qry_src != NULL, this message is relayed, otherwise it is locally issued */
+
+	/* Get the routing data out of the message if any (in case of re-transmit) */
+	CHECK_FCT( fd_msg_rt_get ( msgptr, &rtd ) );
+
+	/* If there is no routing data already, let's create it */
+	if (rtd == NULL) {
+		CHECK_FCT( fd_rtd_init(&rtd) );
+
+		/* Add all peers currently in OPEN state */
+		CHECK_FCT( pthread_rwlock_rdlock(&fd_g_activ_peers_rw) );
+		for (li = fd_g_activ_peers.next; li != &fd_g_activ_peers; li = li->next) {
+			struct fd_peer * p = (struct fd_peer *)li->o;
+			CHECK_FCT_DO( ret = fd_rtd_candidate_add(rtd, 
+							p->p_hdr.info.pi_diamid, 
+							p->p_hdr.info.pi_diamidlen, 
+							p->p_hdr.info.runtime.pir_realm,
+							p->p_hdr.info.runtime.pir_realmlen), 
+				{ CHECK_FCT_DO( pthread_rwlock_unlock(&fd_g_activ_peers_rw), ); return ret; } );
+		}
+		CHECK_FCT( pthread_rwlock_unlock(&fd_g_activ_peers_rw) );
+
+		/* Now let's remove all peers from the Route-Records */
+		CHECK_FCT(  fd_msg_browse(msgptr, MSG_BRW_FIRST_CHILD, &avp, NULL)  );
+		while (avp) {
+			struct avp_hdr * ahdr;
+			struct fd_pei error_info;
+			CHECK_FCT(  fd_msg_avp_hdr( avp, &ahdr )  );
+
+			if ((ahdr->avp_code == AC_ROUTE_RECORD) && (! (ahdr->avp_flags & AVP_FLAG_VENDOR)) ) {
+				/* Parse this AVP */
+				CHECK_FCT_DO( ret = fd_msg_parse_dict ( avp, fd_g_config->cnf_dict, &error_info ),
+					{
+						if (error_info.pei_errcode) {
+							CHECK_FCT( return_error( &msgptr, error_info.pei_errcode, error_info.pei_message, error_info.pei_avp) );
+							if (error_info.pei_avp_free) { fd_msg_free(error_info.pei_avp); }
+							return 0;
+						} else {
+							return ret;
+						}
+					} );
+				ASSERT( ahdr->avp_value );
+				/* Remove this value from the list. We don't need to pay special attention to the contents here. */
+				fd_rtd_candidate_del(rtd, ahdr->avp_value->os.data, ahdr->avp_value->os.len);
+			}
+
+			/* Go to next AVP */
+			CHECK_FCT(  fd_msg_browse(avp, MSG_BRW_NEXT, &avp, NULL)  );
+		}
+		
+		/* Save the routing information in the message */
+		CHECK_FCT( fd_msg_rt_associate ( msgptr, rtd ) );
+	}
+
+	/* Note: we reset the scores and pass the message to the callbacks, maybe we could re-use the saved scores when we have received an error ? -- TODO */
+
+	/* Ok, we have our list in rtd now, let's (re)initialize the scores */
+	fd_rtd_candidate_extract(rtd, &candidates, FD_SCORE_INI);
+
+	/* Pass the list to registered callbacks (even if it is empty list) */
+	{
+		CHECK_FCT( pthread_rwlock_rdlock( &rt_out_lock ) );
+		pthread_cleanup_push( fd_cleanup_rwlock, &rt_out_lock );
+
+		/* We call the cb by reverse priority order */
+		for (	li = rt_out_list.prev ; (msgptr != NULL) && (li != &rt_out_list) ; li = li->prev ) {
+			struct rt_hdl * rh = (struct rt_hdl *)li;
+
+			TRACE_DEBUG(ANNOYING, "Calling next OUT callback on %p : %p (prio %d)", msgptr, rh->rt_out_cb, rh->prio);
+			CHECK_FCT_DO( ret = (*rh->rt_out_cb)(rh->cbdata, &msgptr, candidates),
+				{
+					char buf[256];
+					snprintf(buf, sizeof(buf), "An OUT routing callback returned an error: %s", strerror(ret));
+					fd_hook_call(HOOK_MESSAGE_ROUTING_ERROR, msgptr, NULL, buf, fd_msg_pmdl_get(msgptr));
+					fd_hook_call(HOOK_MESSAGE_DROPPED, msgptr, NULL, buf, fd_msg_pmdl_get(msgptr));
+					fd_msg_free(msgptr);
+					msgptr = NULL;
+				} );
+		}
+
+		pthread_cleanup_pop(0);
+		CHECK_FCT( pthread_rwlock_unlock( &rt_out_lock ) );
+
+		/* If an error occurred or the callback disposed of the message, go to next message */
+		if (! msgptr) {
+			return 0;
+		}
+	}
+	
+	/* Order the candidate peers by score attributed by the callbacks */
+	CHECK_FCT( fd_rtd_candidate_reorder(candidates) );
+
+	/* Now try sending the message */
+	for (li = candidates->prev; li != candidates; li = li->prev) {
+		struct fd_peer * peer;
+
+		c = (struct rtd_candidate *) li;
+
+		/* Stop when we have reached the end of valid candidates */
+		if (c->score < 0)
+			break;
+
+		/* Search for the peer */
+		CHECK_FCT( fd_peer_getbyid( c->diamid, c->diamidlen, 0, (void *)&peer ) );
+
+		if (fd_peer_getstate(peer) == STATE_OPEN) {
+			/* Send to this one */
+			CHECK_FCT_DO( fd_out_send(&msgptr, NULL, peer, 1), continue );
+			
+			/* If the sending was successful */
+			break;
+		}
+	}
+
+	/* If the message has not been sent, return an error */
+	if (msgptr) {
+		fd_hook_call(HOOK_MESSAGE_ROUTING_ERROR, msgptr, NULL, "No remaining suitable candidate to route the message to", fd_msg_pmdl_get(msgptr));
+		return_error( &msgptr, "DIAMETER_UNABLE_TO_DELIVER", "No suitable candidate to route the message to", NULL);
+	}
+
+	/* We're done with this message */
+	
+	return 0;
+}
+
+
+/********************************************************************************/
+/*                     Management of the threads                                */
+/********************************************************************************/
+
+/* Note: in the first version, we only create one thread of each kind.
+ We could improve the scalability by using the threshold feature of the queues
+ to create additional threads if a queue is filling up, or at least giving a configurable
+ number of threads of each kind.
+ */
+
+/* Control of the threads */
+static enum { RUN = 0, STOP = 1 } order_val = RUN;
+static pthread_mutex_t order_state_lock = PTHREAD_MUTEX_INITIALIZER;
+
+/* Threads report their status */
+enum thread_state { NOTRUNNING = 0, RUNNING = 1 };
+static void cleanup_state(void * state_loc)
+{
+	CHECK_POSIX_DO( pthread_mutex_lock(&order_state_lock), );
+	*(enum thread_state *)state_loc = NOTRUNNING;
+	CHECK_POSIX_DO( pthread_mutex_unlock(&order_state_lock), );
+}
+
+/* This is the common thread code (same for routing and dispatching) */
+static void * process_thr(void * arg, int (*action_cb)(struct msg * msg), struct fifo * queue, char * action_name)
+{
+	TRACE_ENTRY("%p %p %p %p", arg, action_cb, queue, action_name);
+	
+	/* Set the thread name */
+	{
+		char buf[48];
+		snprintf(buf, sizeof(buf), "%s (%p)", action_name, arg);
+		fd_log_threadname ( buf );
+	}
+	
+	/* The thread reports its status when canceled */
+	CHECK_PARAMS_DO(arg, return NULL);
+	pthread_cleanup_push( cleanup_state, arg );
+	
+	/* Mark the thread running */
+	CHECK_POSIX_DO( pthread_mutex_lock(&order_state_lock), );
+	*(enum thread_state *)arg = RUNNING;
+	CHECK_POSIX_DO( pthread_mutex_unlock(&order_state_lock), );
+	
+	do {
+		struct msg * msg;
+	
+		/* Test the current order */
+		{
+			int must_stop;
+			CHECK_POSIX_DO( pthread_mutex_lock(&order_state_lock), { ASSERT(0); } ); /* we lock to flush the caches */
+			must_stop = (order_val == STOP);
+			CHECK_POSIX_DO( pthread_mutex_unlock(&order_state_lock), { ASSERT(0); } );
+			if (must_stop)
+				goto end;
+			
+			pthread_testcancel();
+		}
+		
+		/* Ok, we are allowed to run */
+		
+		/* Get the next message from the queue */
+		{
+			int ret;
+			struct timespec ts;
+			
+			CHECK_SYS_DO( clock_gettime(CLOCK_REALTIME, &ts), goto fatal_error );
+			ts.tv_sec += 1;
+			
+			ret = fd_fifo_timedget ( queue, &msg, &ts );
+			if (ret == ETIMEDOUT)
+				/* loop, check if the thread must stop now */
+				continue;
+			if (ret == EPIPE)
+				/* The queue was destroyed, we are probably exiting */
+				goto end;
+			
+			/* check if another error occurred */
+			CHECK_FCT_DO( ret, goto fatal_error );
+		}
+		
+		LOG_A("%s: Picked next message", action_name);
+
+		/* Now process the message */
+		CHECK_FCT_DO( (*action_cb)(msg), goto fatal_error);
+
+		/* We're done with this message */
+	
+	} while (1);
+	
+fatal_error:
+	TRACE_DEBUG(INFO, "An unrecoverable error occurred, %s thread is terminating...", action_name);
+	CHECK_FCT_DO(fd_core_shutdown(), );
+	
+end:	
+	; /* noop so that we get rid of "label at end of compund statement" warning */
+	/* Mark the thread as terminated */
+	pthread_cleanup_pop(1);
+	return NULL;
+}
+
+/* The dispatch thread */
+static void * dispatch_thr(void * arg)
+{
+	return process_thr(arg, msg_dispatch, fd_g_local, "Dispatch");
+}
+
+/* The (routing-in) thread -- see description in freeDiameter.h */
+static void * routing_in_thr(void * arg)
+{
+	return process_thr(arg, msg_rt_in, fd_g_incoming, "Routing-IN");
+}
+
+/* The (routing-out) thread -- see description in freeDiameter.h */
+static void * routing_out_thr(void * arg)
+{
+	return process_thr(arg, msg_rt_out, fd_g_outgoing, "Routing-OUT");
+}
+
+
+/********************************************************************************/
+/*                     The functions for the other files                        */
+/********************************************************************************/
+
+static pthread_t * dispatch = NULL;
+static enum thread_state * disp_state = NULL;
+
+/* Later: make this more dynamic */
+static pthread_t rt_out = (pthread_t)NULL;
+static enum thread_state out_state = NOTRUNNING;
+
+static pthread_t rt_in  = (pthread_t)NULL;
+static enum thread_state in_state = NOTRUNNING;
+
+/* Initialize the routing and dispatch threads */
+int fd_rtdisp_init(void)
+{
+	int i;
+	
+	/* Prepare the array for dispatch */
+	CHECK_MALLOC( disp_state = calloc(fd_g_config->cnf_dispthr, sizeof(enum thread_state)) );
+	CHECK_MALLOC( dispatch = calloc(fd_g_config->cnf_dispthr, sizeof(pthread_t)) );
+	
+	/* Create the threads */
+	for (i=0; i < fd_g_config->cnf_dispthr; i++) {
+		CHECK_POSIX( pthread_create( &dispatch[i], NULL, dispatch_thr, &disp_state[i] ) );
+	}
+	CHECK_POSIX( pthread_create( &rt_out, NULL, routing_out_thr, &out_state) );
+	CHECK_POSIX( pthread_create( &rt_in,  NULL, routing_in_thr,  &in_state) );
+	
+	/* Later: TODO("Set the thresholds for the queues to create more threads as needed"); */
+	
+	/* Register the built-in callbacks */
+	CHECK_FCT( fd_rt_out_register( dont_send_if_no_common_app, NULL, 10, NULL ) );
+	CHECK_FCT( fd_rt_out_register( score_destination_avp, NULL, 10, NULL ) );
+	
+	return 0;
+}
+
+/* Ask the thread to terminate after next iteration */
+int fd_rtdisp_cleanstop(void)
+{
+	CHECK_POSIX_DO( pthread_mutex_lock(&order_state_lock), );
+	order_val = STOP;
+	CHECK_POSIX_DO( pthread_mutex_unlock(&order_state_lock), );
+
+	return 0;
+}
+
+static void stop_thread_delayed(enum thread_state *st, pthread_t * thr, char * th_name)
+{
+	TRACE_ENTRY("%p %p", st, thr);
+	CHECK_PARAMS_DO(st && thr, return);
+	int terminated;
+	
+	CHECK_POSIX_DO( pthread_mutex_lock(&order_state_lock), );
+	terminated = (*st == NOTRUNNING);
+	CHECK_POSIX_DO( pthread_mutex_unlock(&order_state_lock), );
+	
+
+	/* Wait for a second for the thread to complete, by monitoring my_state */
+	if (!terminated) {
+		TRACE_DEBUG(INFO, "Waiting for the %s thread to have a chance to terminate", th_name);
+		do {
+			struct timespec	 ts, ts_final;
+
+			CHECK_SYS_DO( clock_gettime(CLOCK_REALTIME, &ts), break );
+			
+			ts_final.tv_sec = ts.tv_sec + 1;
+			ts_final.tv_nsec = ts.tv_nsec;
+			
+			while (TS_IS_INFERIOR( &ts, &ts_final )) {
+			
+				CHECK_POSIX_DO( pthread_mutex_lock(&order_state_lock), );
+				terminated = (*st == NOTRUNNING);
+				CHECK_POSIX_DO( pthread_mutex_unlock(&order_state_lock), );
+				if (terminated)
+					break;
+				
+				usleep(100000);
+				CHECK_SYS_DO( clock_gettime(CLOCK_REALTIME, &ts), break );
+			}
+		} while (0);
+	}
+
+	/* Now stop the thread and reclaim its resources */
+	CHECK_FCT_DO( fd_thr_term(thr ), /* continue */);
+	
+}
+
+/* Stop the thread after up to one second of wait */
+int fd_rtdisp_fini(void)
+{
+	int i;
+	
+	/* Destroy the incoming queue */
+	CHECK_FCT_DO( fd_queues_fini(&fd_g_incoming), /* ignore */);
+	
+	/* Stop the routing IN thread */
+	stop_thread_delayed(&in_state, &rt_in, "IN routing");
+	
+	/* Destroy the outgoing queue */
+	CHECK_FCT_DO( fd_queues_fini(&fd_g_outgoing), /* ignore */);
+	
+	/* Stop the routing OUT thread */
+	stop_thread_delayed(&out_state, &rt_out, "OUT routing");
+	
+	/* Destroy the local queue */
+	CHECK_FCT_DO( fd_queues_fini(&fd_g_local), /* ignore */);
+	
+	/* Stop the Dispatch threads */
+	if (dispatch != NULL) {
+		for (i=0; i < fd_g_config->cnf_dispthr; i++) {
+			stop_thread_delayed(&disp_state[i], &dispatch[i], "Dispatching");
+		}
+		free(dispatch);
+		dispatch = NULL;
+	}
+	if (disp_state != NULL) {
+		free(disp_state);
+		disp_state = NULL;
+	}
+	
+	return 0;
+}
+
+/* Cleanup handlers */
+int fd_rtdisp_cleanup(void)
+{
+	/* Cleanup all remaining handlers */
+	while (!FD_IS_LIST_EMPTY(&rt_fwd_list)) {
+		CHECK_FCT_DO( fd_rt_fwd_unregister ( (void *)rt_fwd_list.next, NULL ), /* continue */ );
+	}
+	while (!FD_IS_LIST_EMPTY(&rt_out_list)) {
+		CHECK_FCT_DO( fd_rt_out_unregister ( (void *)rt_out_list.next, NULL ), /* continue */ );
+	}
+	
+	fd_disp_unregister_all(); /* destroy remaining handlers */
+
+	return 0;
+}
+
+
+/********************************************************************************/
+/*                     For extensions to register a new appl                    */
+/********************************************************************************/
+
+/* Add an application into the peer's supported apps */
+int fd_disp_app_support ( struct dict_object * app, struct dict_object * vendor, int auth, int acct )
+{
+	application_id_t aid = 0;
+	vendor_id_t	 vid = 0;
+	
+	TRACE_ENTRY("%p %p %d %d", app, vendor, auth, acct);
+	CHECK_PARAMS( app && (auth || acct) );
+	
+	{
+		enum dict_object_type type = 0;
+		struct dict_application_data data;
+		CHECK_FCT( fd_dict_gettype(app, &type) );
+		CHECK_PARAMS( type == DICT_APPLICATION );
+		CHECK_FCT( fd_dict_getval(app, &data) );
+		aid = data.application_id;
+	}
+
+	if (vendor) {
+		enum dict_object_type type = 0;
+		struct dict_vendor_data data;
+		CHECK_FCT( fd_dict_gettype(vendor, &type) );
+		CHECK_PARAMS( type == DICT_VENDOR );
+		CHECK_FCT( fd_dict_getval(vendor, &data) );
+		vid = data.vendor_id;
+	}
+	
+	return fd_app_merge(&fd_g_config->cnf_apps, aid, vid, auth, acct);
+}
+
+
+
diff --git a/libfdcore/sctp.c b/libfdcore/sctp.c
new file mode 100644
index 0000000..c80a497
--- /dev/null
+++ b/libfdcore/sctp.c
@@ -0,0 +1,1353 @@
+/*********************************************************************************************************
+* Software License Agreement (BSD License)                                                               *
+* Author: Sebastien Decugis <sdecugis@freediameter.net>							 *
+*													 *
+* Copyright (c) 2015, WIDE Project and NICT								 *
+* All rights reserved.											 *
+* 													 *
+* Redistribution and use of this software in source and binary forms, with or without modification, are  *
+* permitted provided that the following conditions are met:						 *
+* 													 *
+* * Redistributions of source code must retain the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer.										 *
+*    													 *
+* * Redistributions in binary form must reproduce the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer in the documentation and/or other						 *
+*   materials provided with the distribution.								 *
+* 													 *
+* * Neither the name of the WIDE Project or NICT nor the 						 *
+*   names of its contributors may be used to endorse or 						 *
+*   promote products derived from this software without 						 *
+*   specific prior written permission of WIDE Project and 						 *
+*   NICT.												 *
+* 													 *
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED *
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
+* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR *
+* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 	 *
+* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 	 *
+* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR *
+* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF   *
+* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.								 *
+*********************************************************************************************************/
+
+#include "fdcore-internal.h"
+#include "cnxctx.h"
+
+#include <netinet/sctp.h>
+#include <sys/uio.h>
+
+/* Size of buffer to receive ancilliary data. May need to be enlarged if more sockopt are set... */
+#ifndef CMSG_BUF_LEN
+#define CMSG_BUF_LEN	1024
+#endif /* CMSG_BUF_LEN */
+
+/* Use old draft-ietf-tsvwg-sctpsocket-17 API ? If not defined, RFC6458 API will be used */
+/* #define OLD_SCTP_SOCKET_API */
+
+/* Automatically fallback to old API if some of the new symbols are not defined */
+#if (!defined(SCTP_CONNECTX_4_ARGS) || (!defined(SCTP_RECVRCVINFO)) || (!defined(SCTP_SNDINFO))) 
+# define OLD_SCTP_SOCKET_API
+#endif
+
+
+/* Temper with the retransmission timers to try and improve disconnection detection response? Undef this to keep the defaults of SCTP stack */
+#ifndef USE_DEFAULT_SCTP_RTX_PARAMS	/* make this a configuration option if useful */
+#define ADJUST_RTX_PARAMS
+#endif /* USE_DEFAULT_SCTP_RTX_PARAMS */
+
+/* Pre-binding socket options -- # streams read in config */
+static int fd_setsockopt_prebind(int sk)
+{
+	socklen_t sz;
+	
+	TRACE_ENTRY( "%d", sk);
+	
+	CHECK_PARAMS( sk > 0 );
+	
+	{
+		int reuse = 1;
+		CHECK_SYS(  setsockopt(sk, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse))  );
+	}
+	
+#ifdef ADJUST_RTX_PARAMS
+	/* Set the retransmit parameters */
+	#ifdef SCTP_RTOINFO
+	{
+		struct sctp_rtoinfo rtoinfo;
+		memset(&rtoinfo, 0, sizeof(rtoinfo));
+
+		if (TRACE_BOOL(ANNOYING)) {
+			sz = sizeof(rtoinfo);
+			/* Read socket defaults */
+			CHECK_SYS(  getsockopt(sk, IPPROTO_SCTP, SCTP_RTOINFO, &rtoinfo, &sz)  );
+			if (sz != sizeof(rtoinfo))
+			{
+				TRACE_DEBUG(INFO, "Invalid size of socket option: %d / %d", sz, (socklen_t)sizeof(rtoinfo));
+				return ENOTSUP;
+			}
+			fd_log_debug( "Def SCTP_RTOINFO : srto_initial : %u", rtoinfo.srto_initial);
+			fd_log_debug( "                   srto_min     : %u", rtoinfo.srto_min);
+			fd_log_debug( "                   srto_max     : %u", rtoinfo.srto_max);
+		}
+
+		/* rtoinfo.srto_initial: Estimate of the RTT before it can be measured; keep the default value */
+		rtoinfo.srto_max = 5000; /* Maximum retransmit timer (in ms), we want fast retransmission time. */
+		rtoinfo.srto_min = 1000; /* Value under which the RTO does not descend, we set this value to not conflict with srto_max */
+
+		/* Set the option to the socket */
+		CHECK_SYS(  setsockopt(sk, IPPROTO_SCTP, SCTP_RTOINFO, &rtoinfo, sizeof(rtoinfo))  );
+		
+		if (TRACE_BOOL(ANNOYING)) {
+			/* Check new values */
+			CHECK_SYS(  getsockopt(sk, IPPROTO_SCTP, SCTP_RTOINFO, &rtoinfo, &sz)  );
+			fd_log_debug( "New SCTP_RTOINFO : srto_initial : %u", rtoinfo.srto_initial);
+			fd_log_debug( "                   srto_max     : %u", rtoinfo.srto_max);
+			fd_log_debug( "                   srto_min     : %u", rtoinfo.srto_min);
+		}
+	}
+	#else /* SCTP_RTOINFO */
+	TRACE_DEBUG(ANNOYING, "Skipping SCTP_RTOINFO");
+	#endif /* SCTP_RTOINFO */
+	
+	/* Set the association parameters: max number of retransmits, ... */
+	#ifdef SCTP_ASSOCINFO
+	{
+		struct sctp_assocparams assoc;
+		memset(&assoc, 0, sizeof(assoc));
+
+		if (TRACE_BOOL(ANNOYING)) {
+			sz = sizeof(assoc);
+			/* Read socket defaults */
+			CHECK_SYS(  getsockopt(sk, IPPROTO_SCTP, SCTP_ASSOCINFO, &assoc, &sz)  );
+			if (sz != sizeof(assoc))
+			{
+				TRACE_DEBUG(INFO, "Invalid size of socket option: %d / %d", sz, (socklen_t)sizeof(assoc));
+				return ENOTSUP;
+			}
+			fd_log_debug( "Def SCTP_ASSOCINFO : sasoc_asocmaxrxt               : %hu", assoc.sasoc_asocmaxrxt);
+			fd_log_debug( "                     sasoc_number_peer_destinations : %hu", assoc.sasoc_number_peer_destinations);
+			fd_log_debug( "                     sasoc_peer_rwnd                : %u" , assoc.sasoc_peer_rwnd);
+			fd_log_debug( "                     sasoc_local_rwnd               : %u" , assoc.sasoc_local_rwnd);
+			fd_log_debug( "                     sasoc_cookie_life              : %u" , assoc.sasoc_cookie_life);
+		}
+
+		assoc.sasoc_asocmaxrxt = 4;	/* Maximum number of retransmission attempts: we want fast detection of errors */
+						/* Note that this must remain less than the sum of retransmission parameters of the different paths. */
+		
+		/* Set the option to the socket */
+		CHECK_SYS(  setsockopt(sk, IPPROTO_SCTP, SCTP_ASSOCINFO, &assoc, sizeof(assoc))  );
+		
+		if (TRACE_BOOL(ANNOYING)) {
+			/* Check new values */
+			CHECK_SYS(  getsockopt(sk, IPPROTO_SCTP, SCTP_ASSOCINFO, &assoc, &sz)  );
+			fd_log_debug( "New SCTP_ASSOCINFO : sasoc_asocmaxrxt               : %hu", assoc.sasoc_asocmaxrxt);
+			fd_log_debug( "                     sasoc_number_peer_destinations : %hu", assoc.sasoc_number_peer_destinations);
+			fd_log_debug( "                     sasoc_peer_rwnd                : %u" , assoc.sasoc_peer_rwnd);
+			fd_log_debug( "                     sasoc_local_rwnd               : %u" , assoc.sasoc_local_rwnd);
+			fd_log_debug( "                     sasoc_cookie_life              : %u" , assoc.sasoc_cookie_life);
+		}
+	}
+	#else /* SCTP_ASSOCINFO */
+	TRACE_DEBUG(ANNOYING, "Skipping SCTP_ASSOCINFO");
+	#endif /* SCTP_ASSOCINFO */
+#endif /* ADJUST_RTX_PARAMS */
+	
+	/* Set the INIT parameters, such as number of streams */
+	#ifdef SCTP_INITMSG
+	{
+		struct sctp_initmsg init;
+		memset(&init, 0, sizeof(init));
+		
+		if (TRACE_BOOL(ANNOYING)) {
+			sz = sizeof(init);
+
+			/* Read socket defaults */
+			CHECK_SYS(  getsockopt(sk, IPPROTO_SCTP, SCTP_INITMSG, &init, &sz)  );
+			if (sz != sizeof(init))
+			{
+				TRACE_DEBUG(INFO, "Invalid size of socket option: %d / %d", sz, (socklen_t)sizeof(init));
+				return ENOTSUP;
+			}
+			fd_log_debug( "Def SCTP_INITMSG : sinit_num_ostreams   : %hu", init.sinit_num_ostreams);
+			fd_log_debug( "                   sinit_max_instreams  : %hu", init.sinit_max_instreams);
+			fd_log_debug( "                   sinit_max_attempts   : %hu", init.sinit_max_attempts);
+			fd_log_debug( "                   sinit_max_init_timeo : %hu", init.sinit_max_init_timeo);
+		}
+
+		/* Set the init options -- need to receive SCTP_COMM_UP to confirm the requested parameters, but we don't care (best effort) */
+		init.sinit_num_ostreams	  = fd_g_config->cnf_sctp_str;	/* desired number of outgoing streams */
+		init.sinit_max_init_timeo = CNX_TIMEOUT * 1000;
+
+		/* Set the option to the socket */
+		CHECK_SYS(  setsockopt(sk, IPPROTO_SCTP, SCTP_INITMSG, &init, sizeof(init))  );
+		
+		if (TRACE_BOOL(ANNOYING)) {
+			/* Check new values */
+			CHECK_SYS(  getsockopt(sk, IPPROTO_SCTP, SCTP_INITMSG, &init, &sz)  );
+			fd_log_debug( "New SCTP_INITMSG : sinit_num_ostreams   : %hu", init.sinit_num_ostreams);
+			fd_log_debug( "                   sinit_max_instreams  : %hu", init.sinit_max_instreams);
+			fd_log_debug( "                   sinit_max_attempts   : %hu", init.sinit_max_attempts);
+			fd_log_debug( "                   sinit_max_init_timeo : %hu", init.sinit_max_init_timeo);
+		}
+	}
+	#else /* SCTP_INITMSG */
+	TRACE_DEBUG(ANNOYING, "Skipping SCTP_INITMSG");
+	#endif /* SCTP_INITMSG */
+	
+	/* The SO_LINGER option will be reset if we want to perform SCTP ABORT */
+	#ifdef SO_LINGER
+	{
+		struct linger linger;
+		memset(&linger, 0, sizeof(linger));
+		
+		if (TRACE_BOOL(ANNOYING)) {
+			sz = sizeof(linger);
+			/* Read socket defaults */
+			CHECK_SYS(  getsockopt(sk, SOL_SOCKET, SO_LINGER, &linger, &sz)  );
+			if (sz != sizeof(linger))
+			{
+				TRACE_DEBUG(INFO, "Invalid size of socket option: %d / %d", sz, (socklen_t)sizeof(linger));
+				return ENOTSUP;
+			}
+			fd_log_debug( "Def SO_LINGER : l_onoff  : %d", linger.l_onoff);
+			fd_log_debug( " 	       l_linger : %d", linger.l_linger);
+		}
+		
+		linger.l_onoff	= 0;	/* Do not activate the linger */
+		linger.l_linger = 0;	/* Ignored, but it would mean : Return immediately when closing (=> abort) (graceful shutdown in background) */
+		
+		/* Set the option */
+		CHECK_SYS(  setsockopt(sk, SOL_SOCKET, SO_LINGER, &linger, sizeof(linger))  );
+		
+		if (TRACE_BOOL(ANNOYING)) {
+			/* Check new values */
+			CHECK_SYS(  getsockopt(sk, SOL_SOCKET, SO_LINGER, &linger, &sz)  );
+			fd_log_debug( "New SO_LINGER : l_onoff  : %d", linger.l_onoff);
+			fd_log_debug( "		  l_linger : %d", linger.l_linger);
+		}
+	}
+	#else /* SO_LINGER */
+	TRACE_DEBUG(ANNOYING, "Skipping SO_LINGER");
+	#endif /* SO_LINGER */
+	
+	/* Set the NODELAY option (Nagle-like algorithm) */
+	#ifdef SCTP_NODELAY
+	{
+		int nodelay;
+		
+		if (TRACE_BOOL(ANNOYING)) {
+			sz = sizeof(nodelay);
+			/* Read socket defaults */
+			CHECK_SYS(  getsockopt(sk, IPPROTO_SCTP, SCTP_NODELAY, &nodelay, &sz)  );
+			if (sz != sizeof(nodelay))
+			{
+				TRACE_DEBUG(INFO, "Invalid size of socket option: %d / %d", sz, (socklen_t)sizeof(nodelay));
+				return ENOTSUP;
+			}
+			fd_log_debug( "Def SCTP_NODELAY value : %s", nodelay ? "true" : "false");
+		}
+
+		nodelay = 1;	/* We turn ON to disable the Nagle algorithm, so that packets are sent ASAP. */
+		
+		/* Set the option to the socket */
+		CHECK_SYS(  setsockopt(sk, IPPROTO_SCTP, SCTP_NODELAY, &nodelay, sizeof(nodelay))  );
+		
+		if (TRACE_BOOL(ANNOYING)) {
+			/* Check new values */
+			CHECK_SYS(  getsockopt(sk, IPPROTO_SCTP, SCTP_NODELAY, &nodelay, &sz)  );
+			fd_log_debug( "New SCTP_NODELAY value : %s", nodelay ? "true" : "false");
+		}
+	}
+	#else /* SCTP_NODELAY */
+	TRACE_DEBUG(ANNOYING, "Skipping SCTP_NODELAY");
+	#endif /* SCTP_NODELAY */
+	
+	/*
+	   SO_RCVBUF			size of receiver window
+	   SO_SNDBUF			size of pending data to send
+	   SCTP_AUTOCLOSE		for one-to-many only
+	   SCTP_PRIMARY_ADDR		use this address as primary locally
+	   SCTP_ADAPTATION_LAYER	set adaptation layer indication, we don't use this 
+	*/
+	
+	/* Set the SCTP_DISABLE_FRAGMENTS option, required for TLS */
+	#ifdef SCTP_DISABLE_FRAGMENTS
+	{
+		int nofrag;
+		
+		if (TRACE_BOOL(ANNOYING)) {
+			sz = sizeof(nofrag);
+			/* Read socket defaults */
+			CHECK_SYS(  getsockopt(sk, IPPROTO_SCTP, SCTP_DISABLE_FRAGMENTS, &nofrag, &sz)  );
+			if (sz != sizeof(nofrag))
+			{
+				TRACE_DEBUG(INFO, "Invalid size of socket option: %d / %d", sz, (socklen_t)sizeof(nofrag));
+				return ENOTSUP;
+			}
+			fd_log_debug( "Def SCTP_DISABLE_FRAGMENTS value : %s", nofrag ? "true" : "false");
+		}
+
+		nofrag = 0;	/* We turn ON the fragmentation, since Diameter messages & TLS messages can be quite large. */
+		
+		/* Set the option to the socket */
+		CHECK_SYS(  setsockopt(sk, IPPROTO_SCTP, SCTP_DISABLE_FRAGMENTS, &nofrag, sizeof(nofrag))  );
+		
+		if (TRACE_BOOL(ANNOYING)) {
+			/* Check new values */
+			CHECK_SYS(  getsockopt(sk, IPPROTO_SCTP, SCTP_DISABLE_FRAGMENTS, &nofrag, &sz)  );
+			fd_log_debug( "New SCTP_DISABLE_FRAGMENTS value : %s", nofrag ? "true" : "false");
+		}
+	}
+	#else /* SCTP_DISABLE_FRAGMENTS */
+	# error "TLS requires support of SCTP_DISABLE_FRAGMENTS"
+	#endif /* SCTP_DISABLE_FRAGMENTS */
+	
+	/* SCTP_PEER_ADDR_PARAMS	control heartbeat per peer address. We set it as a default for all addresses in the association; not sure if it works ... */
+	#ifdef SCTP_PEER_ADDR_PARAMS
+	{
+		struct sctp_paddrparams parms;
+		memset(&parms, 0, sizeof(parms));
+		
+		/* Some kernel versions need this to be set */
+		parms.spp_address.ss_family = AF_INET;
+		
+		if (TRACE_BOOL(ANNOYING)) {
+			sz = sizeof(parms);
+
+			/* Read socket defaults */
+			CHECK_SYS(  getsockopt(sk, IPPROTO_SCTP, SCTP_PEER_ADDR_PARAMS, &parms, &sz)  );
+			if (sz != sizeof(parms))
+			{
+				TRACE_DEBUG(INFO, "Invalid size of socket option: %d / %d", sz, (socklen_t)sizeof(parms));
+				return ENOTSUP;
+			}
+			fd_log_debug( "Def SCTP_PEER_ADDR_PARAMS : spp_hbinterval    : %u",  parms.spp_hbinterval);
+			fd_log_debug( "                            spp_pathmaxrxt    : %hu", parms.spp_pathmaxrxt);
+			fd_log_debug( "                            spp_pathmtu       : %u",  parms.spp_pathmtu);
+			fd_log_debug( "                            spp_flags         : %x",  parms.spp_flags);
+			// fd_log_debug( "                            spp_ipv6_flowlabel: %u",  parms.spp_ipv6_flowlabel);
+			// fd_log_debug( "                            spp_ipv4_tos      : %hhu",parms.spp_ipv4_tos);
+		}
+
+		parms.spp_flags = SPP_HB_ENABLE;	/* Enable heartbeat for the association */
+		#ifdef SPP_PMTUD_ENABLE
+		parms.spp_flags |= SPP_PMTUD_ENABLE;	/* also enable path MTU discovery mechanism */
+		#endif /* SPP_PMTUD_ENABLE */
+		
+#ifdef ADJUST_RTX_PARAMS
+		parms.spp_hbinterval = 6000;		/* Send an heartbeat every 6 seconds to quickly start retransmissions */
+		/* parms.spp_pathmaxrxt : max nbr of restransmissions on this address. There is a relationship with sasoc_asocmaxrxt, so we leave the default here */
+#endif /* ADJUST_RTX_PARAMS */
+
+		/* Set the option to the socket */
+		CHECK_SYS(  setsockopt(sk, IPPROTO_SCTP, SCTP_PEER_ADDR_PARAMS, &parms, sizeof(parms)) );
+		
+		if (TRACE_BOOL(ANNOYING)) {
+			/* Check new values */
+			CHECK_SYS(  getsockopt(sk, IPPROTO_SCTP, SCTP_PEER_ADDR_PARAMS, &parms, &sz)  );
+			fd_log_debug( "New SCTP_PEER_ADDR_PARAMS : spp_hbinterval    : %u",  parms.spp_hbinterval);
+			fd_log_debug( "                            spp_pathmaxrxt    : %hu", parms.spp_pathmaxrxt);
+			fd_log_debug( "                            spp_pathmtu       : %u",  parms.spp_pathmtu);
+			fd_log_debug( "                            spp_flags         : %x",  parms.spp_flags);
+			// fd_log_debug( "                            spp_ipv6_flowlabel: %u",  parms.spp_ipv6_flowlabel);
+			// fd_log_debug( "                            spp_ipv4_tos      : %hhu",parms.spp_ipv4_tos);
+		}
+	}
+	#else /* SCTP_PEER_ADDR_PARAMS */
+	TRACE_DEBUG(ANNOYING, "Skipping SCTP_PEER_ADDR_PARAMS");
+	#endif /* SCTP_PEER_ADDR_PARAMS */
+	
+	/*
+	   SCTP_DEFAULT_SEND_PARAM - DEPRECATED // parameters for the sendto() call, we don't use it.
+	*/
+
+	/* Subscribe to some notifications */
+#ifdef OLD_SCTP_SOCKET_API
+	#ifdef SCTP_EVENTS /* DEPRECATED */
+	{
+		struct sctp_event_subscribe event;
+
+		memset(&event, 0, sizeof(event));
+		event.sctp_data_io_event	= 1;	/* to receive the stream ID in SCTP_SNDRCV ancilliary data on message reception */
+		event.sctp_association_event	= 0;	/* new or closed associations (mostly for one-to-many style sockets) */
+		event.sctp_address_event	= 1;	/* address changes */
+		event.sctp_send_failure_event	= 1;	/* delivery failures */
+		event.sctp_peer_error_event	= 1;	/* remote peer sends an error */
+		event.sctp_shutdown_event	= 1;	/* peer has sent a SHUTDOWN */
+		event.sctp_partial_delivery_event = 1;	/* a partial delivery is aborted, probably indicating the connection is being shutdown */
+		// event.sctp_adaptation_layer_event = 0;	/* adaptation layer notifications */
+		// event.sctp_authentication_event = 0;	/* when new key is made active */
+
+		/* Set the option to the socket */
+		CHECK_SYS(  setsockopt(sk, IPPROTO_SCTP, SCTP_EVENTS, &event, sizeof(event)) );
+		
+		if (TRACE_BOOL(ANNOYING)) {
+			sz = sizeof(event);
+			CHECK_SYS(  getsockopt(sk, IPPROTO_SCTP, SCTP_EVENTS, &event, &sz) );
+			if (sz != sizeof(event))
+			{
+				TRACE_DEBUG(INFO, "Invalid size of socket option: %d / %d", sz, (socklen_t)sizeof(event));
+				return ENOTSUP;
+			}
+
+			fd_log_debug( "SCTP_EVENTS : sctp_data_io_event          : %hhu", event.sctp_data_io_event);
+			fd_log_debug( "       	     sctp_association_event      : %hhu", event.sctp_association_event);
+			fd_log_debug( "       	     sctp_address_event	         : %hhu", event.sctp_address_event);
+			fd_log_debug( "       	     sctp_send_failure_event     : %hhu", event.sctp_send_failure_event);
+			fd_log_debug( "       	     sctp_peer_error_event       : %hhu", event.sctp_peer_error_event);
+			fd_log_debug( "       	     sctp_shutdown_event	 : %hhu", event.sctp_shutdown_event);
+			fd_log_debug( "       	     sctp_partial_delivery_event : %hhu", event.sctp_partial_delivery_event);
+			fd_log_debug( "       	     sctp_adaptation_layer_event : %hhu", event.sctp_adaptation_layer_event);
+			// fd_log_debug( "             sctp_authentication_event    : %hhu", event.sctp_authentication_event);
+		}
+	}
+	#else /* SCTP_EVENTS */
+	TRACE_DEBUG(ANNOYING, "Skipping SCTP_EVENTS");
+	#endif /* SCTP_EVENTS */
+#endif /*  OLD_SCTP_SOCKET_API */
+	
+	/* Set the v4 mapped addresses option */
+	#ifdef SCTP_I_WANT_MAPPED_V4_ADDR
+	if (!fd_g_config->cnf_flags.no_ip6) {
+		int v4mapped;
+		
+		if (TRACE_BOOL(ANNOYING)) {
+			sz = sizeof(v4mapped);
+			/* Read socket defaults */
+			CHECK_SYS(  getsockopt(sk, IPPROTO_SCTP, SCTP_I_WANT_MAPPED_V4_ADDR, &v4mapped, &sz)  );
+			if (sz != sizeof(v4mapped))
+			{
+				TRACE_DEBUG(INFO, "Invalid size of socket option: %d / %d", sz, (socklen_t)sizeof(v4mapped));
+				return ENOTSUP;
+			}
+			fd_log_debug( "Def SCTP_I_WANT_MAPPED_V4_ADDR value : %s", v4mapped ? "true" : "false");
+		}
+
+		#ifndef SCTP_USE_MAPPED_ADDRESSES
+		v4mapped = 0;	/* We don't want v4 mapped addresses */
+		#else /* SCTP_USE_MAPPED_ADDRESSES */
+		v4mapped = 1;	/* but we may have to, otherwise the bind fails in some environments */
+		#endif /* SCTP_USE_MAPPED_ADDRESSES */
+		
+		/* Set the option to the socket */
+		CHECK_SYS(  setsockopt(sk, IPPROTO_SCTP, SCTP_I_WANT_MAPPED_V4_ADDR, &v4mapped, sizeof(v4mapped))  );
+		
+		if (TRACE_BOOL(ANNOYING)) {
+			/* Check new values */
+			CHECK_SYS(  getsockopt(sk, IPPROTO_SCTP, SCTP_I_WANT_MAPPED_V4_ADDR, &v4mapped, &sz)  );
+			fd_log_debug( "New SCTP_I_WANT_MAPPED_V4_ADDR value : %s", v4mapped ? "true" : "false");
+		}
+	} else {
+		TRACE_DEBUG(ANNOYING, "Skipping SCTP_I_WANT_MAPPED_V4_ADDR, since IPv6 disabled.");
+	}
+	#else /* SCTP_I_WANT_MAPPED_V4_ADDR */
+	TRACE_DEBUG(ANNOYING, "Skipping SCTP_I_WANT_MAPPED_V4_ADDR");
+	#endif /* SCTP_I_WANT_MAPPED_V4_ADDR */
+	
+	/*
+	   SCTP_MAXSEG			max size of fragmented segments -- bound to PMTU
+	   SCTP_HMAC_IDENT		authentication algorithms
+	   SCTP_AUTH_ACTIVE_KEY		set the active key
+	   SCTP_DELAYED_SACK		control delayed acks
+	*/
+	
+	
+	/* Set the interleaving option */
+	#ifdef SCTP_FRAGMENT_INTERLEAVE
+	{
+		int interleave;
+		
+		if (TRACE_BOOL(ANNOYING)) {
+			sz = sizeof(interleave);
+			/* Read socket defaults */
+			CHECK_SYS(  getsockopt(sk, IPPROTO_SCTP, SCTP_FRAGMENT_INTERLEAVE, &interleave, &sz)  );
+			if (sz != sizeof(interleave))
+			{
+				TRACE_DEBUG(INFO, "Invalid size of socket option: %d / %d", sz, (socklen_t)sizeof(interleave));
+				return ENOTSUP;
+			}
+			fd_log_debug( "Def SCTP_FRAGMENT_INTERLEAVE value : %d", interleave);
+		}
+
+		#if 0
+		interleave = 2;	/* Allow partial delivery on several streams at the same time, since we are stream-aware in our security modules */
+		#else /* 0 */
+		interleave = 1;	/* hmmm actually, we are not yet capable of handling this, and we don t need it. */
+		#endif /* 0 */
+		
+		/* Set the option to the socket */
+		CHECK_SYS(  setsockopt(sk, IPPROTO_SCTP, SCTP_FRAGMENT_INTERLEAVE, &interleave, sizeof(interleave))  );
+		
+		if (TRACE_BOOL(ANNOYING)) {
+			/* Check new values */
+			CHECK_SYS(  getsockopt(sk, IPPROTO_SCTP, SCTP_FRAGMENT_INTERLEAVE, &interleave, &sz)  );
+			fd_log_debug( "New SCTP_FRAGMENT_INTERLEAVE value : %d", interleave);
+		}
+	}
+	#else /* SCTP_FRAGMENT_INTERLEAVE */
+	TRACE_DEBUG(ANNOYING, "Skipping SCTP_FRAGMENT_INTERLEAVE");
+	#endif /* SCTP_FRAGMENT_INTERLEAVE */
+	
+	/*
+	   SCTP_PARTIAL_DELIVERY_POINT	control partial delivery size
+	   SCTP_USE_EXT_RCVINFO	- DEPRECATED	use extended receive info structure (information about the next message if available)
+	 */
+	/* SCTP_AUTO_ASCONF is set by the postbind function */
+	/*
+	   SCTP_MAX_BURST		number of packets that can be burst emitted
+	   SCTP_CONTEXT			save a context information along with the association.
+	 */
+	 
+	/* SCTP_EXPLICIT_EOR: we assume implicit EOR in freeDiameter, so let's ensure this is known by the stack */
+	#ifdef SCTP_EXPLICIT_EOR
+	{
+		int bool;
+		
+		if (TRACE_BOOL(ANNOYING)) {
+			sz = sizeof(bool);
+			/* Read socket defaults */
+			CHECK_SYS(  getsockopt(sk, IPPROTO_SCTP, SCTP_EXPLICIT_EOR, &bool, &sz)  );
+			if (sz != sizeof(bool))
+			{
+				TRACE_DEBUG(INFO, "Invalid size of socket option: %d / %d", sz, (socklen_t)sizeof(bool));
+				return ENOTSUP;
+			}
+			fd_log_debug( "Def SCTP_EXPLICIT_EOR value : %s", bool ? "true" : "false");
+		}
+
+		bool = 0;
+		
+		/* Set the option to the socket */
+		CHECK_SYS(  setsockopt(sk, IPPROTO_SCTP, SCTP_EXPLICIT_EOR, &bool, sizeof(bool))  );
+		
+		if (TRACE_BOOL(ANNOYING)) {
+			/* Check new values */
+			CHECK_SYS(  getsockopt(sk, IPPROTO_SCTP, SCTP_EXPLICIT_EOR, &bool, &sz)  );
+			fd_log_debug( "New SCTP_EXPLICIT_EOR value : %s", bool ? "true" : "false");
+		}
+	}
+	#else /* SCTP_EXPLICIT_EOR */
+	TRACE_DEBUG(ANNOYING, "Skipping SCTP_EXPLICIT_EOR");
+	#endif /* SCTP_EXPLICIT_EOR */
+	
+	/*
+	   SCTP_REUSE_PORT		share one listening port with several sockets
+	*/
+	
+#ifndef OLD_SCTP_SOCKET_API
+	#ifdef SCTP_EVENT
+	{
+		/* Subscribe to the following events */
+		int events_I_want[] = {
+		#ifdef SCTP_ASSOC_CHANGE
+			/* SCTP_ASSOC_CHANGE, */
+		#endif 
+		#ifdef SCTP_PEER_ADDR_CHANGE
+			SCTP_PEER_ADDR_CHANGE,
+		#endif
+		#ifdef SCTP_REMOTE_ERROR
+			SCTP_REMOTE_ERROR,
+		#endif
+		#ifdef SCTP_SEND_FAILED_EVENT
+			SCTP_SEND_FAILED_EVENT,
+		#endif
+		#ifdef SCTP_SHUTDOWN_EVENT
+			SCTP_SHUTDOWN_EVENT,
+		#endif
+		#ifdef SCTP_ADAPTATION_INDICATION
+			/* SCTP_ADAPTATION_INDICATION, */
+		#endif
+		#ifdef SCTP_PARTIAL_DELIVERY_EVENT
+			/* SCTP_PARTIAL_DELIVERY_EVENT, */
+		#endif
+		#ifdef SCTP_AUTHENTICATION_EVENT
+			/* SCTP_AUTHENTICATION_EVENT, */
+		#endif
+		#ifdef SCTP_SENDER_DRY_EVENT
+			/* SCTP_SENDER_DRY_EVENT, */
+		#endif
+			0
+		};
+		int i;
+		
+		struct sctp_event event;
+		
+		for (i = 0; i < (sizeof(events_I_want) / sizeof(events_I_want[0]) - 1); i++) {
+			memset(&event, 0, sizeof(event));
+			event.se_type = events_I_want[i];
+			event.se_on = 1;
+			
+			/* Set the option to the socket */
+			CHECK_SYS(  setsockopt(sk, IPPROTO_SCTP, SCTP_EVENT, &event, sizeof(event)) );
+		}
+	}
+	#else /* SCTP_EVENT */
+	TRACE_DEBUG(ANNOYING, "Skipping SCTP_EVENT");
+	#endif /* SCTP_EVENT */
+	
+	
+	#ifdef SCTP_RECVRCVINFO /* Replaces SCTP_SNDRCV */
+	{
+		int bool = 1;
+		
+		/* Set the option to the socket */
+		CHECK_SYS(  setsockopt(sk, IPPROTO_SCTP, SCTP_RECVRCVINFO, &bool, sizeof(bool))  );
+		
+	}
+	#else /* SCTP_RECVRCVINFO */
+	TRACE_DEBUG(ANNOYING, "Skipping SCTP_RECVRCVINFO");
+	#endif /* SCTP_RECVRCVINFO */
+	
+	
+#endif /* OLD_SCTP_SOCKET_API */
+	
+	/* 
+		SCTP_RECVNXTINFO
+		
+		SCTP_DEFAULT_SNDINFO : send defaults
+		SCTP_DEFAULT_PRINFO  : default PR-SCTP
+	*/
+	
+
+	/* In case of no_ip4, force the v6only option */
+	#ifdef IPV6_V6ONLY
+	if (fd_g_config->cnf_flags.no_ip4) {
+		int opt = 1;
+		CHECK_SYS(setsockopt(sk, IPPROTO_IPV6, IPV6_V6ONLY, &opt, sizeof(opt)));
+	}
+	#endif /* IPV6_V6ONLY */
+	
+	return 0;
+}
+
+
+/* Post-binding socket options */
+static int fd_setsockopt_postbind(int sk, int bound_to_default)
+{
+	TRACE_ENTRY( "%d %d", sk, bound_to_default);
+	
+	CHECK_PARAMS( (sk > 0) );
+	
+	/* Set the ASCONF option */
+	#ifdef SCTP_AUTO_ASCONF
+	if (bound_to_default) {
+		int asconf;
+		
+		if (TRACE_BOOL(ANNOYING)) {
+			socklen_t sz;
+
+			sz = sizeof(asconf);
+			/* Read socket defaults */
+			CHECK_SYS(  getsockopt(sk, IPPROTO_SCTP, SCTP_AUTO_ASCONF, &asconf, &sz)  );
+			if (sz != sizeof(asconf))
+			{
+				TRACE_DEBUG(INFO, "Invalid size of socket option: %d / %d", sz, (socklen_t)sizeof(asconf));
+				return ENOTSUP;
+			}
+			fd_log_debug( "Def SCTP_AUTO_ASCONF value : %s", asconf ? "true" : "false");
+		}
+
+		asconf = 1;	/* allow automatic use of added or removed addresses in the association (for bound-all sockets) */
+		
+		/* Set the option to the socket */
+		CHECK_SYS(  setsockopt(sk, IPPROTO_SCTP, SCTP_AUTO_ASCONF, &asconf, sizeof(asconf))  );
+		
+		if (TRACE_BOOL(ANNOYING)) {
+			socklen_t sz = sizeof(asconf);
+			/* Check new values */
+			CHECK_SYS(  getsockopt(sk, IPPROTO_SCTP, SCTP_AUTO_ASCONF, &asconf, &sz)  );
+			fd_log_debug( "New SCTP_AUTO_ASCONF value : %s", asconf ? "true" : "false");
+		}
+	}
+	#else /* SCTP_AUTO_ASCONF */
+	TRACE_DEBUG(ANNOYING, "Skipping SCTP_AUTO_ASCONF");
+	#endif /* SCTP_AUTO_ASCONF */
+	
+	return 0;
+}
+
+/* Add addresses from a list to an array, with filter on the flags */
+static int add_addresses_from_list_mask(uint8_t ** array, size_t * size, int * addr_count, int target_family, uint16_t port, struct fd_list * list, uint32_t mask, uint32_t val)
+{
+	struct fd_list * li;
+	int to_add4 = 0;
+	int to_add6 = 0;
+	union {
+		uint8_t *buf;
+		sSA4	*sin;
+		sSA6	*sin6;
+	} ptr;
+	size_t sz;
+	
+	/* First, count the number of addresses to add */
+	for (li = list->next; li != list; li = li->next) {
+		struct fd_endpoint * ep = (struct fd_endpoint *) li;
+		
+		/* Do the flag match ? */
+		if ((val & mask) != (ep->flags & mask))
+			continue;
+		
+		if (ep->sa.sa_family == AF_INET) {
+			to_add4 ++;
+		} else {
+			to_add6 ++;
+		}
+	}
+	
+	if ((to_add4 + to_add6) == 0)
+		return 0; /* nothing to do */
+	
+	/* The size to add */
+	if (target_family == AF_INET) {
+		sz = to_add4 * sizeof(sSA4);
+	} else {
+		#ifndef SCTP_USE_MAPPED_ADDRESSES
+			sz = (to_add4 * sizeof(sSA4)) + (to_add6 * sizeof(sSA6));
+		#else /* SCTP_USE_MAPPED_ADDRESSES */
+			sz = (to_add4 + to_add6) * sizeof(sSA6);
+		#endif /* SCTP_USE_MAPPED_ADDRESSES */
+	}
+	
+	/* Now, (re)alloc the array to store the new addresses */
+	CHECK_MALLOC( *array = realloc(*array, *size + sz) );
+	
+	/* Finally, add the addresses */
+	for (li = list->next; li != list; li = li->next) {
+		struct fd_endpoint * ep = (struct fd_endpoint *) li;
+		
+		/* Skip v6 addresses for v4 socket */
+		if ((target_family == AF_INET) && (ep->sa.sa_family == AF_INET6))
+			continue;
+		
+		/* Are the flags matching ? */
+		if ((val & mask) != (ep->flags & mask))
+			continue;
+		
+		/* Size of the new SA we are adding (array may contain a mix of sockaddr_in and sockaddr_in6) */
+		#ifndef SCTP_USE_MAPPED_ADDRESSES
+		if (ep->sa.sa_family == AF_INET6)
+		#else /* SCTP_USE_MAPPED_ADDRESSES */
+		if (target_family == AF_INET6)
+		#endif /* SCTP_USE_MAPPED_ADDRESSES */
+			sz = sizeof(sSA6);
+		else
+			sz = sizeof(sSA4);
+		
+		/* Place where we add the new address */
+		ptr.buf = *array + *size; /* place of the new SA */
+		
+		/* Update other information */
+		*size += sz;
+		*addr_count += 1;
+		
+		/* And write the addr in the buffer */
+		if (sz == sizeof(sSA4)) {
+			memcpy(ptr.buf, &ep->sin, sz);
+			ptr.sin->sin_port = port;
+		} else {
+			if (ep->sa.sa_family == AF_INET) { /* We must map the address */ 
+				memset(ptr.buf, 0, sz);
+				ptr.sin6->sin6_family = AF_INET6;
+				IN6_ADDR_V4MAP( &ptr.sin6->sin6_addr.s6_addr, ep->sin.sin_addr.s_addr );
+			} else {
+				memcpy(ptr.sin6, &ep->sin6, sz);
+			}
+			ptr.sin6->sin6_port = port;
+		}
+	}
+	
+	return 0;
+}
+
+/* Create a socket server and bind it according to daemon s configuration */
+int fd_sctp_create_bind_server( int * sock, int family, struct fd_list * list, uint16_t port )
+{
+	int bind_default;
+	
+	TRACE_ENTRY("%p %i %p %hu", sock, family, list, port);
+	CHECK_PARAMS(sock);
+	
+	/* Create the socket */
+	CHECK_SYS( *sock = socket(family, SOCK_STREAM, IPPROTO_SCTP) );
+	
+	/* Set pre-binding socket options, including number of streams etc... */
+	CHECK_FCT( fd_setsockopt_prebind(*sock) );
+	
+	bind_default = (! list) || (FD_IS_LIST_EMPTY(list)) ;
+redo:
+	if ( bind_default ) {
+		/* Implicit endpoints : bind to default addresses */
+		union {
+			sSS  ss;
+			sSA  sa;
+			sSA4 sin;
+			sSA6 sin6;
+		} s;
+		
+		/* 0.0.0.0 and [::] are all zeros */
+		memset(&s, 0, sizeof(s));
+		
+		s.sa.sa_family = family;
+		
+		if (family == AF_INET)
+			s.sin.sin_port = htons(port);
+		else
+			s.sin6.sin6_port = htons(port);
+		
+		CHECK_SYS( bind(*sock, &s.sa, sSAlen(&s)) );
+		
+	} else {
+		/* Explicit endpoints to bind to from config */
+		
+		sSA * sar = NULL; /* array of addresses */
+		size_t sz = 0; /* size of the array */
+		int count = 0; /* number of sock addr in the array */
+		
+		/* Create the array of configured addresses */
+		CHECK_FCT( add_addresses_from_list_mask((void *)&sar, &sz, &count, family, htons(port), list, EP_FL_CONF, EP_FL_CONF) );
+		
+		if (!count) {
+			/* None of the addresses in the list came from configuration, we bind to default */
+			bind_default = 1;
+			goto redo;
+		}
+		
+		#if 0
+			union {
+				sSA	*sa;
+				uint8_t *buf;
+			} ptr;
+			int i;
+			ptr.sa = sar;
+			fd_log_debug("Calling sctp_bindx with the following address array:");
+			for (i = 0; i < count; i++) {
+				TRACE_sSA(FD_LOG_DEBUG, FULL, "    - ", ptr.sa, NI_NUMERICHOST | NI_NUMERICSERV, "" );
+				ptr.buf += (ptr.sa->sa_family == AF_INET) ? sizeof(sSA4) : sizeof(sSA6) ;
+			}
+		#endif
+		
+		/* Bind to this array */
+		CHECK_SYS(  sctp_bindx(*sock, sar, count, SCTP_BINDX_ADD_ADDR)  );
+		
+		/* We don't need sar anymore */
+		free(sar);
+	}
+	
+	/* Now, the server is bound, set remaining sockopt */
+	CHECK_FCT( fd_setsockopt_postbind(*sock, bind_default) );
+	
+	/* Debug: show all local listening addresses */
+	#if 0
+		sSA *sar;
+		union {
+			sSA	*sa;
+			uint8_t *buf;
+		} ptr;
+		int sz;
+		
+		CHECK_SYS(  sz = sctp_getladdrs(*sock, 0, &sar)  );
+		
+		fd_log_debug("SCTP server bound on :");
+		for (ptr.sa = sar; sz-- > 0; ptr.buf += (ptr.sa->sa_family == AF_INET) ? sizeof(sSA4) : sizeof(sSA6)) {
+			TRACE_sSA(FD_LOG_DEBUG, FULL, "    - ", ptr.sa, NI_NUMERICHOST | NI_NUMERICSERV, "" );
+		}
+		sctp_freeladdrs(sar);
+	#endif
+
+	return 0;
+}
+
+/* Allow clients connections on server sockets */
+int fd_sctp_listen( int sock )
+{
+	TRACE_ENTRY("%d", sock);
+	CHECK_SYS( listen(sock, 5) );
+	return 0;
+}
+
+/* Create a client socket and connect to remote server */
+int fd_sctp_client( int *sock, int no_ip6, uint16_t port, struct fd_list * list )
+{
+	int family;
+	union {
+		uint8_t *buf;
+		sSA	*sa;
+	} sar;
+	size_t size = 0;
+	int count = 0;
+	int ret;
+	
+	sar.buf = NULL;
+	
+	TRACE_ENTRY("%p %i %hu %p", sock, no_ip6, port, list);
+	CHECK_PARAMS( sock && list && (!FD_IS_LIST_EMPTY(list)) );
+	
+	if (no_ip6) {
+		family = AF_INET;
+	} else {
+		family = AF_INET6;
+	}
+	
+	/* Create the socket */
+	CHECK_SYS( *sock = socket(family, SOCK_STREAM, IPPROTO_SCTP) );
+	
+	/* Cleanup if we are cancelled */
+	pthread_cleanup_push(fd_cleanup_socket, sock);
+	
+	/* Set the socket options */
+	CHECK_FCT_DO( ret = fd_setsockopt_prebind(*sock), goto out );
+	
+	/* Create the array of addresses, add first the configured addresses, then the discovered, then the other ones */
+	CHECK_FCT_DO( ret = add_addresses_from_list_mask(&sar.buf, &size, &count, family, htons(port), list, EP_FL_CONF,              EP_FL_CONF	), goto out );
+	CHECK_FCT_DO( ret = add_addresses_from_list_mask(&sar.buf, &size, &count, family, htons(port), list, EP_FL_CONF | EP_FL_DISC, EP_FL_DISC	), goto out );
+	CHECK_FCT_DO( ret = add_addresses_from_list_mask(&sar.buf, &size, &count, family, htons(port), list, EP_FL_CONF | EP_FL_DISC, 0		), goto out );
+	
+	/* Try connecting */
+	LOG_A("Attempting SCTP connection (%d addresses attempted) ", count);
+		
+#if 0
+		/* Dump the SAs */
+		union {
+			uint8_t *buf;
+			sSA	*sa;
+			sSA4	*sin;
+			sSA6	*sin6;
+		} ptr;
+		int i;
+		ptr.buf = sar.buf;
+		for (i=0; i< count; i++) {
+			TRACE_sSA(FD_LOG_DEBUG, FULL, "  - ", ptr.sa, NI_NUMERICHOST | NI_NUMERICSERV, "" );
+			ptr.buf += (ptr.sa->sa_family == AF_INET) ? sizeof(sSA4) : sizeof(sSA6);
+		}
+#endif
+	
+	/* Bug in some Linux kernel, the sctp_connectx is not a cancellation point. To avoid blocking freeDiameter, we allow async cancel here */
+	pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL);
+#ifdef SCTP_CONNECTX_4_ARGS
+	ret = sctp_connectx(*sock, sar.sa, count, NULL);
+#else /* SCTP_CONNECTX_4_ARGS */
+	ret = sctp_connectx(*sock, sar.sa, count);
+#endif /* SCTP_CONNECTX_4_ARGS */
+	/* back to normal cancelation behabior */
+	pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, NULL);
+	
+	if (ret < 0) {
+		ret = errno;
+		/* Some errors are expected, we log at different level */
+		LOG_A("sctp_connectx returned an error: %s", strerror(ret));
+		goto out;
+	}
+	
+	free(sar.buf); sar.buf = NULL;
+	
+	/* Set the remaining sockopts */
+	CHECK_FCT_DO( ret = fd_setsockopt_postbind(*sock, 1), 
+		{ 
+			CHECK_SYS_DO( shutdown(*sock, SHUT_RDWR), /* continue */ );
+		} );
+	
+out:
+	;
+	pthread_cleanup_pop(0);
+	
+	if (ret) {
+		if (*sock > 0) {
+			CHECK_SYS_DO( close(*sock), /* continue */ );
+			*sock = -1;
+		}
+		free(sar.buf);
+	}
+	return ret;
+}
+
+/* Retrieve streams information from a connected association -- optionally provide the primary address */
+int fd_sctp_get_str_info( int sock, uint16_t *in, uint16_t *out, sSS *primary )
+{
+	struct sctp_status status;
+	socklen_t sz = sizeof(status);
+	
+	TRACE_ENTRY("%d %p %p %p", sock, in, out, primary);
+	CHECK_PARAMS( (sock > 0) && in && out );
+	
+	/* Read the association parameters */
+	memset(&status, 0, sizeof(status));
+	CHECK_SYS(  getsockopt(sock, IPPROTO_SCTP, SCTP_STATUS, &status, &sz) );
+	if (sz != sizeof(status))
+	{
+		TRACE_DEBUG(INFO, "Invalid size of socket option: %d / %zd", sz, sizeof(status));
+		return ENOTSUP;
+	}
+#if 0
+		char sa_buf[sSA_DUMP_STRLEN];
+		fd_sa_sdump_numeric(sa_buf, &status.sstat_primary.spinfo_address);
+		fd_log_debug( "SCTP_STATUS : sstat_state                  : %i" , status.sstat_state);
+		fd_log_debug( "              sstat_rwnd  	          : %u" , status.sstat_rwnd);
+		fd_log_debug( "		     sstat_unackdata	          : %hu", status.sstat_unackdata);
+		fd_log_debug( "		     sstat_penddata 	          : %hu", status.sstat_penddata);
+		fd_log_debug( "		     sstat_instrms  	          : %hu", status.sstat_instrms);
+		fd_log_debug( "		     sstat_outstrms 	          : %hu", status.sstat_outstrms);
+		fd_log_debug( "		     sstat_fragmentation_point    : %u" , status.sstat_fragmentation_point);
+		fd_log_debug( "		     sstat_primary.spinfo_address : %s" , sa_buf);
+		fd_log_debug( "		     sstat_primary.spinfo_state   : %d" , status.sstat_primary.spinfo_state);
+		fd_log_debug( "		     sstat_primary.spinfo_cwnd    : %u" , status.sstat_primary.spinfo_cwnd);
+		fd_log_debug( "		     sstat_primary.spinfo_srtt    : %u" , status.sstat_primary.spinfo_srtt);
+		fd_log_debug( "		     sstat_primary.spinfo_rto     : %u" , status.sstat_primary.spinfo_rto);
+		fd_log_debug( "		     sstat_primary.spinfo_mtu     : %u" , status.sstat_primary.spinfo_mtu);
+#endif /* 0 */
+	
+	*in = status.sstat_instrms;
+	*out = status.sstat_outstrms;
+	
+	if (primary)
+		memcpy(primary, &status.sstat_primary.spinfo_address, sizeof(sSS));
+	
+	return 0;
+}
+
+/* Get the list of remote endpoints of the socket */
+int fd_sctp_get_remote_ep(int sock, struct fd_list * list)
+{
+	union {
+		sSA	*sa;
+		uint8_t	*buf;
+	} ptr;
+	
+	sSA * data = NULL;
+	int count;
+	
+	TRACE_ENTRY("%d %p", sock, list);
+	CHECK_PARAMS(list);
+	
+	/* Read the list on the socket */
+	CHECK_SYS( count = sctp_getpaddrs(sock, 0, &data)  );
+	ptr.sa = data;
+	
+	while (count) {
+		socklen_t sl;
+		switch (ptr.sa->sa_family) {
+			case AF_INET:	sl = sizeof(sSA4); break;
+			case AF_INET6:	sl = sizeof(sSA6); break;
+			default:
+				TRACE_DEBUG(INFO, "Unknown address family returned in sctp_getpaddrs: %d, skip", ptr.sa->sa_family);
+				/* There is a bug in current Linux kernel: http://www.spinics.net/lists/linux-sctp/msg00760.html */
+				goto stop;
+		}
+				
+		CHECK_FCT( fd_ep_add_merge( list, ptr.sa, sl, EP_FL_LL ) );
+		ptr.buf += sl;
+		count --;
+	}
+stop:	
+	/* Free the list */
+	sctp_freepaddrs(data);
+	
+	/* Now get the primary address, the add function will take care of merging with existing entry */
+	{
+		 
+		struct sctp_status status;
+		socklen_t sz = sizeof(status);
+		int ret;
+		
+		memset(&status, 0, sizeof(status));
+		/* Attempt to use SCTP_STATUS message to retrieve the primary address */
+		CHECK_SYS_DO( ret = getsockopt(sock, IPPROTO_SCTP, SCTP_STATUS, &status, &sz), /* continue */);
+		if (sz != sizeof(status))
+			ret = -1;
+		sz = sizeof(sSS);
+		if (ret < 0)
+		{
+			/* Fallback to getsockname -- not recommended by draft-ietf-tsvwg-sctpsocket-19#section-7.4 */
+			CHECK_SYS(getpeername(sock, (sSA *)&status.sstat_primary.spinfo_address, &sz));
+		}
+			
+		CHECK_FCT( fd_ep_add_merge( list, (sSA *)&status.sstat_primary.spinfo_address, sz, EP_FL_PRIMARY ) );
+	}
+	
+	/* Done! */
+	return 0;
+}
+
+/* Send a vector over a specified stream */
+ssize_t fd_sctp_sendstrv(struct cnxctx * conn, uint16_t strid, const struct iovec *iov, int iovcnt)
+{
+	struct msghdr mhdr;
+	struct cmsghdr 		*hdr;
+#ifdef OLD_SCTP_SOCKET_API
+	struct sctp_sndrcvinfo	*sndrcv;
+	uint8_t anci[CMSG_SPACE(sizeof(struct sctp_sndrcvinfo))];
+#else /* OLD_SCTP_SOCKET_API */
+	struct sctp_sndinfo 	*sndinf;
+	uint8_t anci[CMSG_SPACE(sizeof(struct sctp_sndinfo))];	
+#endif /* OLD_SCTP_SOCKET_API */
+	ssize_t ret;
+	struct timespec ts, now;
+	
+	TRACE_ENTRY("%p %hu %p %d", conn, strid, iov, iovcnt);
+	CHECK_PARAMS_DO(conn && iov && iovcnt, { errno = EINVAL; return -1; } );
+	CHECK_SYS_DO(  clock_gettime(CLOCK_REALTIME, &ts), return -1 );
+	
+	memset(&mhdr, 0, sizeof(mhdr));
+	memset(&anci, 0, sizeof(anci));
+	
+	/* Anciliary data: specify SCTP stream */
+	hdr = (struct cmsghdr *)anci;
+	hdr->cmsg_len   = sizeof(anci);
+	hdr->cmsg_level = IPPROTO_SCTP;
+#ifdef OLD_SCTP_SOCKET_API
+	hdr->cmsg_type  = SCTP_SNDRCV;
+	sndrcv = (struct sctp_sndrcvinfo *)CMSG_DATA(hdr);
+	sndrcv->sinfo_stream = strid;
+#else /* OLD_SCTP_SOCKET_API */
+	hdr->cmsg_type  = SCTP_SNDINFO;
+	sndinf = (struct sctp_sndinfo *)CMSG_DATA(hdr);
+	sndinf->snd_sid = strid;
+#endif /* OLD_SCTP_SOCKET_API */
+	/* note : we could store other data also, for example in .sinfo_ppid for remote peer or in .sinfo_context for errors. */
+	
+	/* We don't use mhdr.msg_name here; it could be used to specify an address different from the primary */
+	
+	mhdr.msg_iov    = (struct iovec *)iov;
+	mhdr.msg_iovlen = iovcnt;
+	
+	mhdr.msg_control    = anci;
+	mhdr.msg_controllen = sizeof(anci);
+	
+	TRACE_DEBUG(FULL, "Sending %d chunks of data (first:%zdb) on stream %hu of socket %d", iovcnt, iov[0].iov_len, strid, conn->cc_socket);
+again:	
+	ret = sendmsg(conn->cc_socket, &mhdr, 0);
+	/* Handle special case of timeout */
+	if ((ret < 0) && ((errno == EAGAIN) || (errno == EINTR))) {
+		pthread_testcancel();
+		/* Check how much time we were blocked for this sending. */
+		CHECK_SYS_DO(  clock_gettime(CLOCK_REALTIME, &now), return -1 );
+		if ( ((now.tv_sec - ts.tv_sec) * 1000 + ((now.tv_nsec - ts.tv_nsec) / 1000000L)) > MAX_HOTL_BLOCKING_TIME) {
+			LOG_D("Unable to send any data for %dms, closing the connection", MAX_HOTL_BLOCKING_TIME);
+		} else if (! fd_cnx_teststate(conn, CC_STATUS_CLOSING )) {
+			goto again; /* don't care, just ignore */
+		}
+		
+		/* propagate the error */
+		errno = -ret;
+		ret = -1;
+	}
+	
+	CHECK_SYS_DO( ret, ); /* for tracing error only */
+	
+	return ret;
+}
+
+/* Receive the next data from the socket, or next notification */
+int fd_sctp_recvmeta(struct cnxctx * conn, uint16_t * strid, uint8_t ** buf, size_t * len, int *event)
+{
+	ssize_t 		 ret = 0;
+	struct msghdr 		 mhdr;
+	char   			 ancidata[ CMSG_BUF_LEN ];
+	struct iovec 		 iov;
+	uint8_t			*data = NULL;
+	size_t 			 bufsz = 0, datasize = 0;
+	size_t			 mempagesz = sysconf(_SC_PAGESIZE); /* We alloc buffer by memory pages for efficiency */
+	int 			 timedout = 0;
+	
+	TRACE_ENTRY("%p %p %p %p %p", conn, strid, buf, len, event);
+	CHECK_PARAMS( conn && buf && len && event );
+	
+	/* Cleanup out parameters */
+	*buf = NULL;
+	*len = 0;
+	*event = 0;
+	
+	/* Prepare header for receiving message */
+	memset(&mhdr, 0, sizeof(mhdr));
+	mhdr.msg_iov    = &iov;
+	mhdr.msg_iovlen = 1;
+	mhdr.msg_control    = &ancidata;
+	mhdr.msg_controllen = sizeof(ancidata);
+	
+next_message:
+	datasize = 0;
+	
+	/* We will loop while all data is not received. */
+incomplete:
+	while (datasize >= bufsz ) {
+		/* The buffer is full, enlarge it */
+		bufsz += mempagesz;
+		CHECK_MALLOC( data = realloc(data, bufsz ) );
+	}
+	/* the new data will be received following the preceding */
+	memset(&iov,  0, sizeof(iov));
+	iov.iov_base = data + datasize ;
+	iov.iov_len  = bufsz - datasize;
+
+	/* Receive data from the socket */
+again:
+	pthread_cleanup_push(free, data);
+	ret = recvmsg(conn->cc_socket, &mhdr, 0);
+	pthread_testcancel();
+	pthread_cleanup_pop(0);
+	
+	/* First, handle timeouts (same as fd_cnx_s_recv) */
+	if ((ret < 0) && ((errno == EAGAIN) || (errno == EINTR))) {
+		if (! fd_cnx_teststate(conn, CC_STATUS_CLOSING ))
+			goto again; /* don't care, just ignore */
+		if (!timedout) {
+			timedout ++; /* allow for one timeout while closing */
+			goto again;
+		}
+		/* fallback to normal handling */
+	}
+	
+	/* Handle errors */
+	if (ret <= 0) { /* Socket timedout, closed, or an error occurred */
+		CHECK_SYS_DO(ret, /* to log in case of error */);
+		free(data);
+		*event = FDEVP_CNX_ERROR;
+		return 0;
+	}
+	
+	/* Update the size of data we received */
+	datasize += ret;
+
+	/* SCTP provides an indication when we received a full record; loop if it is not the case */
+	if ( ! (mhdr.msg_flags & MSG_EOR) ) {
+		goto incomplete;
+	}
+	
+	/* Handle the case where the data received is a notification */
+	if (mhdr.msg_flags & MSG_NOTIFICATION) {
+		union sctp_notification * notif = (union sctp_notification *) data;
+		
+		TRACE_DEBUG(FULL, "Received %zdb data of notification on socket %d", datasize, conn->cc_socket);
+	
+		switch (notif->sn_header.sn_type) {
+			
+			case SCTP_ASSOC_CHANGE: /* We should not receive these as we did not subscribe for it */
+				TRACE_DEBUG(FULL, "Received SCTP_ASSOC_CHANGE notification");
+				TRACE_DEBUG(ANNOYING, "    state : %hu", notif->sn_assoc_change.sac_state);
+				TRACE_DEBUG(ANNOYING, "    error : %hu", notif->sn_assoc_change.sac_error);
+				TRACE_DEBUG(ANNOYING, "    instr : %hu", notif->sn_assoc_change.sac_inbound_streams);
+				TRACE_DEBUG(ANNOYING, "   outstr : %hu", notif->sn_assoc_change.sac_outbound_streams);
+				
+				*event = FDEVP_CNX_EP_CHANGE;
+				break;
+	
+			case SCTP_PEER_ADDR_CHANGE:
+				TRACE_DEBUG(FULL, "Received SCTP_PEER_ADDR_CHANGE notification");
+				/* TRACE_sSA(FD_LOG_DEBUG, ANNOYING, "    intf_change : ", &(notif->sn_paddr_change.spc_aaddr), NI_NUMERICHOST | NI_NUMERICSERV, "" ); */
+				TRACE_DEBUG(ANNOYING, "          state : %d", notif->sn_paddr_change.spc_state);
+				TRACE_DEBUG(ANNOYING, "          error : %d", notif->sn_paddr_change.spc_error);
+				
+				*event = FDEVP_CNX_EP_CHANGE;
+				break;
+	
+			case SCTP_REMOTE_ERROR:
+				TRACE_DEBUG(FULL, "Received SCTP_REMOTE_ERROR notification");
+				TRACE_DEBUG(ANNOYING, "    err : %hu", ntohs(notif->sn_remote_error.sre_error));
+				TRACE_DEBUG(ANNOYING, "    len : %hu", ntohs(notif->sn_remote_error.sre_length));
+				
+				*event = FDEVP_CNX_ERROR;
+				break;
+	
+#ifdef OLD_SCTP_SOCKET_API
+			case SCTP_SEND_FAILED:
+				TRACE_DEBUG(FULL, "Received SCTP_SEND_FAILED notification");
+				TRACE_DEBUG(ANNOYING, "    len : %hu", notif->sn_send_failed.ssf_length);
+				TRACE_DEBUG(ANNOYING, "    err : %d",  notif->sn_send_failed.ssf_error);
+				
+				*event = FDEVP_CNX_ERROR;
+				break;
+#else /*  OLD_SCTP_SOCKET_API */
+			case SCTP_SEND_FAILED_EVENT:
+				TRACE_DEBUG(FULL, "Received SCTP_SEND_FAILED_EVENT notification");
+				*event = FDEVP_CNX_ERROR;
+				break;
+#endif	/*  OLD_SCTP_SOCKET_API */		
+			case SCTP_SHUTDOWN_EVENT:
+				TRACE_DEBUG(FULL, "Received SCTP_SHUTDOWN_EVENT notification");
+				
+				*event = FDEVP_CNX_SHUTDOWN;
+				break;
+				
+#ifndef OLD_SCTP_SOCKET_API
+			case SCTP_NOTIFICATIONS_STOPPED_EVENT:
+				TRACE_DEBUG(INFO, "Received SCTP_NOTIFICATIONS_STOPPED_EVENT notification, marking the association in error state");
+				*event = FDEVP_CNX_ERROR;
+				break;
+#endif	/*  OLD_SCTP_SOCKET_API */		
+			
+			default:	
+				TRACE_DEBUG(FULL, "Received unknown notification %d, ignored", notif->sn_header.sn_type);
+				goto next_message;
+		}
+		
+		free(data);
+		return 0;
+	}
+	
+	/* From this point, we have received a message */
+	*event = FDEVP_CNX_MSG_RECV;
+	*buf = data;
+	*len = datasize;
+	
+	if (strid) {
+		struct cmsghdr 		*hdr;
+#ifdef OLD_SCTP_SOCKET_API
+		struct sctp_sndrcvinfo	*sndrcv;
+#else /*  OLD_SCTP_SOCKET_API */
+		struct sctp_rcvinfo	*rcvinf;
+#endif /*  OLD_SCTP_SOCKET_API */
+		
+		/* Handle the anciliary data */
+		for (hdr = CMSG_FIRSTHDR(&mhdr); hdr; hdr = CMSG_NXTHDR(&mhdr, hdr)) {
+
+			/* We deal only with anciliary data at SCTP level */
+			if (hdr->cmsg_level != IPPROTO_SCTP) {
+				TRACE_DEBUG(FULL, "Received some anciliary data at level %d, skipped", hdr->cmsg_level);
+				continue;
+			}
+			
+#ifdef OLD_SCTP_SOCKET_API
+			/* Also only interested in SCTP_SNDRCV message for the moment */
+			if (hdr->cmsg_type != SCTP_SNDRCV) {
+				TRACE_DEBUG(FULL, "Anciliary block IPPROTO_SCTP / %d, skipped", hdr->cmsg_type);
+				continue;
+			}
+			
+			sndrcv = (struct sctp_sndrcvinfo *) CMSG_DATA(hdr);
+			if (TRACE_BOOL(ANNOYING)) {
+				fd_log_debug( "Anciliary block IPPROTO_SCTP / SCTP_SNDRCV");
+				fd_log_debug( "    sinfo_stream    : %hu", sndrcv->sinfo_stream);
+				fd_log_debug( "    sinfo_ssn       : %hu", sndrcv->sinfo_ssn);
+				fd_log_debug( "    sinfo_flags     : %hu", sndrcv->sinfo_flags);
+				/* fd_log_debug( "    sinfo_pr_policy : %hu", sndrcv->sinfo_pr_policy); */
+				fd_log_debug( "    sinfo_ppid      : %u" , sndrcv->sinfo_ppid);
+				fd_log_debug( "    sinfo_context   : %u" , sndrcv->sinfo_context);
+				/* fd_log_debug( "    sinfo_pr_value  : %u" , sndrcv->sinfo_pr_value); */
+				fd_log_debug( "    sinfo_tsn       : %u" , sndrcv->sinfo_tsn);
+				fd_log_debug( "    sinfo_cumtsn    : %u" , sndrcv->sinfo_cumtsn);
+			}
+
+			*strid = sndrcv->sinfo_stream;
+#else /*  OLD_SCTP_SOCKET_API */
+			/* Also only interested in SCTP_RCVINFO message for the moment */
+			if (hdr->cmsg_type != SCTP_RCVINFO) {
+				TRACE_DEBUG(FULL, "Anciliary block IPPROTO_SCTP / %d, skipped", hdr->cmsg_type);
+				continue;
+			}
+			
+			rcvinf = (struct sctp_rcvinfo *) CMSG_DATA(hdr);
+
+			*strid = rcvinf->rcv_sid;
+#endif /*  OLD_SCTP_SOCKET_API */
+			
+			
+		}
+		TRACE_DEBUG(FULL, "Received %zdb data on socket %d, stream %hu", datasize, conn->cc_socket, *strid);
+	} else {
+		TRACE_DEBUG(FULL, "Received %zdb data on socket %d (stream ignored)", datasize, conn->cc_socket);
+	}
+	
+	return 0;
+}
diff --git a/libfdcore/sctp3436.c b/libfdcore/sctp3436.c
new file mode 100644
index 0000000..f45a1ab
--- /dev/null
+++ b/libfdcore/sctp3436.c
@@ -0,0 +1,793 @@
+/*********************************************************************************************************
+* Software License Agreement (BSD License)                                                               *
+* Author: Sebastien Decugis <sdecugis@freediameter.net>							 *
+*													 *
+* Copyright (c) 2013, WIDE Project and NICT								 *
+* All rights reserved.											 *
+* 													 *
+* Redistribution and use of this software in source and binary forms, with or without modification, are  *
+* permitted provided that the following conditions are met:						 *
+* 													 *
+* * Redistributions of source code must retain the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer.										 *
+*    													 *
+* * Redistributions in binary form must reproduce the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer in the documentation and/or other						 *
+*   materials provided with the distribution.								 *
+* 													 *
+* * Neither the name of the WIDE Project or NICT nor the 						 *
+*   names of its contributors may be used to endorse or 						 *
+*   promote products derived from this software without 						 *
+*   specific prior written permission of WIDE Project and 						 *
+*   NICT.												 *
+* 													 *
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED *
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
+* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR *
+* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 	 *
+* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 	 *
+* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR *
+* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF   *
+* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.								 *
+*********************************************************************************************************/
+
+/* This file contains code for TLS over multi-stream SCTP wrapper implementation (GnuTLS does not support this) */
+/* See http://aaa.koganei.wide.ad.jp/blogs/index.php/waaad/2008/08/18/tls-over-sctp for history */
+
+#include "fdcore-internal.h"
+#include "cnxctx.h"
+
+#include <netinet/sctp.h>
+#include <sys/uio.h>
+
+/*
+
+Architecture of this wrapper:
+ - we have several fifo queues (1 per stream pairs).
+ GnuTLS is configured to use custom push / pull functions:
+ - the pull function retrieves the data from the fifo queue corresponding to a stream #.
+ - the push function sends the data on a certain stream.
+ We also have a demux thread that reads the socket and store received data in the appropriate fifo
+ 
+ We have one gnutls_session per stream pair, and as many threads that read the gnutls records and save incoming data to the target queue.
+ 
+This complexity is required because we cannot read a socket for a given stream only; we can only get the next message and find its stream.
+*/
+
+/* Note that this mechanism is replaced by DTLS in RFC6733 */
+
+/*************************************************************/
+/*                      threads                              */
+/*************************************************************/
+
+/* Demux received data and store in the appropriate fifo */
+static void * demuxer(void * arg)
+{
+	struct cnxctx * conn = arg;
+	uint8_t * buf;
+	size_t    bufsz;
+	int	  event;
+	uint16_t  strid;
+	
+	TRACE_ENTRY("%p", arg);
+	CHECK_PARAMS_DO(conn && (conn->cc_socket > 0), goto out);
+	
+	/* Set the thread name */
+	{
+		char buf[48];
+		snprintf(buf, sizeof(buf), "Demuxer (%d:%s)", conn->cc_socket, conn->cc_remid);
+		fd_log_threadname ( buf );
+	}
+	
+	ASSERT( conn->cc_proto == IPPROTO_SCTP );
+	ASSERT( fd_cnx_target_queue(conn) );
+	ASSERT( conn->cc_sctp3436_data.array );
+	
+	do {
+		CHECK_FCT_DO( fd_sctp_recvmeta(conn, &strid, &buf, &bufsz, &event), goto fatal );
+		switch (event) {
+			case FDEVP_CNX_MSG_RECV:
+				/* Demux this message to the appropriate fifo, another thread will pull, gnutls process, and send to target queue */
+				if (strid < conn->cc_sctp_para.pairs) {
+					CHECK_FCT_DO(fd_event_send(conn->cc_sctp3436_data.array[strid].raw_recv, event, bufsz, buf), goto fatal );
+				} else {
+					TRACE_DEBUG(INFO, "Received packet (%zd bytes) on out-of-range stream #%d from %s, discarded.", bufsz, strid, conn->cc_remid);
+					free(buf);
+				}
+				break;
+				
+			case FDEVP_CNX_EP_CHANGE:
+				/* Send this event to the target queue */
+				CHECK_FCT_DO( fd_event_send( fd_cnx_target_queue(conn), event, bufsz, buf), goto fatal );
+				break;
+			
+			case FDEVP_CNX_ERROR:
+				goto out;
+				
+			case FDEVP_CNX_SHUTDOWN:
+				/* Just ignore the notification for now, we will get another error later anyway */
+				continue;
+				
+			default:
+				goto fatal;
+		}
+		
+	} while (conn->cc_loop);
+	
+out:
+	/* Signal termination of the connection to all decipher threads */
+	for (strid = 0; strid < conn->cc_sctp_para.pairs; strid++) {
+		if (conn->cc_sctp3436_data.array[strid].raw_recv) {
+			CHECK_FCT_DO(fd_event_send(conn->cc_sctp3436_data.array[strid].raw_recv, FDEVP_CNX_ERROR, 0, NULL), goto fatal );
+		}
+	}
+	fd_cnx_markerror(conn);
+	TRACE_DEBUG(FULL, "Thread terminated");	
+	return NULL;
+	
+fatal:
+	/* An unrecoverable error occurred, stop the daemon */
+	CHECK_FCT_DO(fd_core_shutdown(), );
+	goto out;
+}
+
+/* Decrypt the data received in this stream pair and store it in the target queue */
+static void * decipher(void * arg)
+{
+	struct sctp3436_ctx * ctx = arg;
+	struct cnxctx 	 *cnx;
+	
+	TRACE_ENTRY("%p", arg);
+	CHECK_PARAMS_DO(ctx && ctx->raw_recv && ctx->parent, goto error);
+	cnx = ctx->parent;
+	ASSERT( fd_cnx_target_queue(cnx) );
+	
+	/* Set the thread name */
+	{
+		char buf[48];
+		snprintf(buf, sizeof(buf), "Decipher (%hu@%d:%s)", ctx->strid, cnx->cc_socket, cnx->cc_remid);
+		fd_log_threadname ( buf );
+	}
+	
+	/* The next function loops while there is no error */
+	CHECK_FCT_DO(fd_tls_rcvthr_core(cnx, ctx->strid ? ctx->session : cnx->cc_tls_para.session), /* continue */);
+error:
+	fd_cnx_markerror(cnx);
+	TRACE_DEBUG(FULL, "Thread terminated");	
+	return NULL;
+}
+
+/*************************************************************/
+/*                     push / pull                           */
+/*************************************************************/
+
+#ifdef GNUTLS_VERSION_300
+/* Check if data is available for gnutls on a given context */
+static int sctp3436_pull_timeout(gnutls_transport_ptr_t tr, unsigned int ms)
+{
+	struct sctp3436_ctx * ctx = (struct sctp3436_ctx *) tr;
+	struct timespec tsstore, *ts = NULL;
+	int ret;
+	
+	TRACE_ENTRY("%p %d", tr, ms);
+	
+	if (ctx->partial.buf)
+		return 1; /* data is already available for pull */
+	
+	if (ms) {
+		CHECK_SYS_DO(  clock_gettime(CLOCK_REALTIME, &tsstore),  return -1  );
+		tsstore.tv_nsec += (long)ms * 1000000;
+		tsstore.tv_sec += tsstore.tv_nsec / 1000000000L;
+		tsstore.tv_nsec %= 1000000000L;
+		ts = &tsstore;
+	}
+	
+	ret = fd_fifo_select ( ctx->raw_recv, ts );
+	if (ret < 0) {
+		errno = -ret;
+		ret = -1;
+	}
+		
+	return ret;
+}
+#endif /* GNUTLS_VERSION_300 */
+
+/* Send data over the connection, called by gnutls */
+#ifndef GNUTLS_VERSION_212
+static ssize_t sctp3436_push(gnutls_transport_ptr_t tr, const void * data, size_t len)
+{
+	struct sctp3436_ctx * ctx = (struct sctp3436_ctx *) tr;
+	struct iovec iov;
+	
+	TRACE_ENTRY("%p %p %zd", tr, data, len);
+	CHECK_PARAMS_DO( tr && data, { errno = EINVAL; return -1; } );
+	
+	iov.iov_base = (void *)data;
+	iov.iov_len  = len;
+	
+	return fd_sctp_sendstrv(ctx->parent, ctx->strid, &iov, 1);
+}
+#else /*  GNUTLS_VERSION_212 */
+static ssize_t sctp3436_pushv(gnutls_transport_ptr_t tr, const giovec_t * iov, int iovcnt)
+{
+	struct sctp3436_ctx * ctx = (struct sctp3436_ctx *) tr;
+	
+	TRACE_ENTRY("%p %p %d", tr, iov, iovcnt);
+	CHECK_PARAMS_DO( tr && iov, { errno = EINVAL; return -1; } );
+	
+	return fd_sctp_sendstrv(ctx->parent, ctx->strid, (const struct iovec *)iov, iovcnt);
+}
+#endif /*  GNUTLS_VERSION_212 */
+
+/* Retrieve data received on a stream and already demultiplexed */
+static ssize_t sctp3436_pull(gnutls_transport_ptr_t tr, void * buf, size_t len)
+{
+	struct sctp3436_ctx * ctx = (struct sctp3436_ctx *) tr;
+	size_t pulled = 0;
+	int emptied;
+	
+	TRACE_ENTRY("%p %p %zd", tr, buf, len);
+	CHECK_PARAMS_DO( tr && buf, { errno = EINVAL; goto error; } );
+	
+	/* If we don't have data available now, pull new message from the fifo -- this is blocking (until the queue is destroyed) */
+	if (!ctx->partial.buf) {
+		int ev;
+		CHECK_FCT_DO( errno = fd_event_get(ctx->raw_recv, &ev, &ctx->partial.bufsz, (void *)&ctx->partial.buf), goto error );
+		if (ev == FDEVP_CNX_ERROR) {
+			/* Documentations says to return 0 on connection closed, but it does hang within gnutls_handshake */
+			return -1;
+		}
+	}
+		
+	pulled = ctx->partial.bufsz - ctx->partial.offset;
+	if (pulled <= len) {
+		emptied = 1;
+	} else {
+		/* limit to the capacity of destination buffer */
+		emptied = 0;
+		pulled = len;
+	}
+
+	/* Store the data in the destination buffer */
+	memcpy(buf, ctx->partial.buf + ctx->partial.offset, pulled);
+
+	/* Free the buffer if we read all its content, and reset the partial structure */
+	if (emptied) {
+		free(ctx->partial.buf);
+		memset(&ctx->partial, 0, sizeof(ctx->partial));
+	} else {
+		ctx->partial.offset += pulled;
+	}
+
+	/* We are done */
+	return pulled;
+	
+error:
+	gnutls_transport_set_errno (ctx->session, errno);
+	return -1;
+}
+
+/* Set the parameters of a session to use the appropriate fifo and stream information */
+#ifndef GNUTLS_VERSION_300
+GCC_DIAG_OFF("-Wdeprecated-declarations")
+#endif /* !GNUTLS_VERSION_300 */
+static void set_sess_transport(gnutls_session_t session, struct sctp3436_ctx *ctx)
+{
+	/* Set the transport pointer passed to push & pull callbacks */
+	GNUTLS_TRACE( gnutls_transport_set_ptr( session, (gnutls_transport_ptr_t) ctx ) );
+	
+	/* Reset the low water value, since we don't use sockets */
+#ifndef GNUTLS_VERSION_300
+	/* starting version 2.12, this call is not needed */
+	GNUTLS_TRACE( gnutls_transport_set_lowat( session, 0 ) );
+#else  /* GNUTLS_VERSION_300 */
+	/* but in 3.0 we have to provide the pull_timeout callback */
+	GNUTLS_TRACE( gnutls_transport_set_pull_timeout_function( session, sctp3436_pull_timeout ) );
+#endif /* GNUTLS_VERSION_300 */
+	
+	/* Set the push and pull callbacks */
+	GNUTLS_TRACE( gnutls_transport_set_pull_function(session, sctp3436_pull) );
+#ifndef GNUTLS_VERSION_212
+	GNUTLS_TRACE( gnutls_transport_set_push_function(session, sctp3436_push) );
+#else /* GNUTLS_VERSION_212 */
+	GNUTLS_TRACE( gnutls_transport_set_vec_push_function(session, sctp3436_pushv) );
+#endif /* GNUTLS_VERSION_212 */
+
+	return;
+}
+#ifndef GNUTLS_VERSION_300
+GCC_DIAG_ON("-Wdeprecated-declarations")
+#endif /* !GNUTLS_VERSION_300 */
+
+/*************************************************************/
+/*               Session resuming support                    */
+/*************************************************************/
+
+struct sr_store {
+	struct fd_list	 list;	/* list of sr_data, ordered by key.size then key.data */
+	pthread_rwlock_t lock;
+	struct cnxctx   *parent;
+	/* Add another list to chain in a global list to implement a garbage collector on sessions -- TODO if needed */
+};
+
+/* Saved master session data for resuming sessions */
+struct sr_data {
+	struct fd_list	chain;
+	gnutls_datum_t	key;
+	gnutls_datum_t 	data;
+};
+
+/* Initialize the store area for a connection */
+static int store_init(struct cnxctx * conn)
+{
+	TRACE_ENTRY("%p", conn);
+	CHECK_PARAMS( conn && !conn->cc_sctp3436_data.sess_store );
+	
+	CHECK_MALLOC( conn->cc_sctp3436_data.sess_store = malloc(sizeof(struct sr_store)) );
+	memset(conn->cc_sctp3436_data.sess_store, 0, sizeof(struct sr_store));
+	
+	fd_list_init(&conn->cc_sctp3436_data.sess_store->list, NULL);
+	CHECK_POSIX( pthread_rwlock_init(&conn->cc_sctp3436_data.sess_store->lock, NULL) );
+	conn->cc_sctp3436_data.sess_store->parent = conn;
+	
+	return 0;
+}
+
+/* Destroy the store area for a connection, and all its content */
+static void store_destroy(struct cnxctx * conn)
+{
+	/* Del all list entries */
+	TRACE_ENTRY("%p", conn);
+	CHECK_PARAMS_DO( conn, return );
+	
+	if (!conn->cc_sctp3436_data.sess_store)
+		return;
+	
+	CHECK_POSIX_DO( pthread_rwlock_destroy(&conn->cc_sctp3436_data.sess_store->lock), /* continue */ );
+	
+	while (!FD_IS_LIST_EMPTY(&conn->cc_sctp3436_data.sess_store->list)) {
+		struct sr_data * sr = (struct sr_data *) conn->cc_sctp3436_data.sess_store->list.next;
+		fd_list_unlink( &sr->chain );
+		free(sr->key.data);
+		free(sr->data.data);
+		free(sr);
+	}
+	
+	free(conn->cc_sctp3436_data.sess_store);
+	conn->cc_sctp3436_data.sess_store = NULL;
+	return;
+}
+
+/* Search the position (or next if not found) of a key in a store */
+static struct fd_list * find_or_next(struct sr_store * sto, gnutls_datum_t key, int * match)
+{
+	struct fd_list * ret;
+	*match = 0;
+	
+	for (ret = sto->list.next; ret != &sto->list; ret = ret->next) {
+		int cmp = 0;
+		struct sr_data * sr = (struct sr_data *)ret;
+		
+		cmp = fd_os_cmp(key.data, key.size, sr->key.data, sr->key.size);
+		if (cmp > 0)
+			continue;
+		
+		if (cmp == 0)
+			*match = 1;
+		
+		break;
+	}
+	
+	return ret;
+}
+
+/* Callbacks for the TLS server side of the connection, called during gnutls_handshake */
+static int sr_store (void *dbf, gnutls_datum_t key, gnutls_datum_t data)
+{
+	struct sr_store * sto = (struct sr_store *)dbf;
+	struct fd_list * li;
+	struct sr_data * sr;
+	int match = 0;
+	int ret = 0;
+	
+	TRACE_DEBUG( GNUTLS_DBG_LEVEL, "GNUTLS Callback: %s", __PRETTY_FUNCTION__ );
+	CHECK_PARAMS_DO( sto && key.data && data.data, return -1 );
+	
+	CHECK_POSIX_DO( pthread_rwlock_wrlock(&sto->lock), return -1 );
+	TRACE_BUFFER(FD_LOG_DEBUG, GNUTLS_DBG_LEVEL, "Session store [key ", key.data, key.size, "]");
+	
+	li = find_or_next(sto, key, &match);
+	if (match) {
+		sr = (struct sr_data *)li;
+		
+		/* Check the data is the same */
+		if ((data.size != sr->data.size) || memcmp(data.data, sr->data.data, data.size)) {
+			TRACE_DEBUG(INFO, "GnuTLS tried to store a session with same key and different data!");
+			TRACE_BUFFER(FD_LOG_DEBUG, INFO, "Session store [key ", key.data, key.size, "]");
+			TRACE_BUFFER(FD_LOG_DEBUG, INFO, "  -- old data [", sr->data.data, sr->data.size, "]");
+			TRACE_BUFFER(FD_LOG_DEBUG, INFO, "  -- new data [", data.data, data.size, "]");
+			
+			ret = -1;
+		} else {
+			TRACE_DEBUG(GNUTLS_DBG_LEVEL, "GnuTLS tried to store a session with same key and same data, skipped.");
+		}
+		goto out;
+	}
+	
+	/* Create a new entry */
+	CHECK_MALLOC_DO( sr = malloc(sizeof(struct sr_data)), { ret = -1; goto out; } );
+	memset(sr, 0, sizeof(struct sr_data));
+
+	fd_list_init(&sr->chain, sr);
+
+	CHECK_MALLOC_DO( sr->key.data = malloc(key.size), { ret = -1; goto out; } );
+	sr->key.size = key.size;
+	memcpy(sr->key.data, key.data, key.size);
+
+	CHECK_MALLOC_DO( sr->data.data = malloc(data.size), { ret = -1; goto out; } );
+	sr->data.size = data.size;
+	memcpy(sr->data.data, data.data, data.size);
+	
+	/* Save this new entry in the list, we are done */
+	fd_list_insert_before(li, &sr->chain);
+
+out:	
+	CHECK_POSIX_DO( pthread_rwlock_unlock(&sto->lock), return -1 );
+	return ret;
+}
+
+static int sr_remove (void *dbf, gnutls_datum_t key)
+{
+	struct sr_store * sto = (struct sr_store *)dbf;
+	struct fd_list * li;
+	struct sr_data * sr;
+	int match = 0;
+	int ret = 0;
+	
+	TRACE_DEBUG( GNUTLS_DBG_LEVEL, "GNUTLS Callback: %s", __PRETTY_FUNCTION__ );
+	CHECK_PARAMS_DO( sto && key.data, return -1 );
+	
+	CHECK_POSIX_DO( pthread_rwlock_wrlock(&sto->lock), return -1 );
+	TRACE_BUFFER(FD_LOG_DEBUG, GNUTLS_DBG_LEVEL, "Session delete [key ", key.data, key.size, "]");
+	
+	li = find_or_next(sto, key, &match);
+	if (match) {
+		sr = (struct sr_data *)li;
+		
+		/* Destroy this data */
+		fd_list_unlink(li);
+		free(sr->key.data);
+		free(sr->data.data);
+		free(sr);
+	} else {
+		/* It was not found */
+		ret = -1;
+	}
+	
+	CHECK_POSIX_DO( pthread_rwlock_unlock(&sto->lock), return -1 );
+	return ret;
+}
+
+static gnutls_datum_t sr_fetch (void *dbf, gnutls_datum_t key)
+{
+	struct sr_store * sto = (struct sr_store *)dbf;
+	struct fd_list * li;
+	struct sr_data * sr;
+	int match = 0;
+	gnutls_datum_t res = { NULL, 0 };
+	gnutls_datum_t error = { NULL, 0 };
+
+	TRACE_DEBUG( GNUTLS_DBG_LEVEL, "GNUTLS Callback: %s", __PRETTY_FUNCTION__ );
+	CHECK_PARAMS_DO( sto && key.data, return error );
+
+	CHECK_POSIX_DO( pthread_rwlock_rdlock(&sto->lock), return error );
+	TRACE_BUFFER(FD_LOG_DEBUG, GNUTLS_DBG_LEVEL, "Session fetch [key ", key.data, key.size, "]");
+	
+	li = find_or_next(sto, key, &match);
+	if (match) {
+		sr = (struct sr_data *)li;
+		GNUTLS_TRACE( CHECK_MALLOC_DO(res.data = gnutls_malloc(sr->data.size), goto out ) );
+		res.size = sr->data.size;
+		memcpy(res.data, sr->data.data, res.size);
+	}
+out:	
+	TRACE_DEBUG(GNUTLS_DBG_LEVEL, "Fetched (%p, %d) from store %p", res.data, res.size, sto);
+	CHECK_POSIX_DO( pthread_rwlock_unlock(&sto->lock), return error);
+	return res;
+}
+
+/* Set the session pointer in a session object */
+static void set_resume_callbacks(gnutls_session_t session, struct cnxctx * conn)
+{
+	TRACE_ENTRY("%p", conn);
+	
+	GNUTLS_TRACE( gnutls_db_set_retrieve_function(session, sr_fetch));
+	GNUTLS_TRACE( gnutls_db_set_remove_function  (session, sr_remove));
+	GNUTLS_TRACE( gnutls_db_set_store_function   (session, sr_store));
+	GNUTLS_TRACE( gnutls_db_set_ptr              (session, conn->cc_sctp3436_data.sess_store));
+	
+	return;
+}
+
+/* The handshake is made in parallel in several threads to speed up */
+static void * handshake_resume_th(void * arg)
+{
+	struct sctp3436_ctx * ctx = (struct sctp3436_ctx *) arg;
+	int resumed;
+	
+	TRACE_ENTRY("%p", arg);
+	
+	/* Set the thread name */
+	{
+		char buf[48];
+		snprintf(buf, sizeof(buf), "Handshake resume (%hu@%d)", ctx->strid, ctx->parent->cc_socket);
+		fd_log_threadname ( buf );
+	}
+	
+	TRACE_DEBUG(FULL, "Starting TLS resumed handshake on stream %hu", ctx->strid);
+
+	CHECK_GNUTLS_DO( gnutls_handshake( ctx->session ), return NULL);
+			
+	GNUTLS_TRACE( resumed = gnutls_session_is_resumed(ctx->session) );
+	#ifndef GNUTLS_VERSION_300
+	if (!resumed) {
+		/* Check the credentials here also */
+		CHECK_FCT_DO( fd_tls_verify_credentials(ctx->session, ctx->parent, 0), return NULL );
+	}
+	#endif /* GNUTLS_VERSION_300 */
+	if (TRACE_BOOL(FULL)) {
+		if (resumed) {
+			fd_log_debug("Session was resumed successfully on stream %hu (conn: '%s')", ctx->strid, fd_cnx_getid(ctx->parent));
+		} else {
+			fd_log_debug("Session was NOT resumed on stream %hu  (full handshake) (conn: '%s')", ctx->strid, fd_cnx_getid(ctx->parent));
+		}
+	}
+			
+	/* Finished, OK */
+	return arg;
+}
+
+
+/*************************************************************/
+/*                     Exported functions                    */
+/*************************************************************/
+
+/* Initialize the wrapper for the connection */
+int fd_sctp3436_init(struct cnxctx * conn)
+{
+	uint16_t i;
+	
+	TRACE_ENTRY("%p", conn);
+	CHECK_PARAMS( conn && (conn->cc_sctp_para.pairs > 1) && (!conn->cc_sctp3436_data.array) );
+	
+	/* First, alloc the array and initialize the non-TLS data */
+	CHECK_MALLOC( conn->cc_sctp3436_data.array = calloc(conn->cc_sctp_para.pairs, sizeof(struct sctp3436_ctx))  );
+	for (i = 0; i < conn->cc_sctp_para.pairs; i++) {
+		conn->cc_sctp3436_data.array[i].parent = conn;
+		conn->cc_sctp3436_data.array[i].strid  = i;
+		CHECK_FCT( fd_fifo_new(&conn->cc_sctp3436_data.array[i].raw_recv, 10) );
+	}
+	
+	/* Set push/pull functions in the master session, using fifo in array[0] */
+	set_sess_transport(conn->cc_tls_para.session, &conn->cc_sctp3436_data.array[0]);
+	
+	/* For server side, we also initialize the resuming capabilities */
+	if (conn->cc_tls_para.mode == GNUTLS_SERVER) {
+		
+		/* Prepare the store for sessions data */
+		CHECK_FCT( store_init(conn) );
+		
+		/* Set the callbacks for resuming in the master session */
+		set_resume_callbacks(conn->cc_tls_para.session, conn);
+	}
+
+	/* Start the demux thread */
+	CHECK_POSIX( pthread_create( &conn->cc_rcvthr, NULL, demuxer, conn ) );
+	
+	return 0;
+}
+
+/* Handshake other streams, after full handshake on the master session */
+int fd_sctp3436_handshake_others(struct cnxctx * conn, char * priority, void * alt_creds)
+{
+	uint16_t i;
+	int errors = 0;
+	gnutls_datum_t 	master_data;
+	
+	TRACE_ENTRY("%p %p", conn, priority);
+	CHECK_PARAMS( conn && (conn->cc_sctp_para.pairs > 1) && conn->cc_sctp3436_data.array );
+
+	/* Server side: we set all the parameters, the resume callback will take care of resuming the session */
+	/* Client side: we duplicate the parameters of the master session, then set the transport pointer */
+	
+	/* For client side, retrieve the master session parameters */
+	if (conn->cc_tls_para.mode == GNUTLS_CLIENT) {
+		CHECK_GNUTLS_DO( gnutls_session_get_data2(conn->cc_tls_para.session, &master_data), return ENOMEM );
+		/* For debug: */
+		if (TRACE_BOOL(GNUTLS_DBG_LEVEL)) {
+			uint8_t  id[256];
+			size_t	 ids = sizeof(id);
+			CHECK_GNUTLS_DO( gnutls_session_get_id(conn->cc_tls_para.session, id, &ids), /* continue */ );
+			TRACE_BUFFER(FD_LOG_DEBUG, GNUTLS_DBG_LEVEL, "Master session id: [", id, ids, "]");
+		}
+	}
+	
+	/* Initialize the session objects and start the handshake in a separate thread */
+	for (i = 1; i < conn->cc_sctp_para.pairs; i++) {
+		/* Set credentials and priority */
+		CHECK_FCT( fd_tls_prepare(&conn->cc_sctp3436_data.array[i].session, conn->cc_tls_para.mode, 0, priority, alt_creds) );
+		
+		/* additional initialization for gnutls 3.x */
+		#ifdef GNUTLS_VERSION_300
+			/* the verify function has already been set in the global initialization in config.c */
+
+		/* fd_tls_verify_credentials_2 uses the connection */
+		gnutls_session_set_ptr (conn->cc_sctp3436_data.array[i].session, (void *) conn);
+
+		if ((conn->cc_tls_para.cn != NULL) && (conn->cc_tls_para.mode == GNUTLS_CLIENT)) {
+			/* this might allow virtual hosting on the remote peer */
+			CHECK_GNUTLS_DO( gnutls_server_name_set (conn->cc_sctp3436_data.array[i].session, GNUTLS_NAME_DNS, conn->cc_tls_para.cn, strlen(conn->cc_tls_para.cn)), /* ignore failure */);
+		}
+
+		#endif /* GNUTLS_VERSION_300 */
+
+		#ifdef GNUTLS_VERSION_310
+		GNUTLS_TRACE( gnutls_handshake_set_timeout( conn->cc_sctp3436_data.array[i].session, GNUTLS_DEFAULT_HANDSHAKE_TIMEOUT));
+		#endif /* GNUTLS_VERSION_310 */
+
+		/* For the client, copy data from master session; for the server, set session resuming pointers */
+		if (conn->cc_tls_para.mode == GNUTLS_CLIENT) {
+			CHECK_GNUTLS_DO( gnutls_session_set_data(conn->cc_sctp3436_data.array[i].session, master_data.data, master_data.size), return ENOMEM );
+		} else {
+			set_resume_callbacks(conn->cc_sctp3436_data.array[i].session, conn);
+		}
+		
+		/* Set transport parameters */
+		set_sess_transport(conn->cc_sctp3436_data.array[i].session, &conn->cc_sctp3436_data.array[i]);
+		
+		/* Start the handshake thread */
+		CHECK_POSIX( pthread_create( &conn->cc_sctp3436_data.array[i].thr, NULL, handshake_resume_th, &conn->cc_sctp3436_data.array[i] ) );
+	}
+	
+	/* We can now release the memory of master session data if any */
+	if (conn->cc_tls_para.mode == GNUTLS_CLIENT) {
+		GNUTLS_TRACE( gnutls_free(master_data.data) );
+	}
+	
+	/* Now wait for all handshakes to finish */
+	for (i = 1; i < conn->cc_sctp_para.pairs; i++) {
+		void * ret;
+		CHECK_POSIX( pthread_join(conn->cc_sctp3436_data.array[i].thr, &ret) );
+		conn->cc_sctp3436_data.array[i].thr = (pthread_t) NULL;
+		if (ret == NULL) {
+			errors++; /* Handshake failed on this stream */
+		}
+	}
+	
+	if (errors) {
+		TRACE_DEBUG(INFO, "Handshake failed on %d/%hd stream pairs", errors, conn->cc_sctp_para.pairs);
+		fd_cnx_markerror(conn);
+		return ENOTCONN;
+	}
+	
+	return 0;
+}
+
+/* Receive messages from others ? all other stream pairs : the master pair */
+int fd_sctp3436_startthreads(struct cnxctx * conn, int others)
+{
+	uint16_t i;
+	
+	TRACE_ENTRY("%p", conn);
+	CHECK_PARAMS( conn && conn->cc_sctp3436_data.array );
+	
+	if (others) {
+		for (i = 1; i < conn->cc_sctp_para.pairs; i++) {
+
+			/* Start the decipher thread */
+			CHECK_POSIX( pthread_create( &conn->cc_sctp3436_data.array[i].thr, NULL, decipher, &conn->cc_sctp3436_data.array[i] ) );
+		}
+	} else {
+		CHECK_POSIX( pthread_create( &conn->cc_sctp3436_data.array[0].thr, NULL, decipher, &conn->cc_sctp3436_data.array[0] ) );
+	}
+	return 0;
+}
+
+/* Initiate a "bye" on all stream pairs */
+void fd_sctp3436_bye(struct cnxctx * conn)
+{
+	uint16_t i;
+	
+	CHECK_PARAMS_DO( conn && conn->cc_sctp3436_data.array, return );
+	
+	/* End all TLS sessions, in series (not as efficient as paralel, but simpler) */
+	for (i = 1; i < conn->cc_sctp_para.pairs; i++) {
+		if ( ! fd_cnx_teststate(conn, CC_STATUS_ERROR)) {
+			CHECK_GNUTLS_DO( gnutls_bye(conn->cc_sctp3436_data.array[i].session, GNUTLS_SHUT_WR), fd_cnx_markerror(conn) );
+		}
+	}
+}
+
+/* After "bye" was sent on all streams, read from sessions until an error is received */
+void fd_sctp3436_waitthreadsterm(struct cnxctx * conn)
+{
+	uint16_t i;
+	
+	TRACE_ENTRY("%p", conn);
+	CHECK_PARAMS_DO( conn && conn->cc_sctp3436_data.array, return );
+	
+	for (i = 0; i < conn->cc_sctp_para.pairs; i++) {
+		if (conn->cc_sctp3436_data.array[i].thr != (pthread_t)NULL) {
+			CHECK_POSIX_DO( pthread_join(conn->cc_sctp3436_data.array[i].thr, NULL), /* continue */ );
+			conn->cc_sctp3436_data.array[i].thr = (pthread_t)NULL;
+		}
+	}
+	return;
+}
+
+/* Free gnutls resources of all sessions */
+void fd_sctp3436_gnutls_deinit_others(struct cnxctx * conn)
+{
+	uint16_t i;
+	
+	TRACE_ENTRY("%p", conn);
+	CHECK_PARAMS_DO( conn && conn->cc_sctp3436_data.array, return );
+	
+	for (i = 1; i < conn->cc_sctp_para.pairs; i++) {
+		if (conn->cc_sctp3436_data.array[i].session) {
+			GNUTLS_TRACE( gnutls_deinit(conn->cc_sctp3436_data.array[i].session) );
+			conn->cc_sctp3436_data.array[i].session = NULL;
+		}
+	}
+}
+
+
+/* Stop all receiver threads */
+void fd_sctp3436_stopthreads(struct cnxctx * conn)
+{
+	uint16_t i;
+	
+	TRACE_ENTRY("%p", conn);
+	CHECK_PARAMS_DO( conn && conn->cc_sctp3436_data.array, return );
+	
+	for (i = 0; i < conn->cc_sctp_para.pairs; i++) {
+		CHECK_FCT_DO( fd_thr_term(&conn->cc_sctp3436_data.array[i].thr), /* continue */ );
+	}
+	return;
+}
+
+/* Destroy a wrapper context */
+void fd_sctp3436_destroy(struct cnxctx * conn)
+{
+	uint16_t i;
+	
+	CHECK_PARAMS_DO( conn && conn->cc_sctp3436_data.array, return );
+	
+	/* Terminate all receiving threads in case we did not do it yet */
+	fd_sctp3436_stopthreads(conn);
+	
+	/* Now, stop the demux thread */
+	CHECK_FCT_DO( fd_thr_term(&conn->cc_rcvthr), /* continue */ );
+	
+	/* Free remaining data in the array */
+	for (i = 0; i < conn->cc_sctp_para.pairs; i++) {
+		if (conn->cc_sctp3436_data.array[i].raw_recv)
+			fd_event_destroy( &conn->cc_sctp3436_data.array[i].raw_recv, free );
+		free(conn->cc_sctp3436_data.array[i].partial.buf);
+		if (conn->cc_sctp3436_data.array[i].session) {
+			GNUTLS_TRACE( gnutls_deinit(conn->cc_sctp3436_data.array[i].session) );
+			conn->cc_sctp3436_data.array[i].session = NULL;
+		}
+	}
+	
+	/* Free the array itself now */
+	free(conn->cc_sctp3436_data.array);
+	conn->cc_sctp3436_data.array = NULL;
+	
+	/* Delete the store of sessions */
+	store_destroy(conn);
+	
+	return ;
+}
diff --git a/libfdcore/server.c b/libfdcore/server.c
new file mode 100644
index 0000000..85a8568
--- /dev/null
+++ b/libfdcore/server.c
@@ -0,0 +1,509 @@
+/*********************************************************************************************************
+* Software License Agreement (BSD License)                                                               *
+* Author: Sebastien Decugis <sdecugis@freediameter.net>							 *
+*													 *
+* Copyright (c) 2013, WIDE Project and NICT								 *
+* All rights reserved.											 *
+* 													 *
+* Redistribution and use of this software in source and binary forms, with or without modification, are  *
+* permitted provided that the following conditions are met:						 *
+* 													 *
+* * Redistributions of source code must retain the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer.										 *
+*    													 *
+* * Redistributions in binary form must reproduce the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer in the documentation and/or other						 *
+*   materials provided with the distribution.								 *
+* 													 *
+* * Neither the name of the WIDE Project or NICT nor the 						 *
+*   names of its contributors may be used to endorse or 						 *
+*   promote products derived from this software without 						 *
+*   specific prior written permission of WIDE Project and 						 *
+*   NICT.												 *
+* 													 *
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED *
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
+* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR *
+* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 	 *
+* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 	 *
+* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR *
+* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF   *
+* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.								 *
+*********************************************************************************************************/
+
+#include "fdcore-internal.h"
+
+/* Server (listening) part of the framework */
+
+static struct fd_list	FD_SERVERS = FD_LIST_INITIALIZER(FD_SERVERS);	/* The list of all server objects */
+/* We don't need to protect this list, it is only accessed from the main framework thread. */
+
+enum s_state {
+	NOT_CREATED=0,
+	RUNNING,
+	TERMINATED,
+	ERROR	/* an error occurred, this is not a valid status */
+};
+
+/* Servers information */
+struct server {
+	struct fd_list	chain;		/* link in the FD_SERVERS list */
+
+	struct cnxctx *	conn;		/* server connection context (listening socket) */
+	int 		proto;		/* IPPROTO_TCP or IPPROTO_SCTP */
+	int 		secur;		/* TLS is started immediatly after connection ? 0: no; 1: RFU; 2: yes (TLS/TCP or TLS/SCTP) */
+	
+	pthread_t	thr;		/* The thread waiting for new connections (will store the data in the clients fifo) */
+	enum s_state	state;		/* state of the thread */
+	
+	struct fifo	*pending;	/* FIFO of struct cnxctx */
+	struct pool_workers {
+		struct server * s;	/* pointer to the parent server structure */
+		int		id;	/* The worker id for logs */
+		pthread_t	worker; /* The thread */
+	}		*workers;	/* array of cnf_thr_srv items */
+};
+
+
+/* Micro functions to read/change the status thread-safely */
+static pthread_mutex_t s_lock = PTHREAD_MUTEX_INITIALIZER;
+static enum s_state get_status(struct server * s)
+{
+	enum s_state r;
+	CHECK_POSIX_DO( pthread_mutex_lock(&s_lock), return ERROR );
+	r = s->state;
+	CHECK_POSIX_DO( pthread_mutex_unlock(&s_lock), return ERROR );
+	return r;
+}
+static void set_status(struct server * s, enum s_state st)
+{
+	CHECK_POSIX_DO( pthread_mutex_lock(&s_lock), return );
+	s->state = st;
+	CHECK_POSIX_DO( pthread_mutex_unlock(&s_lock), return );
+}
+	
+
+/* dump one item of the server->pending fifo */
+static DECLARE_FD_DUMP_PROTOTYPE(dump_cnx, void * item) {
+	struct cnxctx * c = item;
+	CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, " '%s'", fd_cnx_getid(c)), return NULL);
+	return *buf;
+}
+
+/* Dump all servers information */
+DECLARE_FD_DUMP_PROTOTYPE(fd_servers_dump, int details)
+{
+	struct fd_list * li;
+	
+	FD_DUMP_HANDLE_OFFSET();
+	
+	for (li = FD_SERVERS.next; li != &FD_SERVERS; li = li->next) {
+		struct server * s = (struct server *)li;
+		enum s_state st = get_status(s);
+		
+		if (details) {
+			CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "{server}(@%p)'%s': %s, %s(%d), %s", s, fd_cnx_getid(s->conn), 
+					IPPROTO_NAME( s->proto ),
+					s->secur ? "Secur" : "NotSecur", s->secur,
+					(st == NOT_CREATED) ? "Thread not created" :
+					((st == RUNNING) ? "Thread running" :
+					((st == TERMINATED) ? "Thread terminated" :
+								  "Thread status unknown"))), return NULL);
+			/* Dump the client list of this server */
+			CHECK_MALLOC_DO( fd_fifo_dump(FD_DUMP_STD_PARAMS, "pending connections", s->pending, dump_cnx), return NULL );
+
+			if (li->next != &FD_SERVERS) {
+				CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "\n"), return NULL);
+			}
+		} else {
+			CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "'%s'(%s,%s)  ", fd_cnx_getid(s->conn), 
+					IPPROTO_NAME( s->proto ), s->secur ? "Secur" : "NotSecur"), return NULL);
+		}
+	}
+	
+	return *buf;
+}
+
+
+/* The thread in the pool for handling new clients connecting to a server */
+static void * client_worker(void * arg)
+{
+	struct pool_workers * pw = arg;
+	struct server * s = pw->s;
+	struct cnxctx * c = NULL;
+	int fatal = 0;
+	struct timespec ts;
+	struct fd_cnx_rcvdata rcv_data;
+	struct fd_msg_pmdl * pmdl = NULL;
+	struct msg    * msg = NULL;
+	struct msg_hdr *hdr = NULL;
+	struct fd_pei pei;
+	
+	TRACE_ENTRY("%p", arg);
+	
+	/* Set the thread name */
+	{
+		char buf[48];
+		snprintf(buf, sizeof(buf), "Worker#%d[%s%s]", pw->id, IPPROTO_NAME(s->proto), s->secur?", Sec" : "");
+		fd_log_threadname ( buf );
+	}
+	
+	/* Loop until canceled / error */
+next_client:
+	LOG_A("Ready to process next incoming connection");
+
+	memset(&rcv_data, 0, sizeof(rcv_data));
+	
+	/* Get the next connection */
+	CHECK_FCT_DO( fd_fifo_get( s->pending, &c ), { fatal = 1; goto cleanup; } );
+
+	/* Handshake if we are a secure server port, or start clear otherwise */
+	if (s->secur) {
+		LOG_D("Starting handshake with %s", fd_cnx_getid(c));
+
+		int ret = fd_cnx_handshake(c, GNUTLS_SERVER, (s->secur == 1) ? ALGO_HANDSHAKE_DEFAULT : ALGO_HANDSHAKE_3436, NULL, NULL);
+		if (ret != 0) {
+			char buf[1024];
+			snprintf(buf, sizeof(buf), "TLS handshake failed for connection '%s', connection closed.", fd_cnx_getid(c));
+
+			fd_hook_call(HOOK_PEER_CONNECT_FAILED, NULL, NULL, buf, NULL);
+
+			goto cleanup;
+		}
+	} else {
+		CHECK_FCT_DO( fd_cnx_start_clear(c, 0), goto cleanup );
+	}
+	
+	/* Set the timeout to receive the first message */
+	CHECK_SYS_DO( clock_gettime(CLOCK_REALTIME, &ts), { fatal = 1; goto cleanup; } );
+	ts.tv_sec += INCNX_TIMEOUT;
+	
+	/* Receive the first Diameter message on the connection -- cleanup in case of timeout */
+	CHECK_FCT_DO( fd_cnx_receive(c, &ts, &rcv_data.buffer, &rcv_data.length), 
+		{
+			char buf[1024];
+			
+			switch (__ret__) {
+			case ETIMEDOUT:
+				snprintf(buf, sizeof(buf), "Client '%s' did not send CER within %ds, connection aborted.", fd_cnx_getid(c), INCNX_TIMEOUT);
+				fd_hook_call(HOOK_PEER_CONNECT_FAILED, NULL, NULL, buf, NULL);
+				break;
+			
+			case ENOTCONN:
+				snprintf(buf, sizeof(buf), "Connection from '%s' in error before CER was received.", fd_cnx_getid(c));
+				fd_hook_call(HOOK_PEER_CONNECT_FAILED, NULL, NULL, buf, NULL);
+				break;
+			
+			default:
+				snprintf(buf, sizeof(buf), "Connection from '%s': unspecified error, connection aborted.", fd_cnx_getid(c));
+				fd_hook_call(HOOK_PEER_CONNECT_FAILED, NULL, NULL, buf, NULL);
+			}
+			goto cleanup;
+		} );
+	
+	TRACE_DEBUG(FULL, "Received %zdb from new client '%s'", rcv_data.length, fd_cnx_getid(c));
+	
+	pmdl = fd_msg_pmdl_get_inbuf(rcv_data.buffer, rcv_data.length);
+	
+	/* Try parsing this message */
+	CHECK_FCT_DO( fd_msg_parse_buffer( &rcv_data.buffer, rcv_data.length, &msg ), 
+		{ 	/* Parsing failed */ 
+			fd_hook_call(HOOK_MESSAGE_PARSING_ERROR, NULL, NULL, &rcv_data, pmdl );
+			goto cleanup;
+		} );
+	
+	/* Log incoming message */
+	fd_hook_associate(msg, pmdl);
+	fd_hook_call(HOOK_MESSAGE_RECEIVED, msg, NULL, fd_cnx_getid(c), fd_msg_pmdl_get(msg));
+	
+	/* We expect a CER, it must parse with our dictionary and rules */
+	CHECK_FCT_DO( fd_msg_parse_rules( msg, fd_g_config->cnf_dict, &pei ), 
+		{ /* Parsing failed -- trace details */ 
+			char buf[1024];
+			
+			fd_hook_call(HOOK_MESSAGE_PARSING_ERROR, msg, NULL, pei.pei_message ?: pei.pei_errcode, fd_msg_pmdl_get(msg));
+			
+			snprintf(buf, sizeof(buf), "Error parsing CER from '%s', connection aborted.", fd_cnx_getid(c));
+			fd_hook_call(HOOK_PEER_CONNECT_FAILED, NULL, NULL, buf, NULL);
+			
+			goto cleanup;
+		} );
+	
+	/* Now check we received a CER */
+	CHECK_FCT_DO( fd_msg_hdr ( msg, &hdr ), { fatal = 1; goto cleanup; }  );
+	CHECK_PARAMS_DO( (hdr->msg_appl == 0) && (hdr->msg_flags & CMD_FLAG_REQUEST) && (hdr->msg_code == CC_CAPABILITIES_EXCHANGE),
+		{ /* Parsing failed -- trace details */ 
+			char buf[1024];
+			snprintf(buf, sizeof(buf), "Expected CER from '%s', received a different message, connection aborted.", fd_cnx_getid(c));
+			fd_hook_call(HOOK_PEER_CONNECT_FAILED, msg, NULL, buf, NULL);
+			goto cleanup;
+		} );
+	
+	/* Finally, pass the information to the peers module which will handle it in a separate thread */
+	pthread_cleanup_push((void *)fd_cnx_destroy, c);
+	pthread_cleanup_push((void *)fd_msg_free, msg);
+	CHECK_FCT_DO( fd_peer_handle_newCER( &msg, &c ),  );
+	pthread_cleanup_pop(0);
+	pthread_cleanup_pop(0);
+
+cleanup:
+	/* Cleanup the parsed message if any */
+	if (msg) {
+		CHECK_FCT_DO( fd_msg_free(msg), /* continue */);
+		msg = NULL;
+	}
+	
+	/* Close the connection if needed */
+	if (c != NULL) {
+		fd_cnx_destroy(c);
+		c = NULL;
+	}
+	
+	/* Cleanup the received buffer if any */
+	free(rcv_data.buffer);
+	
+	
+	if (!fatal)
+		goto next_client;
+
+	LOG_E("Worker thread exiting.");
+	return NULL;
+}	
+
+/* The thread managing a server */
+static void * serv_th(void * arg)
+{
+	struct server *s = (struct server *)arg;
+	
+	CHECK_PARAMS_DO(s, goto error);
+	fd_log_threadname ( fd_cnx_getid(s->conn) );
+	
+	set_status(s, RUNNING);
+	
+	/* Accept incoming connections */
+	CHECK_FCT_DO( fd_cnx_serv_listen(s->conn), goto error );
+	
+	do {
+		struct cnxctx * conn = NULL;
+		
+		/* Wait for a new client or cancel */
+		CHECK_MALLOC_DO( conn = fd_cnx_serv_accept(s->conn), break );
+		
+		/* Store this connection in the fifo for processing by the worker pool. Will block when the fifo is full */
+		pthread_cleanup_push((void *)fd_cnx_destroy, conn);
+		CHECK_FCT_DO( fd_fifo_post( s->pending, &conn ), break );
+		pthread_cleanup_pop(0);
+		
+	} while (1);
+error:	
+	if (s)
+		set_status(s, TERMINATED);
+
+	/* Send error signal to the core */
+	LOG_F( "An error occurred in server module! Thread is terminating...");
+	CHECK_FCT_DO(fd_core_shutdown(), );
+
+	return NULL;
+}
+
+
+/* Create a new server structure */
+static struct server * new_serv( int proto, int secur )
+{
+	struct server * new;
+	int i;
+	
+	/* New server structure */
+	CHECK_MALLOC_DO( new = malloc(sizeof(struct server)), return NULL );
+	
+	memset(new, 0, sizeof(struct server));
+	fd_list_init(&new->chain, new);
+	new->proto = proto;
+	new->secur = secur;
+	
+	CHECK_FCT_DO( fd_fifo_new(&new->pending, 5), return NULL);
+	CHECK_MALLOC_DO( new->workers = calloc( fd_g_config->cnf_thr_srv, sizeof(struct pool_workers) ), return NULL );
+	
+	for (i = 0; i < fd_g_config->cnf_thr_srv; i++) {
+		/* Create the pool */
+		new->workers[i].s = new;
+		new->workers[i].id = i;
+		CHECK_POSIX_DO( pthread_create( &new->workers[i].worker, NULL, client_worker, &new->workers[i]), return NULL );
+	}
+	
+	return new;
+}
+
+/* Start all the servers */
+int fd_servers_start()
+{
+	struct server * s;
+	
+	int empty_conf_ep = FD_IS_LIST_EMPTY(&fd_g_config->cnf_endpoints);
+	
+	/* SCTP */
+	if (!fd_g_config->cnf_flags.no_sctp) {
+#ifdef DISABLE_SCTP
+		ASSERT(0);
+#else /* DISABLE_SCTP */
+		
+		/* Create the server on unsecure port */
+		if (fd_g_config->cnf_port) {
+			CHECK_MALLOC( s = new_serv(IPPROTO_SCTP, 0) );
+			CHECK_MALLOC( s->conn = fd_cnx_serv_sctp(fd_g_config->cnf_port, empty_conf_ep ? NULL : &fd_g_config->cnf_endpoints) );
+			fd_list_insert_before( &FD_SERVERS, &s->chain );
+			CHECK_POSIX( pthread_create( &s->thr, NULL, serv_th, s ) );
+		}
+		
+		/* Create the server on secure port */
+		if (fd_g_config->cnf_port_tls) {
+			CHECK_MALLOC( s = new_serv(IPPROTO_SCTP, 2 /* Change when DTLS is introduced */) );
+			CHECK_MALLOC( s->conn = fd_cnx_serv_sctp(fd_g_config->cnf_port_tls, empty_conf_ep ? NULL : &fd_g_config->cnf_endpoints) );
+			fd_list_insert_before( &FD_SERVERS, &s->chain );
+			CHECK_POSIX( pthread_create( &s->thr, NULL, serv_th, s ) );
+		}
+		
+		/* Create the other server on 3436 secure port */
+		/*if (fd_g_config->cnf_port_3436) {
+			CHECK_MALLOC( s = new_serv(IPPROTO_SCTP, 2) );
+			CHECK_MALLOC( s->conn = fd_cnx_serv_sctp(fd_g_config->cnf_port_3436, empty_conf_ep ? NULL : &fd_g_config->cnf_endpoints) );
+			fd_list_insert_before( &FD_SERVERS, &s->chain );
+			CHECK_POSIX( pthread_create( &s->thr, NULL, serv_th, s ) );
+		}*/
+		
+#endif /* DISABLE_SCTP */
+	}
+	
+	/* TCP */
+	if (!fd_g_config->cnf_flags.no_tcp) {
+		
+		if (empty_conf_ep) {
+			/* Bind TCP servers on [0.0.0.0] */
+			if (!fd_g_config->cnf_flags.no_ip4) {
+				
+				if (fd_g_config->cnf_port) {
+					CHECK_MALLOC( s = new_serv(IPPROTO_TCP, 0) );
+					CHECK_MALLOC( s->conn = fd_cnx_serv_tcp(fd_g_config->cnf_port, AF_INET, NULL) );
+					fd_list_insert_before( &FD_SERVERS, &s->chain );
+					CHECK_POSIX( pthread_create( &s->thr, NULL, serv_th, s ) );
+				}
+
+				if (fd_g_config->cnf_port_tls) {
+					CHECK_MALLOC( s = new_serv(IPPROTO_TCP, 1) );
+					CHECK_MALLOC( s->conn = fd_cnx_serv_tcp(fd_g_config->cnf_port_tls, AF_INET, NULL) );
+					fd_list_insert_before( &FD_SERVERS, &s->chain );
+					CHECK_POSIX( pthread_create( &s->thr, NULL, serv_th, s ) );
+				}
+			}
+			
+			/* Bind TCP servers on [::] */
+			if (!fd_g_config->cnf_flags.no_ip6) {
+
+				if (fd_g_config->cnf_port) {
+					CHECK_MALLOC( s = new_serv(IPPROTO_TCP, 0) );
+					CHECK_MALLOC( s->conn = fd_cnx_serv_tcp(fd_g_config->cnf_port, AF_INET6, NULL) );
+					fd_list_insert_before( &FD_SERVERS, &s->chain );
+					CHECK_POSIX( pthread_create( &s->thr, NULL, serv_th, s ) );
+				}
+
+				if (fd_g_config->cnf_port_tls) {
+					CHECK_MALLOC( s = new_serv(IPPROTO_TCP, 1) );
+					CHECK_MALLOC( s->conn = fd_cnx_serv_tcp(fd_g_config->cnf_port_tls, AF_INET6, NULL) );
+					fd_list_insert_before( &FD_SERVERS, &s->chain );
+					CHECK_POSIX( pthread_create( &s->thr, NULL, serv_th, s ) );
+				}
+			}
+		} else {
+			/* Create all endpoints -- check flags */
+			struct fd_list * li;
+			for (li = fd_g_config->cnf_endpoints.next; li != &fd_g_config->cnf_endpoints; li = li->next) {
+				struct fd_endpoint * ep = (struct fd_endpoint *)li;
+				sSA * sa = (sSA *) &ep->ss;
+				if (! (ep->flags & EP_FL_CONF))
+					continue;
+				if (fd_g_config->cnf_flags.no_ip4 && (sa->sa_family == AF_INET))
+					continue;
+				if (fd_g_config->cnf_flags.no_ip6 && (sa->sa_family == AF_INET6))
+					continue;
+				
+				if (fd_g_config->cnf_port) {
+					CHECK_MALLOC( s = new_serv(IPPROTO_TCP, 0) );
+					CHECK_MALLOC( s->conn = fd_cnx_serv_tcp(fd_g_config->cnf_port, sa->sa_family, ep) );
+					fd_list_insert_before( &FD_SERVERS, &s->chain );
+					CHECK_POSIX( pthread_create( &s->thr, NULL, serv_th, s ) );
+				}
+
+				if (fd_g_config->cnf_port_tls) {
+					CHECK_MALLOC( s = new_serv(IPPROTO_TCP, 1) );
+					CHECK_MALLOC( s->conn = fd_cnx_serv_tcp(fd_g_config->cnf_port_tls, sa->sa_family, ep) );
+					fd_list_insert_before( &FD_SERVERS, &s->chain );
+					CHECK_POSIX( pthread_create( &s->thr, NULL, serv_th, s ) );
+				}
+			}
+		}
+	}
+	
+	/* Now, if we had an empty list of local adresses (no address configured), try to read the real addresses from the kernel */
+	if (empty_conf_ep) {
+		CHECK_FCT(fd_cnx_get_local_eps(&fd_g_config->cnf_endpoints));
+		if (FD_IS_LIST_EMPTY(&fd_g_config->cnf_endpoints)) {
+			TRACE_DEBUG(INFO, "Unable to find the address(es) of the local system. " 
+					"Please use \"ListenOn\" parameter in the configuration. "
+					"This information is required to generate the CER/CEA messages.");
+			return EINVAL;
+		}
+	}
+	
+	{
+		char * buf = NULL;
+		size_t len = 0, offset = 0;
+		CHECK_MALLOC_DO( fd_dump_extend( &buf, &len, &offset , "Local server address(es): "), );
+		CHECK_MALLOC_DO( fd_ep_dump(  &buf, &len, &offset, 0, 0, &fd_g_config->cnf_endpoints ), );
+		LOG_N("%s", buf ?: "Error dumping addresses");
+		free(buf);
+	}
+	return 0;
+}
+
+/* Terminate all the servers */
+int fd_servers_stop()
+{
+	TRACE_ENTRY("");
+	
+	TRACE_DEBUG(INFO, "Shutting down server sockets...");
+	
+	/* Loop on all servers */
+	while (!FD_IS_LIST_EMPTY(&FD_SERVERS)) {
+		struct server * s = (struct server *)(FD_SERVERS.next);
+		int i;
+		struct cnxctx * c;
+		
+		/* cancel thread */
+		CHECK_FCT_DO( fd_thr_term(&s->thr), /* continue */);
+		
+		/* destroy server connection context */
+		fd_cnx_destroy(s->conn);
+		
+		/* cancel and destroy all worker threads */
+		for (i = 0; i < fd_g_config->cnf_thr_srv; i++) {
+			/* Destroy worker thread */
+			CHECK_FCT_DO( fd_thr_term(&s->workers[i].worker), /* continue */);
+		}
+		free(s->workers);
+		
+		/* Close any pending connection */
+		while ( fd_fifo_tryget( s->pending, &c ) == 0 ) {
+			fd_cnx_destroy(c);
+		}
+		CHECK_FCT_DO( fd_fifo_del(&s->pending), );
+		
+		/* Now destroy the server object */
+		fd_list_unlink(&s->chain);
+		free(s);
+	}
+	
+	/* We're done! */
+	return 0;
+}
diff --git a/libfdcore/tcp.c b/libfdcore/tcp.c
new file mode 100644
index 0000000..fb6cf1e
--- /dev/null
+++ b/libfdcore/tcp.c
@@ -0,0 +1,168 @@
+/*********************************************************************************************************
+* Software License Agreement (BSD License)                                                               *
+* Author: Sebastien Decugis <sdecugis@freediameter.net>							 *
+*													 *
+* Copyright (c) 2013, WIDE Project and NICT								 *
+* All rights reserved.											 *
+* 													 *
+* Redistribution and use of this software in source and binary forms, with or without modification, are  *
+* permitted provided that the following conditions are met:						 *
+* 													 *
+* * Redistributions of source code must retain the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer.										 *
+*    													 *
+* * Redistributions in binary form must reproduce the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer in the documentation and/or other						 *
+*   materials provided with the distribution.								 *
+* 													 *
+* * Neither the name of the WIDE Project or NICT nor the 						 *
+*   names of its contributors may be used to endorse or 						 *
+*   promote products derived from this software without 						 *
+*   specific prior written permission of WIDE Project and 						 *
+*   NICT.												 *
+* 													 *
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED *
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
+* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR *
+* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 	 *
+* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 	 *
+* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR *
+* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF   *
+* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.								 *
+*********************************************************************************************************/
+
+#include "fdcore-internal.h"
+#include "cnxctx.h"
+
+#include <netinet/tcp.h>
+#include <netinet/ip6.h>
+#include <sys/socket.h>
+
+/* Set the socket options for TCP sockets, before bind is called */
+static int fd_tcp_setsockopt(int family, int sk)
+{
+	int ret = 0;
+	int opt;
+	
+	/* Clear the NODELAY option in case it was set, as requested by rfc3539#section-3.2 */
+	/* Note that this is supposed to be the default, so we could probably remove this call ... */
+	opt = 0;
+	ret = setsockopt(sk, IPPROTO_TCP, TCP_NODELAY, &opt, sizeof(opt));
+	if (ret != 0) {
+		ret = errno;
+		TRACE_DEBUG(INFO, "Unable to set the socket TCP_NODELAY option: %s", strerror(ret));
+		return ret;
+	}
+	
+	/* Under Linux, we may also set the TCP_CONGESTION option to one of the following strings:
+	    - reno (default)
+	    - bic
+	    - cubic
+	    - highspeed
+	    - htcp
+	    - hybla
+	    - illinois
+	    - lp
+	    - scalable
+	    - vegas
+	    - veno
+	    - westwood
+	    - yeah
+	*/
+	
+	/* In case of v6 address, force the v6only option, we use a different socket for v4 */
+	#ifdef IPV6_V6ONLY
+	if (family == AF_INET6) {
+		opt = 1;
+		CHECK_SYS(setsockopt(sk, IPPROTO_IPV6, IPV6_V6ONLY, &opt, sizeof(opt)));
+	}
+	#endif /* IPV6_V6ONLY */
+	
+	{
+		opt = 1;
+		CHECK_SYS(  setsockopt(sk, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt))  );
+	}
+	
+	/* There are also others sockopt that can be set, but nothing useful for us AFAICT */
+	
+	return 0;
+}
+
+/* Create a socket server and bind it */
+int fd_tcp_create_bind_server( int * sock, sSA * sa, socklen_t salen )
+{
+	TRACE_ENTRY("%p %p %d", sock, sa, salen);
+	
+	CHECK_PARAMS(  sock && sa  );
+	
+	/* Create the socket */
+	CHECK_SYS(  *sock = socket(sa->sa_family, SOCK_STREAM, IPPROTO_TCP)  );
+
+	/* Set the socket options */
+	CHECK_FCT(  fd_tcp_setsockopt(sa->sa_family, *sock)  );
+	
+	/* Bind the socket */
+	CHECK_SYS(  bind( *sock, sa, salen )  );
+			
+	/* We're done */
+	return 0;
+}
+
+/* Allow clients connections on server sockets */
+int fd_tcp_listen( int sock )
+{
+	TRACE_ENTRY("%d", sock);
+	CHECK_SYS( listen(sock, 5) );
+	return 0;
+}
+
+/* Create a client socket and connect to remote server */
+int fd_tcp_client( int *sock, sSA * sa, socklen_t salen )
+{
+	int ret = 0;
+	int s;
+	
+	TRACE_ENTRY("%p %p %d", sock, sa, salen);
+	CHECK_PARAMS( sock && (*sock <= 0) && sa && salen );
+	
+	/* Create the socket */
+	CHECK_SYS(  s = socket(sa->sa_family, SOCK_STREAM, IPPROTO_TCP)  );
+	
+	/* Set the socket options */
+	CHECK_FCT(  fd_tcp_setsockopt(sa->sa_family, s)  );
+	
+	/* Cleanup if we are cancelled */
+	pthread_cleanup_push(fd_cleanup_socket, &s);
+	
+	/* Try connecting to the remote address */
+	ret = connect(s, sa, salen);
+	
+	pthread_cleanup_pop(0);
+	
+	if (ret < 0) {
+		ret = errno;
+		LOG_A( "connect returned an error: %s", strerror(ret));
+		CHECK_SYS_DO( close(s), /* continue */ );
+		*sock = -1;
+		return ret;
+	}
+	
+	/* Done! */
+	*sock = s;
+	return ret;
+}
+
+/* Get the remote name of a TCP socket */
+int fd_tcp_get_remote_ep(int sock, sSS * ss, socklen_t *sl)
+{
+	TRACE_ENTRY("%d %p %p", sock, ss, sl);
+	CHECK_PARAMS( ss && sl );
+	
+	*sl = sizeof(sSS);
+	CHECK_SYS(getpeername(sock, (sSA *)ss, sl));
+	
+	return 0;
+}
+
diff --git a/libfdcore/version.c b/libfdcore/version.c
new file mode 100644
index 0000000..fa3a732
--- /dev/null
+++ b/libfdcore/version.c
@@ -0,0 +1,47 @@
+/*********************************************************************************************************
+* Software License Agreement (BSD License)                                                               *
+* Author: Sebastien Decugis <sdecugis@freediameter.net>							 *
+*													 *
+* Copyright (c) 2013, WIDE Project and NICT								 *
+* All rights reserved.											 *
+* 													 *
+* Redistribution and use of this software in source and binary forms, with or without modification, are  *
+* permitted provided that the following conditions are met:						 *
+* 													 *
+* * Redistributions of source code must retain the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer.										 *
+*    													 *
+* * Redistributions in binary form must reproduce the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer in the documentation and/or other						 *
+*   materials provided with the distribution.								 *
+* 													 *
+* * Neither the name of the WIDE Project or NICT nor the 						 *
+*   names of its contributors may be used to endorse or 						 *
+*   promote products derived from this software without 						 *
+*   specific prior written permission of WIDE Project and 						 *
+*   NICT.												 *
+* 													 *
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED *
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
+* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR *
+* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 	 *
+* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 	 *
+* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR *
+* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF   *
+* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.								 *
+*********************************************************************************************************/
+
+#include <fdcore-internal.h>
+#include <freeDiameter/version.h>
+
+#ifdef FD_PROJECT_VERSION_HG
+# define FD_LIBFDCORE_VERSION \
+	_stringize(FD_PROJECT_VERSION_MAJOR) "." _stringize(FD_PROJECT_VERSION_MINOR) "." _stringize(FD_PROJECT_VERSION_REV) "-" FD_PROJECT_VERSION_HG_VAL
+#else
+# define FD_LIBFDCORE_VERSION \
+	_stringize(FD_PROJECT_VERSION_MAJOR) "." _stringize(FD_PROJECT_VERSION_MINOR) "." _stringize(FD_PROJECT_VERSION_REV)
+#endif
+
+const char fd_core_version[] = FD_LIBFDCORE_VERSION;
diff --git a/libfdproto/CMakeLists.txt b/libfdproto/CMakeLists.txt
new file mode 100644
index 0000000..3650719
--- /dev/null
+++ b/libfdproto/CMakeLists.txt
@@ -0,0 +1,58 @@
+# Name of the subproject
+Project("libfdproto" C)
+
+# Configuration for newer cmake
+cmake_policy(VERSION 2.6)
+if (POLICY CMP0022)
+	cmake_policy(SET CMP0022 OLD)
+endif (POLICY CMP0022)
+
+# List of source files for the library
+SET(LFDPROTO_SRC
+	fdproto-internal.h
+	dictionary.c
+	dictionary_functions.c
+	dispatch.c
+	fifo.c
+	init.c
+	lists.c
+	log.c
+	messages.c
+	ostr.c
+	portability.c
+	rt_data.c
+	sessions.c
+	utils.c
+	version.c
+	)
+
+
+# Save the list of files for testcases in the core's directory
+SET(LFDPROTO_SRC ${LFDPROTO_SRC} PARENT_SCOPE)
+
+# Include path
+INCLUDE_DIRECTORIES(${LFDPROTO_INCLUDES})
+
+# Build as a shared library
+ADD_LIBRARY(libfdproto SHARED ${LFDPROTO_SRC})
+
+ADD_DEPENDENCIES(libfdproto version_information)
+
+# Avoid the liblib name, and set the version
+SET_TARGET_PROPERTIES(libfdproto PROPERTIES 
+	OUTPUT_NAME "fdproto"
+	SOVERSION ${FD_PROJECT_VERSION_API}
+	VERSION ${FD_PROJECT_VERSION_MAJOR}.${FD_PROJECT_VERSION_MINOR}.${FD_PROJECT_VERSION_REV}
+	LINK_INTERFACE_LIBRARIES "${LFDPROTO_LINK_INTERFACES}")
+
+# The library itself needs other libraries 
+TARGET_LINK_LIBRARIES(libfdproto ${LFDPROTO_LIBS})
+
+
+####
+## INSTALL section ##
+
+INSTALL(TARGETS libfdproto
+	LIBRARY DESTINATION ${INSTALL_LIBRARY_SUFFIX}
+	COMPONENT freeDiameter-common)
+
diff --git a/libfdproto/dictionary.c b/libfdproto/dictionary.c
new file mode 100644
index 0000000..ff902a0
--- /dev/null
+++ b/libfdproto/dictionary.c
@@ -0,0 +1,2306 @@
+/*********************************************************************************************************
+* Software License Agreement (BSD License)                                                               *
+* Author: Sebastien Decugis <sdecugis@freediameter.net>							 *
+*													 *
+* Copyright (c) 2015, WIDE Project and NICT								 *
+* All rights reserved.											 *
+* 													 *
+* Redistribution and use of this software in source and binary forms, with or without modification, are  *
+* permitted provided that the following conditions are met:						 *
+* 													 *
+* * Redistributions of source code must retain the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer.										 *
+*    													 *
+* * Redistributions in binary form must reproduce the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer in the documentation and/or other						 *
+*   materials provided with the distribution.								 *
+* 													 *
+* * Neither the name of the WIDE Project or NICT nor the 						 *
+*   names of its contributors may be used to endorse or 						 *
+*   promote products derived from this software without 						 *
+*   specific prior written permission of WIDE Project and 						 *
+*   NICT.												 *
+* 													 *
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED *
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
+* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR *
+* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 	 *
+* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 	 *
+* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR *
+* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF   *
+* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.								 *
+*********************************************************************************************************/
+
+#include "fdproto-internal.h"
+#include <inttypes.h>
+
+/* Names of the base types */
+const char * type_base_name[] = { /* must keep in sync with dict_avp_basetype */
+	"GROUPED", 	/* AVP_TYPE_GROUPED */
+	"OCTETSTRING", 	/* AVP_TYPE_OCTETSTRING */
+	"INTEGER32", 	/* AVP_TYPE_INTEGER32 */
+	"INTEGER64", 	/* AVP_TYPE_INTEGER64 */
+	"UNSIGNED32", 	/* AVP_TYPE_UNSIGNED32 */
+	"UNSIGNED64", 	/* AVP_TYPE_UNSIGNED64 */
+	"FLOAT32", 	/* AVP_TYPE_FLOAT32 */
+	"FLOAT64"	/* AVP_TYPE_FLOAT64 */
+	};
+
+/* The number of lists in an object */
+#define NB_LISTS_PER_OBJ	3
+
+/* Some eye catchers definitions */
+#define OBJECT_EYECATCHER	(0x0b13c7)
+#define DICT_EYECATCHER		(0x00d1c7)
+
+/* Definition of the dictionary objects */
+struct dict_object {
+	enum dict_object_type	type;	/* What type of object is this? */
+	int			objeyec;/* eyecatcher for this object */
+	int			typeyec;/* eyecatcher for this type of object */
+	struct dictionary	*dico;  /* The dictionary this object belongs to */
+	
+	union {
+		struct dict_vendor_data		vendor;		/* datastr_len = strlen(vendor_name) */
+		struct dict_application_data	application;	/* datastr_len = strlen(application_name) */
+		struct dict_type_data		type;		/* datastr_len = strlen(type_name) */
+		struct dict_enumval_data	enumval;	/* datastr_len = strlen(enum_name) */
+		struct dict_avp_data		avp;		/* datastr_len = strlen(avp_name) */
+		struct dict_cmd_data		cmd;		/* datastr_len = strlen(cmd_name) */
+		struct dict_rule_data		rule;		/* datastr_len = 0 */
+	} data;				/* The data of this object */
+	
+	size_t			datastr_len; /* cached length of the string inside the data. Saved when the object is created. */
+	
+	struct dict_object *	parent; /* The parent of this object, if any */
+	
+	struct fd_list		list[NB_LISTS_PER_OBJ];/* used to chain objects.*/
+	/* More information about the lists :
+	
+	 - the use for each list depends on the type of object. See detail below.
+	 
+	 - a sentinel for a list has its 'o' field cleared. (this is the criteria to detect end of a loop)
+	 
+	 - The lists are always ordered. The criteria are described below. the functions to order them are referenced in dict_obj_info
+	 
+	 - The dict_lock must be held for any list operation.
+	 
+	 => VENDORS:
+	 list[0]: list of the vendors, ordered by their id. The sentinel is g_dict_vendors (vendor with id 0)
+	 list[1]: sentinel for the list of AVPs from this vendor, ordered by AVP code.
+	 list[2]: sentinel for the list of AVPs from this vendor, ordered by AVP name (fd_os_cmp).
+	 
+	 => APPLICATIONS:
+	 list[0]: list of the applications, ordered by their id. The sentinel is g_dict_applications (application with id 0)
+	 list[1]: not used
+	 list[2]: not used.
+	 
+	 => TYPES:
+	 list[0]: list of the types, ordered by their names. The sentinel is g_list_types.
+	 list[1]: sentinel for the type_enum list of this type, ordered by their constant name (fd_os_cmp).
+	 list[2]: sentinel for the type_enum list of this type, ordered by their constant value.
+	 
+	 => TYPE_ENUMS:
+	 list[0]: list of the contants for a given type, ordered by the constant name (fd_os_cmp). Sentinel is a (list[1]) element of a TYPE object.
+	 list[1]: list of the contants for a given type, ordered by the constant value. Sentinel is a (list[2]) element of a TYPE object.
+	 list[2]: not used
+	 
+	 => AVPS:
+	 list[0]: list of the AVP from a given vendor, ordered by avp code. Sentinel is a list[1] element of a VENDOR object.
+	 list[1]: list of the AVP from a given vendor, ordered by avp name (fd_os_cmp). Sentinel is a list[2] element of a VENDOR object.
+	 list[2]: sentinel for the rule list that apply to this AVP.
+	 
+	 => COMMANDS:
+	 list[0]: list of the commands, ordered by their names (fd_os_cmp). The sentinel is g_list_cmd_name.
+	 list[1]: list of the commands, ordered by their command code and 'R' flag. The sentinel is g_list_cmd_code.
+	 list[2]: sentinel for the rule list that apply to this command.
+	 
+	 => RULES:
+	 list[0]: list of the rules for a given (grouped) AVP or Command, ordered by the AVP vendor & code to which they refer. sentinel is list[2] of a command or (grouped) avp.
+	 list[1]: not used
+	 list[2]: not used.
+	 
+	 */
+	 
+	 /* Sentinel for the dispatch callbacks */
+	 struct fd_list		disp_cbs;
+	
+};
+
+/* Definition of the dictionary structure */
+struct dictionary {
+	int		 	dict_eyec;		/* Eye-catcher for the dictionary (DICT_EYECATCHER) */
+	
+	pthread_rwlock_t 	dict_lock;		/* The global rwlock for the dictionary */
+	
+	struct dict_object	dict_vendors;		/* Sentinel for the list of vendors, corresponding to vendor 0 */
+	struct dict_object	dict_applications;	/* Sentinel for the list of applications, corresponding to app 0 */
+	struct fd_list		dict_types;		/* Sentinel for the list of types */
+	struct fd_list		dict_cmd_name;		/* Sentinel for the list of commands, ordered by names */
+	struct fd_list		dict_cmd_code;		/* Sentinel for the list of commands, ordered by codes */
+	
+	struct dict_object	dict_cmd_error;		/* Special command object for answers with the 'E' bit set */
+	
+	int			dict_count[DICT_TYPE_MAX + 1]; /* Number of objects of each type */
+};
+
+/* Forward declarations of dump functions */
+static DECLARE_FD_DUMP_PROTOTYPE(dump_vendor_data, void * data );
+static DECLARE_FD_DUMP_PROTOTYPE(dump_application_data, void * data );
+static DECLARE_FD_DUMP_PROTOTYPE(dump_type_data, void * data );
+  /* the dump function for enum has a different prototype since it need the datatype */
+static DECLARE_FD_DUMP_PROTOTYPE(dump_avp_data, void * data );
+static DECLARE_FD_DUMP_PROTOTYPE(dump_command_data, void * data );
+static DECLARE_FD_DUMP_PROTOTYPE(dump_rule_data, void * data );
+
+/* Forward declarations of search functions */
+static int search_vendor 	( struct dictionary * dict, int criteria, const void * what, struct dict_object **result );
+static int search_application   ( struct dictionary * dict, int criteria, const void * what, struct dict_object **result );
+static int search_type 		( struct dictionary * dict, int criteria, const void * what, struct dict_object **result );
+static int search_enumval 	( struct dictionary * dict, int criteria, const void * what, struct dict_object **result );
+static int search_avp		( struct dictionary * dict, int criteria, const void * what, struct dict_object **result );
+static int search_cmd		( struct dictionary * dict, int criteria, const void * what, struct dict_object **result );
+static int search_rule		( struct dictionary * dict, int criteria, const void * what, struct dict_object **result );
+
+/* The following array contains lot of data about the different types of objects, for automated handling */
+static struct {
+	enum dict_object_type 	type; 		/* information for this type */
+	char *			name;		/* string describing this object, for debug */
+	size_t			datasize;	/* The size of the data structure */
+	int			parent;		/* 0: never; 1: may; 2: must */
+	enum dict_object_type	parenttype;	/* The type of the parent, when relevant */
+	int			eyecatcher;	/* A kind of signature for this object */
+	DECLARE_FD_DUMP_PROTOTYPE( (*dump_data), void * data );	/* The function to dump the data section */
+	int 		      (*search_fct)(struct dictionary * dict, int criteria, const void * what, struct dict_object **result );;	/* The function to search an object of this type */
+	int			haslist[NB_LISTS_PER_OBJ];	/* Tell if this list is used */
+} dict_obj_info[] = { { 0, "(error)", 0, 0, 0, 0, NULL, NULL, {0, 0, 0} }
+
+	/* type			 name		datasize		   	  parent  	parenttype 
+			eyecatcher		dump_data	  	search_fct,		haslist[] 	*/
+
+	,{ DICT_VENDOR,		"VENDOR",	sizeof(struct dict_vendor_data),	0, 	0,
+			OBJECT_EYECATCHER + 1, 	dump_vendor_data, 	search_vendor, 		{ 1, 0, 0 } }
+	
+	,{ DICT_APPLICATION,	"APPLICATION",	sizeof(struct dict_application_data),	1, 	DICT_VENDOR,
+			OBJECT_EYECATCHER + 2,	dump_application_data,	search_application,	{ 1, 0, 0 } }
+	
+	,{ DICT_TYPE,		"TYPE",		sizeof(struct dict_type_data),		1, 	DICT_APPLICATION,
+			OBJECT_EYECATCHER + 3,	dump_type_data,		search_type,		{ 1, 0, 0 } }
+	
+	,{ DICT_ENUMVAL,	"ENUMVAL",	sizeof(struct dict_enumval_data),	2, 	DICT_TYPE,
+			OBJECT_EYECATCHER + 4,	NULL,			search_enumval,	{ 1, 1, 0 } }
+	
+	,{ DICT_AVP,		"AVP",		sizeof(struct dict_avp_data),		1, 	DICT_TYPE,
+			OBJECT_EYECATCHER + 5,	dump_avp_data,		search_avp,		{ 1, 1,	0 } }
+	
+	,{ DICT_COMMAND,	"COMMAND",	sizeof(struct dict_cmd_data),		1, 	DICT_APPLICATION,
+			OBJECT_EYECATCHER + 6,	dump_command_data,	search_cmd,		{ 1, 1, 0 } }
+	
+	,{ DICT_RULE,		"RULE",		sizeof(struct dict_rule_data),		2, 	-1 /* special case: grouped avp or command */,
+			OBJECT_EYECATCHER + 7,	dump_rule_data,		search_rule,		{ 1, 0, 0 } }
+	
+};
+	
+/* Macro to verify a "type" value */
+#define CHECK_TYPE( type ) ( ((type) > 0) && ((type) <= DICT_TYPE_MAX) )
+
+/* Cast macro */
+#define _O( object ) ((struct dict_object *) (object))
+
+/* Get information line for a given object */
+#define _OBINFO(object) (dict_obj_info[CHECK_TYPE(_O(object)->type) ? _O(object)->type : 0])
+
+
+
+
+/*******************************************************************************************************/
+/*******************************************************************************************************/
+/*                                                                                                     */
+/*                                  Objects management                                                 */
+/*                                                                                                     */
+/*******************************************************************************************************/
+/*******************************************************************************************************/
+
+/* Functions to manage the objects creation and destruction. */
+
+/* Duplicate a string inplace, save its length */
+#define DUP_string_len( str, plen ) {		\
+	*(plen) = strlen((str));		\
+	str = os0dup( str, *(plen));		\
+}
+	
+/* Initialize an object */
+static void init_object( struct dict_object * obj, enum dict_object_type type )
+{
+	int i;
+	
+	TRACE_ENTRY("%p %d", obj, type);
+	
+	/* Clean the object first */
+	memset ( obj, 0, sizeof(struct dict_object));
+	
+	CHECK_PARAMS_DO(  CHECK_TYPE(type),  return  );
+
+	obj->type = type;
+	obj->objeyec = OBJECT_EYECATCHER;
+	obj->typeyec = _OBINFO(obj).eyecatcher;
+
+	/* We don't initialize the data nor the parent here */
+	
+	/* Now init the lists */
+	for (i=0; i<NB_LISTS_PER_OBJ; i++) {
+		if (_OBINFO(obj).haslist[i] != 0) 
+			fd_list_init(&obj->list[i], obj);
+		else
+			fd_list_init(&obj->list[i], NULL);
+	}
+	
+	fd_list_init(&obj->disp_cbs, NULL);
+}
+
+/* Initialize the "data" part of an object */
+static int init_object_data(struct dict_object * dest, void * source, enum dict_object_type type, int dupos)
+{
+	TRACE_ENTRY("%p %p %d", dest, source, type);
+	CHECK_PARAMS( dest && source && CHECK_TYPE(type) );
+	
+	/* Generic: copy the full data structure */	
+	memcpy( &dest->data, source, dict_obj_info[type].datasize );
+	
+	/* Then strings must be duplicated, not copied */
+	/* This function might be simplified by always defining the "name" field as the first field of the structures, but... it's error-prone */
+	switch (type) {
+		case DICT_VENDOR:
+			DUP_string_len( dest->data.vendor.vendor_name, &dest->datastr_len );
+			break;
+		
+		case DICT_APPLICATION:
+			DUP_string_len( dest->data.application.application_name, &dest->datastr_len );
+			break;
+			
+		case DICT_TYPE:
+			DUP_string_len( dest->data.type.type_name, &dest->datastr_len );
+			break;
+			
+		case DICT_ENUMVAL:
+			DUP_string_len( dest->data.enumval.enum_name, &dest->datastr_len );
+			if (dupos) {
+				// we also need to duplicate the octetstring constant value since it is a pointer.
+				dest->data.enumval.enum_value.os.data = os0dup( 
+						((struct dict_enumval_data *)source)->enum_value.os.data, 
+						((struct dict_enumval_data *)source)->enum_value.os.len
+					);
+			}
+			break;
+
+		case DICT_AVP:
+			DUP_string_len( dest->data.avp.avp_name, &dest->datastr_len );
+			break;
+			
+		case DICT_COMMAND:
+			DUP_string_len( dest->data.cmd.cmd_name, &dest->datastr_len );
+			break;
+		
+		default:
+			/* Nothing to do for RULES */
+			;
+	}
+	
+	return 0;
+}
+
+/* Check that an object is valid (1: OK, 0: error) */
+static int verify_object( struct dict_object * obj )
+{
+	TRACE_ENTRY("%p", obj);
+	
+	CHECK_PARAMS_DO(  obj
+			&& (obj->objeyec == OBJECT_EYECATCHER)
+			&& CHECK_TYPE(obj->type)
+			&& (obj->typeyec == dict_obj_info[obj->type].eyecatcher),
+		{
+			if (obj) {
+				TRACE_DEBUG(FULL, "Invalid object: %p, obj->objeyec: %x/%x, obj->type: %d, obj->objeyec: %x/%x, obj->typeyec: %x/%x",
+						obj,
+						obj->objeyec, OBJECT_EYECATCHER,
+						obj->type,
+						obj->objeyec, OBJECT_EYECATCHER,
+						obj->typeyec, _OBINFO(obj).eyecatcher);
+			} else {
+				TRACE_DEBUG(FULL, "Invalid object : NULL pointer");
+			}
+			return 0;
+		}  );
+	
+	/* The object is probably valid. */
+	return 1;
+}
+
+/* Free the data associated to an object */
+static void destroy_object_data(struct dict_object * obj)
+{
+	/* TRACE_ENTRY("%p", obj); */
+	
+	switch (obj->type) {
+		case DICT_VENDOR:
+			free( obj->data.vendor.vendor_name );
+			break;
+		
+		case DICT_APPLICATION:
+			free( obj->data.application.application_name );
+			break;
+			
+		case DICT_TYPE:
+			free( obj->data.type.type_name );
+			break;
+			
+		case DICT_ENUMVAL:
+			free( obj->data.enumval.enum_name );
+			break;
+
+		case DICT_AVP:
+			free( obj->data.avp.avp_name );
+			break;
+			
+		case DICT_COMMAND:
+			free( obj->data.cmd.cmd_name );
+			break;
+		
+		default:
+			/* nothing to do */
+			;
+	}
+}
+
+/* Forward declaration */
+static void destroy_object(struct dict_object * obj);
+
+/* Destroy all objects in a list - the lock must be held */
+static void destroy_list(struct fd_list * head) 
+{
+	/* TRACE_ENTRY("%p", head); */
+	
+	/* loop in the list */
+	while (!FD_IS_LIST_EMPTY(head))
+	{
+		/* When destroying the object, it is unlinked from the list */
+		destroy_object(_O(head->next->o));
+	}
+}
+	
+/* Free an object and its sublists */
+static void destroy_object(struct dict_object * obj)
+{
+	int i;
+	
+	/* TRACE_ENTRY("%p", obj); */
+	
+	/* Update global count */
+	if (obj->dico) 
+		obj->dico->dict_count[obj->type]--;
+	
+	/* Mark the object as invalid */
+	obj->objeyec = 0xdead;
+	
+	/* First, destroy the data associated to the object */
+	destroy_object_data(obj);
+	
+	for (i=0; i<NB_LISTS_PER_OBJ; i++) {
+		if (_OBINFO(obj).haslist[i])
+			/* unlink the element from the list */
+			fd_list_unlink( &obj->list[i] );
+		else
+			/* This is either a sentinel or unused (=emtpy) list, let's destroy it */
+			destroy_list( &obj->list[i] );
+	}
+	
+	/* Unlink all elements from the dispatch list; they will be freed when callback is unregistered */
+	CHECK_POSIX_DO( pthread_rwlock_wrlock(&fd_disp_lock), /* continue */ );
+	while (!FD_IS_LIST_EMPTY(&obj->disp_cbs)) {
+		fd_list_unlink( obj->disp_cbs.next );
+	}
+	CHECK_POSIX_DO( pthread_rwlock_unlock(&fd_disp_lock), /* continue */ );
+	
+	/* Last, destroy the object */
+	free(obj);
+}
+
+/*******************************************************************************************************/
+/*******************************************************************************************************/
+/*                                                                                                     */
+/*                                  Compare functions                                                  */
+/*                                                                                                     */
+/*******************************************************************************************************/
+/*******************************************************************************************************/
+
+/* Compare two values */
+#define ORDER_scalar( i1, i2 ) \
+	((i1 < i2 ) ? -1 : ( i1 > i2 ? 1 : 0 )) 
+
+
+/* Compare two vendor objects by their id (checks already performed) */
+static int order_vendor_by_id ( struct dict_object *o1, struct dict_object *o2 )
+{
+	TRACE_ENTRY("%p %p", o1, o2);
+	
+	return ORDER_scalar( o1->data.vendor.vendor_id, o2->data.vendor.vendor_id );
+}
+
+/* Compare two application objects by their id (checks already performed) */
+static int order_appli_by_id  ( struct dict_object *o1, struct dict_object *o2 )
+{
+	TRACE_ENTRY("%p %p", o1, o2);
+	
+	return ORDER_scalar( o1->data.application.application_id, o2->data.application.application_id );
+}
+
+/* Compare two type objects by their name (checks already performed) */
+static int order_type_by_name ( struct dict_object *o1, struct dict_object *o2 )
+{
+	TRACE_ENTRY("%p %p", o1, o2);
+	
+	return fd_os_cmp( o1->data.type.type_name, o1->datastr_len, o2->data.type.type_name, o2->datastr_len );
+}
+
+/* Compare two type_enum objects by their names (checks already performed) */
+static int order_enum_by_name ( struct dict_object *o1, struct dict_object *o2 )
+{
+	TRACE_ENTRY("%p %p", o1, o2);
+	
+	return fd_os_cmp( o1->data.enumval.enum_name, o1->datastr_len, o2->data.enumval.enum_name, o2->datastr_len );
+}
+
+/* Compare two type_enum objects by their values (checks already performed) */
+static int order_enum_by_val  ( struct dict_object *o1, struct dict_object *o2 )
+{
+	TRACE_ENTRY("%p %p", o1, o2);
+	
+	/* The comparison function depends on the type of data */
+	switch ( o1->parent->data.type.type_base ) {
+		case AVP_TYPE_OCTETSTRING:
+			return fd_os_cmp( o1->data.enumval.enum_value.os.data, o1->data.enumval.enum_value.os.len, 
+					  o2->data.enumval.enum_value.os.data, o2->data.enumval.enum_value.os.len);
+		
+		case AVP_TYPE_INTEGER32:
+			return ORDER_scalar( o1->data.enumval.enum_value.i32, o2->data.enumval.enum_value.i32 );
+
+		case AVP_TYPE_INTEGER64:
+			return ORDER_scalar( o1->data.enumval.enum_value.i64, o2->data.enumval.enum_value.i64 );
+
+		case AVP_TYPE_UNSIGNED32:
+			return ORDER_scalar( o1->data.enumval.enum_value.u32, o2->data.enumval.enum_value.u32 );
+
+		case AVP_TYPE_UNSIGNED64:
+			return ORDER_scalar( o1->data.enumval.enum_value.u64, o2->data.enumval.enum_value.u64 );
+
+		case AVP_TYPE_FLOAT32:
+			return ORDER_scalar( o1->data.enumval.enum_value.f32, o2->data.enumval.enum_value.f32 );
+
+		case AVP_TYPE_FLOAT64:
+			return ORDER_scalar( o1->data.enumval.enum_value.f64, o2->data.enumval.enum_value.f64 );
+
+		case AVP_TYPE_GROUPED:
+		default:
+			ASSERT(0);
+	}
+	return 0;
+}
+
+/* Compare two avp objects by their codes (checks already performed) */
+static int order_avp_by_code  ( struct dict_object *o1, struct dict_object *o2 )
+{
+	TRACE_ENTRY("%p %p", o1, o2);
+	
+	return ORDER_scalar( o1->data.avp.avp_code, o2->data.avp.avp_code );
+}
+
+/* Compare two avp objects by their names (checks already performed) */
+static int order_avp_by_name  ( struct dict_object *o1, struct dict_object *o2 )
+{
+	TRACE_ENTRY("%p %p", o1, o2);
+	
+	return fd_os_cmp( o1->data.avp.avp_name, o1->datastr_len, o2->data.avp.avp_name, o2->datastr_len );
+}
+
+/* Compare two command objects by their names (checks already performed) */
+static int order_cmd_by_name  ( struct dict_object *o1, struct dict_object *o2 )
+{
+	TRACE_ENTRY("%p %p", o1, o2);
+	
+	return fd_os_cmp( o1->data.cmd.cmd_name, o1->datastr_len, o2->data.cmd.cmd_name, o2->datastr_len );
+}
+
+/* Compare two command objects by their codes and flags (request or answer) (checks already performed) */
+static int order_cmd_by_codefl( struct dict_object *o1, struct dict_object *o2 )
+{
+	uint8_t fl1, fl2;
+	int cmp = 0;
+	
+	TRACE_ENTRY("%p %p", o1, o2);
+	
+	cmp = ORDER_scalar( o1->data.cmd.cmd_code, o2->data.cmd.cmd_code );
+	if (cmp) 
+		return cmp;
+	
+	/* Same command code, we must compare the value of the 'R' flag */
+	fl1 = o1->data.cmd.cmd_flag_val & CMD_FLAG_REQUEST;
+	fl2 = o2->data.cmd.cmd_flag_val & CMD_FLAG_REQUEST;
+	
+	/* We want requests first, so we reverse the operators here */
+	return ORDER_scalar(fl2, fl1);
+		
+}
+
+/* Compare two rule object by the AVP vendor & code that they refer (checks already performed) */
+static int order_rule_by_avpvc ( struct dict_object *o1, struct dict_object *o2 )
+{
+	TRACE_ENTRY("%p %p", o1, o2);
+	
+	return ORDER_scalar(o1->data.rule.rule_avp->data.avp.avp_vendor, o2->data.rule.rule_avp->data.avp.avp_vendor) 
+		?: ORDER_scalar(o1->data.rule.rule_avp->data.avp.avp_code, o2->data.rule.rule_avp->data.avp.avp_code) ;
+}
+
+/*******************************************************************************************************/
+/*******************************************************************************************************/
+/*                                                                                                     */
+/*                                  Search  functions                                                  */
+/*                                                                                                     */
+/*******************************************************************************************************/
+/*******************************************************************************************************/
+
+/* Functions used to search for objects in the lists, according to some criteria */
+
+/* On a general note, if result is not NULL, ENOENT is not returned but *result is NULL. */
+
+/* The following macros assume that "what", "ret", "result" (variables), and "end" (label) exist
+in the local context where they are called. They are meant to be called only from the functions that follow. */
+
+/* For searchs of type "xxx_OF_xxx": children's parent or default parent */
+#define SEARCH_childs_parent( type_of_child, default_parent ) {			\
+	struct dict_object *__child = (struct dict_object *) what;		\
+	CHECK_PARAMS_DO( verify_object(__child) && 				\
+		(__child->type == (type_of_child)), 				\
+		   {  ret = EINVAL; goto end;  }  );				\
+	ret = 0;								\
+	if (result)								\
+		*result = (__child->parent ? __child->parent :(default_parent));\
+}
+
+/* For search of strings in lists. isindex= 1 if the string is the ordering key of the list */
+/* it is expected that object->datastr_len is the length of the datafield parameter */
+#define SEARCH_os0_l( str, len, sentinel, datafield, isindex ) {		\
+	char *  __str = (char *) (str);						\
+	size_t __strlen = (size_t)(len);					\
+	int __cmp;								\
+	struct fd_list * __li;							\
+	ret = 0;								\
+	for  (__li = (sentinel)->next; __li != (sentinel); __li = __li->next) {	\
+		__cmp = fd_os_cmp(__str, __strlen,				\
+			_O(__li->o)->data. datafield, _O(__li->o)->datastr_len);\
+		if (__cmp == 0) {						\
+			if (result)						\
+				*result = _O(__li->o);				\
+			goto end;						\
+		}								\
+		if ((isindex) && (__cmp < 0))					\
+			break;							\
+	}									\
+	if (result)								\
+		*result = NULL;							\
+	else									\
+		ret = ENOENT;							\
+}
+
+/* When len is not provided */
+#define SEARCH_os0( str, sentinel, datafield, isindex ) {			\
+	char *  _str = (char *) (str);						\
+	size_t  _strlen = strlen(_str);						\
+	SEARCH_os0_l( _str, _strlen, sentinel, datafield, isindex );		\
+}
+
+
+/* For search of octetstrings in lists. */
+#define SEARCH_os(  str, strlen, sentinel, osdatafield, isindex ) {		\
+	uint8_t * __str = (uint8_t *) (str);					\
+	size_t __strlen = (size_t)(strlen);					\
+	int __cmp;								\
+	struct fd_list * __li;							\
+	ret = 0;								\
+	for  (__li = (sentinel)->next; __li != (sentinel); __li = __li->next) {	\
+		__cmp = fd_os_cmp(__str, __strlen,				\
+			_O(__li->o)->data. osdatafield .data,			\
+			_O(__li->o)->data. osdatafield .len);			\
+		if (__cmp == 0) {						\
+			if (result)						\
+				*result = _O(__li->o);				\
+			goto end;						\
+		}								\
+		if ((isindex) && (__cmp < 0))					\
+			break;							\
+	}									\
+	if (result)								\
+		*result = NULL;							\
+	else									\
+		ret = ENOENT;							\
+}
+
+/* For search of AVP name in rule lists -- the list is not ordered by AVP names! */
+#define SEARCH_ruleavpname( str, strlen, sentinel ) {				\
+	char * __str = (char *) (str);						\
+	size_t __strlen = (size_t) (strlen);					\
+	int __cmp;								\
+	struct fd_list * __li;							\
+	ret = 0;								\
+	for  (__li = (sentinel)->next; __li != (sentinel); __li = __li->next) {	\
+		__cmp = fd_os_cmp(__str, __strlen, 				\
+		  	_O(__li->o)->data.rule.rule_avp->data.avp.avp_name,	\
+			_O(__li->o)->data.rule.rule_avp->datastr_len);		\
+		if (__cmp == 0) {						\
+			if (result)						\
+				*result = _O(__li->o);				\
+			goto end;						\
+		}								\
+	}									\
+	if (result)								\
+		*result = NULL;							\
+	else									\
+		ret = ENOENT;							\
+}
+
+/* For search of scalars in lists. isindex= 1 if the value is the ordering key of the list */
+#define SEARCH_scalar( value, sentinel, datafield, isindex, defaultobj ) {	\
+	int __cmp;								\
+	struct fd_list * __li;							\
+	ret = 0;								\
+	if (  ((defaultobj) != NULL) 						\
+		   && (_O(defaultobj)->data. datafield  == value)) {		\
+		if (result)							\
+			*result = _O(defaultobj);				\
+		goto end;							\
+	}									\
+	for  (__li = (sentinel)->next; __li != (sentinel); __li = __li->next) {	\
+		__cmp= ORDER_scalar(value, _O(__li->o)->data. datafield );	\
+		if (__cmp == 0) {						\
+			if (result)						\
+				*result = _O(__li->o);				\
+			goto end;						\
+		}								\
+		if ((isindex) && (__cmp < 0))					\
+			break;							\
+	}									\
+	if (result)								\
+		*result = NULL;							\
+	else									\
+		ret = ENOENT;							\
+}
+
+/* For search of commands in lists by code and flag. R_flag_val = 0 or CMD_FLAG_REQUEST */
+#define SEARCH_codefl( value, R_flag_val, sentinel) {					\
+	int __cmp;								\
+	struct fd_list * __li;							\
+	ret = 0;								\
+	for  (__li = (sentinel)->next; __li != (sentinel); __li = __li->next) {	\
+		__cmp = ORDER_scalar(value, 					\
+				_O(__li->o)->data.cmd.cmd_code );		\
+		if (__cmp == 0) {						\
+			uint8_t __mask, __val;					\
+			__mask = _O(__li->o)->data.cmd.cmd_flag_mask;		\
+			__val  = _O(__li->o)->data.cmd.cmd_flag_val;		\
+			if ( ! (__mask & CMD_FLAG_REQUEST) )			\
+				continue;					\
+			if ( ( __val & CMD_FLAG_REQUEST ) != R_flag_val )	\
+				continue;					\
+			if (result)						\
+				*result = _O(__li->o);				\
+			goto end;						\
+		}								\
+		if (__cmp < 0)							\
+			break;							\
+	}									\
+	if (result)								\
+		*result = NULL;							\
+	else									\
+		ret = ENOENT;							\
+}
+
+/* For searchs of type "xxx_OF_xxx": if the search object is sentinel list for the "what" object */
+#define SEARCH_sentinel( type_of_what, what_list_nr, sentinel_list_nr ) {			\
+	struct dict_object *__what = (struct dict_object *) what;				\
+	CHECK_PARAMS_DO( verify_object(__what) && 						\
+		(__what->type == (type_of_what)), 						\
+		   {  ret = EINVAL; goto end;  }  );						\
+	ret = 0;										\
+	if (result) {										\
+		/* this is similar to the "container_of" */					\
+		*result = (struct dict_object *)((char *)(__what->list[what_list_nr].head) - 	\
+		   		(size_t)&(((struct dict_object *)0)->list[sentinel_list_nr]));	\
+	}											\
+}
+
+
+static int search_vendor ( struct dictionary * dict, int criteria, const void * what, struct dict_object **result )
+{
+	int ret = 0;
+	vendor_id_t id;
+	
+	TRACE_ENTRY("%p %d %p %p", dict, criteria, what, result);
+	
+	switch (criteria) {
+		case VENDOR_BY_ID:
+			id = *(vendor_id_t *) what;
+			SEARCH_scalar( id, &dict->dict_vendors.list[0], vendor.vendor_id, 1, &dict->dict_vendors );
+			break;
+				
+		case VENDOR_BY_NAME:
+			/* "what" is a vendor name */
+			SEARCH_os0( what, &dict->dict_vendors.list[0], vendor.vendor_name, 0);
+			break;
+			
+		case VENDOR_OF_APPLICATION:
+			/* "what" should be an application object */
+			SEARCH_childs_parent( DICT_APPLICATION, &dict->dict_vendors );
+			break;
+		
+		case VENDOR_OF_AVP:
+			/* "what" should be an avp object */
+			SEARCH_sentinel( DICT_AVP, 0, 1 );
+			break;
+		
+		default:
+			/* Invalid criteria */
+			CHECK_PARAMS( criteria = 0 );
+	}
+end:
+	return ret;
+}
+
+static int search_application ( struct dictionary * dict, int criteria, const void * what, struct dict_object **result )
+{
+	int ret = 0;
+	application_id_t id;
+	
+	TRACE_ENTRY("%p %d %p %p", dict, criteria, what, result);
+	
+	switch (criteria) {
+		case APPLICATION_BY_ID:
+			id = *(application_id_t *) what;
+
+			SEARCH_scalar( id, &dict->dict_applications.list[0],  application.application_id, 1, &dict->dict_applications );
+			break;
+				
+		case APPLICATION_BY_NAME:
+			/* "what" is an application name */
+			SEARCH_os0( what, &dict->dict_applications.list[0], application.application_name, 0);
+			break;
+			
+		case APPLICATION_OF_TYPE:
+			/* "what" should be a type object */
+			SEARCH_childs_parent( DICT_TYPE, &dict->dict_applications );
+			break;
+		
+		case APPLICATION_OF_COMMAND:
+			/* "what" should be a command object */
+			SEARCH_childs_parent( DICT_COMMAND, &dict->dict_applications );
+			break;
+		
+		default:
+			/* Invalid criteria */
+			CHECK_PARAMS( criteria = 0 );
+	}
+end:
+	return ret;
+}
+
+static int search_type ( struct dictionary * dict, int criteria, const void * what, struct dict_object **result )
+{
+	int ret = 0;
+	
+	TRACE_ENTRY("%p %d %p %p", dict, criteria, what, result);
+	
+	switch (criteria) {
+		case TYPE_BY_NAME:
+			/* "what" is a type name */
+			SEARCH_os0( what, &dict->dict_types, type.type_name, 1);
+			break;
+			
+		case TYPE_OF_ENUMVAL:
+			/* "what" should be a type_enum object */
+			SEARCH_childs_parent( DICT_ENUMVAL, NULL );
+			break;
+		
+		case TYPE_OF_AVP:
+			/* "what" should be an avp object */
+			SEARCH_childs_parent( DICT_AVP, NULL );
+			break;
+		
+				
+		default:
+			/* Invalid criteria */
+			CHECK_PARAMS( criteria = 0 );
+	}
+end:
+	return ret;
+}
+
+static int search_enumval ( struct dictionary * dict, int criteria, const void * what, struct dict_object **result )
+{
+	int ret = 0;
+	
+	TRACE_ENTRY("%p %d %p %p", dict, criteria, what, result);
+	
+	switch (criteria) {
+		case ENUMVAL_BY_STRUCT:
+			{
+				struct dict_object * parent = NULL;
+				struct dict_enumval_request * _what = (struct dict_enumval_request *) what;
+				
+				CHECK_PARAMS(  _what  &&  ( _what->type_obj || _what->type_name )  );
+				
+				if (_what->type_obj != NULL) {
+					parent = _what->type_obj;
+					CHECK_PARAMS(  verify_object(parent)  &&  (parent->type == DICT_TYPE)  );
+				} else {
+					/* We received only the type name, we must find it first */
+					CHECK_FCT_DO( search_type( dict, TYPE_BY_NAME, _what->type_name, &parent ),
+							CHECK_PARAMS( 0 ) );
+				}
+				
+				/* From here the "parent" object is valid */
+				
+				if ( _what->search.enum_name != NULL ) {
+					/* We are looking for this string */
+					SEARCH_os0(  _what->search.enum_name, &parent->list[1], enumval.enum_name, 1 );
+				} else {
+					/* We are looking for the value in enum_value */
+					switch (parent->data.type.type_base) {
+						case AVP_TYPE_OCTETSTRING:
+							SEARCH_os(	 _what->search.enum_value.os.data, 
+									 _what->search.enum_value.os.len, 
+									 &parent->list[2], 
+									 enumval.enum_value.os , 
+									 1 );
+							break;
+
+						case AVP_TYPE_INTEGER32:
+							SEARCH_scalar(	_what->search.enum_value.i32,
+									&parent->list[2],
+									enumval.enum_value.i32,
+									1,
+									(struct dict_object *)NULL);
+							break;
+							
+						case AVP_TYPE_INTEGER64:
+							SEARCH_scalar(	_what->search.enum_value.i64,
+									&parent->list[2],
+									enumval.enum_value.i64,
+									1,
+									(struct dict_object *)NULL);
+							break;
+							
+						case AVP_TYPE_UNSIGNED32:
+							SEARCH_scalar(	_what->search.enum_value.u32,
+									&parent->list[2],
+									enumval.enum_value.u32,
+									1,
+									(struct dict_object *)NULL);
+							break;
+							
+						case AVP_TYPE_UNSIGNED64:
+							SEARCH_scalar(	_what->search.enum_value.u64,
+									&parent->list[2],
+									enumval.enum_value.u64,
+									1,
+									(struct dict_object *)NULL);
+							break;
+							
+						case AVP_TYPE_FLOAT32:
+							SEARCH_scalar(	_what->search.enum_value.f32,
+									&parent->list[2],
+									enumval.enum_value.f32,
+									1,
+									(struct dict_object *)NULL);
+							break;
+							
+						case AVP_TYPE_FLOAT64:
+							SEARCH_scalar(	_what->search.enum_value.f64,
+									&parent->list[2],
+									enumval.enum_value.f64,
+									1,
+									(struct dict_object *)NULL);
+							break;
+							
+						default:
+							/* Invalid parent type basetype */
+							CHECK_PARAMS( parent = NULL );
+					}
+				}
+				
+			}
+			break;
+		
+				
+		default:
+			/* Invalid criteria */
+			CHECK_PARAMS( criteria = 0 );
+	}
+end:
+	return ret;
+}
+
+static int search_avp ( struct dictionary * dict, int criteria, const void * what, struct dict_object **result )
+{
+	int ret = 0;
+	
+	TRACE_ENTRY("%p %d %p %p", dict, criteria, what, result);
+	
+	switch (criteria) {
+		case AVP_BY_CODE:
+			{
+				avp_code_t code;
+				code = *(avp_code_t *) what;
+
+				SEARCH_scalar( code, &dict->dict_vendors.list[1],  avp.avp_code, 1, (struct dict_object *)NULL );
+			}
+			break;
+				
+		case AVP_BY_NAME:
+			/* "what" is the AVP name, vendor 0 */
+			SEARCH_os0( what, &dict->dict_vendors.list[2], avp.avp_name, 1);
+			break;
+			
+		case AVP_BY_CODE_AND_VENDOR:
+		case AVP_BY_NAME_AND_VENDOR:
+			{
+				struct dict_avp_request * _what = (struct dict_avp_request *) what;
+				struct dict_object * vendor = NULL;
+				
+				CHECK_PARAMS( (criteria != AVP_BY_NAME_AND_VENDOR) || _what->avp_name  );
+				
+				/* Now look for the vendor first */
+				CHECK_FCT( search_vendor( dict, VENDOR_BY_ID, &_what->avp_vendor, &vendor ) );
+				if (vendor == NULL) {
+					if (result)
+						*result = NULL;
+					else
+						ret = ENOENT;
+					goto end;
+				}
+				
+				/* We now have our vendor = head of the appropriate avp list */
+				if (criteria == AVP_BY_NAME_AND_VENDOR) {
+					SEARCH_os0( _what->avp_name, &vendor->list[2], avp.avp_name, 1);
+				} else {
+					/* AVP_BY_CODE_AND_VENDOR */
+					SEARCH_scalar( _what->avp_code, &vendor->list[1], avp.avp_code, 1, (struct dict_object *)NULL );
+				}
+			}
+			break;
+		
+		case AVP_BY_STRUCT:
+			{
+				struct dict_avp_request_ex * _what = (struct dict_avp_request_ex *) what;
+				struct dict_object * vendor = NULL;
+				
+				CHECK_PARAMS( _what->avp_vendor.vendor || _what->avp_vendor.vendor_id || _what->avp_vendor.vendor_name );
+				CHECK_PARAMS( _what->avp_data.avp_code || _what->avp_data.avp_name );
+				
+				/* Now look for the vendor first */
+				if (_what->avp_vendor.vendor) {
+					CHECK_PARAMS( ! _what->avp_vendor.vendor_id && ! _what->avp_vendor.vendor_name );
+					vendor = _what->avp_vendor.vendor;
+				} else if (_what->avp_vendor.vendor_id) {
+					CHECK_PARAMS( ! _what->avp_vendor.vendor_name );
+					CHECK_FCT( search_vendor( dict, VENDOR_BY_ID, &_what->avp_vendor.vendor_id, &vendor ) );
+				} else {
+					CHECK_FCT( search_vendor( dict, VENDOR_BY_NAME, _what->avp_vendor.vendor_name, &vendor ) );
+				}
+				
+				if (vendor == NULL) {
+					if (result)
+						*result = NULL;
+					else
+						ret = ENOENT;
+					goto end;
+				}
+				
+				/* We now have our vendor = head of the appropriate avp list */
+				if (_what->avp_data.avp_code) {
+					CHECK_PARAMS( ! _what->avp_data.avp_name );
+					SEARCH_scalar( _what->avp_data.avp_code, &vendor->list[1], avp.avp_code, 1, (struct dict_object *)NULL );
+				} else {
+					SEARCH_os0( _what->avp_data.avp_name, &vendor->list[2], avp.avp_name, 1);
+				}
+			}
+			break;
+		
+		case AVP_BY_NAME_ALL_VENDORS:
+			{
+				struct fd_list * li;
+				size_t wl = strlen((char *)what);
+				
+				/* First, search for vendor 0 */
+				SEARCH_os0_l( what, wl, &dict->dict_vendors.list[2], avp.avp_name, 1);
+				
+				/* If not found, loop for all vendors, until found */
+				for (li = dict->dict_vendors.list[0].next; li != &dict->dict_vendors.list[0]; li = li->next) {
+					SEARCH_os0_l( what, wl, &_O(li->o)->list[2], avp.avp_name, 1);
+				}
+			}
+			break;
+		
+		default:
+			/* Invalid criteria */
+			CHECK_PARAMS( criteria = 0 );
+	}
+end:
+	return ret;
+}
+
+static int search_cmd ( struct dictionary * dict, int criteria, const void * what, struct dict_object **result )
+{
+	int ret = 0;
+	
+	TRACE_ENTRY("%p %d %p %p", dict, criteria, what, result);
+	
+	switch (criteria) {
+		case CMD_BY_NAME:
+			/* "what" is a command name */
+			SEARCH_os0( what, &dict->dict_cmd_name, cmd.cmd_name, 1);
+			break;
+			
+		case CMD_BY_CODE_R:
+		case CMD_BY_CODE_A:
+			{
+				command_code_t code;
+				uint8_t searchfl = 0;
+				
+				/* The command code that we are searching */
+				code = *(command_code_t *) what;
+				
+				/* The flag (request or answer) of the command we are searching */
+				if (criteria == CMD_BY_CODE_R) {
+					searchfl = CMD_FLAG_REQUEST;
+				}
+				
+				/* perform the search */
+				SEARCH_codefl( code, searchfl, &dict->dict_cmd_code );
+			}
+			break;
+				
+		case CMD_ANSWER:
+			{
+				/* "what" is a command object of type "request" */
+				struct dict_object * req = (struct dict_object *) what;
+				struct dict_object * ans = NULL;
+				
+				CHECK_PARAMS( verify_object(req) 
+						&& (req->type == DICT_COMMAND)
+						&& (req->data.cmd.cmd_flag_mask & CMD_FLAG_REQUEST)
+						&& (req->data.cmd.cmd_flag_val  & CMD_FLAG_REQUEST) );
+				
+				/* The answer is supposed to be the next element in the list, if it exists */
+				ans = req->list[1].next->o;
+				if ( ans == NULL ) {
+					TRACE_DEBUG( FULL, "the request was the last element in the list" );
+					ret = ENOENT;
+					goto end;
+				}
+				
+				/* Now check that the ans element is really the correct one */
+				if (  (ans->data.cmd.cmd_code != req->data.cmd.cmd_code)
+				   || (!(ans->data.cmd.cmd_flag_mask & CMD_FLAG_REQUEST))
+				   || (  ans->data.cmd.cmd_flag_val  & CMD_FLAG_REQUEST ) ) {
+					TRACE_DEBUG( FULL, "the answer does not follow the request in the list" );
+					ret = ENOENT;
+					goto end;
+				}
+				
+				if (result)
+					*result = ans;
+				ret = 0;
+			}						
+			break;
+			
+		default:
+			/* Invalid criteria */
+			CHECK_PARAMS( criteria = 0 );
+	}
+end:
+	return ret;
+}
+
+static int search_rule ( struct dictionary * dict, int criteria, const void * what, struct dict_object **result )
+{
+	int ret = 0;
+	
+	TRACE_ENTRY("%p %d %p %p", dict, criteria, what, result);
+	
+	switch (criteria) {
+		case RULE_BY_AVP_AND_PARENT:
+			{
+				struct dict_object * parent = NULL;
+				struct dict_object * avp = NULL;
+				struct dict_rule_request * _what = (struct dict_rule_request *) what;
+				
+				CHECK_PARAMS( _what 
+						&& (parent = _what->rule_parent)
+						&& (avp    = _what->rule_avp   ) );
+				
+				CHECK_PARAMS( verify_object(parent) 
+						&& ((parent->type == DICT_COMMAND) 
+						 || ((parent->type == DICT_AVP) && (parent->data.avp.avp_basetype == AVP_TYPE_GROUPED))) );
+				
+				CHECK_PARAMS( verify_object(avp) && (avp->type == DICT_AVP) );
+				
+				/* Perform the search */
+				SEARCH_ruleavpname( avp->data.avp.avp_name, avp->datastr_len, &parent->list[2]);
+				
+			}
+			break;
+			
+		default:
+			/* Invalid criteria */
+			CHECK_PARAMS( criteria = 0 );
+	}
+end:
+	return ret;
+}
+
+/*******************************************************************************************************/
+/*******************************************************************************************************/
+/*                                                                                                     */
+/*                                  Dump / debug functions                                             */
+/*                                                                                                     */
+/*******************************************************************************************************/
+/*******************************************************************************************************/
+/* The following functions are used to debug the module, and allow to print out the content of the dictionary */
+static DECLARE_FD_DUMP_PROTOTYPE(dump_vendor_data, void * data )
+{
+	struct dict_vendor_data * vendor = (struct dict_vendor_data *)data;
+	
+	return fd_dump_extend( FD_DUMP_STD_PARAMS, "data: %-6u \"%s\"", vendor->vendor_id, vendor->vendor_name);
+}
+static DECLARE_FD_DUMP_PROTOTYPE(dump_application_data, void * data )
+{
+	struct dict_application_data * appli = (struct dict_application_data *) data;
+	return fd_dump_extend( FD_DUMP_STD_PARAMS, "data: %-6u \"%s\"", appli->application_id, appli->application_name);
+}
+static DECLARE_FD_DUMP_PROTOTYPE(dump_type_data, void * data )
+{
+	struct dict_type_data * type = ( struct dict_type_data * ) data;
+	
+	return fd_dump_extend( FD_DUMP_STD_PARAMS, "data: %-12s \"%s\"", 
+			type_base_name[type->type_base], 
+			type->type_name);
+}
+static DECLARE_FD_DUMP_PROTOTYPE(dump_enumval_data, struct dict_enumval_data * enumval, enum dict_avp_basetype type )
+{
+	const int LEN_MAX = 20;
+	CHECK_MALLOC_DO(fd_dump_extend( FD_DUMP_STD_PARAMS, "data: (%-12s) \"%s\" -> ", type_base_name[type], enumval->enum_name), return NULL);
+	switch (type) {
+		case AVP_TYPE_OCTETSTRING:
+			{
+				int i, n=LEN_MAX;
+				if (enumval->enum_value.os.len < LEN_MAX)
+					n = enumval->enum_value.os.len;
+				for (i=0; i < n; i++)
+					CHECK_MALLOC_DO(fd_dump_extend( FD_DUMP_STD_PARAMS, "0x%2hhX/'%c' ", enumval->enum_value.os.data[i], ASCII(enumval->enum_value.os.data[i])), return NULL);
+				if (n == LEN_MAX)
+					CHECK_MALLOC_DO(fd_dump_extend( FD_DUMP_STD_PARAMS, "..."), return NULL);
+			}
+			break;
+		
+		case AVP_TYPE_INTEGER32:
+			CHECK_MALLOC_DO(fd_dump_extend( FD_DUMP_STD_PARAMS, "%i", enumval->enum_value.i32), return NULL);
+			break;
+
+		case AVP_TYPE_INTEGER64:
+			CHECK_MALLOC_DO(fd_dump_extend( FD_DUMP_STD_PARAMS, "%"PRId64, enumval->enum_value.i64), return NULL);
+			break;
+
+		case AVP_TYPE_UNSIGNED32:
+			CHECK_MALLOC_DO(fd_dump_extend( FD_DUMP_STD_PARAMS, "%u", enumval->enum_value.u32), return NULL);
+			break;
+
+		case AVP_TYPE_UNSIGNED64:
+			CHECK_MALLOC_DO(fd_dump_extend( FD_DUMP_STD_PARAMS, "%"PRIu64, enumval->enum_value.u64), return NULL);
+			break;
+
+		case AVP_TYPE_FLOAT32:
+			CHECK_MALLOC_DO(fd_dump_extend( FD_DUMP_STD_PARAMS, "%f", enumval->enum_value.f32), return NULL);
+			break;
+
+		case AVP_TYPE_FLOAT64:
+			CHECK_MALLOC_DO(fd_dump_extend( FD_DUMP_STD_PARAMS, "%g", enumval->enum_value.f64), return NULL);
+			break;
+		
+		default:
+			CHECK_MALLOC_DO(fd_dump_extend( FD_DUMP_STD_PARAMS, "??? (ERROR unknown type %d)", type), return NULL);
+	}
+	return *buf;
+}
+static DECLARE_FD_DUMP_PROTOTYPE(dump_avp_data, void * data )
+{
+	struct dict_avp_data * avp = (struct dict_avp_data * ) data;
+	return fd_dump_extend( FD_DUMP_STD_PARAMS, "data: v/m:" DUMP_AVPFL_str "/" DUMP_AVPFL_str ", %12s, %-6u \"%s\"", 
+			DUMP_AVPFL_val(avp->avp_flag_val), 
+			DUMP_AVPFL_val(avp->avp_flag_mask), 
+			type_base_name[avp->avp_basetype], 
+			avp->avp_code, 
+			avp->avp_name );
+}
+static DECLARE_FD_DUMP_PROTOTYPE(dump_command_data, void * data )
+{
+	struct dict_cmd_data * cmd = (struct dict_cmd_data *) data;
+	return fd_dump_extend( FD_DUMP_STD_PARAMS, "data: v/m:" DUMP_CMDFL_str "/" DUMP_CMDFL_str ", %-6u \"%s\"", 
+			DUMP_CMDFL_val(cmd->cmd_flag_val), DUMP_CMDFL_val(cmd->cmd_flag_mask), cmd->cmd_code, cmd->cmd_name);
+}
+static DECLARE_FD_DUMP_PROTOTYPE(dump_rule_data, void * data )
+{
+	struct dict_rule_data * rule = (struct dict_rule_data * )data;
+	return fd_dump_extend( FD_DUMP_STD_PARAMS, "data: pos:%d ord:%d m/M:%2d/%2d avp:\"%s\"",
+			rule->rule_position, 
+			rule->rule_order, 
+			rule->rule_min, 
+			rule->rule_max,
+			rule->rule_avp->data.avp.avp_name);
+}
+
+static DECLARE_FD_DUMP_PROTOTYPE(dump_object, struct dict_object * obj, int parents, int depth, int indent );
+
+static DECLARE_FD_DUMP_PROTOTYPE(dump_list, struct fd_list * sentinel, int parents, int depth, int indent )
+{
+	struct fd_list * li = sentinel;
+	/* We don't lock here, the caller must have taken the dictionary lock for reading already */
+	if (FD_IS_LIST_EMPTY(sentinel)) {
+		CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "\n%*s{empty list}", indent, ""), return NULL);
+	} else {
+		while (li->next != sentinel)
+		{
+			li = li->next;
+			CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "\n"), return NULL);
+			CHECK_MALLOC_DO( dump_object (FD_DUMP_STD_PARAMS, _O(li->o), parents, depth, indent ), return NULL);
+		}
+	}
+	return *buf;
+}
+
+static DECLARE_FD_DUMP_PROTOTYPE(dump_object, struct dict_object * obj, int parents, int depth, int indent )
+{
+	CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "%*s{dictobj}(@%p): ", indent, "", obj), return NULL);
+	
+	if (!verify_object(obj)) {
+		CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "INVALID/NULL"), return NULL);
+		return *buf;
+	}
+	
+	CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "%s p:%p ", 
+								_OBINFO(obj).name, 
+								obj->parent), return NULL);
+	
+	if (obj->type == DICT_ENUMVAL) {
+		CHECK_MALLOC_DO( dump_enumval_data ( FD_DUMP_STD_PARAMS, &obj->data.enumval, obj->parent->data.type.type_base ), return NULL);
+	} else {
+		CHECK_MALLOC_DO( _OBINFO(obj).dump_data(FD_DUMP_STD_PARAMS, &obj->data), return NULL);
+	}
+	
+	if (parents) {
+		CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "\n%*sparent:", indent + 1, ""), return NULL);
+		CHECK_MALLOC_DO( dump_object (FD_DUMP_STD_PARAMS, obj->parent, parents-1, 0, 0 ), return NULL);
+	}
+	
+	if (depth) {
+		int i;
+		for (i=0; i<NB_LISTS_PER_OBJ; i++) {
+			if ((obj->list[i].o == NULL) && (obj->list[i].next != &obj->list[i])) {
+				CHECK_MALLOC_DO( dump_list(FD_DUMP_STD_PARAMS, &obj->list[i], 0, depth - 1, indent + 2), return NULL);
+				break; /* we get duplicate information sorted by another criteria otherwise, which is not very useful */
+			}
+		}
+	}
+	
+	return *buf;
+}
+
+DECLARE_FD_DUMP_PROTOTYPE(fd_dict_dump_object, struct dict_object * obj)
+{
+	FD_DUMP_HANDLE_OFFSET();
+	
+	CHECK_MALLOC_DO( dump_object(FD_DUMP_STD_PARAMS, obj, 1, 2, 0), return NULL);
+	
+	return *buf;
+}
+
+DECLARE_FD_DUMP_PROTOTYPE(fd_dict_dump, struct dictionary * dict)
+{
+	int i;
+	struct fd_list * li;
+	
+	FD_DUMP_HANDLE_OFFSET();
+		
+	CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "{dictionary}(@%p): ", dict), return NULL);
+	
+	if ((dict == NULL) || (dict->dict_eyec != DICT_EYECATCHER)) {
+		return fd_dump_extend(FD_DUMP_STD_PARAMS, "INVALID/NULL");
+	}
+	
+	CHECK_POSIX_DO(  pthread_rwlock_rdlock( &dict->dict_lock ), /* ignore */  );
+	
+	CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "\n {dict(%p) : VENDORS / AVP / RULES}\n", dict), goto error);
+	CHECK_MALLOC_DO( dump_object (FD_DUMP_STD_PARAMS, &dict->dict_vendors, 0, 3, 3 ), goto error);
+	for (li = dict->dict_vendors.list[0].next; li != &dict->dict_vendors.list[0]; li = li->next) {
+		CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "\n"), return NULL);
+		CHECK_MALLOC_DO( dump_object (FD_DUMP_STD_PARAMS, li->o, 0, 3, 3 ), goto error);
+	}
+	
+	CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "\n {dict(%p) : APPLICATIONS}\n", dict), goto error);
+	CHECK_MALLOC_DO( dump_object (FD_DUMP_STD_PARAMS, &dict->dict_applications, 0, 1, 3 ), goto error);
+	for (li = dict->dict_applications.list[0].next; li != &dict->dict_applications.list[0]; li = li->next) {
+		CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "\n"), return NULL);
+		CHECK_MALLOC_DO( dump_object (FD_DUMP_STD_PARAMS, li->o, 0, 1, 3 ), goto error);
+	}
+	
+	CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "\n {dict(%p) : TYPES / ENUMVAL}", dict), goto error);
+	CHECK_MALLOC_DO( dump_list(FD_DUMP_STD_PARAMS, &dict->dict_types, 0, 2, 3 ), goto error);
+	
+	CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "\n {dict(%p) : COMMANDS / RULES}", dict), goto error);
+	CHECK_MALLOC_DO( dump_list(FD_DUMP_STD_PARAMS, &dict->dict_cmd_code, 0, 0, 3 ), goto error);
+	
+	CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "\n {dict(%p) : statistics}", dict), goto error);
+	for (i=1; i<=DICT_TYPE_MAX; i++)
+		CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "\n   %5d: %s",  dict->dict_count[i], dict_obj_info[i].name), goto error);
+	
+	CHECK_POSIX_DO(  pthread_rwlock_unlock( &dict->dict_lock ), /* ignore */  );
+	return *buf;
+error:	
+	/* Free the rwlock */
+	CHECK_POSIX_DO(  pthread_rwlock_unlock( &dict->dict_lock ), /* ignore */  );
+	return NULL;
+}
+
+/**************************** Dump AVP values ********************************/
+
+/* Default dump functions */
+static DECLARE_FD_DUMP_PROTOTYPE(dump_val_os, union avp_value * value)
+{
+	int i;
+	
+	CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "<"), return NULL);
+	for (i = 0; i < value->os.len; i++) {
+		if (i == 1024) { /* Dump only up to 1024 bytes of the buffer */
+			CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "[...] (len=%zd)", value->os.len), return NULL);
+			break;
+		}
+		CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "%s%02hhX", (i==0 ? "" : " "), value->os.data[i]), return NULL);
+	}
+	CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, ">"), return NULL);
+	return *buf;
+}
+
+static DECLARE_FD_DUMP_PROTOTYPE(dump_val_i32, union avp_value * value)
+{
+	return fd_dump_extend( FD_DUMP_STD_PARAMS, "%i (0x%x)", value->i32, value->i32);
+}
+
+static DECLARE_FD_DUMP_PROTOTYPE(dump_val_i64, union avp_value * value)
+{
+	return fd_dump_extend( FD_DUMP_STD_PARAMS, "%" PRId64 " (0x%" PRIx64 ")", value->i64, value->i64);
+}
+
+static DECLARE_FD_DUMP_PROTOTYPE(dump_val_u32, union avp_value * value)
+{
+	return fd_dump_extend( FD_DUMP_STD_PARAMS, "%u (0x%x)", value->u32, value->u32);
+}
+
+static DECLARE_FD_DUMP_PROTOTYPE(dump_val_u64, union avp_value * value)
+{
+	return fd_dump_extend( FD_DUMP_STD_PARAMS, "%" PRIu64 " (0x%" PRIx64 ")", value->u64, value->u64);
+}
+
+static DECLARE_FD_DUMP_PROTOTYPE(dump_val_f32, union avp_value * value)
+{
+	return fd_dump_extend( FD_DUMP_STD_PARAMS, "%f", value->f32);
+}
+
+static DECLARE_FD_DUMP_PROTOTYPE(dump_val_f64, union avp_value * value)
+{
+	return fd_dump_extend( FD_DUMP_STD_PARAMS, "%g", value->f64);
+}
+
+/* Get the dump function for basic dict_avp_basetype */
+static DECLARE_FD_DUMP_PROTOTYPE((*get_default_dump_val_cb(enum dict_avp_basetype datatype)), union avp_value *)
+{
+	switch (datatype) {
+		case AVP_TYPE_OCTETSTRING:
+			return &dump_val_os;
+		
+		case AVP_TYPE_INTEGER32:
+			return &dump_val_i32;
+
+		case AVP_TYPE_INTEGER64:
+			return &dump_val_i64;
+
+		case AVP_TYPE_UNSIGNED32:
+			return &dump_val_u32;
+
+		case AVP_TYPE_UNSIGNED64:
+			return &dump_val_u64;
+
+		case AVP_TYPE_FLOAT32:
+			return &dump_val_f32;
+
+		case AVP_TYPE_FLOAT64:
+			return &dump_val_f64;
+		
+		case AVP_TYPE_GROUPED:
+			TRACE_DEBUG(FULL, "error: grouped AVP with a value!");
+	}
+	return NULL;
+}
+
+/* indent inside an object (duplicate from messages.c) */
+#define INOBJHDR 	"%*s   "
+#define INOBJHDRVAL 	indent<0 ? 1 : indent, indent<0 ? "-" : "|"
+
+typedef DECLARE_FD_DUMP_PROTOTYPE((*dump_val_cb_t), union avp_value *);
+
+/* Formatter for the AVP value dump line */
+static DECLARE_FD_DUMP_PROTOTYPE(dump_avp_val, union avp_value *avp_value, 
+			dump_val_cb_t def_dump_val_cb, 
+			dump_val_cb_t dump_val_cb, 
+			enum dict_avp_basetype datatype, 
+			char * type_name, 
+			char * const_name, 
+			int indent, 
+		        int header)
+{
+	if (header) {
+		/* Header for all AVP values dumps: */
+		CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, INOBJHDR "value ", INOBJHDRVAL), return NULL);
+	
+		/* If the type is provided, write it */
+		if (type_name) {
+			CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "t: '%s' ", type_name), return NULL);
+		}
+	
+		/* Always give the base datatype anyway */
+		CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "(%s) ", type_base_name[datatype]), return NULL);
+
+		/* Now, the value */
+		CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "v: "), return NULL);
+	}
+	if (const_name) {
+		CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "'%s' (", const_name), return NULL);
+	}
+	if (dump_val_cb) {
+		CHECK_MALLOC_DO( (*dump_val_cb)( FD_DUMP_STD_PARAMS, avp_value), fd_dump_extend( FD_DUMP_STD_PARAMS, "(dump failed)"));
+	} else {
+		CHECK_MALLOC_DO( (*def_dump_val_cb)( FD_DUMP_STD_PARAMS, avp_value), return NULL);
+	}
+	if (const_name) {
+		CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, ")"), return NULL);
+	}
+	
+	/* Done! */
+	return *buf;
+}
+
+/* Dump the value of an AVP of known type into the returned str */
+DECLARE_FD_DUMP_PROTOTYPE(fd_dict_dump_avp_value, union avp_value *avp_value, struct dict_object * model, int indent, int header)
+{
+	DECLARE_FD_DUMP_PROTOTYPE((*dump_val_cb), union avp_value *avp_value) = NULL;
+	struct dict_object * type = NULL;
+	char * type_name = NULL;
+	char * const_name = NULL;
+	
+	FD_DUMP_HANDLE_OFFSET();
+	
+	/* Handle invalid parameters */
+	if (!avp_value) {
+		CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "(avp value not set)"), return NULL);
+		return *buf;
+	}
+
+	if (!model) {
+		CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "(model not set)"), return NULL);
+		return *buf;
+	}
+	
+	if (! (	verify_object(model) && (model->type == DICT_AVP) )) {
+		CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "(invalid model)"), return NULL);
+		return *buf;
+	}
+	
+	/* Get the type definition of this AVP */
+	type = model->parent;
+	if (type) {
+		struct dict_enumval_request  request;
+		struct dict_object * enumval = NULL;
+		
+		type_name = type->data.type.type_name;
+		
+		/* overwrite the dump function ? */
+		if (type->data.type.type_dump)
+			dump_val_cb = type->data.type.type_dump;
+		
+		/* Now check if the AVP value matches a constant */
+		memset(&request, 0, sizeof(request));
+		request.type_obj = type;
+		memcpy(&request.search.enum_value, avp_value, sizeof(union avp_value));
+		/* bypass checks */
+		if ((search_enumval( type->dico, ENUMVAL_BY_STRUCT, &request, &enumval ) == 0) && (enumval)) {
+			/* We found a constant, get its name */
+			const_name = enumval->data.enumval.enum_name;
+		}
+	}
+	
+	/* And finally, dump the value */
+	CHECK_MALLOC_DO( dump_avp_val(FD_DUMP_STD_PARAMS, avp_value, get_default_dump_val_cb(model->data.avp.avp_basetype), dump_val_cb, model->data.avp.avp_basetype, type_name, const_name, indent, header), return NULL );
+	return *buf;
+}
+
+/*******************************************************************************************************/
+/*******************************************************************************************************/
+/*                                                                                                     */
+/*                                  Exported functions                                                 */
+/*                                                                                                     */
+/*******************************************************************************************************/
+/*******************************************************************************************************/
+
+/* These are the functions exported outside libfreeDiameter. */
+
+/* Get the data associated to an object */
+int fd_dict_gettype ( struct dict_object * object, enum dict_object_type * type)
+{
+	TRACE_ENTRY("%p %p", object, type);
+	
+	CHECK_PARAMS( type && verify_object(object) );
+	
+	/* Copy the value and return */
+	*type = object->type;
+	return 0;
+}
+
+int fd_dict_getdict ( struct dict_object * object, struct dictionary ** dict)
+{
+	TRACE_ENTRY("%p %p", object, dict);
+	
+	CHECK_PARAMS( dict && verify_object(object) );
+	
+	/* Copy the value and return */
+	*dict = object->dico;
+	return 0;
+}
+
+
+/* Get the data associated to an object */
+int fd_dict_getval ( struct dict_object * object, void * val)
+{
+	TRACE_ENTRY("%p %p", object, val);
+	
+	CHECK_PARAMS( val && verify_object(object) );
+	
+	/* Copy the value and return */
+	memcpy(val, &object->data, _OBINFO(object).datasize);;
+	return 0;
+}
+
+/* Add a new object in the dictionary */
+int fd_dict_new ( struct dictionary * dict, enum dict_object_type type, void * data, struct dict_object * parent, struct dict_object **ref )
+{
+	int ret = 0;
+	int dupos = 0;
+	struct dict_object * new = NULL;
+	struct dict_object * vendor = NULL;
+	struct dict_object * locref = NULL;
+	
+	TRACE_ENTRY("%p %d(%s) %p %p %p", dict, type, dict_obj_info[CHECK_TYPE(type) ? type : 0].name, data, parent, ref);
+	
+	/* Check parameters */
+	CHECK_PARAMS( dict && (dict->dict_eyec == DICT_EYECATCHER) && CHECK_TYPE(type) && data  );
+	
+	/* Check the "parent" parameter */
+	switch (dict_obj_info[type].parent) {
+		case 0:	/* parent is forbidden */
+			CHECK_PARAMS_DO( parent == NULL, goto error_param );
+		
+		case 1:	/* parent is optional */
+			if (parent == NULL)
+				break;
+		
+		case 2: /* parent is mandatory */
+			CHECK_PARAMS_DO(  verify_object(parent), goto error_param  );
+			
+			if (type == DICT_RULE ) { /* Special case : grouped AVP or Command parents are allowed */
+				CHECK_PARAMS_DO( (parent->type == DICT_COMMAND ) 
+						|| ( (parent->type == DICT_AVP) && (parent->data.avp.avp_basetype == AVP_TYPE_GROUPED ) ), goto error_param );
+			} else {
+				CHECK_PARAMS_DO( parent->type == dict_obj_info[type].parenttype, goto error_param );
+			}
+	}
+	
+	/* For AVP object, we must also check that the "vendor" referenced exists */
+	if (type == DICT_AVP) {
+		CHECK_FCT_DO(  fd_dict_search( dict, DICT_VENDOR, VENDOR_BY_ID, &(((struct dict_avp_data *)data)->avp_vendor), (void*)&vendor, ENOENT ),
+			{ TRACE_DEBUG(INFO, "Unable to find vendor '%d' referenced in the AVP data", ((struct dict_avp_data *)data)->avp_vendor); goto error_param; }  );
+		
+		/* Also check if a parent is provided, that the type are the same */
+		if (parent) {
+			CHECK_PARAMS_DO(  parent->data.type.type_base == ((struct dict_avp_data *)data)->avp_basetype, goto error_param  );
+		}
+	}
+	
+	/* For RULE object, we must also check that the "avp" referenced exists */
+	if (type == DICT_RULE) {
+		CHECK_PARAMS_DO(  verify_object(((struct dict_rule_data *)data)->rule_avp), goto error_param  );
+		CHECK_PARAMS_DO(  ((struct dict_rule_data *)data)->rule_avp->type == DICT_AVP, goto error_param  );
+	}
+	
+	/* For COMMAND object, check that the 'R' flag is fixed */
+	if (type == DICT_COMMAND) {
+		CHECK_PARAMS_DO( ((struct dict_cmd_data *)data)->cmd_flag_mask & CMD_FLAG_REQUEST, goto error_param   );
+	}
+
+	/* For ENUMVAL object, check if the parent type is an OctetString */
+	if (type == DICT_ENUMVAL) {
+		if (parent->data.type.type_base == AVP_TYPE_OCTETSTRING)
+			dupos = 1;
+	}
+	
+	/* We have to check that the new values are not equal to the sentinels */
+	if (type == DICT_VENDOR) {
+		CHECK_PARAMS_DO( ((struct dict_vendor_data *)data)->vendor_id != 0, goto error_param   );
+	}
+	if (type == DICT_APPLICATION) {
+		CHECK_PARAMS_DO( ((struct dict_application_data *)data)->application_id != 0, goto error_param   );
+	}
+	
+	/* Parameters are valid, create the new object */
+	CHECK_MALLOC(  new = malloc(sizeof(struct dict_object))  );
+	
+	/* Initialize the data of the new object */
+	init_object(new, type);
+	init_object_data(new, data, type, dupos);
+	new->dico = dict;
+	new->parent = parent;
+	
+	/* We will change the dictionary => acquire the write lock */
+	CHECK_POSIX_DO(  ret = pthread_rwlock_wrlock(&dict->dict_lock),  goto error_free  );
+	
+	/* Now link the object -- this also checks that no object with same keys already exists */
+	switch (type) {
+		case DICT_VENDOR:
+			/* A vendor object is linked in the g_dict_vendors.list[0], by their id */
+			ret = fd_list_insert_ordered ( &dict->dict_vendors.list[0], &new->list[0], (int (*)(void*, void *))order_vendor_by_id, (void **)&locref );
+			if (ret)
+				goto error_unlock;
+			break;
+		
+		case DICT_APPLICATION:
+			/* An application object is linked in the g_dict_applciations.list[0], by their id */
+			ret = fd_list_insert_ordered ( &dict->dict_applications.list[0], &new->list[0], (int (*)(void*, void *))order_appli_by_id, (void **)&locref );
+			if (ret)
+				goto error_unlock;
+			break;
+		
+		case DICT_TYPE:
+			/* A type object is linked in g_list_types by its name */
+			ret = fd_list_insert_ordered ( &dict->dict_types, &new->list[0], (int (*)(void*, void *))order_type_by_name, (void **)&locref );
+			if (ret)
+				goto error_unlock;
+			break;
+		
+		case DICT_ENUMVAL:
+			/* A type_enum object is linked in it's parent 'type' object lists 1 and 2 by its name and values */
+			ret = fd_list_insert_ordered ( &parent->list[1], &new->list[0], (int (*)(void*, void *))order_enum_by_name, (void **)&locref );
+			if (ret)
+				goto error_unlock;
+			
+			ret = fd_list_insert_ordered ( &parent->list[2], &new->list[1], (int (*)(void*, void *))order_enum_by_val, (void **)&locref );
+			if (ret) { 
+				fd_list_unlink(&new->list[0]); 
+				goto error_unlock; 
+			}
+			break;
+		
+		case DICT_AVP:
+			/* An avp object is linked in lists 1 and 2 of its vendor, by code and name */
+			ret = fd_list_insert_ordered ( &vendor->list[1], &new->list[0], (int (*)(void*, void *))order_avp_by_code, (void **)&locref );
+			if (ret)
+				goto error_unlock;
+			
+			ret = fd_list_insert_ordered ( &vendor->list[2], &new->list[1], (int (*)(void*, void *))order_avp_by_name, (void **)&locref );
+			if (ret) {
+				fd_list_unlink(&new->list[0]);
+				goto error_unlock;
+			}
+			break;
+			
+		case DICT_COMMAND:
+			/* A command object is linked in g_list_cmd_name and g_list_cmd_code by its name and code */
+			ret = fd_list_insert_ordered ( &dict->dict_cmd_code, &new->list[1], (int (*)(void*, void *))order_cmd_by_codefl, (void **)&locref );
+			if (ret)
+				goto error_unlock;
+			
+			ret = fd_list_insert_ordered ( &dict->dict_cmd_name, &new->list[0], (int (*)(void*, void *))order_cmd_by_name, (void **)&locref );
+			if (ret) {
+				fd_list_unlink(&new->list[1]);
+				goto error_unlock;
+			}
+			break;
+		
+		case DICT_RULE:
+			/* A rule object is linked in list[2] of its parent command or AVP by the name of the AVP it refers */
+			ret = fd_list_insert_ordered ( &parent->list[2], &new->list[0], (int (*)(void*, void *))order_rule_by_avpvc, (void **)&locref );
+			if (ret)
+				goto error_unlock;
+			break;
+			
+		default:
+			ASSERT(0);
+	}
+	
+	/* A new object has been created, increment the global counter */
+	dict->dict_count[type]++;
+	
+	/* Unlock the dictionary */
+	CHECK_POSIX_DO(  ret = pthread_rwlock_unlock(&dict->dict_lock),  goto error_free  );
+	
+	/* Save the pointer to the new object */
+	if (ref)
+		*ref = new;
+	
+	return 0;
+	
+error_param:
+	ret = EINVAL;
+	goto all_errors;
+
+error_unlock:
+	CHECK_POSIX_DO(  pthread_rwlock_unlock(&dict->dict_lock),  /* continue */  );
+	if (ret == EEXIST) {
+		/* We have a duplicate key in locref. Check if the pointed object is the same or not */
+		switch (type) {
+			case DICT_VENDOR:
+				TRACE_DEBUG(FULL, "Vendor %s already in dictionary", new->data.vendor.vendor_name);
+				/* if we are here, it means the two vendors id are identical */
+				if (fd_os_cmp(locref->data.vendor.vendor_name, locref->datastr_len, 
+						new->data.vendor.vendor_name, new->datastr_len)) {
+					TRACE_DEBUG(INFO, "Conflicting vendor name: %s", new->data.vendor.vendor_name);
+					break;
+				}
+				/* Otherwise (same name), we consider the function succeeded, since the (same) object is in the dictionary */
+				ret = 0; 
+				break;
+
+			case DICT_APPLICATION:
+				TRACE_DEBUG(FULL, "Application %s already in dictionary", new->data.application.application_name);
+				/* got same id */
+				if (fd_os_cmp(locref->data.application.application_name, locref->datastr_len, 
+						new->data.application.application_name, new->datastr_len)) {
+					TRACE_DEBUG(FULL, "Conflicting application name");
+					break;
+				}
+				ret = 0;
+				break;
+
+			case DICT_TYPE:
+				TRACE_DEBUG(FULL, "Type %s already in dictionary", new->data.type.type_name);
+				/* got same name */
+				if (locref->data.type.type_base != new->data.type.type_base) {
+					TRACE_DEBUG(FULL, "Conflicting base type");
+					break;
+				}
+				/* discard new definition only it a callback is provided and different from the previous one */
+				if ((new->data.type.type_interpret) && (locref->data.type.type_interpret != new->data.type.type_interpret)) {
+					TRACE_DEBUG(FULL, "Conflicting interpret cb");
+					break;
+				}
+				if ((new->data.type.type_encode) && (locref->data.type.type_encode != new->data.type.type_encode)) {
+					TRACE_DEBUG(FULL, "Conflicting encode cb");
+					break;
+				}
+				if ((new->data.type.type_dump) && (locref->data.type.type_dump != new->data.type.type_dump)) {
+					TRACE_DEBUG(FULL, "Conflicting dump cb");
+					break;
+				}
+				ret = 0;
+				break;
+
+			case DICT_ENUMVAL:
+				TRACE_DEBUG(FULL, "Enum %s already in dictionary", new->data.enumval.enum_name);
+				/* got either same name or same value. We check that both are true */
+				if (order_enum_by_name(locref, new)) {
+					TRACE_DEBUG(FULL, "Conflicting enum name");
+					break;
+				}
+				if (order_enum_by_val(locref, new)) {
+					TRACE_DEBUG(FULL, "Conflicting enum value");
+					break;
+				}
+				ret = 0;
+				break;
+
+			case DICT_AVP:
+				TRACE_DEBUG(FULL, "AVP %s already in dictionary", new->data.avp.avp_name);
+				/* got either same name or code */
+				if (order_avp_by_code(locref, new)) {
+					TRACE_DEBUG(FULL, "Conflicting AVP code");
+					break;
+				}
+				if (order_avp_by_name(locref, new)) {
+					TRACE_DEBUG(FULL, "Conflicting AVP name");
+					break;
+				}
+				if  (locref->data.avp.avp_vendor != new->data.avp.avp_vendor) {
+					TRACE_DEBUG(FULL, "Conflicting AVP vendor");
+					break;
+				}
+				if  (locref->data.avp.avp_flag_mask != new->data.avp.avp_flag_mask) {
+					TRACE_DEBUG(FULL, "Conflicting AVP flags mask");
+					break;
+				}
+				if  ((locref->data.avp.avp_flag_val & locref->data.avp.avp_flag_mask) != (new->data.avp.avp_flag_val & new->data.avp.avp_flag_mask)) {
+					TRACE_DEBUG(FULL, "Conflicting AVP flags value");
+					break;
+				}
+				if  (locref->data.avp.avp_basetype != new->data.avp.avp_basetype) {
+					TRACE_DEBUG(FULL, "Conflicting AVP base type");
+					break;
+				}
+				ret = 0;
+				break;
+
+			case DICT_COMMAND:
+				TRACE_DEBUG(FULL, "Command %s already in dictionary", new->data.cmd.cmd_name);
+				/* We got either same name, or same code + R flag */
+				if (order_cmd_by_name(locref, new)) {
+					TRACE_DEBUG(FULL, "Conflicting command name");
+					break;
+				}
+				if (locref->data.cmd.cmd_code != new->data.cmd.cmd_code) {
+					TRACE_DEBUG(FULL, "Conflicting command code");
+					break;
+				}
+				if (locref->data.cmd.cmd_flag_mask != new->data.cmd.cmd_flag_mask) {
+					TRACE_DEBUG(FULL, "Conflicting command flags mask %hhx:%hhx", locref->data.cmd.cmd_flag_mask, new->data.cmd.cmd_flag_mask);
+					break;
+				}
+				if ((locref->data.cmd.cmd_flag_val & locref->data.cmd.cmd_flag_mask) != (new->data.cmd.cmd_flag_val & new->data.cmd.cmd_flag_mask)) {
+					TRACE_DEBUG(FULL, "Conflicting command flags value");
+					break;
+				}
+				ret = 0;
+				break;
+
+			case DICT_RULE:
+				/* Both rules point to the same AVPs (code & vendor) */
+				if (locref->data.rule.rule_position != new->data.rule.rule_position) {
+					TRACE_DEBUG(FULL, "Conflicting rule position");
+					break;
+				}
+				if ( ((locref->data.rule.rule_position == RULE_FIXED_HEAD) ||
+					(locref->data.rule.rule_position == RULE_FIXED_TAIL))
+				    && (locref->data.rule.rule_order != new->data.rule.rule_order)) {
+					TRACE_DEBUG(FULL, "Conflicting rule order");
+					break;
+				}
+				if (locref->data.rule.rule_min != new->data.rule.rule_min) {
+					int r1 = locref->data.rule.rule_min;
+					int r2 = new->data.rule.rule_min;
+					int p  = locref->data.rule.rule_position;
+					if (  ((r1 != -1) && (r2 != -1)) /* none of the definitions contains the "default" value */
+					   || ((p == RULE_OPTIONAL) && (r1 != 0) && (r2 != 0)) /* the other value is not 0 for an optional rule */
+					   || ((r1 != 1) && (r2 != 1)) /* the other value is not 1 for another rule */
+					) {
+						TRACE_DEBUG(FULL, "Conflicting rule min");
+						break;
+					}
+				}
+				if (locref->data.rule.rule_max != new->data.rule.rule_max) {
+					TRACE_DEBUG(FULL, "Conflicting rule max");
+					break;
+				}
+				ret = 0;
+				break;
+		}
+		if (!ret) {
+			TRACE_DEBUG(FULL, "An existing object with the same data was found, ignoring the error...");
+		}
+		if (ref)
+			*ref = locref;
+	}
+all_errors:
+	if (ret != 0) {
+		char * buf = NULL;
+		size_t len = 0, offset=0;
+		
+		if (type == DICT_ENUMVAL) {
+			CHECK_MALLOC( dump_enumval_data ( &buf, &len, &offset, data, parent->data.type.type_base ));
+		} else {
+			CHECK_MALLOC( dict_obj_info[CHECK_TYPE(type) ? type : 0].dump_data(&buf, &len, &offset, data) );
+		}
+	
+		TRACE_DEBUG(INFO, "An error occurred while adding the following data in the dictionary: %s", buf);
+		
+		if (ret == EEXIST) {
+			offset=0;
+			CHECK_MALLOC( dump_object(&buf, &len, &offset, locref, 0, 0, 0) );
+			TRACE_DEBUG(INFO, "Conflicting entry in the dictionary: %s", buf);
+		}
+		free(buf);
+	}
+error_free:
+	free(new);
+	return ret;
+}
+
+
+int fd_dict_delete(struct dict_object * obj)
+{
+	int i;
+	struct dictionary * dict;
+	int ret=0;
+	
+	/* check params */
+	CHECK_PARAMS( verify_object(obj) && obj->dico);
+	dict = obj->dico;
+
+	/* Lock the dictionary for change */
+	CHECK_POSIX(  pthread_rwlock_wrlock(&dict->dict_lock)  );
+	
+	/* check the object is not sentinel for another list */
+	for (i=0; i<NB_LISTS_PER_OBJ; i++) {
+		if (!_OBINFO(obj).haslist[i] && !(FD_IS_LIST_EMPTY(&obj->list[i]))) {
+			/* There are children, this is not good */
+			ret = EINVAL;
+			TRACE_DEBUG (FULL, "Cannot delete object, list %d not empty:", i);
+			#if 0
+			dump_list(&obj->list[i], 0,0,0);
+			#endif
+			break;
+		}
+	}
+	
+	/* ok, now destroy the object */
+	if (!ret)
+		destroy_object(obj);
+	
+	/* Unlock */
+	CHECK_POSIX(  pthread_rwlock_unlock(&dict->dict_lock)  );
+	
+	return ret;
+}
+
+
+int fd_dict_search ( struct dictionary * dict, enum dict_object_type type, int criteria, const void * what, struct dict_object **result, int retval )
+{
+	int ret = 0;
+	
+	TRACE_ENTRY("%p %d(%s) %d %p %p %d", dict, type, dict_obj_info[CHECK_TYPE(type) ? type : 0].name, criteria, what, result, retval);
+	
+	/* Check param */
+	CHECK_PARAMS( dict && (dict->dict_eyec == DICT_EYECATCHER) && CHECK_TYPE(type) );
+	
+	/* Lock the dictionary for reading */
+	CHECK_POSIX(  pthread_rwlock_rdlock(&dict->dict_lock)  );
+	
+	/* Now call the type-specific search function */
+	ret = dict_obj_info[type].search_fct (dict, criteria, what, result);
+	
+	/* Unlock */
+	CHECK_POSIX(  pthread_rwlock_unlock(&dict->dict_lock)  );
+	
+	/* Update the return value as needed */
+	if ((result != NULL) && (*result == NULL))
+		ret = retval;
+	
+	return ret;
+}
+
+/* Function to retrieve list of objects in the dictionary. Use with care (read only).
+
+All returned list must be accessed like this:
+
+  for (li = sentinel->next; li != sentinel; li=li->next) {
+	struct dict_object * obj = li->o;
+	...
+  }
+
+The following criteria are allowed, with corresponding parent. 
+The parent is either struct dictionary * or struct dict_object *
+		
+VENDOR_BY_ID : (parent = dictionary) returns list of vendors ordered by ID
+APPLICATION_BY_ID : (parent = dictionary) returns list of applications ordered by ID
+  ** for these two lists, the Vendor with id 0 and applciation with id 0 are excluded. 
+     You must resolve them separatly with dict_search.
+		
+TYPE_BY_NAME : (parent = dictionary) returns list of types ordered by name (osstring order)
+ENUMVAL_BY_NAME : (parent = type object) return list of constants for this type ordered by name (osstring order)
+ENUMVAL_BY_VALUE : (parent = type object) return list of constants for this type ordered by values
+AVP_BY_NAME : (parent = vendor object) return list of AVP for this vendor ordered by name (osstring order)
+AVP_BY_CODE : (parent = vendor object) return list of AVP for this vendor ordered by code
+CMD_BY_NAME : (parent = dictionary) returns list of commands ordered by name (osstring order)
+CMD_BY_CODE_R : (parent = dictionary) returns list of commands ordered by code
+RULE_BY_AVP_AND_PARENT: (parent = command or grouped AVP object) return list of rules for this object ordered by AVP vendor/code
+
+All other criteria are rejected.
+ */
+int fd_dict_getlistof(int criteria, void * parent, struct fd_list ** sentinel)
+{
+	struct dictionary * dict = parent;
+	struct dict_object * obj_parent = parent;
+	
+	TRACE_ENTRY("%i %p %p", criteria, parent, sentinel);
+	
+	CHECK_PARAMS(sentinel && parent);
+	
+	switch(criteria) {
+		case VENDOR_BY_ID: /* parent must be the dictionary */
+			CHECK_PARAMS(dict->dict_eyec == DICT_EYECATCHER);
+			*sentinel = &dict->dict_vendors.list[0];
+			break;
+			
+		case APPLICATION_BY_ID: /* parent must be the dictionary */
+			CHECK_PARAMS(dict->dict_eyec == DICT_EYECATCHER);
+			*sentinel = &dict->dict_applications.list[0];
+			break;
+			
+		case TYPE_BY_NAME: /* parent must be the dictionary */
+			CHECK_PARAMS(dict->dict_eyec == DICT_EYECATCHER);
+			*sentinel = &dict->dict_types;
+			break;
+			
+		case ENUMVAL_BY_NAME: /* parent must be a type object */
+			CHECK_PARAMS(verify_object(obj_parent) && (obj_parent->type == DICT_TYPE));
+			*sentinel = &obj_parent->list[1];
+			break;
+			
+		case ENUMVAL_BY_VALUE: /* parent must be a type object */
+			CHECK_PARAMS(verify_object(obj_parent) && (obj_parent->type == DICT_TYPE));
+			*sentinel = &obj_parent->list[2];
+			break;
+			
+		case AVP_BY_NAME: /* parent must be a VENDOR object */
+			CHECK_PARAMS(verify_object(obj_parent) && (obj_parent->type == DICT_VENDOR));
+			*sentinel = &obj_parent->list[2];
+			break;
+			
+		case AVP_BY_CODE: /* parent must be a VENDOR object */
+			CHECK_PARAMS(verify_object(obj_parent) && (obj_parent->type == DICT_VENDOR));
+			*sentinel = &obj_parent->list[1];
+			break;
+			
+		case CMD_BY_NAME: /* parent must be the dictionary */
+			CHECK_PARAMS(dict->dict_eyec == DICT_EYECATCHER);
+			*sentinel = &dict->dict_cmd_name;
+			break;
+			
+		case CMD_BY_CODE_R: /* parent must be the dictionary */
+			CHECK_PARAMS(dict->dict_eyec == DICT_EYECATCHER);
+			*sentinel = &dict->dict_cmd_code;
+			break;
+			
+		case RULE_BY_AVP_AND_PARENT: /* parent must be command or grouped AVP */
+			CHECK_PARAMS(verify_object(obj_parent));
+			CHECK_PARAMS(	(obj_parent->type == DICT_COMMAND) ||
+					((obj_parent->type == DICT_AVP) 
+					  && (obj_parent->data.avp.avp_basetype == AVP_TYPE_GROUPED)) );
+			*sentinel = &obj_parent->list[2];
+			break;
+			
+		default:
+			CHECK_PARAMS(0);
+	}
+	
+	return 0;
+}
+
+/*******************************************************************************************************/
+/*******************************************************************************************************/
+/*                                                                                                     */
+/*                                  The init/fini functions                                            */
+/*                                                                                                     */
+/*******************************************************************************************************/
+/*******************************************************************************************************/
+
+/* Initialize the dictionary */
+int fd_dict_init ( struct dictionary ** dict)
+{
+	struct dictionary * new = NULL;
+	
+	TRACE_ENTRY("%p", dict);
+	
+	/* Sanity checks */
+	ASSERT( (sizeof(type_base_name) / sizeof(type_base_name[0])) == (AVP_TYPE_MAX + 1) );
+	ASSERT( (sizeof(dict_obj_info)  / sizeof(dict_obj_info[0]))  == (DICT_TYPE_MAX + 1) );
+	CHECK_PARAMS(dict);
+	
+	/* Allocate the memory for the dictionary */
+	CHECK_MALLOC( new = malloc(sizeof(struct dictionary)) );
+	memset(new, 0, sizeof(struct dictionary));
+	
+	new->dict_eyec = DICT_EYECATCHER;
+	
+	/* Initialize the lock for the dictionary */
+	CHECK_POSIX(  pthread_rwlock_init(&new->dict_lock, NULL)  );
+	
+	/* Initialize the sentinel for vendors and AVP lists */
+	init_object( &new->dict_vendors, DICT_VENDOR );
+	#define NO_VENDOR_NAME	"(no vendor)"
+	new->dict_vendors.data.vendor.vendor_name = NO_VENDOR_NAME;
+	new->dict_vendors.datastr_len = CONSTSTRLEN(NO_VENDOR_NAME);
+	/* new->dict_vendors.list[0].o = NULL; *//* overwrite since element is also sentinel for this list. */
+	new->dict_vendors.dico = new;
+	
+	/* Initialize the sentinel for applications */
+	init_object( &new->dict_applications, DICT_APPLICATION );
+	#define APPLICATION_0_NAME	"Diameter Common Messages"
+	new->dict_applications.data.application.application_name = APPLICATION_0_NAME;
+	new->dict_applications.datastr_len = CONSTSTRLEN(APPLICATION_0_NAME);
+	/* new->dict_applications.list[0].o = NULL; *//* overwrite since since element is also sentinel for this list. */
+	new->dict_applications.dico = new;
+			
+	/* Initialize the sentinel for types */
+	fd_list_init ( &new->dict_types, NULL );
+	
+	/* Initialize the sentinels for commands */
+	fd_list_init ( &new->dict_cmd_name, NULL );
+	fd_list_init ( &new->dict_cmd_code, NULL );
+	
+	/* Initialize the error command object */
+	init_object( &new->dict_cmd_error, DICT_COMMAND );
+	#define GENERIC_ERROR_NAME	"(generic error format)"
+	new->dict_cmd_error.data.cmd.cmd_name = GENERIC_ERROR_NAME;
+	new->dict_cmd_error.datastr_len = CONSTSTRLEN(GENERIC_ERROR_NAME);
+	new->dict_cmd_error.data.cmd.cmd_flag_mask=CMD_FLAG_ERROR | CMD_FLAG_REQUEST | CMD_FLAG_RETRANSMIT;
+	new->dict_cmd_error.data.cmd.cmd_flag_val =CMD_FLAG_ERROR;
+	new->dict_cmd_error.dico = new;
+	
+	*dict = new;
+	
+	/* Done */
+	return 0;
+}
+
+/* Destroy a dictionary */
+int fd_dict_fini ( struct dictionary ** dict)
+{
+	int i;
+	
+	TRACE_ENTRY("");
+	CHECK_PARAMS( dict && *dict && ((*dict)->dict_eyec == DICT_EYECATCHER) );
+	
+	/* Acquire the write lock to make sure no other operation is ongoing */
+	CHECK_POSIX(  pthread_rwlock_wrlock(&(*dict)->dict_lock)  );
+	
+	/* Empty all the lists, free the elements */
+	destroy_list ( &(*dict)->dict_cmd_error.list[2] );
+	destroy_list ( &(*dict)->dict_cmd_code );
+	destroy_list ( &(*dict)->dict_cmd_name );
+	destroy_list ( &(*dict)->dict_types );
+	for (i=0; i< NB_LISTS_PER_OBJ; i++) {
+		destroy_list ( &(*dict)->dict_applications.list[i] );
+		destroy_list ( &(*dict)->dict_vendors.list[i] );
+	}
+	
+	/* Dictionary is empty, now destroy the lock */
+	CHECK_POSIX(  pthread_rwlock_unlock(&(*dict)->dict_lock)  );
+	CHECK_POSIX(  pthread_rwlock_destroy(&(*dict)->dict_lock)  );
+	
+	free(*dict);
+	*dict = NULL;
+	
+	return 0;
+}
+
+/*******************************************************************************************************/
+/*******************************************************************************************************/
+/*                                                                                                     */
+/*                                  Other functions                                                    */
+/*                                                                                                     */
+/*******************************************************************************************************/
+/*******************************************************************************************************/
+
+/* Iterate a callback on the rules for an object */
+int fd_dict_iterate_rules ( struct dict_object *parent, void * data, int (*cb)(void *, struct dict_rule_data *) )
+{
+	int ret = 0;
+	struct fd_list * li;
+	
+	TRACE_ENTRY("%p %p %p", parent, data, cb);
+	
+	/* Check parameters */
+	CHECK_PARAMS(  verify_object(parent)  );
+	CHECK_PARAMS(  (parent->type == DICT_COMMAND) 
+			|| ((parent->type == DICT_AVP) && (parent->data.avp.avp_basetype == AVP_TYPE_GROUPED)) );
+	TRACE_DEBUG (FULL, "Iterating on rules of %s: '%s'.", 
+			_OBINFO(parent).name, 
+			parent->type == DICT_COMMAND ? 
+				  parent->data.cmd.cmd_name
+				: parent->data.avp.avp_name);
+	
+	/* Acquire the read lock  */
+	CHECK_POSIX(  pthread_rwlock_rdlock(&parent->dico->dict_lock)  );
+	
+	/* go through the list and call the cb on each rule data */
+	for (li = &(parent->list[2]); li->next != &(parent->list[2]); li = li->next) {
+		ret = (*cb)(data, &(_O(li->next->o)->data.rule));
+		if (ret != 0)
+			break;
+	}
+		
+	/* Release the lock */
+	CHECK_POSIX(  pthread_rwlock_unlock(&parent->dico->dict_lock)  );
+	
+	return ret;
+}
+
+/* Create the list of vendors. Returns a 0-terminated array, that must be freed after use. Returns NULL on error. */
+uint32_t * fd_dict_get_vendorid_list(struct dictionary * dict)
+{
+	uint32_t * ret = NULL;
+	int i = 0;
+	struct fd_list * li;
+	
+	TRACE_ENTRY();
+	
+	/* Acquire the read lock */
+	CHECK_POSIX_DO(  pthread_rwlock_rdlock(&dict->dict_lock), return NULL  );
+	
+	/* Allocate an array to contain all the elements */
+	CHECK_MALLOC_DO( ret = calloc( dict->dict_count[DICT_VENDOR] + 1, sizeof(uint32_t) ), goto out );
+	
+	/* Copy the vendors IDs */
+	for (li = dict->dict_vendors.list[0].next; li != &(dict->dict_vendors.list[0]); li = li->next) {
+		ret[i] = _O(li->o)->data.vendor.vendor_id;
+		i++;
+		ASSERT( i <= dict->dict_count[DICT_VENDOR] );
+	}
+out:	
+	/* Release the lock */
+	CHECK_POSIX_DO(  pthread_rwlock_unlock(&dict->dict_lock), return NULL  );
+	
+	return ret;
+}
+
+/* Return the location of the cb list for an object, after checking its type */
+int fd_dict_disp_cb(enum dict_object_type type, struct dict_object *obj, struct fd_list ** cb_list)
+{
+	TRACE_ENTRY("%d %p %p", type, obj, cb_list);
+	CHECK_PARAMS( verify_object(obj) );
+	CHECK_PARAMS( _OBINFO(obj).type == type );
+	CHECK_PARAMS( cb_list );
+	*cb_list = &obj->disp_cbs;
+	return 0;
+}
+
+int fd_dict_get_error_cmd(struct dictionary * dict, struct dict_object **obj)
+{
+	TRACE_ENTRY("%p %p", dict, obj);
+	CHECK_PARAMS( dict && (dict->dict_eyec == DICT_EYECATCHER) && obj );
+	*obj = &dict->dict_cmd_error;
+	return 0;
+}
diff --git a/libfdproto/dictionary_functions.c b/libfdproto/dictionary_functions.c
new file mode 100644
index 0000000..315b417
--- /dev/null
+++ b/libfdproto/dictionary_functions.c
@@ -0,0 +1,387 @@
+/*********************************************************************************************************
+* Software License Agreement (BSD License)                                                               *
+* Author: Sebastien Decugis <sdecugis@freediameter.net>							 *
+*													 *
+* Copyright (c) 2015, WIDE Project and NICT								 *
+* All rights reserved.											 *
+* 													 *
+* Redistribution and use of this software in source and binary forms, with or without modification, are  *
+* permitted provided that the following conditions are met:						 *
+* 													 *
+* * Redistributions of source code must retain the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer.										 *
+*    													 *
+* * Redistributions in binary form must reproduce the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer in the documentation and/or other						 *
+*   materials provided with the distribution.								 *
+* 													 *
+* * Neither the name of the WIDE Project or NICT nor the 						 *
+*   names of its contributors may be used to endorse or 						 *
+*   promote products derived from this software without 						 *
+*   specific prior written permission of WIDE Project and 						 *
+*   NICT.												 *
+* 													 *
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED *
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
+* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR *
+* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 	 *
+* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 	 *
+* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR *
+* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF   *
+* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.								 *
+*********************************************************************************************************/
+
+#include "fdproto-internal.h"
+#include <time.h>
+
+/* This file contains helpers functions to be reused as callbacks in the struct dict_type_data structure.
+There are three callbacks there:
+
+ - type_encode    :
+ - type_interpret :
+ 	  Those two callbacks allow to manipulate more natural structures of data in the code, and to 
+	map transparently these natural structures with the AVP-encoded format by calling the functions
+	msg_avp_value_encode or msg_avp_value_interpret.
+ - type_dump : 
+ 	  This callback if provided gives a more human-readable debug information.
+
+ */
+
+/****************************/
+/*    Address  AVP  type    */
+/****************************/
+
+/* The interpret and encode functions work with a "struct sockaddr_storage" pointer for mapping 
+the contents of the AVP */
+
+int fd_dictfct_Address_encode(void * data, union avp_value * avp_value)
+{
+	sSS * ss = (sSS *) data;
+	uint16_t AddressType = 0;
+	size_t	size = 0;
+	unsigned char * buf = NULL;
+	
+	TRACE_ENTRY("%p %p", data, avp_value);
+	CHECK_PARAMS( data && avp_value  );
+	
+	switch (ss->ss_family) {
+		case AF_INET:
+			{
+				/* We are encoding an IP address */
+				sSA4 * sin = (sSA4 *)ss;
+				
+				AddressType = 1;/* see http://www.iana.org/assignments/address-family-numbers/ */
+				size = 6;	/* 2 for AddressType + 4 for data */
+				
+				CHECK_MALLOC(  buf = malloc(size)  );
+				
+				/* may not work because of alignment: *(uint32_t *)(buf+2) = htonl(sin->sin_addr.s_addr); */
+				memcpy(buf + 2, &sin->sin_addr.s_addr, 4);
+			}
+			break;
+				
+		case AF_INET6:
+			{
+				/* We are encoding an IPv6 address */
+				sSA6 * sin6 = (sSA6 *)ss;
+				
+				AddressType = 2;/* see http://www.iana.org/assignments/address-family-numbers/ */
+				size = 18;	/* 2 for AddressType + 16 for data */
+				
+				CHECK_MALLOC(  buf = malloc(size)  );
+				
+				/* The order is already good here */
+				memcpy(buf + 2, &sin6->sin6_addr.s6_addr, 16);
+				
+			}
+			break;
+				
+		default:
+			CHECK_PARAMS( AddressType = 0 );
+	}
+	
+	*(uint16_t *)buf = htons(AddressType);
+
+	avp_value->os.len = size;
+	avp_value->os.data = buf;
+	
+	return 0;
+}
+
+int fd_dictfct_Address_interpret(union avp_value * avp_value, void * interpreted)
+{
+	uint16_t AddressType = 0;
+	unsigned char * buf;
+	
+	TRACE_ENTRY("%p %p", avp_value, interpreted);
+	
+	CHECK_PARAMS( avp_value && interpreted && (avp_value->os.len >= 2)  );
+	
+	AddressType = ntohs(*(uint16_t *)avp_value->os.data);
+	buf = &avp_value->os.data[2];
+	
+	switch (AddressType) {
+		case 1 /* IP */:
+			{
+				sSA4 * sin = (sSA4 *)interpreted;
+				
+				CHECK_PARAMS(  avp_value->os.len == 6  );
+				
+				sin->sin_family = AF_INET;
+				/* sin->sin_addr.s_addr = ntohl( * (uint32_t *) buf); -- may not work because of bad alignment */
+				memcpy(&sin->sin_addr.s_addr, buf, 4);
+			}
+			break;
+				
+		case 2 /* IP6 */:
+			{
+				sSA6 * sin6 = (sSA6 *)interpreted;
+				
+				CHECK_PARAMS(  avp_value->os.len == 18  );
+				
+				sin6->sin6_family = AF_INET6;
+				memcpy(&sin6->sin6_addr.s6_addr, buf, 16);
+				
+			}
+			break;
+				
+		default:
+			CHECK_PARAMS( AddressType = 0 );
+	}
+	
+	return 0;
+}
+
+/* Dump the content of an Address AVP */
+DECLARE_FD_DUMP_PROTOTYPE(fd_dictfct_Address_dump, union avp_value * avp_value)
+{
+	union {
+		sSA	sa;
+		sSS	ss;
+		sSA4	sin;
+		sSA6	sin6;
+	} s;
+	uint16_t fam;
+	
+	FD_DUMP_HANDLE_OFFSET();
+	
+	memset(&s, 0, sizeof(s));
+	
+	/* The first two octets represent the address family, http://www.iana.org/assignments/address-family-numbers/ */
+	if (avp_value->os.len < 2) {
+		CHECK_MALLOC_DO( fd_dump_extend(FD_DUMP_STD_PARAMS, "[invalid length: %zd]", avp_value->os.len), return NULL);
+		return *buf;
+	}
+	
+	/* Following octets are the address in network byte order already */
+	fam = avp_value->os.data[0] << 8 | avp_value->os.data[1];
+	switch (fam) {
+		case 1:
+			/* IP */
+			s.sa.sa_family = AF_INET;
+			if ((avp_value->os.len != 6) && (avp_value->os.len != 8)) {
+				CHECK_MALLOC_DO( fd_dump_extend(FD_DUMP_STD_PARAMS, "[invalid IP length: %zd]", avp_value->os.len), return NULL);
+				return *buf;
+			}
+			memcpy(&s.sin.sin_addr.s_addr, avp_value->os.data + 2, 4);
+			if (avp_value->os.len == 8)
+				memcpy(&s.sin.sin_port, avp_value->os.data + 6, 2);
+			break;
+		case 2:
+			/* IP6 */
+			s.sa.sa_family = AF_INET6;
+			if ((avp_value->os.len != 18) && (avp_value->os.len != 20)) {
+				CHECK_MALLOC_DO( fd_dump_extend(FD_DUMP_STD_PARAMS, "[invalid IP6 length: %zd]", avp_value->os.len), return NULL);
+				return *buf;
+			}
+			memcpy(&s.sin6.sin6_addr.s6_addr, avp_value->os.data + 2, 16);
+			if (avp_value->os.len == 20)
+				memcpy(&s.sin6.sin6_port, avp_value->os.data + 18, 2);
+			break;
+		case 8:
+			/* E.164 */
+			CHECK_MALLOC_DO( fd_dump_extend(FD_DUMP_STD_PARAMS, "%.*s", (int)(avp_value->os.len-2), avp_value->os.data+2), return NULL);
+			return *buf;
+		default:
+			CHECK_MALLOC_DO( fd_dump_extend(FD_DUMP_STD_PARAMS, "[unsupported family: 0x%hx]", fam), return NULL);
+			return *buf;
+	}
+	
+	return fd_sa_dump(FD_DUMP_STD_PARAMS, &s.sa, NI_NUMERICHOST);
+}
+
+
+
+/*******************************/
+/*    UTF8String  AVP  type    */
+/*******************************/
+
+/* Dump the AVP in a natural human-readable format. This dumps the complete length of the AVP, it is up to the caller to truncate if needed */
+DECLARE_FD_DUMP_PROTOTYPE(fd_dictfct_UTF8String_dump, union avp_value * avp_value)
+{
+	size_t l;
+	FD_DUMP_HANDLE_OFFSET();
+	
+	l = avp_value->os.len;
+	/* Just in case the string ends in invalid UTF-8 chars, we shorten it */
+	while ((l > 0) && (avp_value->os.data[l - 1] & 0x80)) {
+		/* this byte is start or cont. of multibyte sequence, as we do not know the next byte we need to delete it. */
+		l--;
+		if (avp_value->os.data[l] & 0x40)
+			break; /* This was a start byte, we can stop the loop */
+	}
+	
+	CHECK_MALLOC_DO( fd_dump_extend(FD_DUMP_STD_PARAMS, "\"%.*s\"", (int)l, (char *)avp_value->os.data), return NULL);
+	
+	return *buf;
+}
+
+
+/*******************************/
+/*    Time  AVP  type    */
+/*******************************/
+
+/* The interpret and encode functions work with a "time_t" pointer for mapping 
+the contents of the AVP */
+
+/* Unix Epoch starts 1970-01-01, NTP 0 is at 1900-01-01 */
+#define DIFF_EPOCH_TO_NTP ((365*(1970-1900) + 17ul) * 24 * 60 * 60)
+
+static int diameter_string_to_time_t(const char *str, size_t len, time_t *result) {
+    time_t time_stamp;
+    CHECK_PARAMS(len == 4);
+   
+    time_stamp = (((unsigned long)(str[0]&0xff))<<24) + ((str[1]&0xff)<<16) + ((str[2]&0xff)<<8) + ((str[3]&0xff));
+    time_stamp -= DIFF_EPOCH_TO_NTP;
+#ifdef FIX__NEEDED_FOR_YEAR_2036_AND_LATER
+/* NTP overflows in 2036; after that, values start at zero again */
+#define NTP_OVERFLOW_CORRECTION (0x100000000ull)
+    /* XXX: debug and find correct conversion */
+    if (str[0] & 0x80 == 0x00) {
+        time_stamp += NTP_OVERFLOW_CORRECTION;
+    }
+#endif
+    *result = time_stamp;
+    return 0;
+}
+
+static int time_t_to_diameter_string(time_t time_stamp, char **result) {
+    uint64_t out = time_stamp;
+    char *conv;
+    /* XXX: 2036 fix */
+    out += DIFF_EPOCH_TO_NTP;
+    CHECK_PARAMS( (out >> 32) == 0);
+
+    CHECK_MALLOC(conv=(char *)malloc(5));
+    
+    conv[0] = (out>>24) & 0xff;
+    conv[1] = (out>>16) & 0xff;
+    conv[2] = (out>> 8) & 0xff;
+    conv[3] =  out      & 0xff;
+    conv[4] = '\0';
+    *result = conv;
+    return 0;
+}
+
+int fd_dictfct_Time_encode(void * data, union avp_value * avp_value)
+{
+	char * buf;
+	size_t len;
+	
+	TRACE_ENTRY("%p %p", data, avp_value);
+	CHECK_PARAMS( data && avp_value  );
+	
+	CHECK_FCT( time_t_to_diameter_string( *((time_t *)data), &buf) );
+	/* FIXME: return len from the function above? */ len = 4;
+	
+	avp_value->os.len = len;
+	avp_value->os.data = (uint8_t *)buf;
+	return 0;
+}
+
+int fd_dictfct_Time_interpret(union avp_value * avp_value, void * interpreted)
+{
+	TRACE_ENTRY("%p %p", avp_value, interpreted);
+	
+	CHECK_PARAMS( avp_value && interpreted );
+	
+	return diameter_string_to_time_t((const char *)avp_value->os.data, avp_value->os.len, interpreted);
+}
+
+static void _format_offs (long offset, char *buf) {
+    int offs_hours, offs_minutes, sgn = 1;
+    if (offset < 0) {
+        offset = -offset;
+        sgn = 1;
+    }
+    offs_hours = (int)(offset/3600);
+    offs_minutes = (offset%3600)/60;
+
+    char* s = buf;
+
+    *(s++) = sgn == 1 ? '+' : '-';
+    *(s++) = (char)(offs_hours/10) + '0';
+    *(s++) = offs_hours%10 + '0';
+
+    if (offs_minutes == 0) {
+        *(s++) = '\0';
+    } else {
+        *(s++) = (char)(offs_minutes/10) + '0';
+        *(s++) = offs_minutes%10 + '0';
+        *(s++) = '\0';
+    }
+}
+
+DECLARE_FD_DUMP_PROTOTYPE(fd_dictfct_Time_dump, union avp_value * avp_value)
+{
+	time_t val;
+	struct tm conv;
+	char tz_buf[7];
+		
+	FD_DUMP_HANDLE_OFFSET();
+	
+	if (avp_value->os.len != 4) {
+		CHECK_MALLOC_DO( fd_dump_extend(FD_DUMP_STD_PARAMS, "[invalid length: %zd]", avp_value->os.len), return NULL);
+		return *buf;
+	}
+
+	if (diameter_string_to_time_t((char *)avp_value->os.data, avp_value->os.len, &val) != 0) {
+		CHECK_MALLOC_DO( fd_dump_extend(FD_DUMP_STD_PARAMS, "[time conversion error]"), return NULL);
+		return *buf;
+	}
+	
+	CHECK_MALLOC_DO( localtime_r(&val, &conv), return NULL);
+	_format_offs(conv.tm_gmtoff, tz_buf);
+	CHECK_MALLOC_DO( fd_dump_extend(FD_DUMP_STD_PARAMS, "%d%02d%02dT%02d%02d%02d%s", conv.tm_year+1900, conv.tm_mon+1, conv.tm_mday, conv.tm_hour, conv.tm_min, conv.tm_sec, tz_buf), return NULL);
+	return *buf;
+}
+
+/* Check that a given AVP value contains all the characters from data in the same order */
+static char error_message[80];
+int fd_dictfct_CharInOS_check(void * data, union avp_value * val, char ** error_msg)
+{
+	char * inChar = data;
+	char * inData = (char *)val->os.data;
+	int i = 0;
+	CHECK_PARAMS(data);
+	while (*inChar != '\0') {
+		while (i < val->os.len) {
+			if (*inChar == inData[i++]) {
+				inChar++;
+				break;
+			}
+		}
+		if (i >= val->os.len)
+			break;
+	}
+	if (*inChar == '\0')
+		return 0;
+	
+	if (error_msg) {
+		snprintf(error_message, sizeof(error_message), "Could not find '%c' in AVP", *inChar);
+		*error_msg = error_message;
+	}
+	return EBADMSG;
+}
diff --git a/libfdproto/dispatch.c b/libfdproto/dispatch.c
new file mode 100644
index 0000000..6111915
--- /dev/null
+++ b/libfdproto/dispatch.c
@@ -0,0 +1,228 @@
+/*********************************************************************************************************
+* Software License Agreement (BSD License)                                                               *
+* Author: Sebastien Decugis <sdecugis@freediameter.net>							 *
+*													 *
+* Copyright (c) 2013, WIDE Project and NICT								 *
+* All rights reserved.											 *
+* 													 *
+* Redistribution and use of this software in source and binary forms, with or without modification, are  *
+* permitted provided that the following conditions are met:						 *
+* 													 *
+* * Redistributions of source code must retain the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer.										 *
+*    													 *
+* * Redistributions in binary form must reproduce the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer in the documentation and/or other						 *
+*   materials provided with the distribution.								 *
+* 													 *
+* * Neither the name of the WIDE Project or NICT nor the 						 *
+*   names of its contributors may be used to endorse or 						 *
+*   promote products derived from this software without 						 *
+*   specific prior written permission of WIDE Project and 						 *
+*   NICT.												 *
+* 													 *
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED *
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
+* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR *
+* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 	 *
+* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 	 *
+* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR *
+* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF   *
+* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.								 *
+*********************************************************************************************************/
+
+#include "fdproto-internal.h"
+
+/* The dispatch module in the library is quite simple: callbacks are saved in a global list
+ * in no particular order. In addition, they are also linked from the dictionary objects they
+ * refer to. */
+
+/* Protection for the lists managed in this module. */
+pthread_rwlock_t fd_disp_lock = PTHREAD_RWLOCK_INITIALIZER;
+
+/* List of all registered handlers -- useful if we want to cleanup properly at some point... */
+static struct fd_list all_handlers = FD_LIST_INITIALIZER( all_handlers );
+
+/* List of handlers registered for DISP_HOW_ANY. Other handlers are stored in the dictionary */
+static struct fd_list any_handlers = FD_LIST_INITIALIZER( any_handlers );
+
+/* The structure to store a callback */
+struct disp_hdl {
+	int		 eyec;	/* Eye catcher, DISP_EYEC */
+	struct fd_list	 all;	/* link in the all_handlers list */
+	struct fd_list	 parent;/* link in dictionary cb_list or in any_handlers */
+	enum disp_how	 how;	/* Copy of registration parameter */
+	struct disp_when when;	/* Copy of registration parameter */
+	int		(*cb)( struct msg **, struct avp *, struct session *, void *, enum disp_action *);	/* The callback itself */
+	void            *opaque; /* opaque data passed back to the callback */
+};
+
+#define DISP_EYEC	0xD15241C1
+#define VALIDATE_HDL( _hdl ) \
+	( ( ( _hdl ) != NULL ) && ( ((struct disp_hdl *)( _hdl ))->eyec == DISP_EYEC ) )
+
+/**************************************************************************************/
+
+/* Call CBs from a given list (any_handlers if cb_list is NULL) -- must have locked fd_disp_lock before */
+int fd_disp_call_cb_int( struct fd_list * cb_list, struct msg ** msg, struct avp *avp, struct session *sess, enum disp_action *action, 
+			struct dict_object * obj_app, struct dict_object * obj_cmd, struct dict_object * obj_avp, struct dict_object * obj_enu,
+			char ** drop_reason, struct msg ** drop_msg)
+{
+	struct fd_list * senti, *li;
+	int r;
+	TRACE_ENTRY("%p %p %p %p %p %p %p %p %p", cb_list, msg, avp, sess, action, obj_app, obj_cmd, obj_avp, obj_enu);
+	CHECK_PARAMS(msg && action);
+	
+	senti = cb_list;
+	if (!senti)
+		senti = &any_handlers;
+	
+	for (li = senti->next; li != senti; li = li->next) {
+		struct disp_hdl * hdl = (struct disp_hdl *)(li->o);
+		
+		TRACE_DEBUG(ANNOYING, "when: %p %p %p %p", hdl->when.app, hdl->when.command, hdl->when.avp, hdl->when.value);
+		
+		/* Check this handler matches this message / avp */
+		if (hdl->when.app     && (hdl->when.app     != obj_app))
+			continue;
+		if (hdl->when.command && (hdl->when.command != obj_cmd))
+			continue;
+		if (hdl->when.avp     && (hdl->when.avp     != obj_avp))
+			continue;
+		if (hdl->when.value   && (hdl->when.value   != obj_enu))
+			continue;
+		
+		/* We have a match, the cb must be called. */
+		CHECK_FCT_DO( (r = (*hdl->cb)(msg, avp, sess, hdl->opaque, action)),
+			{
+				*drop_reason = "Internal error: a DISPATCH callback returned an error";
+				*drop_msg = *msg;
+				*msg = NULL;
+			}
+		 );
+		
+		if (*action != DISP_ACT_CONT)
+			break;
+		
+		if ( *msg  == NULL )
+			break;
+	}
+	
+	/* We're done on this list */
+	return 0;
+}
+
+/**************************************************************************************/
+
+/* Create a new handler and link it */
+int fd_disp_register ( int (*cb)( struct msg **, struct avp *, struct session *, void *, enum disp_action *), 
+			enum disp_how how, struct disp_when * when, void * opaque, struct disp_hdl ** handle )
+{
+	struct fd_list * cb_list = NULL;
+	struct disp_hdl * new;
+	struct dict_object * type_enum = NULL, * type_avp;
+	struct dictionary  * dict = NULL;
+	
+	TRACE_ENTRY("%p %d %p %p", cb, how, when, handle);
+	CHECK_PARAMS( cb && ( (how == DISP_HOW_ANY) || when ));
+	
+	switch (how) {
+		case DISP_HOW_ANY:
+			cb_list = &any_handlers;
+			break;
+		
+		case DISP_HOW_APPID:
+			CHECK_FCT( fd_dict_disp_cb(DICT_APPLICATION, when->app, &cb_list) );
+			break;
+		
+		case DISP_HOW_CC:
+			CHECK_FCT( fd_dict_disp_cb(DICT_COMMAND, when->command, &cb_list) );
+			break;
+		
+		case DISP_HOW_AVP_ENUMVAL:
+			CHECK_FCT( fd_dict_disp_cb(DICT_ENUMVAL, when->value, &cb_list) ); /* cb_list is then overwritten */
+			CHECK_FCT( fd_dict_getdict(when->value, &dict) );
+			CHECK_FCT( fd_dict_search(dict, DICT_TYPE, TYPE_OF_ENUMVAL, when->value, &type_enum, EINVAL) );
+		case DISP_HOW_AVP:
+			CHECK_FCT( fd_dict_disp_cb(DICT_AVP, when->avp, &cb_list) );
+			if (dict) {
+				CHECK_FCT( fd_dict_search(dict, DICT_TYPE, TYPE_OF_AVP, when->avp, &type_avp, EINVAL) );
+				if (type_enum) {
+					CHECK_PARAMS( type_enum == type_avp );
+				}
+			}
+			break;
+		
+		default:
+			CHECK_PARAMS(how = 0);
+	}
+	/* We might further check optional fields, but we trust the caller ^^ */
+	
+	/* Create the new handler */
+	CHECK_MALLOC( new = malloc( sizeof(struct disp_hdl) ) );
+	memset(new, 0, sizeof(struct disp_hdl));
+	new->eyec = DISP_EYEC;
+	fd_list_init(&new->all, new);
+	fd_list_init(&new->parent, new);
+	new->how = how;
+	switch (how) {
+		case DISP_HOW_ANY:
+			/* there is no "when" in that case */
+			break;
+		case DISP_HOW_AVP_ENUMVAL:
+			new->when.value   = when->value;
+		case DISP_HOW_AVP:
+			new->when.avp     = when->avp;
+		case DISP_HOW_CC:
+			new->when.command = when->command;
+		case DISP_HOW_APPID:
+			new->when.app     = when->app;
+	}
+	new->cb = cb;
+	new->opaque = opaque;
+	
+	/* Now, link this new element in the appropriate lists */
+	CHECK_POSIX( pthread_rwlock_wrlock(&fd_disp_lock) );
+	fd_list_insert_before(&all_handlers, &new->all);
+	fd_list_insert_before(cb_list, &new->parent);
+	CHECK_POSIX( pthread_rwlock_unlock(&fd_disp_lock) );
+	
+	/* We're done */
+	if (handle)
+		*handle = new;
+	
+	return 0;
+}
+
+/* Delete a handler */
+int fd_disp_unregister ( struct disp_hdl ** handle, void ** opaque )
+{
+	struct disp_hdl * del;
+	TRACE_ENTRY("%p", handle);
+	CHECK_PARAMS( handle && VALIDATE_HDL(*handle) );
+	del = *handle;
+	*handle = NULL;
+	
+	CHECK_POSIX( pthread_rwlock_wrlock(&fd_disp_lock) );
+	fd_list_unlink(&del->all);
+	fd_list_unlink(&del->parent);
+	CHECK_POSIX( pthread_rwlock_unlock(&fd_disp_lock) );
+	
+	if (opaque)
+		*opaque = del->opaque;
+	
+	free(del);
+	return 0;
+}
+
+/* Delete all handlers */
+void fd_disp_unregister_all ( void )
+{
+	TRACE_ENTRY("");
+	while (!FD_IS_LIST_EMPTY(&all_handlers)) {
+		CHECK_FCT_DO( fd_disp_unregister((void *)&(all_handlers.next->o), NULL), /* continue */ );
+	}
+	return;
+}
diff --git a/libfdproto/fdproto-internal.h b/libfdproto/fdproto-internal.h
new file mode 100644
index 0000000..a328c57
--- /dev/null
+++ b/libfdproto/fdproto-internal.h
@@ -0,0 +1,65 @@
+/*********************************************************************************************************
+* Software License Agreement (BSD License)                                                               *
+* Author: Sebastien Decugis <sdecugis@freediameter.net>							 *
+*													 *
+* Copyright (c) 2013, WIDE Project and NICT								 *
+* All rights reserved.											 *
+* 													 *
+* Redistribution and use of this software in source and binary forms, with or without modification, are  *
+* permitted provided that the following conditions are met:						 *
+* 													 *
+* * Redistributions of source code must retain the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer.										 *
+*    													 *
+* * Redistributions in binary form must reproduce the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer in the documentation and/or other						 *
+*   materials provided with the distribution.								 *
+* 													 *
+* * Neither the name of the WIDE Project or NICT nor the 						 *
+*   names of its contributors may be used to endorse or 						 *
+*   promote products derived from this software without 						 *
+*   specific prior written permission of WIDE Project and 						 *
+*   NICT.												 *
+* 													 *
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED *
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
+* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR *
+* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 	 *
+* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 	 *
+* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR *
+* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF   *
+* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.								 *
+*********************************************************************************************************/
+
+/* This file contains the definitions for internal use in the freeDiameter protocol library */
+
+#ifndef _LIBFDPROTO_INTERNAL_H
+#define _LIBFDPROTO_INTERNAL_H
+
+#include <freeDiameter/freeDiameter-host.h>
+#include <freeDiameter/libfdproto.h>
+
+/* Internal to the library */
+extern const char * type_base_name[];
+void fd_msg_eteid_init(void);
+int fd_sess_init(void);
+void fd_sess_fini(void);
+
+/* Iterator on the rules of a parent object */
+int fd_dict_iterate_rules ( struct dict_object *parent, void * data, int (*cb)(void *, struct dict_rule_data *) );
+
+/* Dispatch / messages / dictionary API */
+int fd_dict_disp_cb(enum dict_object_type type, struct dict_object *obj, struct fd_list ** cb_list);
+DECLARE_FD_DUMP_PROTOTYPE(fd_dict_dump_avp_value, union avp_value *avp_value, struct dict_object * model, int indent, int header);
+int fd_disp_call_cb_int( struct fd_list * cb_list, struct msg ** msg, struct avp *avp, struct session *sess, enum disp_action *action, 
+			struct dict_object * obj_app, struct dict_object * obj_cmd, struct dict_object * obj_avp, struct dict_object * obj_enu,
+			char ** drop_reason, struct msg ** drop_msg);
+extern pthread_rwlock_t fd_disp_lock;
+
+/* Messages / sessions API */
+int fd_sess_reclaim_msg ( struct session ** session );
+
+
+#endif /* _LIBFDPROTO_INTERNAL_H */
diff --git a/libfdproto/fifo.c b/libfdproto/fifo.c
new file mode 100644
index 0000000..cf5b7fc
--- /dev/null
+++ b/libfdproto/fifo.c
@@ -0,0 +1,700 @@
+/*********************************************************************************************************
+* Software License Agreement (BSD License)                                                               *
+* Author: Sebastien Decugis <sdecugis@freediameter.net>							 *
+*													 *
+* Copyright (c) 2013, WIDE Project and NICT								 *
+* All rights reserved.											 *
+* 													 *
+* Redistribution and use of this software in source and binary forms, with or without modification, are  *
+* permitted provided that the following conditions are met:						 *
+* 													 *
+* * Redistributions of source code must retain the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer.										 *
+*    													 *
+* * Redistributions in binary form must reproduce the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer in the documentation and/or other						 *
+*   materials provided with the distribution.								 *
+* 													 *
+* * Neither the name of the WIDE Project or NICT nor the 						 *
+*   names of its contributors may be used to endorse or 						 *
+*   promote products derived from this software without 						 *
+*   specific prior written permission of WIDE Project and 						 *
+*   NICT.												 *
+* 													 *
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED *
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
+* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR *
+* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 	 *
+* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 	 *
+* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR *
+* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF   *
+* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.								 *
+*********************************************************************************************************/
+
+/* FIFO queues module.
+ *
+ * The threads that call these functions must be in the cancellation state PTHREAD_CANCEL_ENABLE and type PTHREAD_CANCEL_DEFERRED.
+ * This is the default state and type on thread creation.
+ *
+ * In order to destroy properly a queue, the application must:
+ *  -> shutdown any process that can add into the queue first.
+ *  -> pthread_cancel any thread that could be waiting on the queue.
+ *  -> consume any element that is in the queue, using fd_qu_tryget_int.
+ *  -> then destroy the queue using fd_mq_del.
+ */
+
+#include "fdproto-internal.h"
+
+/* Definition of a FIFO queue object */
+struct fifo {
+	int		eyec;	/* An eye catcher, also used to check a queue is valid. FIFO_EYEC */
+	
+	pthread_mutex_t	mtx;	/* Mutex protecting this queue */
+	pthread_cond_t	cond_pull;	/* condition variable for pulling threads */
+	pthread_cond_t	cond_push;	/* condition variable for pushing threads */
+	
+	struct fd_list	list;	/* sentinel for the list of elements */
+	int		count;	/* number of objects in the list */
+	int		thrs;	/* number of threads waiting for a new element (when count is 0) */
+	
+	int 		max;	/* maximum number of items to accept if not 0 */
+	int		thrs_push; /* number of threads waitnig to push an item */
+	
+	uint16_t	high;	/* High level threshold (see libfreeDiameter.h for details) */
+	uint16_t	low;	/* Low level threshhold */
+	void 		*data;	/* Opaque pointer for threshold callbacks */
+	void		(*h_cb)(struct fifo *, void **); /* The callbacks */
+	void		(*l_cb)(struct fifo *, void **);
+	int 		highest;/* The highest count value for which h_cb has been called */
+	int		highest_ever; /* The max count value this queue has reached (for tweaking) */
+	
+	long long	total_items;   /* Cumulated number of items that went through this fifo (excluding current count), always increasing. */
+	struct timespec total_time;    /* Cumulated time all items spent in this queue, including blocking time (always growing, use deltas for monitoring) */
+	struct timespec blocking_time; /* Cumulated time threads trying to post new items were blocked (queue full). */
+	struct timespec last_time;     /* For the last element retrieved from the queue, how long it take between posting (including blocking) and poping */
+	
+};
+
+struct fifo_item {
+	struct fd_list   item;
+	struct timespec  posted_on;
+};
+
+/* The eye catcher value */
+#define FIFO_EYEC	0xe7ec1130
+
+/* Macro to check a pointer */
+#define CHECK_FIFO( _queue ) (( (_queue) != NULL) && ( (_queue)->eyec == FIFO_EYEC) )
+
+
+/* Create a new queue, with max number of items -- use 0 for no max */
+int fd_fifo_new ( struct fifo ** queue, int max )
+{
+	struct fifo * new;
+	
+	TRACE_ENTRY( "%p", queue );
+	
+	CHECK_PARAMS( queue );
+	
+	/* Create a new object */
+	CHECK_MALLOC( new = malloc (sizeof (struct fifo) )  );
+	
+	/* Initialize the content */
+	memset(new, 0, sizeof(struct fifo));
+	
+	new->eyec = FIFO_EYEC;
+	CHECK_POSIX( pthread_mutex_init(&new->mtx, NULL) );
+	CHECK_POSIX( pthread_cond_init(&new->cond_pull, NULL) );
+	CHECK_POSIX( pthread_cond_init(&new->cond_push, NULL) );
+	new->max = max;
+	
+	fd_list_init(&new->list, NULL);
+	
+	/* We're done */
+	*queue = new;
+	return 0;
+}
+
+/* Dump the content of a queue */
+DECLARE_FD_DUMP_PROTOTYPE(fd_fifo_dump, char * name, struct fifo * queue, fd_fifo_dump_item_cb dump_item)
+{
+	FD_DUMP_HANDLE_OFFSET();
+	
+	if (name) {
+		CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "'%s'(@%p): ", name, queue), return NULL);	
+	} else {
+		CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "{fifo}(@%p): ", queue), return NULL);
+	}
+	
+	if (!CHECK_FIFO( queue )) {
+		return fd_dump_extend(FD_DUMP_STD_PARAMS, "INVALID/NULL");
+	}
+	
+	CHECK_POSIX_DO(  pthread_mutex_lock( &queue->mtx ), /* continue */  );
+	CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "items:%d,%d,%d threads:%d,%d stats:%lld/%ld.%06ld,%ld.%06ld,%ld.%06ld thresholds:%d,%d,%d,%p,%p,%p", 
+						queue->count, queue->highest_ever, queue->max,
+						queue->thrs, queue->thrs_push,
+						queue->total_items,(long)queue->total_time.tv_sec,(long)(queue->total_time.tv_nsec/1000),(long)queue->blocking_time.tv_sec,(long)(queue->blocking_time.tv_nsec/1000),(long)queue->last_time.tv_sec,(long)(queue->last_time.tv_nsec/1000),
+						queue->high, queue->low, queue->highest, queue->h_cb, queue->l_cb, queue->data), 
+			 goto error);
+	
+	if (dump_item) {
+		struct fd_list * li;
+		int i = 0;
+		for (li = queue->list.next; li != &queue->list; li = li->next) {
+			struct fifo_item * fi = (struct fifo_item *)li;
+			CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "\n [#%i](@%p)@%ld.%06ld: ", 
+						i++, fi->item.o, (long)fi->posted_on.tv_sec,(long)(fi->posted_on.tv_nsec/1000)), 
+					 goto error);
+			CHECK_MALLOC_DO( (*dump_item)(FD_DUMP_STD_PARAMS, fi->item.o), goto error);
+		}
+	}
+	CHECK_POSIX_DO(  pthread_mutex_unlock( &queue->mtx ), /* continue */  );
+	
+	return *buf;
+error:
+	CHECK_POSIX_DO(  pthread_mutex_unlock( &queue->mtx ), /* continue */  );
+	return NULL;
+}
+
+/* Delete a queue. It must be empty. */ 
+int fd_fifo_del ( struct fifo  ** queue )
+{
+	struct fifo * q;
+	int loops = 0;
+	
+	TRACE_ENTRY( "%p", queue );
+
+	CHECK_PARAMS( queue && CHECK_FIFO( *queue ) );
+	
+	q = *queue;
+	
+	CHECK_POSIX(  pthread_mutex_lock( &q->mtx )  );
+	
+	if ((q->count != 0) || (q->data != NULL)) {
+		TRACE_DEBUG(INFO, "The queue cannot be destroyed (%d, %p)", q->count, q->data);
+		CHECK_POSIX_DO(  pthread_mutex_unlock( &q->mtx ), /* no fallback */  );
+		return EINVAL;
+	}
+	
+	/* Ok, now invalidate the queue */
+	q->eyec = 0xdead;
+	
+	/* Have all waiting threads return an error */
+	while (q->thrs) {
+		CHECK_POSIX(  pthread_mutex_unlock( &q->mtx ));
+		CHECK_POSIX(  pthread_cond_signal(&q->cond_pull)  );
+		usleep(1000);
+		
+		CHECK_POSIX(  pthread_mutex_lock( &q->mtx )  );
+		ASSERT( ++loops < 20 ); /* detect infinite loops */
+	}
+	
+	/* sanity check */
+	ASSERT(FD_IS_LIST_EMPTY(&q->list));
+	
+	/* And destroy it */
+	CHECK_POSIX(  pthread_mutex_unlock( &q->mtx )  );
+	
+	CHECK_POSIX_DO(  pthread_cond_destroy( &q->cond_pull ),  );
+	
+	CHECK_POSIX_DO(  pthread_cond_destroy( &q->cond_push ),  );
+	
+	CHECK_POSIX_DO(  pthread_mutex_destroy( &q->mtx ),  );
+	
+	free(q);
+	*queue = NULL;
+	
+	return 0;
+}
+
+/* Move the content of old into new, and update loc_update atomically. We leave the old queue empty but valid */
+int fd_fifo_move ( struct fifo * old, struct fifo * new, struct fifo ** loc_update )
+{
+	int loops = 0;
+	
+	TRACE_ENTRY("%p %p %p", old, new, loc_update);
+	CHECK_PARAMS( CHECK_FIFO( old ) && CHECK_FIFO( new ));
+	
+	CHECK_PARAMS( ! old->data );
+	if (new->high) {
+		TODO("Implement support for thresholds in fd_fifo_move...");
+	}
+	
+	/* Update loc_update */
+	if (loc_update)
+		*loc_update = new;
+	
+	/* Lock the queues */
+	CHECK_POSIX(  pthread_mutex_lock( &old->mtx )  );
+	
+	CHECK_PARAMS_DO( (! old->thrs_push), {
+			pthread_mutex_unlock( &old->mtx );
+			return EINVAL;
+		} );
+	
+	CHECK_POSIX(  pthread_mutex_lock( &new->mtx )  );
+	
+	/* Any waiting thread on the old queue returns an error */
+	old->eyec = 0xdead;
+	while (old->thrs) {
+		CHECK_POSIX(  pthread_mutex_unlock( &old->mtx ));
+		CHECK_POSIX(  pthread_cond_signal( &old->cond_pull )  );
+		usleep(1000);
+		
+		CHECK_POSIX(  pthread_mutex_lock( &old->mtx )  );
+		ASSERT( loops < 20 ); /* detect infinite loops */
+	}
+	
+	/* Move all data from old to new */
+	fd_list_move_end( &new->list, &old->list );
+	if (old->count && (!new->count)) {
+		CHECK_POSIX(  pthread_cond_signal(&new->cond_pull)  );
+	}
+	new->count += old->count;
+	
+	/* Reset old */
+	old->count = 0;
+	old->eyec = FIFO_EYEC;
+	
+	/* Merge the stats in the new queue */
+	new->total_items += old->total_items;
+	old->total_items = 0;
+	
+	new->total_time.tv_nsec += old->total_time.tv_nsec;
+	new->total_time.tv_sec += old->total_time.tv_sec + (new->total_time.tv_nsec / 1000000000);
+	new->total_time.tv_nsec %= 1000000000;
+	old->total_time.tv_nsec = 0;
+	old->total_time.tv_sec = 0;
+	
+	new->blocking_time.tv_nsec += old->blocking_time.tv_nsec;
+	new->blocking_time.tv_sec += old->blocking_time.tv_sec + (new->blocking_time.tv_nsec / 1000000000);
+	new->blocking_time.tv_nsec %= 1000000000;
+	old->blocking_time.tv_nsec = 0;
+	old->blocking_time.tv_sec = 0;
+	
+	/* Unlock, we're done */
+	CHECK_POSIX(  pthread_mutex_unlock( &new->mtx )  );
+	CHECK_POSIX(  pthread_mutex_unlock( &old->mtx )  );
+	
+	return 0;
+}
+
+/* Get the information on the queue */
+int fd_fifo_getstats( struct fifo * queue, int * current_count, int * limit_count, int * highest_count, long long * total_count, 
+				           struct timespec * total, struct timespec * blocking, struct timespec * last)
+{
+	TRACE_ENTRY( "%p %p %p %p %p %p %p %p", queue, current_count, limit_count, highest_count, total_count, total, blocking, last);
+	
+	/* Check the parameters */
+	CHECK_PARAMS( CHECK_FIFO( queue ) );
+	
+	/* lock the queue */
+	CHECK_POSIX(  pthread_mutex_lock( &queue->mtx )  );
+	
+	if (current_count)
+		*current_count = queue->count;
+	
+	if (limit_count)
+		*limit_count = queue->max;
+	
+	if (highest_count)
+		*highest_count = queue->highest_ever;
+	
+	if (total_count)
+		*total_count = queue->total_items;
+	
+	if (total)
+		memcpy(total, &queue->total_time, sizeof(struct timespec));
+	
+	if (blocking)
+		memcpy(blocking, &queue->blocking_time, sizeof(struct timespec));
+	
+	if (last)
+		memcpy(last, &queue->last_time, sizeof(struct timespec));
+	
+	/* Unlock */
+	CHECK_POSIX(  pthread_mutex_unlock( &queue->mtx )  );
+	
+	/* Done */
+	return 0;
+}
+
+
+/* alternate version with no error checking */
+int fd_fifo_length ( struct fifo * queue )
+{
+	if ( !CHECK_FIFO( queue ) )
+		return 0;
+	
+	return queue->count; /* Let's hope it's read atomically, since we are not locking... */
+}
+
+/* Set the thresholds of the queue */
+int fd_fifo_setthrhd ( struct fifo * queue, void * data, uint16_t high, void (*h_cb)(struct fifo *, void **), uint16_t low, void (*l_cb)(struct fifo *, void **) )
+{
+	TRACE_ENTRY( "%p %p %hu %p %hu %p", queue, data, high, h_cb, low, l_cb );
+	
+	/* Check the parameters */
+	CHECK_PARAMS( CHECK_FIFO( queue ) && (high > low) && (queue->data == NULL) );
+	
+	/* lock the queue */
+	CHECK_POSIX(  pthread_mutex_lock( &queue->mtx )  );
+	
+	/* Save the values */
+	queue->high = high;
+	queue->low  = low;
+	queue->data = data;
+	queue->h_cb = h_cb;
+	queue->l_cb = l_cb;
+	
+	/* Unlock */
+	CHECK_POSIX(  pthread_mutex_unlock( &queue->mtx )  );
+	
+	/* Done */
+	return 0;
+}
+
+
+/* This handler is called when a thread is blocked on a queue, and cancelled */
+static void fifo_cleanup_push(void * queue)
+{
+	struct fifo * q = (struct fifo *)queue;
+	TRACE_ENTRY( "%p", queue );
+	
+	/* The thread has been cancelled, therefore it does not wait on the queue anymore */
+	q->thrs_push--;
+	
+	/* Now unlock the queue, and we're done */
+	CHECK_POSIX_DO(  pthread_mutex_unlock( &q->mtx ),  /* nothing */  );
+	
+	/* End of cleanup handler */
+	return;
+}
+
+
+/* Post a new item in the queue */
+int fd_fifo_post_internal ( struct fifo * queue, void ** item, int skip_max )
+{
+	struct fifo_item * new;
+	int call_cb = 0;
+	struct timespec posted_on, queued_on;
+	
+	/* Get the timing of this call */
+	CHECK_SYS(  clock_gettime(CLOCK_REALTIME, &posted_on)  );
+	
+	/* lock the queue */
+	CHECK_POSIX(  pthread_mutex_lock( &queue->mtx )  );
+	
+	if ((!skip_max) && (queue->max)) {
+		while (queue->count >= queue->max) {
+			int ret = 0;
+			
+			/* We have to wait for an item to be pulled */
+			queue->thrs_push++ ;
+			pthread_cleanup_push( fifo_cleanup_push, queue);
+			ret = pthread_cond_wait( &queue->cond_push, &queue->mtx );
+			pthread_cleanup_pop(0);
+			queue->thrs_push-- ;
+			
+			ASSERT( ret == 0 );
+		}
+	}
+	
+	/* Create a new list item */
+	CHECK_MALLOC_DO(  new = malloc (sizeof (struct fifo_item)) , {
+			pthread_mutex_unlock( &queue->mtx );
+			return ENOMEM;
+		} );
+	
+	fd_list_init(&new->item, *item);
+	*item = NULL;
+	
+	/* Add the new item at the end */
+	fd_list_insert_before( &queue->list, &new->item);
+	queue->count++;
+	if (queue->highest_ever < queue->count)
+		queue->highest_ever = queue->count;
+	if (queue->high && ((queue->count % queue->high) == 0)) {
+		call_cb = 1;
+		queue->highest = queue->count;
+	}
+	
+	/* store timing */
+	memcpy(&new->posted_on, &posted_on, sizeof(struct timespec));
+	
+	/* update queue timing info "blocking time" */
+	{
+		long long blocked_ns;
+		CHECK_SYS(  clock_gettime(CLOCK_REALTIME, &queued_on)  );
+		blocked_ns = (queued_on.tv_sec - posted_on.tv_sec) * 1000000000;
+		blocked_ns += (queued_on.tv_nsec - posted_on.tv_nsec);
+		blocked_ns += queue->blocking_time.tv_nsec;
+		queue->blocking_time.tv_sec += blocked_ns / 1000000000;
+		queue->blocking_time.tv_nsec = blocked_ns % 1000000000;
+	}
+	
+	/* Signal if threads are asleep */
+	if (queue->thrs > 0) {
+		CHECK_POSIX(  pthread_cond_signal(&queue->cond_pull)  );
+	}
+	if (queue->thrs_push > 0) {
+		/* cascade */
+		CHECK_POSIX(  pthread_cond_signal(&queue->cond_push)  );
+	}
+	
+	/* Unlock */
+	CHECK_POSIX(  pthread_mutex_unlock( &queue->mtx )  );
+	
+	/* Call high-watermark cb as needed */
+	if (call_cb && queue->h_cb)
+		(*queue->h_cb)(queue, &queue->data);
+	
+	/* Done */
+	return 0;
+}
+
+/* Post a new item in the queue */
+int fd_fifo_post_int ( struct fifo * queue, void ** item )
+{
+	TRACE_ENTRY( "%p %p", queue, item );
+	
+	/* Check the parameters */
+	CHECK_PARAMS( CHECK_FIFO( queue ) && item && *item );
+	
+	return fd_fifo_post_internal ( queue,item, 0 );
+	
+}
+
+/* Post a new item in the queue, not blocking */
+int fd_fifo_post_noblock ( struct fifo * queue, void ** item )
+{
+	TRACE_ENTRY( "%p %p", queue, item );
+	
+	/* Check the parameters */
+	CHECK_PARAMS( CHECK_FIFO( queue ) && item && *item );
+	
+	return fd_fifo_post_internal ( queue,item, 1 );
+	
+}
+
+/* Pop the first item from the queue */
+static void * mq_pop(struct fifo * queue)
+{
+	void * ret = NULL;
+	struct fifo_item * fi;
+	struct timespec now;
+	
+	ASSERT( ! FD_IS_LIST_EMPTY(&queue->list) );
+	
+	fi = (struct fifo_item *)(queue->list.next);
+	ret = fi->item.o;
+	fd_list_unlink(&fi->item);
+	queue->count--;
+	queue->total_items++;
+	
+	/* Update the timings */
+	CHECK_SYS_DO(  clock_gettime(CLOCK_REALTIME, &now), goto skip_timing  );
+	{
+		long long elapsed = (now.tv_sec - fi->posted_on.tv_sec) * 1000000000;
+		elapsed += now.tv_nsec - fi->posted_on.tv_nsec;
+		
+		queue->last_time.tv_sec = elapsed / 1000000000;
+		queue->last_time.tv_nsec = elapsed % 1000000000;
+		
+		elapsed += queue->total_time.tv_nsec;
+		queue->total_time.tv_sec += elapsed / 1000000000;
+		queue->total_time.tv_nsec = elapsed % 1000000000;
+	}
+skip_timing:	
+	free(fi);
+	
+	if (queue->thrs_push) {
+		CHECK_POSIX_DO( pthread_cond_signal( &queue->cond_push ), );
+	}
+	
+	return ret;
+}
+
+/* Check if the low watermark callback must be called. */
+static __inline__ int test_l_cb(struct fifo * queue)
+{
+	if ((queue->high == 0) || (queue->low == 0) || (queue->l_cb == 0))
+		return 0;
+	
+	if (((queue->count % queue->high) == queue->low) && (queue->highest > queue->count)) {
+		queue->highest -= queue->high;
+		return 1;
+	}
+	
+	return 0;
+}
+
+/* Try poping an item */
+int fd_fifo_tryget_int ( struct fifo * queue, void ** item )
+{
+	int wouldblock = 0;
+	int call_cb = 0;
+	
+	TRACE_ENTRY( "%p %p", queue, item );
+	
+	/* Check the parameters */
+	CHECK_PARAMS( CHECK_FIFO( queue ) && item );
+	
+	/* lock the queue */
+	CHECK_POSIX(  pthread_mutex_lock( &queue->mtx )  );
+	
+	/* Check queue status */
+	if (queue->count > 0) {
+got_item:
+		/* There are elements in the queue, so pick the first one */
+		*item = mq_pop(queue);
+		call_cb = test_l_cb(queue);
+	} else {
+		if (queue->thrs_push > 0) {
+			/* A thread is trying to push something, let's give it a chance */
+			CHECK_POSIX(  pthread_mutex_unlock( &queue->mtx )  );
+			CHECK_POSIX(  pthread_cond_signal( &queue->cond_push )  );
+			usleep(1000);
+			CHECK_POSIX(  pthread_mutex_lock( &queue->mtx )  );
+			if (queue->count > 0)
+				goto got_item;
+		}
+		
+		wouldblock = 1;
+		*item = NULL;
+	}
+		
+	/* Unlock */
+	CHECK_POSIX(  pthread_mutex_unlock( &queue->mtx )  );
+	
+	/* Call low watermark callback as needed */
+	if (call_cb)
+		(*queue->l_cb)(queue, &queue->data);
+	
+	/* Done */
+	return wouldblock ? EWOULDBLOCK : 0;
+}
+
+/* This handler is called when a thread is blocked on a queue, and cancelled */
+static void fifo_cleanup(void * queue)
+{
+	struct fifo * q = (struct fifo *)queue;
+	TRACE_ENTRY( "%p", queue );
+	
+	/* The thread has been cancelled, therefore it does not wait on the queue anymore */
+	q->thrs--;
+	
+	/* Now unlock the queue, and we're done */
+	CHECK_POSIX_DO(  pthread_mutex_unlock( &q->mtx ),  /* nothing */  );
+	
+	/* End of cleanup handler */
+	return;
+}
+
+/* The internal function for fd_fifo_timedget and fd_fifo_get */
+static int fifo_tget ( struct fifo * queue, void ** item, int istimed, const struct timespec *abstime)
+{
+	int call_cb = 0;
+	int ret = 0;
+	
+	/* Check the parameters */
+	CHECK_PARAMS( CHECK_FIFO( queue ) && item && (abstime || !istimed) );
+	
+	/* Initialize the return value */
+	*item = NULL;
+	
+	/* lock the queue */
+	CHECK_POSIX(  pthread_mutex_lock( &queue->mtx )  );
+	
+awaken:
+	/* Check queue status */
+	if (!CHECK_FIFO( queue )) {
+		/* The queue is being destroyed */
+		CHECK_POSIX(  pthread_mutex_unlock( &queue->mtx )  );
+		TRACE_DEBUG(FULL, "The queue is being destroyed -> EPIPE");
+		return EPIPE;
+	}
+	
+	if (queue->count > 0) {
+		/* There are items in the queue, so pick the first one */
+		*item = mq_pop(queue);
+		call_cb = test_l_cb(queue);
+	} else {
+		/* We have to wait for a new item */
+		queue->thrs++ ;
+		pthread_cleanup_push( fifo_cleanup, queue);
+		if (istimed) {
+			ret = pthread_cond_timedwait( &queue->cond_pull, &queue->mtx, abstime );
+		} else {
+			ret = pthread_cond_wait( &queue->cond_pull, &queue->mtx );
+		}
+		pthread_cleanup_pop(0);
+		queue->thrs-- ;
+		if (ret == 0)
+			goto awaken;  /* test for spurious wake-ups */
+		
+		/* otherwise (ETIMEDOUT / other error) just continue */
+	}
+	
+	/* Unlock */
+	CHECK_POSIX(  pthread_mutex_unlock( &queue->mtx )  );
+	
+	/* Call low watermark callback as needed */
+	if (call_cb)
+		(*queue->l_cb)(queue, &queue->data);
+	
+	/* Done */
+	return ret;
+}
+
+/* Get the next available item, block until there is one */
+int fd_fifo_get_int ( struct fifo * queue, void ** item )
+{
+	TRACE_ENTRY( "%p %p", queue, item );
+	return fifo_tget(queue, item, 0, NULL);
+}
+
+/* Get the next available item, block until there is one, or the timeout expires */
+int fd_fifo_timedget_int ( struct fifo * queue, void ** item, const struct timespec *abstime )
+{
+	TRACE_ENTRY( "%p %p %p", queue, item, abstime );
+	return fifo_tget(queue, item, 1, abstime);
+}
+
+/* Test if data is available in the queue, without pulling it */
+int fd_fifo_select ( struct fifo * queue, const struct timespec *abstime )
+{
+	int ret = 0;
+	TRACE_ENTRY( "%p %p", queue, abstime );
+	
+	CHECK_PARAMS_DO( CHECK_FIFO( queue ), return -EINVAL );
+	
+	/* lock the queue */
+	CHECK_POSIX_DO(  pthread_mutex_lock( &queue->mtx ), return -__ret__  );
+	
+awaken:	
+	ret = (queue->count > 0 ) ? queue->count : 0;
+	if ((ret == 0) && (abstime != NULL)) {
+		/* We have to wait for a new item */
+		queue->thrs++ ;
+		pthread_cleanup_push( fifo_cleanup, queue);
+		ret = pthread_cond_timedwait( &queue->cond_pull, &queue->mtx, abstime );
+		pthread_cleanup_pop(0);
+		queue->thrs-- ;
+		if (ret == 0)
+			goto awaken;  /* test for spurious wake-ups */
+		
+		if (ret == ETIMEDOUT)
+			ret = 0;
+		else 
+			ret = -ret;
+	}
+	
+	/* Unlock */
+	CHECK_POSIX_DO(  pthread_mutex_unlock( &queue->mtx ), return -__ret__  );
+	
+	return ret;
+}
diff --git a/libfdproto/init.c b/libfdproto/init.c
new file mode 100644
index 0000000..5519ca6
--- /dev/null
+++ b/libfdproto/init.c
@@ -0,0 +1,71 @@
+/*********************************************************************************************************
+* Software License Agreement (BSD License)                                                               *
+* Author: Sebastien Decugis <sdecugis@freediameter.net>							 *
+*													 *
+* Copyright (c) 2013, WIDE Project and NICT								 *
+* All rights reserved.											 *
+* 													 *
+* Redistribution and use of this software in source and binary forms, with or without modification, are  *
+* permitted provided that the following conditions are met:						 *
+* 													 *
+* * Redistributions of source code must retain the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer.										 *
+*    													 *
+* * Redistributions in binary form must reproduce the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer in the documentation and/or other						 *
+*   materials provided with the distribution.								 *
+* 													 *
+* * Neither the name of the WIDE Project or NICT nor the 						 *
+*   names of its contributors may be used to endorse or 						 *
+*   promote products derived from this software without 						 *
+*   specific prior written permission of WIDE Project and 						 *
+*   NICT.												 *
+* 													 *
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED *
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
+* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR *
+* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 	 *
+* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 	 *
+* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR *
+* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF   *
+* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.								 *
+*********************************************************************************************************/
+
+#include "fdproto-internal.h"
+
+/* function to free the threadnames */
+static void freelogstr(void * str) {
+	if (TRACE_BOOL(ANNOYING)) {
+		if (str) {
+			fd_log_debug("(Thread '%s' terminating)", (char *)str);
+		}
+	}
+	free(str);
+}
+
+/* Initialize library variables and threads */
+int fd_libproto_init()
+{
+	int ret = 0;
+	
+	/* Create the thread key that contains thread name for debug messages */
+	ret = pthread_key_create(&fd_log_thname, freelogstr);
+	if (ret != 0) {
+		fprintf(stderr, "Error initializing the libfreeDiameter library: %s\n", strerror(ret) );
+		return ret;
+	}
+	
+	/* Initialize the modules that need it */
+	fd_msg_eteid_init();
+	CHECK_FCT( fd_sess_init() );
+	
+	return 0;
+}
+
+/* Stop all threads created in the library */
+void fd_libproto_fini(void)
+{
+	fd_sess_fini();
+}
diff --git a/libfdproto/lists.c b/libfdproto/lists.c
new file mode 100644
index 0000000..2aa1429
--- /dev/null
+++ b/libfdproto/lists.c
@@ -0,0 +1,168 @@
+/*********************************************************************************************************
+* Software License Agreement (BSD License)                                                               *
+* Author: Sebastien Decugis <sdecugis@freediameter.net>							 *
+*													 *
+* Copyright (c) 2013, WIDE Project and NICT								 *
+* All rights reserved.											 *
+* 													 *
+* Redistribution and use of this software in source and binary forms, with or without modification, are  *
+* permitted provided that the following conditions are met:						 *
+* 													 *
+* * Redistributions of source code must retain the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer.										 *
+*    													 *
+* * Redistributions in binary form must reproduce the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer in the documentation and/or other						 *
+*   materials provided with the distribution.								 *
+* 													 *
+* * Neither the name of the WIDE Project or NICT nor the 						 *
+*   names of its contributors may be used to endorse or 						 *
+*   promote products derived from this software without 						 *
+*   specific prior written permission of WIDE Project and 						 *
+*   NICT.												 *
+* 													 *
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED *
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
+* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR *
+* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 	 *
+* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 	 *
+* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR *
+* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF   *
+* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.								 *
+*********************************************************************************************************/
+
+#include "fdproto-internal.h"
+
+/* Initialize a list element */
+void fd_list_init ( struct fd_list * list, void * obj )
+{
+	memset(list, 0, sizeof(struct fd_list));
+	list->next = list;
+	list->prev = list;
+	list->head = list;
+	list->o    = obj;
+}
+
+#define CHECK_SINGLE( li ) {			\
+	ASSERT( ((struct fd_list *)(li))->next == (li) );	\
+	ASSERT( ((struct fd_list *)(li))->prev == (li) );	\
+	ASSERT( ((struct fd_list *)(li))->head == (li) );	\
+}
+
+/* insert after a reference, checks done */
+static void list_insert_after( struct fd_list * ref, struct fd_list * item )
+{
+	item->prev = ref;
+	item->next = ref->next;
+	item->head = ref->head;
+	ref->next->prev = item;
+	ref->next = item;
+}
+
+/* insert after a reference */
+void fd_list_insert_after  ( struct fd_list * ref, struct fd_list * item )
+{
+	ASSERT(item != NULL);
+	ASSERT(ref != NULL);
+	CHECK_SINGLE ( item );
+	ASSERT(ref->head != item);
+	list_insert_after(ref, item);
+}
+
+/* Move all elements of list senti at the end of list ref */
+void fd_list_move_end(struct fd_list * ref, struct fd_list * senti)
+{
+	struct fd_list * li;
+	ASSERT(ref->head == ref);
+	ASSERT(senti->head == senti);
+	
+	if (senti->next == senti)
+		return;
+	
+	for (li = senti->next; li != senti; li = li->next)
+		li->head = ref;
+	
+	senti->next->prev = ref->prev;
+	ref->prev->next   = senti->next;
+	senti->prev->next = ref;
+	ref->prev         = senti->prev;
+	senti->prev = senti;
+	senti->next = senti;
+}
+
+/* insert before a reference, checks done */
+static void list_insert_before ( struct fd_list * ref, struct fd_list * item )
+{
+	item->prev = ref->prev;
+	item->next = ref;
+	item->head = ref->head;
+	ref->prev->next = item;
+	ref->prev = item;
+}
+
+/* insert before a reference */
+void fd_list_insert_before ( struct fd_list * ref, struct fd_list * item )
+{
+	ASSERT(item != NULL);
+	ASSERT(ref != NULL);
+	CHECK_SINGLE ( item );
+	ASSERT(ref->head != item);
+	list_insert_before(ref, item);
+}
+
+/* Insert an item in an ordered list -- ordering function provided. If duplicate object found, it is returned in ref_duplicate */
+int fd_list_insert_ordered( struct fd_list * head, struct fd_list * item, int (*cmp_fct)(void *, void *), void ** ref_duplicate)
+{
+	struct fd_list * ptr = head;
+	int cmp;
+	
+	/* Some debug sanity checks */
+	ASSERT(head != NULL);
+	ASSERT(item != NULL);
+	ASSERT(cmp_fct != NULL);
+	ASSERT(head->head == head);
+	CHECK_SINGLE ( item );
+	
+	/* loop in the list */
+	while (ptr->next != head)
+	{
+		/* Compare the object to insert with the next object in list */
+		cmp = cmp_fct( item->o, ptr->next->o );
+		if (!cmp) {
+			/* An element with the same key already exists */
+			if (ref_duplicate != NULL)
+				*ref_duplicate = ptr->next->o;
+			return EEXIST;
+		}
+		
+		if (cmp < 0)
+			break; /* We must insert the element here */
+		
+		ptr = ptr->next;
+	}
+	
+	/* Now insert the element between ptr and ptr->next */
+	list_insert_after( ptr, item );
+	
+	/* Ok */
+	return 0;
+}
+	
+/* Unlink an object */
+void fd_list_unlink ( struct fd_list * item )
+{
+	ASSERT(item != NULL);
+	if (item->head == item)
+		return;
+	/* unlink */
+	item->next->prev = item->prev;
+	item->prev->next = item->next;
+	/* sanitize */
+	item->next = item;
+	item->prev = item;
+	item->head = item;
+}
+
+
diff --git a/libfdproto/log.c b/libfdproto/log.c
new file mode 100644
index 0000000..7bbe307
--- /dev/null
+++ b/libfdproto/log.c
@@ -0,0 +1,325 @@
+/*********************************************************************************************************
+* Software License Agreement (BSD License)                                                               *
+* Author: Sebastien Decugis <sdecugis@freediameter.net>							 *
+*													 *
+* Copyright (c) 2015, WIDE Project and NICT								 *
+* All rights reserved.											 *
+* 													 *
+* Redistribution and use of this software in source and binary forms, with or without modification, are  *
+* permitted provided that the following conditions are met:						 *
+* 													 *
+* * Redistributions of source code must retain the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer.										 *
+*    													 *
+* * Redistributions in binary form must reproduce the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer in the documentation and/or other						 *
+*   materials provided with the distribution.								 *
+* 													 *
+* * Neither the name of the WIDE Project or NICT nor the 						 *
+*   names of its contributors may be used to endorse or 						 *
+*   promote products derived from this software without 						 *
+*   specific prior written permission of WIDE Project and 						 *
+*   NICT.												 *
+* 													 *
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED *
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
+* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR *
+* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 	 *
+* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 	 *
+* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR *
+* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF   *
+* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.								 *
+*********************************************************************************************************/
+
+#include "fdproto-internal.h"
+
+#include <stdarg.h>
+
+pthread_mutex_t fd_log_lock = PTHREAD_MUTEX_INITIALIZER;
+pthread_key_t	fd_log_thname;
+int fd_g_debug_lvl = FD_LOG_NOTICE;
+
+static void fd_internal_logger( int, const char *, va_list );
+static int use_colors = 0; /* 0: not init, 1: yes, 2: no */
+
+/* These may be used to pass specific debug requests via the command-line parameters */
+char * fd_debug_one_function = NULL;
+char * fd_debug_one_file = NULL;
+
+/* Useless function, only to ease setting up a breakpoint in gdb (break fd_breakhere) -- use TRACE_HERE */
+int fd_breaks = 0;
+int fd_breakhere(void) { return ++fd_breaks; }
+
+/* Allow passing of the log and debug information from base stack to extensions */
+void (*fd_logger)( int loglevel, const char * format, va_list args ) = fd_internal_logger;
+
+/* Register an external call back for tracing and debug */
+int fd_log_handler_register( void (*logger)(int loglevel, const char * format, va_list args) )
+{
+        CHECK_PARAMS( logger );
+
+        if ( fd_logger != fd_internal_logger )
+        {
+               return EALREADY; /* only one registration allowed */
+        }
+        else
+        {
+               fd_logger = logger;
+        }
+
+        return 0;
+}
+
+/* Implement a simple reset function here */
+int fd_log_handler_unregister ( void )
+{
+        fd_logger = fd_internal_logger;
+        return 0; /* Successfull in all cases. */
+}
+
+static void fd_cleanup_mutex_silent( void * mutex )
+{
+	(void)pthread_mutex_unlock((pthread_mutex_t *)mutex);
+}
+
+
+static void fd_internal_logger( int printlevel, const char *format, va_list ap )
+{
+    char buf[25];
+
+    /* Do we need to trace this ? */
+    if (printlevel < fd_g_debug_lvl)
+    	return;
+
+    /* add timestamp */
+    printf("%s  ", fd_log_time(NULL, buf, sizeof(buf), 
+#if (defined(DEBUG) && defined(DEBUG_WITH_META))
+    	1, 1
+#else /* (defined(DEBUG) && defined(DEBUG_WITH_META)) */
+        0, 0
+#endif /* (defined(DEBUG) && defined(DEBUG_WITH_META)) */
+	    ));
+    /* Use colors on stdout ? */
+    if (!use_colors) {
+	if (isatty(STDOUT_FILENO))
+		use_colors = 1;
+	else
+		use_colors = 2;
+    }
+    
+    switch(printlevel) {
+	    case FD_LOG_ANNOYING:  printf("%s	A   ", (use_colors == 1) ? "\e[0;37m" : ""); break;
+	    case FD_LOG_DEBUG:     printf("%s DBG   ", (use_colors == 1) ? "\e[0;37m" : ""); break;
+	    case FD_LOG_NOTICE:    printf("%sNOTI   ", (use_colors == 1) ? "\e[1;37m" : ""); break;
+	    case FD_LOG_ERROR:     printf("%sERROR  ", (use_colors == 1) ? "\e[0;31m" : ""); break;
+	    case FD_LOG_FATAL:     printf("%sFATAL! ", (use_colors == 1) ? "\e[0;31m" : ""); break;
+	    default:               printf("%s ???   ", (use_colors == 1) ? "\e[0;31m" : "");
+    }
+    vprintf(format, ap);
+    if (use_colors == 1)
+	     printf("\e[00m");
+    printf("\n");
+    
+    fflush(stdout);
+}
+
+/* Log a debug message */
+void fd_log ( int loglevel, const char * format, ... )
+{
+	va_list ap;
+	
+	(void)pthread_mutex_lock(&fd_log_lock);
+	
+	pthread_cleanup_push(fd_cleanup_mutex_silent, &fd_log_lock);
+	
+	va_start(ap, format);
+	fd_logger(loglevel, format, ap);
+	va_end(ap);
+
+	pthread_cleanup_pop(0);
+	
+	(void)pthread_mutex_unlock(&fd_log_lock);
+}
+
+/* Log a debug message */
+void fd_log_va ( int loglevel, const char * format, va_list args )
+{
+	(void)pthread_mutex_lock(&fd_log_lock);
+	
+	pthread_cleanup_push(fd_cleanup_mutex_silent, &fd_log_lock);
+	fd_logger(loglevel, format, args);
+	pthread_cleanup_pop(0);
+	
+	(void)pthread_mutex_unlock(&fd_log_lock);
+}
+
+/* Function to set the thread's friendly name */
+void fd_log_threadname ( const char * name )
+{
+	void * val = NULL;
+	
+	TRACE_ENTRY("%p(%s)", name, name?:"/");
+	
+	/* First, check if a value is already assigned to the current thread */
+	val = pthread_getspecific(fd_log_thname);
+	if (TRACE_BOOL(ANNOYING)) {
+		if (val) {
+			fd_log_debug("(Thread '%s' renamed to '%s')", (char *)val, name?:"(nil)");
+		} else {
+			fd_log_debug("(Thread %p named '%s')", (void *)pthread_self(), name?:"(nil)");
+		}
+	}
+	if (val != NULL) {
+		free(val);
+	}
+	
+	/* Now create the new string */
+	if (name == NULL) {
+		CHECK_POSIX_DO( pthread_setspecific(fd_log_thname, NULL), /* continue */);
+		return;
+	}
+	
+	CHECK_MALLOC_DO( val = strdup(name), return );
+	
+	CHECK_POSIX_DO( pthread_setspecific(fd_log_thname, val), /* continue */);
+	return;
+}
+
+/* Write time into a buffer */
+char * fd_log_time ( struct timespec * ts, char * buf, size_t len, int incl_date, int incl_ms )
+{
+	int ret;
+	size_t offset = 0;
+	struct timespec tp;
+	struct tm tm;
+	
+	/* Get current time */
+	if (!ts) {
+		ret = clock_gettime(CLOCK_REALTIME, &tp);
+		if (ret != 0) {
+			snprintf(buf, len, "%s", strerror(ret));
+			return buf;
+		}
+		ts = &tp;
+	}
+	
+	offset += strftime(buf + offset, len - offset, incl_date?"%D,%T":"%T", localtime_r( &ts->tv_sec , &tm ));
+	if (incl_ms)
+		offset += snprintf(buf + offset, len - offset, ".%6.6ld", ts->tv_nsec / 1000);
+
+	return buf;
+}
+
+
+static size_t sys_mempagesz = 0;
+
+static size_t get_mempagesz(void) {
+	if (!sys_mempagesz) {
+		sys_mempagesz = sysconf(_SC_PAGESIZE); /* We alloc buffer by memory pages for efficiency. This can be readjusted if too memory consuming */
+		if (sys_mempagesz <= 0)
+			sys_mempagesz = 256; /* default size if above call failed */
+	}
+	return sys_mempagesz;
+}
+
+
+/* Helper function for fd_*_dump. Prints the format string from 'offset' into '*buf', extends if needed. The location of buf can be updated by this function. */
+char * fd_dump_extend(char ** buf, size_t *len, size_t *offset, const char * format, ... )
+{
+	va_list ap;
+	int to_write;
+	size_t o = 0;
+	size_t mempagesz = get_mempagesz();
+	
+	/* we do not TRACE_ENTRY this one on purpose */
+	
+	CHECK_PARAMS_DO(buf && len, return NULL);
+	
+	if (*buf == NULL) {
+		CHECK_MALLOC_DO(*buf = malloc(mempagesz), return NULL);
+		*len = mempagesz;
+	}
+	
+	if (offset)
+		o = *offset;
+	
+	va_start(ap, format);
+	to_write = vsnprintf(*buf + o, *len - o, format, ap);
+	va_end(ap);
+	
+	if (to_write + o >= *len) {
+		/* There was no room in the buffer, we extend and redo */
+		size_t new_len = (((to_write + o) / mempagesz) + 1) * mempagesz;
+		CHECK_MALLOC_DO(*buf = realloc(*buf, new_len), return NULL);
+		*len = new_len;
+		
+		va_start(ap, format);
+		to_write = vsnprintf(*buf + o, *len - o, format, ap);
+		va_end(ap);
+	}
+	
+	if (offset)
+		*offset += to_write;
+	
+	return *buf;
+}
+
+char * fd_dump_extend_hexdump(char ** buf, size_t *len, size_t *offset, uint8_t *data, size_t datalen, size_t trunc, size_t wrap )
+{
+	int truncated = 0;
+	size_t towrite = 0;
+	size_t o = 0;
+	int i;
+	char * p;
+	size_t mempagesz = get_mempagesz();
+#define TRUNK_MARK "[...]"
+
+	CHECK_PARAMS_DO(buf && len && data, return NULL);
+	
+	if (trunc && (datalen > trunc)) {
+		datalen = trunc;
+		truncated = 1;
+	}
+	
+	towrite = datalen * 2;
+	
+	if (wrap)
+		towrite += datalen / wrap; /* add 1 '\n' every wrap byte */
+	
+	if (truncated)
+		towrite += CONSTSTRLEN(TRUNK_MARK);
+	
+	
+	if (offset)
+		o = *offset;
+	
+	if (*buf == NULL) {
+		/* Directly allocate the size we need */
+		*len = (((towrite + o) / mempagesz) + 1 ) * mempagesz;
+		CHECK_MALLOC_DO(*buf = malloc(*len), return NULL);
+	} else if ((towrite + o) >= *len) {
+		/* There is no room in the buffer, we extend and redo */
+		size_t new_len = (((towrite + o) / mempagesz) + 1) * mempagesz;
+		CHECK_MALLOC_DO(*buf = realloc(*buf, new_len), return NULL);
+		*len = new_len;
+	}
+	
+	p = *buf + o;
+	for (i = 0; i < datalen; i++) {
+		sprintf(p, "%02hhX", data[i]);
+		p+=2;
+		if ((wrap) && ((i+1) % wrap == 0)) {
+			*p++='\n'; *p ='\0'; /* we want to ensure the buffer is always 0-terminated */
+		}
+	}
+	
+	if (truncated)
+		memcpy(p, TRUNK_MARK, CONSTSTRLEN(TRUNK_MARK));
+		
+	if (offset)
+		*offset += towrite;
+	
+	return *buf;
+}
diff --git a/libfdproto/messages.c b/libfdproto/messages.c
new file mode 100644
index 0000000..3da8d2e
--- /dev/null
+++ b/libfdproto/messages.c
@@ -0,0 +1,2850 @@
+/*********************************************************************************************************
+* Software License Agreement (BSD License)                                                               *
+* Author: Sebastien Decugis <sdecugis@freediameter.net>							 *
+*													 *
+* Copyright (c) 2015, WIDE Project and NICT								 *
+* All rights reserved.											 *
+* 													 *
+* Redistribution and use of this software in source and binary forms, with or without modification, are  *
+* permitted provided that the following conditions are met:						 *
+* 													 *
+* * Redistributions of source code must retain the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer.										 *
+*    													 *
+* * Redistributions in binary form must reproduce the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer in the documentation and/or other						 *
+*   materials provided with the distribution.								 *
+* 													 *
+* * Neither the name of the WIDE Project or NICT nor the 						 *
+*   names of its contributors may be used to endorse or 						 *
+*   promote products derived from this software without 						 *
+*   specific prior written permission of WIDE Project and 						 *
+*   NICT.												 *
+* 													 *
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED *
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
+* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR *
+* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 	 *
+* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 	 *
+* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR *
+* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF   *
+* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.								 *
+*********************************************************************************************************/
+
+/* Messages module.
+ * 
+ * This module allows to manipulate the msg and avp structures that represents a Diameter message in memory.
+ */
+
+#include "fdproto-internal.h"
+
+#include <sys/param.h>
+
+/* Type of object */
+enum msg_objtype {
+	MSG_MSG = 1, 
+	MSG_AVP
+};
+
+/* Chaining of elements as a free hierarchy */
+struct msg_avp_chain {
+	struct fd_list		chaining;	/* Chaining information at this level. */
+	struct fd_list		children;	/* sentinel for the children of this object */
+	enum msg_objtype 	type;		/* Type of this object, _MSG_MSG or _MSG_AVP */
+};
+
+/* Return the chain information from an AVP or MSG. Since it's the first field, we just cast */
+#define _C(_x) ((struct msg_avp_chain *)(_x))
+
+/* Some details about chaining:
+ *
+ *  A message is made of a header ( msg ) and 0 or more AVPs ( avp ).
+ * The structure is a kind of tree, where some AVPs (grouped AVPs) can contain other AVPs.
+ * Example:
+ * msg
+ *  |-avp
+ *  |-gavp
+ *  |   |-avp
+ *  |   |-avp
+ *  |   \-avp
+ *  |-avp
+ *  \-avp
+ *
+ * Each item (msg or avp) structure begins with a msg_avp_chain structure.
+ * The element at the top of the hierarchy (msg in our example) has all the fields of its "chaining" equal to the same value.
+ *
+ * All elements at the same level are linked by their "chaining" list.
+ * The "children" list is the sentinel for the lists of children of this element.
+ */
+
+/* The following definitions are used to recognize objects in memory. */
+#define MSG_MSG_EYEC	(0x11355463)
+#define MSG_AVP_EYEC	(0x11355467)
+
+/* The following structure represents an AVP instance. */
+struct avp {
+	struct msg_avp_chain	 avp_chain;		/* Chaining information of this AVP */
+	int			 avp_eyec;		/* Must be equal to MSG_AVP_EYEC */
+	struct dict_object	*avp_model;		/* If not NULL, pointer to the dictionary object of this avp */
+	struct {
+		avp_code_t	 mnf_code;		
+		vendor_id_t	 mnf_vendor;		
+	}  			 avp_model_not_found;	/* When model resolution has failed, store a copy of the data here to avoid searching again */
+	struct avp_hdr		 avp_public;		/* AVP data that can be managed by other modules */
+	
+	uint8_t			*avp_source;		/* If the message was parsed from a buffer, pointer to the AVP data start in the buffer. */
+	uint8_t			*avp_rawdata;		/* when the data can not be interpreted, the raw data is copied here. The header is not part of it. */
+	size_t			 avp_rawlen;		/* The length of the raw buffer. */
+	union avp_value		 avp_storage;		/* To avoid many alloc/free, store the integer values here and set avp_public.avp_data to &storage */
+	int			 avp_mustfreeos;	/* 1 if an octetstring is malloc'd in avp_storage and must be freed. */
+};
+
+/* Macro to compute the AVP header size */
+#define AVPHDRSZ_NOVEND	8
+#define AVPHDRSZ_VENDOR	12
+#define GETAVPHDRSZ( _flag ) ((_flag & AVP_FLAG_VENDOR) ? AVPHDRSZ_VENDOR : AVPHDRSZ_NOVEND)
+
+/* Macro to cast a msg_avp_t */
+#define _A(_x) ((struct avp *)(_x))
+/* Check the type and eyecatcher */
+#define CHECK_AVP(_x) ((_x) && (_C(_x)->type == MSG_AVP) && (_A(_x)->avp_eyec == MSG_AVP_EYEC))
+
+/* The following structure represents an instance of a message (command and children AVPs). */
+struct msg {
+	struct msg_avp_chain	 msg_chain;		/* List of the AVPs in the message */
+	int			 msg_eyec;		/* Must be equal to MSG_MSG_EYEC */
+	struct dict_object	*msg_model;		/* If not NULL, pointer to the dictionary object of this message */
+	struct {
+		command_code_t	 mnf_code;
+		uint8_t		 mnf_flags;		
+	}  			 msg_model_not_found;	/* When model resolution has failed, store a copy of the data here to avoid searching again */
+	struct msg_hdr		 msg_public;		/* Message data that can be managed by extensions. */
+	
+	uint8_t			*msg_rawbuffer;		/* data buffer that was received, saved during fd_msg_parse_buffer and freed in fd_msg_parse_dict */
+	int			 msg_routable;		/* Is this a routable message? (0: undef, 1: routable, 2: non routable) */
+	struct msg		*msg_query;		/* the associated query if the message is a received answer */
+	int			 msg_associated;	/* and the counter part information in the query, to avoid double free */
+	struct rt_data		*msg_rtdata;		/* Routing list for the query */
+	struct session		*msg_sess;		/* Cached message session if any */
+	struct {
+			void (*anscb)(void *, struct msg **);
+			void (*expirecb)(void *, DiamId_t, size_t, struct msg **);
+			void * data;
+			struct timespec timeout;
+		}		 msg_cb;		/* Callback to be called when an answer is received, or timeout expires, if not NULL */
+	DiamId_t		 msg_src_id;		/* Diameter Id of the peer this message was received from. This string is malloc'd and must be freed */
+	size_t			 msg_src_id_len;	/* cached length of this string */
+	struct fd_msg_pmdl	 msg_pmdl;		/* list of permessagedata structures. */
+};
+
+/* Macro to compute the message header size */
+#define GETMSGHDRSZ() 	20
+
+/* Macro to cast a msg_avp_t */
+#define _M(_x) ((struct msg *)(_x))
+/* Check the type and eyecatcher */
+#define CHECK_MSG(_x) ((_x) && (_C(_x)->type == MSG_MSG) && (_M(_x)->msg_eyec == MSG_MSG_EYEC))
+
+#define VALIDATE_OBJ(_x) ( (CHECK_MSG(_x)) || (CHECK_AVP(_x)) )
+
+
+/* Macro to validate a MSGFL_ value */
+#define CHECK_AVPFL(_fl) ( ((_fl) & (- (AVPFL_MAX << 1) )) == 0 )
+#define CHECK_MSGFL(_fl) ( ((_fl) & (- (MSGFL_MAX << 1) )) == 0 )
+
+
+/* initial sizes of AVP from their types, in bytes. */
+static int avp_value_sizes[] = { 
+	 0,	/* AVP_TYPE_GROUPED: size is dynamic */
+	 0,	/* AVP_TYPE_OCTETSTRING: size is dynamic */
+	 4,	/* AVP_TYPE_INTEGER32: size is 32 bits */
+	 8,	/* AVP_TYPE_INTEGER64: size is 64 bits */
+	 4,	/* AVP_TYPE_UNSIGNED32: size is 32 bits */
+	 8,	/* AVP_TYPE_UNSIGNED64: size is 64 bits */
+	 4,	/* AVP_TYPE_FLOAT32: size is 32 bits */
+	 8	/* AVP_TYPE_FLOAT64: size is 64 bits */
+};
+#define CHECK_BASETYPE( _type ) ( ((_type) <= AVP_TYPE_MAX) && ((_type) >= 0) )
+#define GETINITIALSIZE( _type, _vend ) (avp_value_sizes[ CHECK_BASETYPE(_type) ? (_type) : 0] + GETAVPHDRSZ(_vend))
+
+/* Forward declaration */
+static int parsedict_do_msg(struct dictionary * dict, struct msg * msg, int only_hdr, struct fd_pei *error_info);
+
+/***************************************************************************************************************/
+/* Creating objects */
+
+/* Initialize a msg_avp_chain structure */
+static void init_chain(struct msg_avp_chain * chain, int type)
+{
+	fd_list_init( &chain->chaining, (void *)chain);
+	fd_list_init( &chain->children, (void *)chain);
+	chain->type = type;
+}
+
+/* Initialize a new AVP object */
+static void init_avp ( struct avp * avp )
+{
+	TRACE_ENTRY("%p", avp);
+	
+	memset(avp, 0, sizeof(struct avp));
+	init_chain( &avp->avp_chain, MSG_AVP);
+	avp->avp_eyec = MSG_AVP_EYEC;
+}
+	
+/* Initialize a new MSG object */
+static void init_msg ( struct msg * msg )
+{
+	TRACE_ENTRY("%p", msg);
+	
+	memset(msg, 0, sizeof(struct msg));
+	init_chain( &msg->msg_chain, MSG_MSG);
+	msg->msg_eyec = MSG_MSG_EYEC;
+	
+	fd_list_init(&msg->msg_pmdl.sentinel, NULL);
+	CHECK_POSIX_DO( pthread_mutex_init(&msg->msg_pmdl.lock, NULL), );
+}
+
+
+/* Create a new AVP instance */
+int fd_msg_avp_new ( struct dict_object * model, int flags, struct avp ** avp )
+{
+	struct avp *new = NULL;
+	
+	TRACE_ENTRY("%p %x %p", model, flags, avp);
+	
+	/* Check the parameters */
+	CHECK_PARAMS(  avp && CHECK_AVPFL(flags)  );
+	
+	if (model) {
+		enum dict_object_type 	 dicttype;
+		CHECK_PARAMS( (fd_dict_gettype(model, &dicttype) == 0) && (dicttype == DICT_AVP) );
+	}
+	
+	/* Create a new object */
+	CHECK_MALLOC(  new = malloc (sizeof(struct avp))  );
+	
+	/* Initialize the fields */
+	init_avp(new);
+	
+	if (model) {
+		struct dict_avp_data dictdata;
+		
+		CHECK_FCT_DO(  fd_dict_getval(model, &dictdata), { free(new); return __ret__; }  );
+	
+		new->avp_model = model;
+		new->avp_public.avp_code    = dictdata.avp_code;
+		new->avp_public.avp_flags   = dictdata.avp_flag_val;
+		new->avp_public.avp_len = GETINITIALSIZE(dictdata.avp_basetype, dictdata.avp_flag_val );
+		new->avp_public.avp_vendor  = dictdata.avp_vendor;
+	}
+	
+	if (flags & AVPFL_SET_BLANK_VALUE) {
+		new->avp_public.avp_value = &new->avp_storage;
+	}
+	
+	if (flags & AVPFL_SET_RAWDATA_FROM_AVP) {
+		new->avp_rawlen = (*avp)->avp_public.avp_len - GETAVPHDRSZ( (*avp)->avp_public.avp_flags );
+		if (new->avp_rawlen) {
+			CHECK_MALLOC_DO(  new->avp_rawdata = malloc(new->avp_rawlen), { free(new); return __ret__; }  );
+			memset(new->avp_rawdata, 0x00, new->avp_rawlen);
+		}
+	}
+	
+	/* The new object is ready, return */
+	*avp = new;
+	return 0;
+}
+
+int fd_msg_new ( struct dict_object * model, int flags, struct msg ** msg )
+{
+   return fd_msg_new_appl( model, NULL, flags, msg );
+}
+
+/* Create a new message instance */
+int fd_msg_new_appl ( struct dict_object * model, struct dict_object * appl, int flags, struct msg ** msg )
+{
+	struct msg * new = NULL;
+	
+	TRACE_ENTRY("%p %x %p", model, flags, msg);
+	
+	/* Check the parameters */
+	CHECK_PARAMS(  msg && CHECK_MSGFL(flags)  );
+	
+	if (model) {
+		enum dict_object_type 	 dicttype;
+		CHECK_PARAMS( (fd_dict_gettype(model, &dicttype) == 0) && (dicttype == DICT_COMMAND) );
+	}
+	
+	/* Create a new object */
+	CHECK_MALLOC(  new = malloc (sizeof(struct msg))  );
+	
+	/* Initialize the fields */
+	init_msg(new);
+	new->msg_public.msg_version	= DIAMETER_VERSION;
+	new->msg_public.msg_length	= GETMSGHDRSZ(); /* This will be updated later */
+
+	if (model) {
+		struct dictionary 	*dict;
+		struct dict_cmd_data     dictdata;
+		struct dict_object     	*dictappl;
+		
+		CHECK_FCT_DO( fd_dict_getdict(model, &dict), { free(new); return __ret__; } );
+		CHECK_FCT_DO( fd_dict_getval(model, &dictdata), { free(new); return __ret__; }  );
+		
+		new->msg_model = model;
+		new->msg_public.msg_flags	= dictdata.cmd_flag_val;
+		new->msg_public.msg_code	= dictdata.cmd_code;
+
+		/* Initialize application from the parent, if any */
+		if (appl)
+			dictappl = appl;
+		else
+			CHECK_FCT_DO(  fd_dict_search( dict, DICT_APPLICATION, APPLICATION_OF_COMMAND, model, &dictappl, 0), { free(new); return __ret__; }  );
+		if (dictappl != NULL) {
+			struct dict_application_data appdata;
+			CHECK_FCT_DO(  fd_dict_getval(dictappl, &appdata), { free(new); return __ret__; }  );
+			new->msg_public.msg_appl = appdata.application_id;
+		}
+	}
+	
+	if (flags & MSGFL_ALLOC_ETEID) {
+		new->msg_public.msg_eteid = fd_msg_eteid_get();
+	}
+	
+	/* The new object is ready, return */
+	*msg = new;
+	return 0;
+}	
+
+static int bufferize_avp(unsigned char * buffer, size_t buflen, size_t * offset,  struct avp * avp);
+static int parsebuf_list(unsigned char * buf, size_t buflen, struct fd_list * head);
+static int parsedict_do_chain(struct dictionary * dict, struct fd_list * head, int mandatory, struct fd_pei *error_info);
+
+
+/* Create answer from a request */
+int fd_msg_new_answer_from_req ( struct dictionary * dict, struct msg ** msg, int flags )
+{
+	struct dict_object * model = NULL;
+	struct msg *qry, *ans;
+	struct session * sess = NULL;
+	
+	TRACE_ENTRY("%p %x", msg, flags);
+	
+	/* Check the parameters */
+	CHECK_PARAMS(  msg );
+	qry = *msg;
+	CHECK_PARAMS( CHECK_MSG(qry) && (qry->msg_public.msg_flags & CMD_FLAG_REQUEST) );
+	
+	if (! (flags & MSGFL_ANSW_NOSID)) {
+		/* Get the session of the message */
+		CHECK_FCT_DO( fd_msg_sess_get(dict, qry, &sess, NULL), /* ignore an error */ );
+	}
+	
+	/* Find the model for the answer */
+	if (flags & MSGFL_ANSW_ERROR) {
+		/* The model is the generic error format */
+		CHECK_FCT( fd_dict_get_error_cmd(dict, &model) );
+	} else {
+		/* The model is the answer corresponding to the query. It supposes that these are defined in the dictionary */
+		CHECK_FCT_DO(  parsedict_do_msg( dict, qry, 1, NULL), /* continue */  );
+		if (qry->msg_model) {
+			CHECK_FCT(  fd_dict_search ( dict, DICT_COMMAND, CMD_ANSWER, qry->msg_model, &model, EINVAL )  );
+		}
+	}
+	
+	/* Create the answer */
+	CHECK_FCT(  fd_msg_new( model, flags, &ans )  );
+	
+	/* Set informations in the answer as in the query */
+	ans->msg_public.msg_code = qry->msg_public.msg_code; /* useful for MSGFL_ANSW_ERROR */
+	ans->msg_public.msg_appl = qry->msg_public.msg_appl;
+	ans->msg_public.msg_eteid = qry->msg_public.msg_eteid;
+	ans->msg_public.msg_hbhid = qry->msg_public.msg_hbhid;
+	
+	/* Add the Session-Id AVP if session is known */
+	if (sess && dict) {
+		static struct dict_object * sess_id_avp = NULL;
+		os0_t sid;
+		size_t sidlen;
+		struct avp * avp;
+		union avp_value val;
+		
+		if (!sess_id_avp) {
+			CHECK_FCT_DO( fd_dict_search( dict, DICT_AVP, AVP_BY_NAME, "Session-Id", &sess_id_avp, ENOENT), { free(ans); return __ret__; } );
+		}
+		CHECK_FCT_DO( fd_sess_getsid ( sess, &sid, &sidlen ), { free(ans); return __ret__; } );
+		CHECK_FCT_DO( fd_msg_avp_new ( sess_id_avp, 0, &avp ), { free(ans); return __ret__; } );
+		val.os.data = sid;
+		val.os.len  = sidlen;
+		CHECK_FCT_DO( fd_msg_avp_setvalue( avp, &val ), { free(avp); free(ans); return __ret__; } );
+		CHECK_FCT_DO( fd_msg_avp_add( ans, MSG_BRW_FIRST_CHILD, avp ), { free(avp); free(ans); return __ret__; } );
+		ans->msg_sess = sess;
+		CHECK_FCT_DO( fd_sess_ref_msg(sess), { free(ans); return __ret__; }  );
+	}
+	
+	/* Add all Proxy-Info AVPs from the query if any */
+	if (! (flags & MSGFL_ANSW_NOPROXYINFO)) {
+		struct avp * avp;
+		struct fd_pei pei;
+		struct fd_list avpcpylist = FD_LIST_INITIALIZER(avpcpylist);
+		
+		CHECK_FCT_DO(  fd_msg_browse(qry, MSG_BRW_FIRST_CHILD, &avp, NULL) , { free(ans); return __ret__; } );
+		while (avp) {
+			if ( (avp->avp_public.avp_code   == AC_PROXY_INFO)
+			  && (avp->avp_public.avp_vendor == 0) ) {
+				/* We found a Proxy-Info, need to duplicate it in the answer */
+
+				/* In order to avoid dealing with all different possibilities of states, we just create a buffer then parse it */
+				unsigned char * buf = NULL;
+				size_t offset = 0;
+
+				/* Create a buffer with the content of the AVP. This is easier than going through the list */
+				CHECK_FCT_DO(  fd_msg_update_length(avp), { free(ans); return __ret__; }  );
+				CHECK_MALLOC_DO(  buf = malloc(avp->avp_public.avp_len), { free(ans); return __ret__; }  );
+				CHECK_FCT_DO( bufferize_avp(buf, avp->avp_public.avp_len, &offset, avp), { free(buf); free(ans); return __ret__; }  );
+
+				/* Now we parse this buffer to create a copy AVP */
+				CHECK_FCT_DO( parsebuf_list(buf, avp->avp_public.avp_len, &avpcpylist), { free(buf); free(ans); return __ret__; } );
+				
+				/* Parse dictionary objects now to remove the dependency on the buffer */
+				CHECK_FCT_DO( parsedict_do_chain(dict, &avpcpylist, 0, &pei), { /* leaking the avpcpylist -- this should never happen anyway */ free(buf); free(ans); return __ret__; } );
+
+				/* Done for this AVP */
+				free(buf);
+
+				/* We move this AVP now so that we do not parse again in next loop */
+				fd_list_move_end(&ans->msg_chain.children, &avpcpylist);
+			}
+			/* move to next AVP in the message, we can have several Proxy-Info instances */
+			CHECK_FCT_DO( fd_msg_browse(avp, MSG_BRW_NEXT, &avp, NULL), { free(ans); return __ret__; } );
+		}
+	}
+
+	/* associate with query */
+	ans->msg_query = qry;
+	qry->msg_associated = 1;
+	
+	/* Done */
+	*msg = ans;
+	return 0;
+}
+
+/***************************************************************************************************************/
+
+/* Explore a message */
+int fd_msg_browse_internal ( msg_or_avp * reference, enum msg_brw_dir dir, msg_or_avp ** found, int * depth )
+{
+	struct msg_avp_chain *result = NULL;
+	int diff = 0;
+	struct fd_list *li = NULL;
+	
+	TRACE_ENTRY("%p %d %p %p", reference, dir, found, depth);
+	
+	/* Initialize the "found" result if any */
+	if (found)
+		*found = NULL;
+	
+	/* Check the parameters */
+	CHECK_PARAMS(  VALIDATE_OBJ(reference)  );
+	
+	TRACE_DEBUG(FCTS, "chaining(%p): nxt:%p prv:%p hea:%p top:%p", 
+			&_C(reference)->chaining,
+			_C(reference)->chaining.next,
+			_C(reference)->chaining.prev,
+			_C(reference)->chaining.head,
+			_C(reference)->chaining.o);
+	TRACE_DEBUG(FCTS, "children(%p): nxt:%p prv:%p hea:%p top:%p", 
+			&_C(reference)->children,
+			_C(reference)->children.next,
+			_C(reference)->children.prev,
+			_C(reference)->children.head,
+			_C(reference)->children.o);
+
+	/* Now search */
+	switch (dir) {
+		case MSG_BRW_NEXT:
+			/* Check the reference is an AVP */
+			CHECK_PARAMS(  _C(reference)->type == MSG_AVP  );
+
+			li = &_C(reference)->chaining;
+			
+			/* Check if the next element is not the sentinel ( ==> the parent) */
+			if (li->next != li->head)
+				result = _C(li->next->o);
+			break;
+
+		case MSG_BRW_PREV:
+			/* Check the reference is an AVP */
+			CHECK_PARAMS(  _C(reference)->type == MSG_AVP  );
+
+			li = &_C(reference)->chaining;
+			
+			/* Check if the prev element is not the sentinel ( ==> the parent) */
+			if (li->prev != li->head)
+				result = _C(li->prev->o);
+			break;
+
+		case MSG_BRW_FIRST_CHILD:
+			li = &_C(reference)->children;
+			if (! FD_IS_LIST_EMPTY(li)) {
+				result = _C(li->next->o);
+				diff = 1;
+			}
+			break;
+
+		case MSG_BRW_LAST_CHILD:
+			li = &_C(reference)->children;
+			if (! FD_IS_LIST_EMPTY(li)) {
+				result = _C(li->prev->o);
+				diff = 1;
+			}
+			break;
+
+		case MSG_BRW_PARENT:
+			/* If the object is not chained, it has no parent */
+			li = &_C(reference)->chaining;
+			if (li != li->head) {
+				/* The sentinel is the parent's children list */
+				result = _C(li->head->o);
+				diff = -1;
+			}
+			break;
+
+		case MSG_BRW_WALK:
+			/* First, try to find a child */
+			li = &_C(reference)->children;
+			if ( ! FD_IS_LIST_EMPTY(li) ) {
+				result = _C(li->next->o);
+				diff = 1;
+				break;
+			}
+			
+			/* Then try to find a "next" at this level or one of the parent's */
+			li = &_C(reference)->chaining;
+			do {
+				/* If this element has a "next" element, return it */
+				if (li->next != li->head) {
+					result = _C(li->next->o);
+					break;
+				}
+				/* otherwise, check if we have a parent */
+				if (li == li->head) {
+					/* no parent */
+					break;
+				}
+				/* Go to the parent's chaining information and loop */
+				diff -= 1;
+				li = &_C(li->head->o)->chaining;
+			} while (1); 
+			break;
+			
+		default:
+			/* Other directions are invalid */
+			CHECK_PARAMS( dir = 0 );
+	}
+	
+	/* Save the found object, if any */
+	if (found && result)
+		*found = (void *)result;
+	
+	/* Modify the depth according to the walk direction */
+	if (depth && diff)
+		(*depth) += diff;
+	
+	/* Return ENOENT if found was NULL */
+	if ((!found) && (!result))
+		return ENOENT;
+	else
+		return 0;
+}
+
+/* Add an AVP into a tree */
+int fd_msg_avp_add ( msg_or_avp * reference, enum msg_brw_dir dir, struct avp *avp)
+{
+	TRACE_ENTRY("%p %d %p", reference, dir, avp);
+	
+	/* Check the parameters */
+	CHECK_PARAMS(  VALIDATE_OBJ(reference)  &&  CHECK_AVP(avp)  &&  FD_IS_LIST_EMPTY(&avp->avp_chain.chaining)  );
+	
+	/* Now insert */
+	switch (dir) {
+		case MSG_BRW_NEXT:
+			/* Check the reference is an AVP -- we do not chain AVPs at same level as msgs. */
+			CHECK_PARAMS(  _C(reference)->type == MSG_AVP  );
+			
+			/* Insert the new avp after the reference */
+			fd_list_insert_after( &_A(reference)->avp_chain.chaining, &avp->avp_chain.chaining );
+			break;
+
+		case MSG_BRW_PREV:
+			/* Check the reference is an AVP */
+			CHECK_PARAMS(  _C(reference)->type == MSG_AVP  );
+			
+			/* Insert the new avp before the reference */
+			fd_list_insert_before( &_A(reference)->avp_chain.chaining, &avp->avp_chain.chaining );
+			break;
+
+		case MSG_BRW_FIRST_CHILD:
+			/* Insert the new avp after the children sentinel */
+			fd_list_insert_after( &_C(reference)->children, &avp->avp_chain.chaining );
+			break;
+
+		case MSG_BRW_LAST_CHILD:
+			/* Insert the new avp before the children sentinel */
+			fd_list_insert_before( &_C(reference)->children, &avp->avp_chain.chaining );
+			break;
+
+		default:
+			/* Other directions are invalid */
+			CHECK_PARAMS( dir = 0 );
+	}
+			
+	return 0;
+}
+
+/* Search a given AVP model in a message */
+int fd_msg_search_avp ( struct msg * msg, struct dict_object * what, struct avp ** avp )
+{
+	struct avp * nextavp;
+	struct dict_avp_data 	dictdata;
+	enum dict_object_type 	dicttype;
+	
+	TRACE_ENTRY("%p %p %p", msg, what, avp);
+	
+	CHECK_PARAMS( CHECK_MSG(msg) && what );
+	
+	CHECK_PARAMS( (fd_dict_gettype(what, &dicttype) == 0) && (dicttype == DICT_AVP) );
+	CHECK_FCT(  fd_dict_getval(what, &dictdata)  );
+	
+	/* Loop on all top AVPs */
+	CHECK_FCT(  fd_msg_browse(msg, MSG_BRW_FIRST_CHILD, (void *)&nextavp, NULL)  );
+	while (nextavp) {
+		
+		if ( (nextavp->avp_public.avp_code   == dictdata.avp_code)
+		  && (nextavp->avp_public.avp_vendor == dictdata.avp_vendor) ) /* always 0 if no V flag */
+			break;
+		
+		/* Otherwise move to next AVP in the message */
+		CHECK_FCT( fd_msg_browse(nextavp, MSG_BRW_NEXT, (void *)&nextavp, NULL) );
+	}
+	
+	if (avp)
+		*avp = nextavp;
+	
+	if (avp && nextavp) {
+		struct dictionary * dict;
+		CHECK_FCT( fd_dict_getdict( what, &dict) );
+		CHECK_FCT_DO( fd_msg_parse_dict( nextavp, dict, NULL ), /* nothing */ );
+	}
+	
+	if (avp || nextavp)
+		return 0;
+	else
+		return ENOENT;
+}
+
+
+/***************************************************************************************************************/
+/* Deleting objects */
+
+/* Destroy and free an AVP or message */
+static int destroy_obj (struct msg_avp_chain * obj )
+{
+	TRACE_ENTRY("%p", obj);
+	
+	/* Check the parameter is a valid object */
+	CHECK_PARAMS(  VALIDATE_OBJ(obj) && FD_IS_LIST_EMPTY( &obj->children ) );
+
+	/* Unlink this object if needed */
+	fd_list_unlink( &obj->chaining );
+	
+	/* Free the octetstring if needed */
+	if ((obj->type == MSG_AVP) && (_A(obj)->avp_mustfreeos == 1)) {
+		free(_A(obj)->avp_storage.os.data);
+	}
+	/* Free the rawdata if needed */
+	if ((obj->type == MSG_AVP) && (_A(obj)->avp_rawdata != NULL)) {
+		free(_A(obj)->avp_rawdata);
+	}
+	if ((obj->type == MSG_MSG) && (_M(obj)->msg_rawbuffer != NULL)) {
+		free(_M(obj)->msg_rawbuffer);
+	}
+	
+	if ((obj->type == MSG_MSG) && (_M(obj)->msg_src_id != NULL)) {
+		free(_M(obj)->msg_src_id);
+	}
+	
+	if ((obj->type == MSG_MSG) && (_M(obj)->msg_rtdata != NULL)) {
+		fd_rtd_free(&_M(obj)->msg_rtdata);
+	}
+	
+	if ((obj->type == MSG_MSG) && (_M(obj)->msg_sess != NULL)) {
+		CHECK_FCT_DO( fd_sess_reclaim_msg ( &_M(obj)->msg_sess ), /* continue */);
+	}
+	
+	if ((obj->type == MSG_MSG) && (_M(obj)->msg_pmdl.sentinel.o != NULL)) {
+		((void (*)(struct fd_msg_pmdl *))_M(obj)->msg_pmdl.sentinel.o)(&_M(obj)->msg_pmdl);
+	}
+	
+	/* free the object */
+	free(obj);
+	
+	return 0;
+}
+
+/* Destroy an object and all its children */
+static void destroy_tree(struct msg_avp_chain * obj)
+{
+	struct fd_list *rem;
+	
+	TRACE_ENTRY("%p", obj);
+	
+	/* Destroy any subtree */
+	while ( (rem = obj->children.next) != &obj->children)
+		destroy_tree(_C(rem->o));
+	
+	/* Then unlink and destroy the object */
+	CHECK_FCT_DO(  destroy_obj(obj),  /* nothing */  );
+}
+
+/* Free an object and its tree */
+int fd_msg_free ( msg_or_avp * object )
+{
+	TRACE_ENTRY("%p", object);
+	
+	if (object == NULL)
+		return 0;
+	
+	if (CHECK_MSG(object)) {
+		if (_M(object)->msg_query) {
+			_M(_M(object)->msg_query)->msg_associated = 0;
+			CHECK_FCT(  fd_msg_free( _M(object)->msg_query )  );
+			_M(object)->msg_query = NULL;
+		} else {
+			if (_M(object)->msg_associated) {
+				TRACE_DEBUG(INFO, "Not freeing query %p referenced in an answer (will be freed along the answer).", object);
+				return 0;
+			}
+		}
+	}
+	
+	destroy_tree(_C(object));
+	return 0;
+}
+
+
+/***************************************************************************************************************/
+/* Debug functions: dumping */
+
+/* messages and AVP formatters */
+typedef DECLARE_FD_DUMP_PROTOTYPE( (*msg_dump_formatter_msg), struct msg * msg );
+typedef DECLARE_FD_DUMP_PROTOTYPE( (*msg_dump_formatter_avp), struct avp * avp, int level, int first, int last );
+
+/* Core function to process the dumping */
+static DECLARE_FD_DUMP_PROTOTYPE( msg_dump_process, msg_dump_formatter_msg msg_format, msg_dump_formatter_avp avp_format, msg_or_avp *obj, struct dictionary *dict, int force_parsing, int recurse )
+{
+	FD_DUMP_HANDLE_OFFSET();
+		
+	if (!VALIDATE_OBJ(obj)) {
+		CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "INVALID MESSAGE OR AVP @%p", obj), return NULL);
+		return *buf;
+	}
+	
+	if (force_parsing) {
+		(void) fd_msg_parse_dict(obj, dict, NULL);
+	}
+	
+	switch (_C(obj)->type) {
+		case MSG_AVP:
+			CHECK_MALLOC_DO( (*avp_format)(FD_DUMP_STD_PARAMS, (struct avp *)obj, 0, 1, 1), return NULL);
+			break;
+
+		case MSG_MSG:
+			CHECK_MALLOC_DO( (*msg_format)(FD_DUMP_STD_PARAMS, (struct msg *)obj), return NULL);
+			break;
+
+		default:
+			ASSERT(0);
+			free(*buf);
+			*buf = NULL;
+			return NULL;
+	}
+		
+	if (recurse) {
+		struct avp * avp = NULL;
+		int first = 1;
+		CHECK_FCT_DO(  fd_msg_browse ( obj, MSG_BRW_FIRST_CHILD, &avp, NULL ), avp = NULL );
+		while (avp) {
+			struct avp * nextavp = NULL;
+			CHECK_FCT_DO(  fd_msg_browse ( avp, MSG_BRW_NEXT, &nextavp, NULL ), nextavp = NULL  );
+			CHECK_MALLOC_DO( (*avp_format)(FD_DUMP_STD_PARAMS, avp, 1, first, nextavp ? 0 : 1), return NULL);
+			avp = nextavp;
+			first = 0;
+		};
+	}
+	
+	return *buf;
+}
+
+/*
+ * Tree View message dump
+ */
+static DECLARE_FD_DUMP_PROTOTYPE( msg_format_treeview, struct msg * msg )
+{
+	if (!CHECK_MSG(msg)) {
+		CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "INVALID MESSAGE"), return NULL);
+		return *buf;
+	}
+	
+	if (!msg->msg_model) {
+		if (msg->msg_model_not_found.mnf_code) {
+			CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "(not found in dictionary)\n"), return NULL);
+		} else {
+			CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "(not searched in dictionary)\n"), return NULL);
+		}
+	} else {
+		enum dict_object_type dicttype;
+		struct dict_cmd_data  dictdata;
+		if (fd_dict_gettype(msg->msg_model, &dicttype) || (dicttype != DICT_COMMAND)) {
+			CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "(invalid model information)\n"), return NULL);
+		} else if (fd_dict_getval(msg->msg_model, &dictdata)) {
+			CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "(error getting model information)\n"), return NULL);
+		} else {
+			CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "'%s'\n", dictdata.cmd_name), return NULL);
+		}
+	}
+		
+	CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "  Version: 0x%02hhX\n", msg->msg_public.msg_version), return NULL);
+	CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "  Length: %d\n", msg->msg_public.msg_length), return NULL);
+	CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "  Flags: 0x%02hhX (" DUMP_CMDFL_str ")\n", msg->msg_public.msg_flags, DUMP_CMDFL_val(msg->msg_public.msg_flags)), return NULL);
+	CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "  Command Code: %u\n", msg->msg_public.msg_code), return NULL);
+	CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "  ApplicationId: %d\n", msg->msg_public.msg_appl), return NULL);
+	CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "  Hop-by-Hop Identifier: 0x%08X\n", msg->msg_public.msg_hbhid), return NULL);
+	CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "  End-to-End Identifier: 0x%08X\n", msg->msg_public.msg_eteid), return NULL);
+	CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "   {internal data}: src:%s(%zd) rwb:%p rt:%d cb:%p,%p(%p) qry:%p asso:%d sess:%p", msg->msg_src_id?:"(nil)", msg->msg_src_id_len, msg->msg_rawbuffer, msg->msg_routable, msg->msg_cb.anscb, msg->msg_cb.expirecb, msg->msg_cb.data, msg->msg_query, msg->msg_associated, msg->msg_sess), return NULL);
+	
+	return *buf;
+}
+
+static DECLARE_FD_DUMP_PROTOTYPE( avp_format_treeview, struct avp * avp, int level, int first, int last )
+{
+	char * name;
+	struct dict_avp_data  dictdata;
+	struct dict_avp_data *dictinfo = NULL;
+	struct dict_vendor_data  vendordata;
+	struct dict_vendor_data *vendorinfo = NULL;
+	
+	if (level) {
+		CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "\n"), return NULL);
+	}
+	
+	if (!CHECK_AVP(avp)) {
+		CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "INVALID AVP"), return NULL);
+		return *buf;
+	}
+	
+	if (level) {
+		CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "%*sAVP: ", level * 3, ""), return NULL);
+	}
+	
+	if (!avp->avp_model) {
+		if (avp->avp_model_not_found.mnf_code) {
+			name = "(not found in dictionary)";
+		} else {
+			name = "(not searched in dictionary)";
+		}
+	} else {
+		enum dict_object_type dicttype;
+		if (fd_dict_gettype(avp->avp_model, &dicttype) || (dicttype != DICT_AVP)) {
+			name = "(invalid model information)";
+		} else if (fd_dict_getval(avp->avp_model, &dictdata)) {
+			name = "(error getting model information)";
+		} else {
+			name = dictdata.avp_name;
+			dictinfo = &dictdata;
+			if (avp->avp_public.avp_flags & AVP_FLAG_VENDOR) {
+				struct dictionary * dict;
+				struct dict_object * vendor;
+				if ((!fd_dict_getdict(avp->avp_model, &dict))
+				&& (!fd_dict_search(dict, DICT_VENDOR, VENDOR_OF_AVP, avp->avp_model, &vendor, ENOENT))
+				&& (!fd_dict_getval(vendor, &vendordata))) {
+					vendorinfo = &vendordata;
+				}
+			}
+		}
+	}
+	
+	if (dictinfo) {
+		CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "'%s'(%u)", name, avp->avp_public.avp_code), return NULL);
+	} else {
+		CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "%u%s", avp->avp_public.avp_code, name), return NULL);
+	}
+	
+	if (avp->avp_public.avp_flags & AVP_FLAG_VENDOR) {
+		if (vendorinfo) {
+			CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, " vend='%s'(%u)", vendorinfo->vendor_name, avp->avp_public.avp_vendor), return NULL);
+		} else {
+			CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, " vend=%u", avp->avp_public.avp_vendor), return NULL);
+		}
+	}
+
+	CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, " l=%d f=" DUMP_AVPFL_str " val=", avp->avp_public.avp_len, DUMP_AVPFL_val(avp->avp_public.avp_flags)), return NULL);
+	
+	if (dictinfo && (dictinfo->avp_basetype == AVP_TYPE_GROUPED)) {
+		CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "(grouped)"), return NULL);
+		if (level) {
+			struct avp * inavp = NULL;
+			int first = 1;
+			CHECK_FCT_DO(  fd_msg_browse ( avp, MSG_BRW_FIRST_CHILD, &inavp, NULL ), inavp = NULL );
+			while (inavp) {
+				struct avp * nextavp = NULL;
+				CHECK_FCT_DO(  fd_msg_browse ( inavp, MSG_BRW_NEXT, &nextavp, NULL ), inavp = NULL  );
+				CHECK_MALLOC_DO( avp_format_treeview(FD_DUMP_STD_PARAMS, inavp, level + 1, first, nextavp ? 0 : 1), return NULL);
+				inavp = nextavp;
+				first = 0;
+			};
+		}
+	} else {
+		if (avp->avp_public.avp_value) {
+			CHECK_MALLOC_DO( fd_dict_dump_avp_value(FD_DUMP_STD_PARAMS, avp->avp_public.avp_value, avp->avp_model, 0, 0), return NULL);
+		} else if (avp->avp_rawdata) {
+			CHECK_MALLOC_DO( fd_dump_extend_hexdump(FD_DUMP_STD_PARAMS, avp->avp_rawdata, avp->avp_rawlen, 0, 0), return NULL);
+		} else {
+			CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "(not set)"), return NULL);
+		}
+	}
+
+	return *buf;
+}
+
+/* multi-line human-readable dump similar to wireshark output */
+DECLARE_FD_DUMP_PROTOTYPE( fd_msg_dump_treeview, msg_or_avp *obj, struct dictionary *dict, int force_parsing, int recurse )
+{
+	return msg_dump_process(FD_DUMP_STD_PARAMS, msg_format_treeview, avp_format_treeview, obj, dict, force_parsing, recurse);
+}
+
+
+/*
+ * One-line dumper for compact but complete traces
+ */
+static DECLARE_FD_DUMP_PROTOTYPE( msg_format_full, struct msg * msg )
+{
+	int success = 0;
+	struct dict_cmd_data dictdata;
+	
+	if (!CHECK_MSG(msg)) {
+		CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "INVALID MESSAGE"), return NULL);
+		return *buf;
+	}
+	
+	if (!msg->msg_model) {
+		CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "(no model) "), return NULL);
+	} else {
+		enum dict_object_type dicttype=0;
+		if (fd_dict_gettype(msg->msg_model, &dicttype) || (dicttype != DICT_COMMAND)) {
+			CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "(invalid model %d) ", dicttype), return NULL);
+		} else if (fd_dict_getval(msg->msg_model, &dictdata)) {
+			CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "(error getting model data) "), return NULL);
+		} else {
+			success = 1;
+		}
+	}
+	if (msg->msg_public.msg_appl) {
+		CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, 
+				   "%s(%u/%u)[" DUMP_CMDFL_str "], Length=%u, Hop-By-Hop-Id=0x%08x, End-to-End=0x%08x",
+					success ? dictdata.cmd_name :  "unknown",  msg->msg_public.msg_appl, msg->msg_public.msg_code, DUMP_CMDFL_val(msg->msg_public.msg_flags),
+					msg->msg_public.msg_length, msg->msg_public.msg_hbhid, msg->msg_public.msg_eteid), return NULL);
+	} else {
+		CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, 
+				   "%s(%u)[" DUMP_CMDFL_str "], Length=%u, Hop-By-Hop-Id=0x%08x, End-to-End=0x%08x",
+					success ? dictdata.cmd_name :  "unknown", msg->msg_public.msg_code, DUMP_CMDFL_val(msg->msg_public.msg_flags),
+					msg->msg_public.msg_length, msg->msg_public.msg_hbhid, msg->msg_public.msg_eteid), return NULL);
+	}
+	return *buf;
+}
+
+static DECLARE_FD_DUMP_PROTOTYPE( avp_format_full, struct avp * avp, int level, int first, int last )
+{
+	int success = 0;
+	struct dict_avp_data  dictdata;
+	
+	if (level) {
+		if ((first) && ((*buf)[*offset - 1] == '=')) {
+			/* We are first AVP of a grouped AVP */
+			CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "{ "), return NULL);
+		} else {
+			/* We follow another AVP, or a message header */
+			CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, ", { "), return NULL);
+		}
+	}
+	
+	if (!CHECK_AVP(avp)) {
+		CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "INVALID AVP"), return NULL);
+		goto end;
+	}
+	
+
+	if (avp->avp_model) {
+		enum dict_object_type dicttype;
+		if (fd_dict_gettype(avp->avp_model, &dicttype) || (dicttype != DICT_AVP)) {
+			CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "(invalid model: %d) ", dicttype), return NULL);
+		} else if (fd_dict_getval(avp->avp_model, &dictdata)) {
+			CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "(error getting model data) "), return NULL);
+		} else {
+			success = 1;
+		}
+	}
+	
+	if (avp->avp_public.avp_flags & AVP_FLAG_VENDOR) {
+		CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "%s(%u/%u)[" DUMP_AVPFL_str "]=", 
+					success ? dictdata.avp_name : "unknown", avp->avp_public.avp_vendor, avp->avp_public.avp_code, DUMP_AVPFL_val(avp->avp_public.avp_flags)), return NULL);
+	} else {
+		CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "%s(%u)[" DUMP_AVPFL_str "]=", 
+					success ? dictdata.avp_name : "unknown", avp->avp_public.avp_code, DUMP_AVPFL_val(avp->avp_public.avp_flags)), return NULL);
+	}
+
+		
+	if (success && (dictdata.avp_basetype == AVP_TYPE_GROUPED)) {
+		if (level) {
+			struct avp * inavp = NULL;
+			int first = 1;
+			CHECK_FCT_DO(  fd_msg_browse ( avp, MSG_BRW_FIRST_CHILD, &inavp, NULL ), inavp = NULL );
+			while (inavp) {
+				struct avp * nextavp = NULL;
+				CHECK_FCT_DO(  fd_msg_browse ( inavp, MSG_BRW_NEXT, &nextavp, NULL ), inavp = NULL  );
+				CHECK_MALLOC_DO( avp_format_full(FD_DUMP_STD_PARAMS, inavp, level + 1, first, nextavp ? 0 : 1), return NULL);
+				inavp = nextavp;
+				first = 0;
+			};
+		}
+	} else {
+		if (avp->avp_public.avp_value) {
+			CHECK_MALLOC_DO( fd_dict_dump_avp_value(FD_DUMP_STD_PARAMS, avp->avp_public.avp_value, avp->avp_model, 0, 0), return NULL);
+		} else if (avp->avp_rawdata) {
+			CHECK_MALLOC_DO( fd_dump_extend_hexdump(FD_DUMP_STD_PARAMS, avp->avp_rawdata, avp->avp_rawlen, 0, 0), return NULL);
+		} else {
+			CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "(not set)"), return NULL);
+		}
+	}
+	
+end:
+	if (level) {
+		CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, " }"), return NULL);
+	}
+	
+	return *buf;
+}
+
+/* one-line dump with all the contents of the message */
+DECLARE_FD_DUMP_PROTOTYPE( fd_msg_dump_full, msg_or_avp *obj, struct dictionary *dict, int force_parsing, int recurse )
+{
+	return msg_dump_process(FD_DUMP_STD_PARAMS, msg_format_full, avp_format_full, obj, dict, force_parsing, recurse);
+}
+
+
+
+/*
+ * One-line dumper for compact but complete traces
+ */
+static DECLARE_FD_DUMP_PROTOTYPE( msg_format_summary, struct msg * msg )
+{
+	if (!CHECK_MSG(msg)) {
+		CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "INVALID MESSAGE"), return NULL);
+		return *buf;
+	}
+	
+	if (!msg->msg_model) {
+		CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "(no model)"), return NULL);
+	} else {
+		enum dict_object_type dicttype;
+		struct dict_cmd_data  dictdata;
+		if (fd_dict_gettype(msg->msg_model, &dicttype) || (dicttype != DICT_COMMAND) || (fd_dict_getval(msg->msg_model, &dictdata))) {
+			CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "(model error)"), return NULL);
+		} else {
+			CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "'%s'", dictdata.cmd_name), return NULL);
+		}
+	}
+	CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "%u/%u f:" DUMP_CMDFL_str " src:'%s' len:%d", 
+				msg->msg_public.msg_appl, msg->msg_public.msg_code, DUMP_CMDFL_val(msg->msg_public.msg_flags), msg->msg_src_id?:"(nil)", msg->msg_public.msg_length), return NULL);
+
+	return *buf;
+}
+
+static DECLARE_FD_DUMP_PROTOTYPE( avp_format_summary, struct avp * avp, int level, int first, int last )
+{
+	char * name;
+	struct dict_avp_data  dictdata;
+	struct dict_avp_data *dictinfo = NULL;
+	struct dict_vendor_data  vendordata;
+	struct dict_vendor_data *vendorinfo = NULL;
+	
+	if (level) {
+		if (first) {
+			CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, " {"), return NULL);
+		} else {
+			CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, ","), return NULL);
+		}
+	}
+	
+	if (!CHECK_AVP(avp)) {
+		CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "INVALID AVP"), return NULL);
+		goto end;
+	}
+	
+	if (!level) {
+		/* We have been called to explicitely dump this AVP, so we parse its name if available */
+		if (!avp->avp_model) {
+			name = "(no model)";
+		} else {
+			enum dict_object_type dicttype;
+			if (fd_dict_gettype(avp->avp_model, &dicttype) || (dicttype != DICT_AVP) || (fd_dict_getval(avp->avp_model, &dictdata))) {
+				name = "(model error)";
+			} else {
+				name = dictdata.avp_name;
+				dictinfo = &dictdata;
+				if (avp->avp_public.avp_flags & AVP_FLAG_VENDOR) {
+					struct dictionary * dict;
+					struct dict_object * vendor;
+					if ((!fd_dict_getdict(avp->avp_model, &dict))
+					&& (!fd_dict_search(dict, DICT_VENDOR, VENDOR_OF_AVP, avp->avp_model, &vendor, ENOENT))
+					&& (!fd_dict_getval(vendor, &vendordata))) {
+						vendorinfo = &vendordata;
+					}
+				}
+			}
+		}
+
+		if (dictinfo) {
+			CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "'%s'(%u)", name, avp->avp_public.avp_code), return NULL);
+		} else {
+			CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "%u%s", avp->avp_public.avp_code, name), return NULL);
+		}
+
+		if (avp->avp_public.avp_flags & AVP_FLAG_VENDOR) {
+			if (vendorinfo) {
+				CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, " V='%s'(%u)", vendorinfo->vendor_name, avp->avp_public.avp_vendor), return NULL);
+			} else {
+				CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, " V=%u", avp->avp_public.avp_vendor), return NULL);
+			}
+		}
+
+		CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, " L=%d F=" DUMP_AVPFL_str " V=", avp->avp_public.avp_len, DUMP_AVPFL_val(avp->avp_public.avp_flags)), return NULL);
+
+		if ((!dictinfo) || (dictinfo->avp_basetype != AVP_TYPE_GROUPED)) {
+			if (avp->avp_public.avp_value) {
+				CHECK_MALLOC_DO( fd_dict_dump_avp_value(FD_DUMP_STD_PARAMS, avp->avp_public.avp_value, avp->avp_model, 0, 0), return NULL);
+			} else if (avp->avp_rawdata) {
+				CHECK_MALLOC_DO( fd_dump_extend_hexdump(FD_DUMP_STD_PARAMS, avp->avp_rawdata, avp->avp_rawlen, 0, 0), return NULL);
+			} else {
+				CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "(not set)"), return NULL);
+			}
+		}
+	} else {
+		/* For embedded AVPs, we only display (vendor,) code & length */
+		if (avp->avp_public.avp_flags & AVP_FLAG_VENDOR) {
+			CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "V:%u/", avp->avp_public.avp_vendor), return NULL);
+		}
+		CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "C:%u/l:%d", avp->avp_public.avp_code, avp->avp_public.avp_len), return NULL);
+	}
+	
+end:
+	if ((level) && (last)) {
+		CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "}"), return NULL);
+	}
+	
+	return *buf;
+}
+
+/* This one only prints a short display, does not go into the complete tree */
+DECLARE_FD_DUMP_PROTOTYPE( fd_msg_dump_summary, msg_or_avp *obj, struct dictionary *dict, int force_parsing, int recurse )
+{
+	return msg_dump_process(FD_DUMP_STD_PARAMS, msg_format_summary, avp_format_summary, obj, dict, force_parsing, recurse);
+}
+
+/***************************************************************************************************************/
+/* Simple meta-data management */
+
+/* Retrieve the model of an object */
+int fd_msg_model ( msg_or_avp * reference, struct dict_object ** model )
+{
+	TRACE_ENTRY("%p %p", reference, model);
+	
+	/* Check the parameters */
+	CHECK_PARAMS(  model && VALIDATE_OBJ(reference)  );
+	
+	/* copy the model reference */
+	switch (_C(reference)->type) {
+		case MSG_AVP:
+			*model = _A(reference)->avp_model;
+			break;
+		
+		case MSG_MSG:
+			*model = _M(reference)->msg_model;
+			break;
+		
+		default:
+			CHECK_PARAMS(0);
+	}
+	
+	return 0;
+}
+
+/* Retrieve the address of the msg_public field of a message */
+int fd_msg_hdr ( struct msg *msg, struct msg_hdr **pdata )
+{
+	TRACE_ENTRY("%p %p", msg, pdata);
+	CHECK_PARAMS(  CHECK_MSG(msg) && pdata  );
+	
+	*pdata = &msg->msg_public;
+	return 0;
+}
+
+/* Retrieve the address of the avp_public field of an avp */
+int fd_msg_avp_hdr ( struct avp *avp, struct avp_hdr **pdata )
+{
+	TRACE_ENTRY("%p %p", avp, pdata);
+	CHECK_PARAMS(  CHECK_AVP(avp) && pdata  );
+	
+	*pdata = &avp->avp_public;
+	return 0;
+}
+
+/* Associate answers and queries */
+int fd_msg_answ_associate( struct msg * answer, struct msg * query )
+{
+	TRACE_ENTRY( "%p %p", answer, query );
+	
+	CHECK_PARAMS(  CHECK_MSG(answer) && CHECK_MSG(query) && (answer->msg_query == NULL )  );
+	
+	answer->msg_query = query;
+	query->msg_associated = 1;
+	
+	return 0;
+}	
+
+int fd_msg_answ_getq( struct msg * answer, struct msg ** query )
+{
+	TRACE_ENTRY( "%p %p", answer, query );
+	
+	CHECK_PARAMS(  CHECK_MSG(answer) && query  );
+	
+	*query = answer->msg_query;
+	
+	return 0;
+}	
+
+int fd_msg_answ_detach( struct msg * answer )
+{
+	TRACE_ENTRY( "%p", answer );
+	
+	CHECK_PARAMS(  CHECK_MSG(answer) );
+	
+	answer->msg_query->msg_associated = 0;
+	answer->msg_query = NULL;
+	
+	return 0;
+}
+
+/* Associate / get answer callbacks */
+int fd_msg_anscb_associate( struct msg * msg, void ( *anscb)(void *, struct msg **), void  * data, void (*expirecb)(void *, DiamId_t, size_t, struct msg **), const struct timespec *timeout )
+{
+	TRACE_ENTRY("%p %p %p %p", msg, anscb, expirecb, data);
+	
+	/* Check the parameters */
+	CHECK_PARAMS( CHECK_MSG(msg) );
+	
+	if (! (msg->msg_public.msg_flags & CMD_FLAG_REQUEST ))
+		return anscb ? EINVAL : 0; /* we associate with requests only */
+	
+	CHECK_PARAMS( (anscb == NULL)    || (msg->msg_cb.anscb == NULL) ); /* We are not overwriting a cb */
+	CHECK_PARAMS( (expirecb == NULL) || (msg->msg_cb.expirecb == NULL) ); /* We are not overwriting a cb */
+	
+	/* Associate callback and data with the message, if any */
+	if (anscb) {
+		msg->msg_cb.anscb = anscb;
+		msg->msg_cb.data = data;
+	}
+	if (expirecb) {
+		msg->msg_cb.expirecb = expirecb;
+		if (timeout) {
+			memcpy(&msg->msg_cb.timeout, timeout, sizeof(struct timespec));
+		}
+	}
+	
+	return 0;
+}
+
+/* Remove a callback */
+int fd_msg_anscb_reset(struct msg * msg, int clear_anscb, int clear_expirecb) 
+{
+	TRACE_ENTRY("%p %d %d", msg, clear_anscb, clear_expirecb);
+	
+	/* Check the parameters */
+	CHECK_PARAMS( CHECK_MSG(msg) );
+	
+	if (clear_anscb) {
+		msg->msg_cb.anscb = NULL;
+		msg->msg_cb.data = NULL;
+	}
+	if (clear_expirecb) {
+		msg->msg_cb.expirecb = NULL;
+		memset(&msg->msg_cb.timeout, 0, sizeof(struct timespec));
+	}
+	
+	return 0;
+}
+
+
+int fd_msg_anscb_get( struct msg * msg, void (**anscb)(void *, struct msg **), void (**expirecb)(void *, DiamId_t, size_t, struct msg **), void ** data )
+{
+	TRACE_ENTRY("%p %p %p %p", msg, anscb, expirecb, data);
+	
+	/* Check the parameters */
+	CHECK_PARAMS( CHECK_MSG(msg) );
+	
+	/* Copy the result */
+	if (anscb)
+		*anscb = msg->msg_cb.anscb;
+	if (data)
+		*data  = msg->msg_cb.data;
+	if (expirecb)
+		*expirecb = msg->msg_cb.expirecb;
+	
+	return 0;
+}
+
+struct timespec *fd_msg_anscb_gettimeout( struct msg * msg )
+{
+	TRACE_ENTRY("%p", msg);
+	
+	/* Check the parameters */
+	CHECK_PARAMS_DO( CHECK_MSG(msg), return NULL );
+	
+	if (!msg->msg_cb.timeout.tv_sec) {
+		return NULL;
+	}
+	
+	return &msg->msg_cb.timeout;
+}
+
+/* Associate routing lists */
+int fd_msg_rt_associate( struct msg * msg, struct rt_data * rtd )
+{
+	TRACE_ENTRY( "%p %p", msg, rtd );
+	
+	CHECK_PARAMS(  CHECK_MSG(msg) && rtd  );
+	
+	msg->msg_rtdata = rtd;
+	
+	return 0;
+}
+
+int fd_msg_rt_get( struct msg * msg, struct rt_data ** rtd )
+{
+	TRACE_ENTRY( "%p %p", msg, rtd );
+	
+	CHECK_PARAMS(  CHECK_MSG(msg) && rtd  );
+	
+	*rtd = msg->msg_rtdata;
+	
+	return 0;
+}	
+
+/* Find if a message is routable */
+int fd_msg_is_routable ( struct msg * msg )
+{
+	TRACE_ENTRY("%p", msg);
+	
+	CHECK_PARAMS_DO(  CHECK_MSG(msg),  return 0 /* pretend the message is not routable */ );
+	
+	if ( ! msg->msg_routable ) {
+		/* To define if a message is routable, we rely on the "PXY" flag (for application 0). */
+		msg->msg_routable = ((msg->msg_public.msg_appl != 0) || (msg->msg_public.msg_flags & CMD_FLAG_PROXIABLE)) ? 1 : 2;
+		
+		/* Note : the 'real' criteria according to the Diameter I-D is that the message is 
+		 routable if and only if the "Destination-Realm" AVP is required by the command ABNF.
+		 We could make a test for this here, but it's more computational work and our test
+		 seems accurate (until proven otherwise...) */
+	}
+	
+	return (msg->msg_routable == 1) ? 1 : 0;
+}
+
+/* cache the dictionary model for next function to avoid re-searching at every incoming message */
+static struct dict_object *cached_avp_rr_model = NULL;
+static struct dictionary  *cached_avp_rr_dict  = NULL;
+static pthread_mutex_t     cached_avp_rr_lock = PTHREAD_MUTEX_INITIALIZER;
+
+/* Associate source peer */
+int fd_msg_source_set( struct msg * msg, DiamId_t diamid, size_t diamidlen )
+{
+	TRACE_ENTRY( "%p %p %zd", msg, diamid, diamidlen);
+	
+	/* Check we received a valid message */
+	CHECK_PARAMS( CHECK_MSG(msg) );
+	
+	/* Cleanup any previous source */
+	free(msg->msg_src_id); msg->msg_src_id = NULL; msg->msg_src_id_len = 0;
+	
+	/* If the request is to cleanup the source, we are done */
+	if (diamid == NULL) {
+		return 0;
+	}
+	
+	/* Otherwise save the new informations */
+	CHECK_MALLOC( msg->msg_src_id = os0dup(diamid, diamidlen) );
+	msg->msg_src_id_len = diamidlen;
+	/* done */
+	return 0;
+}
+
+/* Associate source peer */
+int fd_msg_source_setrr( struct msg * msg, DiamId_t diamid, size_t diamidlen, struct dictionary * dict )
+{
+	struct dict_object 	*avp_rr_model = NULL;
+	avp_code_t 		 code = AC_ROUTE_RECORD;
+	struct avp 		*avp;
+	union avp_value		 val;
+
+	TRACE_ENTRY( "%p %p %zd %p", msg, diamid, diamidlen, dict);
+	
+	/* Check we received a valid message */
+	CHECK_PARAMS( CHECK_MSG(msg) && dict );
+	
+	/* Lock the cached values */
+	CHECK_POSIX( pthread_mutex_lock(&cached_avp_rr_lock) );
+	if (cached_avp_rr_dict == dict) {
+		avp_rr_model = cached_avp_rr_model;
+	}
+	CHECK_POSIX( pthread_mutex_unlock(&cached_avp_rr_lock) );
+
+	/* If it was not cached */
+	if (!avp_rr_model) {
+		/* Find the model for Route-Record in the dictionary */
+		CHECK_FCT( fd_dict_search ( dict, DICT_AVP, AVP_BY_CODE, &code, &avp_rr_model, ENOENT) );
+
+		/* Now cache this result */
+		CHECK_POSIX( pthread_mutex_lock(&cached_avp_rr_lock) );
+		cached_avp_rr_dict  = dict;
+		cached_avp_rr_model = avp_rr_model;
+		CHECK_POSIX( pthread_mutex_unlock(&cached_avp_rr_lock) );
+	}
+
+	/* Create the AVP with this model */
+	CHECK_FCT( fd_msg_avp_new ( avp_rr_model, 0, &avp ) );
+
+	/* Set the AVP value with the diameter id */
+	memset(&val, 0, sizeof(val));
+	val.os.data = (uint8_t *)diamid;
+	val.os.len  = diamidlen;
+	CHECK_FCT( fd_msg_avp_setvalue( avp, &val ) );
+
+	/* Add the AVP in the message */
+	CHECK_FCT( fd_msg_avp_add( msg, MSG_BRW_LAST_CHILD, avp ) );
+	
+	/* done */
+	return 0;
+}
+
+int fd_msg_source_get( struct msg * msg, DiamId_t* diamid, size_t * diamidlen )
+{
+	TRACE_ENTRY( "%p %p %p", msg, diamid, diamidlen);
+	
+	/* Check we received valid parameters */
+	CHECK_PARAMS( CHECK_MSG(msg) );
+	CHECK_PARAMS( diamid );
+	
+	/* Copy the informations */
+	*diamid = msg->msg_src_id;
+	
+	if (diamidlen)
+		*diamidlen = msg->msg_src_id_len;
+	
+	/* done */
+	return 0;
+}
+
+/* Associate a session with a message, use only when the session was just created */
+int fd_msg_sess_set(struct msg * msg, struct session * session)
+{
+	TRACE_ENTRY("%p %p", msg, session);
+	
+	/* Check we received valid parameters */
+	CHECK_PARAMS( CHECK_MSG(msg) );
+	CHECK_PARAMS( session );
+	CHECK_PARAMS( msg->msg_sess == NULL );
+	
+	msg->msg_sess = session;
+	return 0;
+}
+
+
+/* Retrieve the session of the message */
+int fd_msg_sess_get(struct dictionary * dict, struct msg * msg, struct session ** session, int * new)
+{
+	struct avp * avp;
+	
+	TRACE_ENTRY("%p %p %p", msg, session, new);
+	
+	/* Check we received valid parameters */
+	CHECK_PARAMS( CHECK_MSG(msg) );
+	CHECK_PARAMS( session );
+	
+	/* If we already resolved the session, just send it back */
+	if (msg->msg_sess) {
+		*session = msg->msg_sess;
+		if (new)
+			*new = 0;
+		return 0;
+	}
+	
+	/* OK, we have to search for Session-Id AVP -- it is usually the first AVP, but let's be permissive here */
+	/* -- note: we accept messages that have not yet been dictionary parsed... */
+	CHECK_FCT(  fd_msg_browse(msg, MSG_BRW_FIRST_CHILD, &avp, NULL)  );
+	while (avp) {
+		if ( (avp->avp_public.avp_code   == AC_SESSION_ID)
+		  && (avp->avp_public.avp_vendor == 0) )
+			break;
+		
+		/* Otherwise move to next AVP in the message */
+		CHECK_FCT( fd_msg_browse(avp, MSG_BRW_NEXT, &avp, NULL) );
+	}
+	
+	if (!avp) {
+		TRACE_DEBUG(FULL, "No Session-Id AVP found in message %p", msg);
+		*session = NULL;
+		return 0;
+	}
+	
+	if (!avp->avp_model) {
+		CHECK_FCT( fd_msg_parse_dict ( avp, dict, NULL ) );
+	}
+	
+	ASSERT( avp->avp_public.avp_value );
+	
+	/* Resolve the session and we are done */
+	if (avp->avp_public.avp_value->os.len > 0) {
+		CHECK_FCT( fd_sess_fromsid_msg ( avp->avp_public.avp_value->os.data, avp->avp_public.avp_value->os.len, &msg->msg_sess, new) );
+		*session = msg->msg_sess;
+	} else {
+		TRACE_DEBUG(FULL, "Session-Id AVP with 0-byte length found in message %p", msg);
+		*session = NULL;
+	}
+	
+	return 0;
+}
+
+/* Retrieve the location of the pmd list for the message; return NULL if failed */
+struct fd_msg_pmdl * fd_msg_pmdl_get(struct msg * msg)
+{
+	CHECK_PARAMS_DO( CHECK_MSG(msg), return NULL );
+	return &msg->msg_pmdl;
+}
+
+
+/******************* End-to-end counter *********************/
+static uint32_t fd_eteid;
+static pthread_mutex_t fd_eteid_lck = PTHREAD_MUTEX_INITIALIZER;
+
+void fd_msg_eteid_init(void)
+{
+	uint32_t t = (uint32_t)time(NULL);
+	srand48(t);
+	fd_eteid = (t << 20) | ((uint32_t)lrand48() & ( (1 << 20) - 1 ));
+}
+
+uint32_t fd_msg_eteid_get ( void )
+{
+	uint32_t ret;
+	
+	CHECK_POSIX_DO( pthread_mutex_lock(&fd_eteid_lck), /* continue */ );
+	
+	ret = fd_eteid ++;
+	
+	CHECK_POSIX_DO( pthread_mutex_unlock(&fd_eteid_lck), /* continue */ );
+	
+	return ret;
+}
+
+/***************************************************************************************************************/
+/* Manage AVPs values */
+
+/* Set the value of an AVP */
+int fd_msg_avp_setvalue ( struct avp *avp, union avp_value *value )
+{
+	enum dict_avp_basetype type = -1;
+	
+	TRACE_ENTRY("%p %p", avp, value);
+	
+	/* Check parameter */
+	CHECK_PARAMS(  CHECK_AVP(avp) && avp->avp_model  );
+	
+	/* Retrieve information from the AVP model */
+	{
+		enum dict_object_type dicttype;
+		struct dict_avp_data  dictdata;
+		
+		CHECK_PARAMS( (fd_dict_gettype(avp->avp_model, &dicttype) == 0) && (dicttype == DICT_AVP) );
+		CHECK_FCT(  fd_dict_getval(avp->avp_model, &dictdata)  );
+		type = dictdata.avp_basetype;
+		CHECK_PARAMS(  type != AVP_TYPE_GROUPED  );
+	}
+	
+	/* First, clean any previous value */
+	if (avp->avp_mustfreeos != 0) {
+		free(avp->avp_storage.os.data);
+		avp->avp_mustfreeos = 0;
+	}
+	
+	memset(&avp->avp_storage, 0, sizeof(union avp_value));
+	
+	/* If the request was to delete a value: */
+	if (!value) {
+		avp->avp_public.avp_value = NULL;
+		return 0;
+	}
+	
+	/* Now we have to set the value */
+	memcpy(&avp->avp_storage, value, sizeof(union avp_value));
+	
+	/* Duplicate an octetstring if needed. */
+	if (type == AVP_TYPE_OCTETSTRING) {
+		CHECK_MALLOC(  avp->avp_storage.os.data = os0dup(value->os.data, value->os.len)  );
+		avp->avp_mustfreeos = 1;
+	}
+	
+	/* Set the data pointer of the public part */
+	avp->avp_public.avp_value = &avp->avp_storage;
+	
+	return 0;		
+}
+
+/* Set the value of an AVP, using formatted data */
+int fd_msg_avp_value_encode ( void *data, struct avp *avp )
+{
+	enum dict_avp_basetype type = -1;
+	struct dict_type_data type_data;
+	
+	TRACE_ENTRY("%p %p", data, avp);
+	
+	/* Check parameter */
+	CHECK_PARAMS(  CHECK_AVP(avp) && avp->avp_model  );
+	
+	/* Retrieve information from the AVP model and it's parent type */
+	{
+		enum dict_object_type dicttype;
+		struct dict_avp_data  dictdata;
+		struct dictionary   * dict;
+		struct dict_object  * parenttype = NULL;
+		
+		/* First check the base type of the AVP */
+		CHECK_PARAMS( (fd_dict_gettype(avp->avp_model, &dicttype) == 0) && (dicttype == DICT_AVP) );
+		CHECK_FCT(  fd_dict_getval(avp->avp_model, &dictdata)  );
+		type = dictdata.avp_basetype;
+		CHECK_PARAMS(  type != AVP_TYPE_GROUPED  );
+		
+		/* Then retrieve information about the parent's type (= derived type) */
+		CHECK_FCT(  fd_dict_getdict( avp->avp_model, &dict )  );
+		CHECK_FCT(  fd_dict_search( dict, DICT_TYPE, TYPE_OF_AVP, avp->avp_model, &parenttype, EINVAL)  );
+		CHECK_FCT(  fd_dict_getval(parenttype, &type_data)  );
+		if (type_data.type_encode == NULL) {
+			TRACE_DEBUG(INFO, "This AVP type does not provide a callback to encode formatted data. ENOTSUP.");
+			return ENOTSUP;
+		}
+	}
+	
+	/* Ok, now we can encode the value */
+	
+	/* First, clean any previous value */
+	if (avp->avp_mustfreeos != 0) {
+		free(avp->avp_storage.os.data);
+		avp->avp_mustfreeos = 0;
+	}
+	avp->avp_public.avp_value = NULL;
+	memset(&avp->avp_storage, 0, sizeof(union avp_value));
+	
+	/* Now call the type's callback to encode the data */
+	CHECK_FCT(  (*type_data.type_encode)(data, &avp->avp_storage)  );
+	
+	/* If an octetstring has been allocated, let's mark it to be freed */
+	if (type == AVP_TYPE_OCTETSTRING)
+		avp->avp_mustfreeos = 1;
+	
+	/* Set the data pointer of the public part */
+	avp->avp_public.avp_value = &avp->avp_storage;
+	
+	return 0;		
+}
+
+/* Interpret the value of an AVP into formatted data */
+int fd_msg_avp_value_interpret ( struct avp *avp, void *data )
+{
+	struct dict_type_data type_data;
+	
+	TRACE_ENTRY("%p %p", avp, data);
+	
+	/* Check parameter */
+	CHECK_PARAMS(  CHECK_AVP(avp) && avp->avp_model && avp->avp_public.avp_value  );
+	
+	/* Retrieve information about the AVP parent type */
+	{
+		struct dictionary   * dict;
+		struct dict_object  * parenttype = NULL;
+		
+		CHECK_FCT(  fd_dict_getdict( avp->avp_model, &dict )  );
+		CHECK_FCT(  fd_dict_search( dict, DICT_TYPE, TYPE_OF_AVP, avp->avp_model, &parenttype, EINVAL)  );
+		CHECK_FCT(  fd_dict_getval(parenttype, &type_data)  );
+		if (type_data.type_interpret == NULL) {
+			TRACE_DEBUG(INFO, "This AVP type does not provide a callback to interpret value in formatted data. ENOTSUP.");
+			return ENOTSUP;
+		}
+	}
+	
+	/* Ok, now we can interpret the value */
+	
+	CHECK_FCT(  (*type_data.type_interpret)(avp->avp_public.avp_value, data)  );
+	
+	return 0;		
+}
+
+/***************************************************************************************************************/
+/* Creating a buffer from memory objects (bufferize a struct msg) */
+
+/* Following macros are used to store 32 and 64 bit fields into a buffer in network byte order */
+#define PUT_in_buf_32( _u32data, _bufptr ) {							\
+	*(uint32_t *)(_bufptr) = htonl((uint32_t)(_u32data));					\
+}
+
+/* The location is not on 64b boundary, so we split the writing in two operations to avoid sigbus */
+#define PUT_in_buf_64( _u64data, _bufptr ) {							\
+	uint64_t __v = htonll((uint64_t)(_u64data));						\
+	memcpy(_bufptr, &__v, sizeof(__v));							\
+}
+
+/* Write a message header in the buffer */
+static int bufferize_msg(unsigned char * buffer, size_t buflen, size_t * offset, struct msg * msg)
+{
+	TRACE_ENTRY("%p %zd %p %p", buffer, buflen, offset, msg);
+	
+	if ((buflen - *offset) < GETMSGHDRSZ())
+		return ENOSPC;
+	
+	if (*offset & 0x3)
+		return EFAULT;	/* We are supposed to start on 32 bit boundaries */
+	
+	PUT_in_buf_32(msg->msg_public.msg_length, buffer + *offset);
+	buffer[*offset] = msg->msg_public.msg_version;
+	*offset += 4;
+	
+	PUT_in_buf_32(msg->msg_public.msg_code, buffer + *offset);
+	buffer[*offset] = msg->msg_public.msg_flags;
+	*offset += 4;
+	
+	PUT_in_buf_32(msg->msg_public.msg_appl, buffer + *offset);
+	*offset += 4;
+	
+	PUT_in_buf_32(msg->msg_public.msg_hbhid, buffer + *offset);
+	*offset += 4;
+	
+	PUT_in_buf_32(msg->msg_public.msg_eteid, buffer + *offset);
+	*offset += 4;
+	
+	return 0;
+}
+
+static int bufferize_chain(unsigned char * buffer, size_t buflen, size_t * offset, struct fd_list * list);
+
+/* Write an AVP in the buffer */
+static int bufferize_avp(unsigned char * buffer, size_t buflen, size_t * offset,  struct avp * avp)
+{
+	struct dict_avp_data dictdata;
+	
+	TRACE_ENTRY("%p %zd %p %p", buffer, buflen, offset, avp);
+	
+	if ((buflen - *offset) < avp->avp_public.avp_len)
+		return ENOSPC;
+	
+	/* Write the header */
+	PUT_in_buf_32(avp->avp_public.avp_code, buffer + *offset);
+	*offset += 4;
+	
+	PUT_in_buf_32(avp->avp_public.avp_len, buffer + *offset);
+	buffer[*offset] = avp->avp_public.avp_flags;
+	*offset += 4;
+	
+	if (avp->avp_public.avp_flags & AVP_FLAG_VENDOR) {
+		PUT_in_buf_32(avp->avp_public.avp_vendor, buffer + *offset);
+		*offset += 4;
+	}
+	
+	/* Then we must write the AVP value */
+	
+	if (avp->avp_model == NULL) {
+		/* In the case where we don't know the type of AVP, just copy the raw data or source */
+		CHECK_PARAMS( avp->avp_source || avp->avp_rawdata );
+		
+		if ( avp->avp_rawdata != NULL ) {
+			/* the content was stored in rawdata */
+			memcpy(&buffer[*offset], avp->avp_rawdata, avp->avp_rawlen);
+			*offset += PAD4(avp->avp_rawlen);
+		} else {
+			/* the message was not parsed completely */
+			size_t datalen = avp->avp_public.avp_len - GETAVPHDRSZ(avp->avp_public.avp_flags);
+			memcpy(&buffer[*offset], avp->avp_source, datalen);
+			*offset += PAD4(datalen);
+		}
+		
+	} else {
+		/* The AVP is defined in the dictionary */
+		CHECK_FCT(  fd_dict_getval(avp->avp_model, &dictdata)  );
+
+		CHECK_PARAMS( ( dictdata.avp_basetype == AVP_TYPE_GROUPED ) || avp->avp_public.avp_value );
+		
+		switch (dictdata.avp_basetype) {
+			case AVP_TYPE_GROUPED:
+				return bufferize_chain(buffer, buflen, offset, &avp->avp_chain.children);
+
+			case AVP_TYPE_OCTETSTRING:
+				if (avp->avp_public.avp_value->os.len)
+					memcpy(&buffer[*offset], avp->avp_public.avp_value->os.data, avp->avp_public.avp_value->os.len);
+				*offset += PAD4(avp->avp_public.avp_value->os.len);
+				break;
+
+			case AVP_TYPE_INTEGER32:
+				PUT_in_buf_32(avp->avp_public.avp_value->i32, buffer + *offset);
+				*offset += 4;
+				break;
+
+			case AVP_TYPE_INTEGER64:
+				PUT_in_buf_64(avp->avp_public.avp_value->i64, buffer + *offset);
+				*offset += 8;
+				break;
+
+			case AVP_TYPE_UNSIGNED32:
+				PUT_in_buf_32(avp->avp_public.avp_value->u32, buffer + *offset);
+				*offset += 4;
+				break;
+
+			case AVP_TYPE_UNSIGNED64:
+				PUT_in_buf_64(avp->avp_public.avp_value->u64, buffer + *offset);
+				*offset += 8;
+				break;
+
+			case AVP_TYPE_FLOAT32:
+				/* We read the f32 as "u32" here to avoid casting to uint make decimals go away. 
+				 The alternative would be something like "*(uint32_t *)(& f32)" but
+				 then the compiler complains about strict-aliasing rules. */
+				PUT_in_buf_32(avp->avp_public.avp_value->u32, buffer + *offset);
+				*offset += 4;
+				break;
+
+			case AVP_TYPE_FLOAT64:
+				/* Same remark as previously */
+				PUT_in_buf_64(avp->avp_public.avp_value->u64, buffer + *offset);
+				*offset += 8;
+				break;
+
+			default:
+				ASSERT(0);
+		}
+	}
+	return 0;
+}
+			
+/* Write a chain of AVPs in the buffer */
+static int bufferize_chain(unsigned char * buffer, size_t buflen, size_t * offset, struct fd_list * list)
+{
+	struct fd_list * avpch;
+	
+	TRACE_ENTRY("%p %zd %p %p", buffer, buflen, offset, list);
+	
+	for (avpch = list->next; avpch != list; avpch = avpch->next) {
+		/* Bufferize the AVP */
+		CHECK_FCT( bufferize_avp(buffer, buflen, offset, _A(avpch->o))  );
+	}
+	return 0;
+}
+
+/* Create the message buffer, in network-byte order. We browse the tree twice, this could be probably improved if needed */
+int fd_msg_bufferize ( struct msg * msg, unsigned char ** buffer, size_t * len )
+{
+	int ret = 0;
+	unsigned char * buf = NULL;
+	size_t offset = 0;
+	
+	TRACE_ENTRY("%p %p %p", msg, buffer, len);
+	
+	/* Check the parameters */
+	CHECK_PARAMS(  buffer && CHECK_MSG(msg)  );
+	
+	/* Update the length. This also checks that all AVP have their values set */
+	CHECK_FCT(  fd_msg_update_length(msg)  );
+	
+	/* Now allocate a buffer to store the message */
+	CHECK_MALLOC(  buf = malloc(msg->msg_public.msg_length)  );
+	
+	/* Clear the memory, so that the padding is always 0 (should not matter) */
+	memset(buf, 0, msg->msg_public.msg_length);
+	
+	/* Write the message header in the buffer */
+	CHECK_FCT_DO( ret = bufferize_msg(buf, msg->msg_public.msg_length, &offset, msg), 
+		{
+			free(buf);
+			return ret;
+		}  );
+	
+	/* Write the list of AVPs */
+	CHECK_FCT_DO( ret = bufferize_chain(buf, msg->msg_public.msg_length, &offset, &msg->msg_chain.children),
+		{
+			free(buf);
+			return ret;
+		}  );
+	
+	ASSERT(offset == msg->msg_public.msg_length); /* or the msg_update_length is buggy */
+		
+	if (len) {
+		*len = offset;
+	}
+	
+	*buffer = buf;
+	return 0;
+}
+
+
+/***************************************************************************************************************/
+/* Parsing buffers and building AVP objects lists (not parsing the AVP values which requires dictionary knowledge) */
+
+/* Parse a buffer containing a supposed list of AVPs */
+static int parsebuf_list(unsigned char * buf, size_t buflen, struct fd_list * head)
+{
+	size_t offset = 0;
+	
+	TRACE_ENTRY("%p %zd %p", buf, buflen, head);
+	
+	while (offset < buflen) {
+		struct avp * avp;
+		
+		if (buflen - offset < AVPHDRSZ_NOVEND) {
+			TRACE_DEBUG(INFO, "truncated buffer: remaining only %zd bytes", buflen - offset);
+			return EBADMSG;
+		}
+		
+		/* Create a new AVP object */
+		CHECK_MALLOC(  avp = malloc (sizeof(struct avp))  );
+		
+		init_avp(avp);
+		
+		/* Initialize the header */
+		avp->avp_public.avp_code    = ntohl(*(uint32_t *)(buf + offset));
+		avp->avp_public.avp_flags   = buf[offset + 4];
+		avp->avp_public.avp_len     = ((uint32_t)buf[offset+5]) << 16 |  ((uint32_t)buf[offset+6]) << 8 |  ((uint32_t)buf[offset+7]) ;
+		
+		offset += 8;
+		
+		if (avp->avp_public.avp_flags & AVP_FLAG_VENDOR) {
+			if (buflen - offset < 4) {
+				TRACE_DEBUG(INFO, "truncated buffer: remaining only %zd bytes for vendor and data", buflen - offset);
+				free(avp);
+				return EBADMSG;
+			}
+			avp->avp_public.avp_vendor  = ntohl(*(uint32_t *)(buf + offset));
+			offset += 4;
+		}
+		
+		/* Check there is enough remaining data in the buffer */
+		if ( (avp->avp_public.avp_len > GETAVPHDRSZ(avp->avp_public.avp_flags))
+		&& (buflen - offset < avp->avp_public.avp_len - GETAVPHDRSZ(avp->avp_public.avp_flags))) {
+			TRACE_DEBUG(INFO, "truncated buffer: remaining only %zd bytes for data, and avp data size is %d", 
+					buflen - offset, 
+					avp->avp_public.avp_len - GETAVPHDRSZ(avp->avp_public.avp_flags));
+			free(avp);
+			return EBADMSG;
+		}
+		
+		/* buf[offset] is now the beginning of the data */
+		avp->avp_source = &buf[offset];
+		
+		/* Now eat the data and eventual padding */
+		offset += PAD4(avp->avp_public.avp_len - GETAVPHDRSZ(avp->avp_public.avp_flags));
+		
+		/* And insert this avp in the list, at the end */
+		fd_list_insert_before( head, &avp->avp_chain.chaining );
+	}
+	
+	return 0;
+}
+
+/* Create a message object from a buffer. Dictionary objects are not resolved, AVP contents are not interpreted, buffer is saved in msg */
+int fd_msg_parse_buffer ( unsigned char ** buffer, size_t buflen, struct msg ** msg )
+{
+	struct msg * new = NULL;
+	int ret = 0;
+	uint32_t msglen = 0;
+	unsigned char * buf;
+	
+	TRACE_ENTRY("%p %zd %p", buffer, buflen, msg);
+	
+	CHECK_PARAMS(  buffer &&  *buffer  &&  msg  &&  (buflen >= GETMSGHDRSZ())  );
+	buf = *buffer;
+	
+	if ( buf[0] != DIAMETER_VERSION) {
+		TRACE_DEBUG(INFO, "Invalid version in message: %d (supported: %d)", buf[0], DIAMETER_VERSION);
+		return EBADMSG;
+	}
+	
+	msglen = ntohl(*(uint32_t *)buf) & 0x00ffffff;
+	if ( buflen < msglen ) {  
+		TRACE_DEBUG(INFO, "Truncated message (%zd / %d)", buflen, msglen );
+		return EBADMSG; 
+	}
+	
+	/* Create a new object */
+	CHECK_MALLOC( new = malloc (sizeof(struct msg)) );
+	
+	/* Initialize the fields */
+	init_msg(new);
+	
+	/* Now read from the buffer */
+	new->msg_public.msg_version = buf[0];
+	new->msg_public.msg_length = msglen;
+
+	new->msg_public.msg_flags = buf[4];
+	new->msg_public.msg_code = ntohl(*(uint32_t *)(buf+4)) & 0x00ffffff;
+	
+	new->msg_public.msg_appl = ntohl(*(uint32_t *)(buf+8));
+	new->msg_public.msg_hbhid = ntohl(*(uint32_t *)(buf+12));
+	new->msg_public.msg_eteid = ntohl(*(uint32_t *)(buf+16));
+	
+	/* Parse the AVP list */
+	CHECK_FCT_DO( ret = parsebuf_list(buf + GETMSGHDRSZ(), buflen - GETMSGHDRSZ(), &new->msg_chain.children), { destroy_tree(_C(new)); return ret; }  );
+	
+	/* Parsing successful */
+	new->msg_rawbuffer = buf;
+	*buffer = NULL;
+	*msg = new;
+	return 0;
+}
+
+		
+/***************************************************************************************************************/
+/* Parsing messages and AVP with dictionary information */
+
+/* Resolve dictionary objects of the cmd and avp instances, from their headers.
+ * When the model is found, the data is interpreted from the avp_source buffer and copied to avp_storage.
+ * When the model is not found, the data is copied as rawdata and saved (in case we FW the message).
+ * Therefore, after this function has been called, the source buffer can be freed.
+ * For command, if the dictionary model is not found, an error is returned.
+ */
+
+static char error_message[256];
+
+/* Process an AVP. If we are not in recheck, the avp_source must be set. */
+static int parsedict_do_avp(struct dictionary * dict, struct avp * avp, int mandatory, struct fd_pei *error_info)
+{
+	struct dict_avp_data dictdata;
+	struct dict_type_data derivedtypedata;
+	struct dict_object * avp_derived_type = NULL;
+	uint8_t * source;
+	
+	TRACE_ENTRY("%p %p %d %p", dict, avp, mandatory, error_info);
+	
+	/* First check we received an AVP as input */
+	CHECK_PARAMS(  CHECK_AVP(avp) );
+	
+	if (avp->avp_model != NULL) {
+		/* the model has already been resolved. we do check it is still valid */
+
+		CHECK_FCT(  fd_dict_getval(avp->avp_model, &dictdata)  );
+
+		if ( avp->avp_public.avp_code == dictdata.avp_code  ) {
+			/* Ok then just process the children if any */
+			return parsedict_do_chain(dict, &avp->avp_chain.children, mandatory && (avp->avp_public.avp_flags & AVP_FLAG_MANDATORY), error_info);
+		} else {
+			/* We just erase the old model */
+			avp->avp_model = NULL;
+		}
+	}
+	
+	/* Check if we already searched for this model without success */
+	if ((avp->avp_model_not_found.mnf_code != avp->avp_public.avp_code)
+	||  (avp->avp_model_not_found.mnf_vendor != avp->avp_public.avp_vendor)) {
+	
+		/* Now try and resolve the model from the avp code and vendor */
+		if (avp->avp_public.avp_flags & AVP_FLAG_VENDOR) {
+			struct dict_avp_request_ex avpreq;
+			memset(&avpreq, 0, sizeof(avpreq));
+			avpreq.avp_vendor.vendor_id = avp->avp_public.avp_vendor;
+			avpreq.avp_data.avp_code = avp->avp_public.avp_code;
+			CHECK_FCT( fd_dict_search ( dict, DICT_AVP, AVP_BY_STRUCT, &avpreq, &avp->avp_model, 0));
+		} else {
+			/* no vendor */
+			CHECK_FCT( fd_dict_search ( dict, DICT_AVP, AVP_BY_CODE, &avp->avp_public.avp_code, &avp->avp_model, 0));
+		}
+		
+		if (!avp->avp_model) {
+			avp->avp_model_not_found.mnf_code = avp->avp_public.avp_code;
+			avp->avp_model_not_found.mnf_vendor = avp->avp_public.avp_vendor;
+		}
+	}
+	
+	/* First handle the case where we have not found this AVP in the dictionary */
+	if (!avp->avp_model) {
+		
+		if (mandatory && (avp->avp_public.avp_flags & AVP_FLAG_MANDATORY)) {
+			TRACE_DEBUG(INFO, "Unsupported mandatory AVP found");
+			if (error_info) {
+				error_info->pei_errcode = "DIAMETER_AVP_UNSUPPORTED";
+				error_info->pei_avp = avp;
+			} else {
+				char * buf = NULL;
+				size_t buflen;
+				CHECK_MALLOC(fd_msg_dump_treeview(&buf, &buflen, NULL, avp, NULL, 0, 0));
+				LOG_E("Unsupported AVP: %s", buf);
+				free(buf);
+			}
+			return ENOTSUP;
+		}
+		
+		if (avp->avp_source) {
+			/* we must copy the data from the source to the internal buffer area */
+			CHECK_PARAMS( !avp->avp_rawdata  );
+			
+			avp->avp_rawlen = avp->avp_public.avp_len - GETAVPHDRSZ( avp->avp_public.avp_flags );
+			
+			if (avp->avp_rawlen) {
+				CHECK_MALLOC(  avp->avp_rawdata = malloc(avp->avp_rawlen)  );
+			
+				memcpy(avp->avp_rawdata, avp->avp_source, avp->avp_rawlen);
+			}
+			
+			avp->avp_source = NULL;
+			
+			TRACE_DEBUG(FULL, "Unsupported optional AVP found, raw source data saved in avp_rawdata.");
+		}
+		
+		return 0;
+	}
+	
+	/* Ok we have resolved the object. Now we need to interpret its content. */
+	
+	CHECK_FCT(  fd_dict_getval(avp->avp_model, &dictdata)  );
+	
+	if (avp->avp_rawdata) {
+		/* This happens if the dictionary object was defined after the first check */
+		avp->avp_source = avp->avp_rawdata;
+	}
+	
+	/* A bit of sanity here... */
+	ASSERT(CHECK_BASETYPE(dictdata.avp_basetype));
+	
+	/* Check the size is valid */
+	if ((avp_value_sizes[dictdata.avp_basetype] != 0) &&
+	    (avp->avp_public.avp_len - GETAVPHDRSZ( avp->avp_public.avp_flags ) != avp_value_sizes[dictdata.avp_basetype])) {
+		TRACE_DEBUG(INFO, "The AVP size is not suitable for the type");
+		if (error_info) {
+			error_info->pei_errcode = "DIAMETER_INVALID_AVP_LENGTH";
+			error_info->pei_avp = avp;
+			snprintf(error_message, sizeof(error_message), "I expected a size of %d for this AVP according to my dictionary", avp_value_sizes[dictdata.avp_basetype]);
+			error_info->pei_message = error_message;
+		} else {
+			char * buf = NULL;
+			size_t buflen;
+			CHECK_MALLOC(fd_msg_dump_treeview(&buf, &buflen, NULL, avp, NULL, 0, 0));
+			LOG_E("Invalid length AVP: %s", buf);
+			free(buf);
+		}
+		avp->avp_model = NULL;
+		return EBADMSG;
+	}
+	
+	source = avp->avp_source;
+	avp->avp_source = NULL;
+
+	/* Now get the value inside */
+	switch (dictdata.avp_basetype) {
+		case AVP_TYPE_GROUPED: {
+			int ret;
+			
+			/* This is a grouped AVP, so let's parse the list of AVPs inside */
+			CHECK_FCT_DO(  ret = parsebuf_list(source, avp->avp_public.avp_len - GETAVPHDRSZ( avp->avp_public.avp_flags ), &avp->avp_chain.children),
+				{
+					if ((ret == EBADMSG) && (error_info)) {
+						error_info->pei_errcode = "DIAMETER_INVALID_AVP_VALUE";
+						error_info->pei_avp = avp;
+						snprintf(error_message, sizeof(error_message), "I cannot parse this AVP as a Grouped AVP");
+						error_info->pei_message = error_message;
+					}
+					avp->avp_source = source;
+					return ret;
+				}  );
+			
+			return parsedict_do_chain(dict, &avp->avp_chain.children, mandatory && (avp->avp_public.avp_flags & AVP_FLAG_MANDATORY), error_info);
+		}
+			
+		case AVP_TYPE_OCTETSTRING:
+			/* We just have to copy the string into the storage area */
+			CHECK_PARAMS_DO( avp->avp_public.avp_len >= GETAVPHDRSZ( avp->avp_public.avp_flags ),
+				{
+					if (error_info) {
+						error_info->pei_errcode = "DIAMETER_INVALID_AVP_LENGTH";
+						error_info->pei_avp = avp;
+					}
+					avp->avp_source = source;
+					return EBADMSG;
+				} );
+			avp->avp_storage.os.len = avp->avp_public.avp_len - GETAVPHDRSZ( avp->avp_public.avp_flags );
+			CHECK_MALLOC(  avp->avp_storage.os.data = os0dup(source, avp->avp_storage.os.len)  );
+			avp->avp_mustfreeos = 1;
+			break;
+		
+		case AVP_TYPE_INTEGER32:
+			avp->avp_storage.i32 = (int32_t)ntohl(*(uint32_t *)source);
+			break;
+	
+		case AVP_TYPE_INTEGER64:
+			/* the storage might not be aligned on 64b boundary, so no direct indirection here is possible */
+			{
+				uint64_t __stor;
+				memcpy(&__stor, source, sizeof(__stor));
+				avp->avp_storage.i64 = (int64_t)ntohll(__stor);
+			}
+			break;
+	
+		case AVP_TYPE_UNSIGNED32:
+		case AVP_TYPE_FLOAT32: /* For float, we must not cast, or the value is changed. Instead we use implicit cast by changing the member of the union */
+			avp->avp_storage.u32 = (uint32_t)ntohl(*(uint32_t *)source);
+			break;
+	
+		case AVP_TYPE_UNSIGNED64:
+		case AVP_TYPE_FLOAT64: /* same as 32 bits */
+			{
+				uint64_t __stor;
+				memcpy(&__stor, source, sizeof(__stor));
+				avp->avp_storage.u64 = (uint64_t)ntohll(__stor);
+			}
+			break;
+	
+	}
+	
+	/* Is there a derived type check function ? */
+	CHECK_FCT ( fd_dict_search ( dict, DICT_TYPE, TYPE_OF_AVP, avp->avp_model, &avp_derived_type, 0) );
+	if (avp_derived_type) {
+		CHECK_FCT(  fd_dict_getval(avp_derived_type, &derivedtypedata)  );
+		if (derivedtypedata.type_check != NULL) {
+			char * err;
+			int ret = (*derivedtypedata.type_check)( derivedtypedata.type_check_param, &avp->avp_storage, &err );
+
+			if (ret != 0) {
+				TRACE_DEBUG(INFO, "The AVP failed to pass the dictionary validation");
+				if (error_info) {				
+						error_info->pei_errcode = "DIAMETER_INVALID_AVP_VALUE";
+						error_info->pei_avp = avp;
+						strncpy(error_message, err, sizeof(error_message));
+						error_info->pei_message = error_message;
+				} else {
+					char * buf = NULL;
+					size_t buflen;
+					CHECK_MALLOC(fd_msg_dump_treeview(&buf, &buflen, NULL, avp, NULL, 0, 0));
+					LOG_E("Invalid AVP: %s", buf);
+					free(buf);
+				}
+				return ret; /* should we just return EBADMSG? */
+			}
+		}
+	}
+	
+	/* The value is now set, so set the data pointer and return 0 */
+	avp->avp_public.avp_value = &avp->avp_storage;
+	return 0;
+}
+
+/* Process a list of AVPs */
+static int parsedict_do_chain(struct dictionary * dict, struct fd_list * head, int mandatory, struct fd_pei *error_info)
+{
+	struct fd_list * avpch;
+	
+	TRACE_ENTRY("%p %p %d %p", dict, head, mandatory, error_info);
+	
+	/* Sanity check */
+	ASSERT ( head == head->head );
+	
+	/* Now process the list */
+	for (avpch=head->next; avpch != head; avpch = avpch->next) {
+		CHECK_FCT(  parsedict_do_avp(dict, _A(avpch->o), mandatory, error_info)  );
+	}
+	
+	/* Done */
+	return 0;
+}
+
+/* Process a msg header. */
+static int parsedict_do_msg(struct dictionary * dict, struct msg * msg, int only_hdr, struct fd_pei *error_info)
+{
+	int ret = 0;
+	
+	TRACE_ENTRY("%p %p %d %p", dict, msg, only_hdr, error_info);
+	
+	CHECK_PARAMS(  CHECK_MSG(msg)  );
+	
+	/* First, check if we already have a model. */
+	if (msg->msg_model != NULL) {
+		/* Check if this model is still valid for the message data */
+		enum dict_object_type 	 dicttype;
+		struct dict_cmd_data     data;
+		ASSERT(((fd_dict_gettype(msg->msg_model, &dicttype) == 0) && (dicttype == DICT_COMMAND)));
+		(void)fd_dict_getval( msg->msg_model, &data);
+		if ((data.cmd_code != msg->msg_public.msg_code) 
+		||  ((data.cmd_flag_val & data.cmd_flag_mask) != (msg->msg_public.msg_flags && data.cmd_flag_mask))) {
+			msg->msg_model = NULL;
+		} else {
+			goto chain;
+		}
+	}
+	
+	/* Check if we already searched for this model without success */
+	if ((msg->msg_model_not_found.mnf_code == msg->msg_public.msg_code) 
+	&& (msg->msg_model_not_found.mnf_flags == msg->msg_public.msg_flags)) {
+		goto no_model;
+	} else {
+		msg->msg_model_not_found.mnf_code = 0;
+	}
+	
+	/* Look for the model from the header */
+	CHECK_FCT_DO( ret = fd_dict_search ( dict, DICT_COMMAND, 
+			(msg->msg_public.msg_flags & CMD_FLAG_REQUEST) ? CMD_BY_CODE_R : CMD_BY_CODE_A,
+			&msg->msg_public.msg_code,
+			&msg->msg_model, ENOTSUP),
+		{
+			if (ret == ENOTSUP) {
+				/* update the model not found info */
+				msg->msg_model_not_found.mnf_code = msg->msg_public.msg_code;
+				msg->msg_model_not_found.mnf_flags = msg->msg_public.msg_flags;
+				goto no_model;
+			}
+			return ret;
+		} );
+chain:	
+	if (!only_hdr) {
+		/* Then process the children */
+		ret = parsedict_do_chain(dict, &msg->msg_chain.children, 1, error_info);
+
+		/* Free the raw buffer if any */
+		if ((ret == 0) && (msg->msg_rawbuffer != NULL)) {
+			free(msg->msg_rawbuffer);
+			msg->msg_rawbuffer=NULL;
+		}
+	}
+	
+	return ret;
+no_model:
+	if (error_info) {
+		error_info->pei_errcode = "DIAMETER_COMMAND_UNSUPPORTED";
+		error_info->pei_protoerr = 1;
+	}
+	return ENOTSUP;
+}
+
+int fd_msg_parse_dict ( msg_or_avp * object, struct dictionary * dict, struct fd_pei *error_info )
+{
+	TRACE_ENTRY("%p %p %p", dict, object, error_info);
+	
+	CHECK_PARAMS(  VALIDATE_OBJ(object)  );
+	
+	if (error_info)
+		memset(error_info, 0, sizeof(struct fd_pei));
+	
+	switch (_C(object)->type) {
+		case MSG_MSG:
+			return parsedict_do_msg(dict, _M(object), 0, error_info);
+		
+		case MSG_AVP:
+			return parsedict_do_avp(dict, _A(object), 0, error_info);
+		
+		default:
+			ASSERT(0);
+	}
+	return EINVAL;
+}
+
+/***************************************************************************************************************/
+/* Parsing messages and AVP for rules (ABNF) compliance */
+
+/* This function is used to get stats (first occurence position, last occurence position, number of occurences) 
+   of AVP instances of a given model in a chain of AVP */
+static void parserules_stat_avps( struct dict_object * model_avp, struct fd_list *list, int * count, int * firstpos, int * lastpos) 
+{
+	struct fd_list * li;
+	int curpos = 0; /* The current position in the list */
+	
+	TRACE_ENTRY("%p %p %p %p %p", model_avp, list, count, firstpos, lastpos);
+	
+	*count = 0;	/* number of instances found */
+	*firstpos = 0;	/* position of the first instance */
+	*lastpos = 0;	/* position of the last instance, starting from the end */
+	
+	for (li = list->next; li != list; li = li->next) {
+		/* Increment the current position counter */
+		curpos++;
+		
+		/* If we previously saved a "lastpos" information, increment it */
+		if (*lastpos != 0)
+			(*lastpos)++;
+		
+		/* Check the type of the next AVP. We can compare the references directly, it is safe. */
+		if (_A(li->o)->avp_model == model_avp) {
+			
+			/* This AVP is of the type we are searching */
+			(*count)++;
+			
+			/* If we don't have yet a "firstpos", save it */
+			if (*firstpos == 0)
+				*firstpos = curpos;
+			
+			/* Reset the lastpos */
+			(*lastpos) = 1;
+		}
+	}
+}
+
+/* We use this structure as parameter for the next function */
+struct parserules_data {
+	struct fd_list  * sentinel;  	/* Sentinel of the list of children AVP */
+	struct fd_pei 	* pei;   	/* If the rule conflicts, save the error here */
+};
+
+/* Create an empty AVP of a given model (to use in Failed-AVP) */
+static struct avp * empty_avp(struct dict_object * model_avp)
+{
+	struct avp * avp = NULL;
+	struct dict_avp_data avp_info;
+	union avp_value val;
+	unsigned char os[1] = { '\0' };
+	
+	/* Create an instance */
+	CHECK_FCT_DO( fd_msg_avp_new(model_avp, 0, &avp ), return NULL );
+	
+	/* Type of the AVP */
+	CHECK_FCT_DO( fd_dict_getval(model_avp, &avp_info), return NULL );
+	
+	/* Set an initial size */
+	avp->avp_public.avp_len = GETAVPHDRSZ( avp->avp_public.avp_flags ) + avp_value_sizes[avp_info.avp_basetype];
+	
+	/* Prepare the empty value */
+	memset(&val, 0, sizeof(val));
+	switch (avp_info.avp_basetype) {
+		case AVP_TYPE_OCTETSTRING:
+			val.os.data = os;
+			val.os.len  = sizeof(os);
+			avp->avp_public.avp_len += val.os.len;
+		case AVP_TYPE_INTEGER32:
+		case AVP_TYPE_INTEGER64:
+		case AVP_TYPE_UNSIGNED32:
+		case AVP_TYPE_UNSIGNED64:
+		case AVP_TYPE_FLOAT32:
+		case AVP_TYPE_FLOAT64:
+			CHECK_FCT_DO( fd_msg_avp_setvalue(avp, &val), return NULL );
+		case AVP_TYPE_GROUPED:
+			/* For AVP_TYPE_GROUPED we don't do anything */
+			break;
+		default:
+			ASSERT(0); /* not handled */
+	}
+	
+	return avp;
+}
+
+/* Check that a list of AVPs is compliant with a given rule -- will be iterated on the list of rules */
+static int parserules_check_one_rule(void * data, struct dict_rule_data *rule)
+{
+	int count, first, last, min;
+	struct parserules_data * pr_data = data;
+	char * avp_name = "<unresolved name>";
+	
+	TRACE_ENTRY("%p %p", data, rule);
+	
+	/* Get statistics of the AVP concerned by this rule in the parent instance */
+	parserules_stat_avps( rule->rule_avp, pr_data->sentinel, &count, &first, &last);
+	
+	if (TRACE_BOOL(INFO))
+	{
+		struct dict_avp_data avpdata;
+		int ret;
+		ret = fd_dict_getval(rule->rule_avp, &avpdata);
+		if (ret == 0)
+			avp_name = avpdata.avp_name;
+		
+		TRACE_DEBUG(ANNOYING, "Checking rule: p:%d(%d) m/M:%2d/%2d. Counted %d (first: %d, last:%d) of AVP '%s'", 
+					rule->rule_position,
+					rule->rule_order,
+					rule->rule_min,
+					rule->rule_max,
+					count, 
+					first, 
+					last,
+					avp_name
+				);
+	}
+	
+	/* Now check the rule is not conflicting */
+	
+	/* Check the "min" value */
+	if ((min = rule->rule_min) == -1) {
+		if (rule->rule_position == RULE_OPTIONAL)
+			min = 0;
+		else
+			min = 1;
+	}
+	if (count < min) {
+		fd_log_error("Conflicting rule: the number of occurences (%d) is < the rule min (%d) for '%s'.", count, min, avp_name);
+		if (pr_data->pei) {
+			pr_data->pei->pei_errcode = "DIAMETER_MISSING_AVP";
+			pr_data->pei->pei_avp = empty_avp(rule->rule_avp);
+			pr_data->pei->pei_avp_free = 1;
+		}
+		return EBADMSG;
+	}
+	
+	/* Check the "max" value */
+	if ((rule->rule_max != -1) && (count > rule->rule_max)) {
+		fd_log_error("Conflicting rule: the number of occurences (%d) is > the rule max (%d) for '%s'.", count, rule->rule_max, avp_name);
+		if (pr_data->pei) {
+			if (rule->rule_max == 0)
+				pr_data->pei->pei_errcode = "DIAMETER_AVP_NOT_ALLOWED";
+			else
+				pr_data->pei->pei_errcode = "DIAMETER_AVP_OCCURS_TOO_MANY_TIMES";
+			pr_data->pei->pei_avp = empty_avp(rule->rule_avp); /* Well we are supposed to return the (max + 1)th instance of the AVP instead... Pfff... */ TODO("Improve...");
+			pr_data->pei->pei_avp_free = 1;
+		}
+		return EBADMSG;
+	}
+		
+	/* Check the position and order (if relevant) */
+	switch (rule->rule_position) {
+		case RULE_OPTIONAL:
+		case RULE_REQUIRED:
+			/* No special position constraints */
+			break;
+		
+		case RULE_FIXED_HEAD:
+			/* Since "0*1<fixed>" is a valid rule specifier, we only reject cases where the AVP appears *after* its fixed position */
+			if (first > rule->rule_order) {
+				fd_log_error("Conflicting rule: the FIXED_HEAD AVP appears first in (%d) position, the rule requires (%d) for '%s'.", first, rule->rule_order, avp_name);
+				if (pr_data->pei) {
+					pr_data->pei->pei_errcode = "DIAMETER_MISSING_AVP";
+					pr_data->pei->pei_message = "AVP was not in its fixed position";
+					pr_data->pei->pei_avp = empty_avp(rule->rule_avp);
+					pr_data->pei->pei_avp_free = 1;
+				}
+				return EBADMSG;
+			}
+			break;
+	
+		case RULE_FIXED_TAIL:
+			/* Since "0*1<fixed>" is a valid rule specifier, we only reject cases where the AVP appears *before* its fixed position */
+			if (last > rule->rule_order) {	/* We have a ">" here because we count in reverse order (i.e. from the end) */
+				fd_log_error("Conflicting rule: the FIXED_TAIL AVP appears last in (%d) position, the rule requires (%d) for '%s'.", last, rule->rule_order, avp_name);
+				if (pr_data->pei) {
+					pr_data->pei->pei_errcode = "DIAMETER_MISSING_AVP";
+					pr_data->pei->pei_message = "AVP was not in its fixed position";
+					pr_data->pei->pei_avp = empty_avp(rule->rule_avp);
+					pr_data->pei->pei_avp_free = 1;
+				}
+				return EBADMSG;
+			}
+			break;
+		
+		default:
+			/* What is this position ??? */
+			ASSERT(0);
+			return ENOTSUP;
+	}
+	
+	/* We've checked all the parameters */
+	return 0;
+}
+
+/* Check the rules recursively */
+static int parserules_do ( struct dictionary * dict, msg_or_avp * object, struct fd_pei *error_info, int mandatory)
+{
+	struct parserules_data data;
+	struct dict_object * model = NULL;
+	
+	TRACE_ENTRY("%p %p %p %d", dict, object, error_info, mandatory);
+	
+	/* object has already been checked and dict-parsed when we are called. */
+	
+	/* First, handle the cases where there is no model */
+	{
+		if (CHECK_MSG(object)) {
+			if ( _M(object)->msg_public.msg_flags & CMD_FLAG_ERROR ) {
+				/* The case of error messages: the ABNF is different */
+				CHECK_FCT( fd_dict_get_error_cmd(dict, &model) );
+			} else {
+				model = _M(object)->msg_model;
+			}
+			/* Commands MUST be supported in the dictionary */
+			if (model == NULL) {
+				TRACE_DEBUG(INFO, "Message with no dictionary model. EBADMSG");
+				if (error_info) {
+					error_info->pei_errcode = "DIAMETER_COMMAND_UNSUPPORTED";
+					error_info->pei_protoerr = 1;
+				}
+				return EBADMSG;
+			}
+		}
+
+		/* AVP with the 'M' flag must also be recognized in the dictionary -- except inside an optional grouped AVP */
+		if (CHECK_AVP(object) && ((model = _A(object)->avp_model) == NULL)) {
+			if ( mandatory && (_A(object)->avp_public.avp_flags & AVP_FLAG_MANDATORY)) {
+				/* Return an error in this case */
+				TRACE_DEBUG(INFO, "Mandatory AVP with no dictionary model. EBADMSG");
+				if (error_info) {
+					error_info->pei_errcode = "DIAMETER_AVP_UNSUPPORTED";
+					error_info->pei_avp = object;
+				}
+				return EBADMSG;
+			} else {
+				/* We don't know any rule for this object, so assume OK */
+				TRACE_DEBUG(FULL, "Unknown informational AVP, ignoring...");
+				return 0;
+			}
+		}
+	}
+	
+	/* At this point we know "model" is set and points to the object's model */
+	
+	/* If we are an AVP with no children, just return OK */
+	if (CHECK_AVP(object)) {
+		struct dict_avp_data	dictdata;
+		CHECK_FCT(  fd_dict_getval(model, &dictdata)  );
+		if (dictdata.avp_basetype != AVP_TYPE_GROUPED) {
+			/* This object has no children and no rules */
+			return 0;
+		}
+	}
+	
+	/* If this object has children, first check the rules for all its children */
+	{
+		int is_child_mand = 0;
+		struct fd_list * ch = NULL;
+		if (  CHECK_MSG(object) 
+		   || (mandatory && (_A(object)->avp_public.avp_flags & AVP_FLAG_MANDATORY)) )
+			is_child_mand = 1;
+		for (ch = _C(object)->children.next; ch != &_C(object)->children; ch = ch->next) {
+			CHECK_FCT(  parserules_do ( dict, _C(ch->o), error_info, is_child_mand )  );
+		}
+	}
+
+	/* Now check all rules of this object */
+	data.sentinel = &_C(object)->children;
+	data.pei  = error_info;
+	CHECK_FCT( fd_dict_iterate_rules ( model, &data, parserules_check_one_rule ) );
+	
+	return 0;
+}
+
+int fd_msg_parse_rules ( msg_or_avp * object, struct dictionary * dict, struct fd_pei *error_info)
+{
+	TRACE_ENTRY("%p %p %p", object, dict, error_info);
+	
+	if (error_info)
+		memset(error_info, 0, sizeof(struct fd_pei));
+	
+	/* Resolve the dictionary objects when missing. This also validates the object. */
+	CHECK_FCT(  fd_msg_parse_dict ( object, dict, error_info )  );
+	
+	/* Call the recursive function */
+	return parserules_do ( dict, object, error_info, 1 ) ;
+}
+
+/***************************************************************************************************************/
+
+/* Compute the lengh of an object and its subtree. */
+int fd_msg_update_length ( msg_or_avp * object )
+{
+	size_t sz = 0;
+	struct dict_object * model;
+	union {
+		struct dict_cmd_data   cmddata;
+		struct dict_avp_data   avpdata;
+	} dictdata;
+	
+	TRACE_ENTRY("%p", object);
+	
+	/* Get the model of the object. This also validates the object */
+	CHECK_FCT( fd_msg_model ( object, &model ) );
+	
+	/* Get the information of the model */
+	if (model) {
+		CHECK_FCT(  fd_dict_getval(model, &dictdata)  );
+	} else {
+		/* For unknown AVP, just don't change the size */
+		if (_C(object)->type == MSG_AVP)
+			return 0;
+	}
+	
+	/* Deal with easy cases: AVPs without children */
+	if ((_C(object)->type == MSG_AVP) && (dictdata.avpdata.avp_basetype != AVP_TYPE_GROUPED)) {
+		/* Sanity check */
+		ASSERT(FD_IS_LIST_EMPTY(&_A(object)->avp_chain.children));
+		
+		/* Now check that the data is set in the AVP */
+		CHECK_PARAMS(  _A(object)->avp_public.avp_value  );
+		
+		sz = GETAVPHDRSZ( _A(object)->avp_public.avp_flags );
+		
+		switch (dictdata.avpdata.avp_basetype) {
+			case AVP_TYPE_OCTETSTRING:
+				sz += _A(object)->avp_public.avp_value->os.len;
+				break;
+			
+			case AVP_TYPE_INTEGER32:
+			case AVP_TYPE_INTEGER64:
+			case AVP_TYPE_UNSIGNED32:
+			case AVP_TYPE_UNSIGNED64:
+			case AVP_TYPE_FLOAT32:
+			case AVP_TYPE_FLOAT64:
+				sz += avp_value_sizes[dictdata.avpdata.avp_basetype];
+				break;
+			
+			default:
+				/* Something went wrong... */
+				ASSERT(0);
+		}
+	}
+	else  /* message or grouped AVP */
+	{
+		struct fd_list * ch = NULL;
+		
+		/* First, compute the header size */
+		if (_C(object)->type == MSG_AVP) {
+			sz = GETAVPHDRSZ( _A(object)->avp_public.avp_flags );
+		} else {
+			sz = GETMSGHDRSZ( );
+		}
+		
+		/* Recurse in all children and update the sz information */
+		for (ch = _C(object)->children.next; ch != &_C(object)->children; ch = ch->next) {
+			CHECK_FCT(  fd_msg_update_length ( ch->o )  );
+			
+			/* Add the padded size to the parent */
+			sz += PAD4( _A(ch->o)->avp_public.avp_len );
+		}
+	}
+	
+	/* When we arrive here, the "sz" variable contains the size to write in the object */
+	if (_C(object)->type == MSG_AVP) 
+		_A(object)->avp_public.avp_len = sz;
+	else
+		_M(object)->msg_public.msg_length = sz;
+	
+	return 0;
+}
+
+/***************************************************************************************************************/
+/* Macro to check if further callbacks must be called */
+#define TEST_ACTION_STOP()					\
+	if ((*msg == NULL) || (*action != DISP_ACT_CONT))	\
+		goto out;
+
+/* Call all dispatch callbacks for a given message */
+int fd_msg_dispatch ( struct msg ** msg, struct session * session, enum disp_action *action, char ** error_code, char ** drop_reason, struct msg ** drop_msg)
+{
+	struct dictionary  * dict;
+	struct dict_object * app;
+	struct dict_object * cmd;
+	struct avp * avp;
+	struct fd_list * cb_list;
+	int ret = 0, r2;
+	
+	TRACE_ENTRY("%p %p %p %p", msg, session, action, error_code);
+	CHECK_PARAMS( msg && CHECK_MSG(*msg) && action);
+	
+	if (error_code)
+		*error_code = NULL;
+	if (drop_reason)
+		*drop_reason = NULL;
+	*action = DISP_ACT_CONT;
+	
+	/* Take the dispatch lock */
+	CHECK_FCT( pthread_rwlock_rdlock(&fd_disp_lock) );
+	pthread_cleanup_push( fd_cleanup_rwlock, &fd_disp_lock );
+	
+	/* First, call the DISP_HOW_ANY callbacks */
+	CHECK_FCT_DO( ret = fd_disp_call_cb_int( NULL, msg, NULL, session, action, NULL, NULL, NULL, NULL, drop_reason, drop_msg ), goto out );
+
+	TEST_ACTION_STOP();
+	
+	/* If we don't know the model at this point, we stop cause we cannot get the dictionary. It's invalid: an error should already have been trigged by ANY callbacks */
+	CHECK_PARAMS_DO(cmd = (*msg)->msg_model, { ret = EINVAL; goto out; } );
+	
+	/* Now resolve message application */
+	CHECK_FCT_DO( ret = fd_dict_getdict( cmd, &dict ), goto out );
+	CHECK_FCT_DO( ret = fd_dict_search( dict, DICT_APPLICATION, APPLICATION_BY_ID, &(*msg)->msg_public.msg_appl, &app, 0 ), goto out );
+	
+	if (app == NULL) {
+		if ((*msg)->msg_public.msg_flags & CMD_FLAG_REQUEST) {
+			if (error_code)
+				*error_code = "DIAMETER_APPLICATION_UNSUPPORTED";
+			*action = DISP_ACT_ERROR;
+		} else {
+			*drop_reason = "Internal error: Received this answer to a local query with an unsupported application";
+			*drop_msg = *msg;
+			*msg = NULL;
+		}
+		goto out;
+	}
+	
+	/* So start browsing the message */
+	CHECK_FCT_DO( ret = fd_msg_browse( *msg, MSG_BRW_FIRST_CHILD, &avp, NULL ), goto out );
+	while (avp != NULL) {
+		/* For unknown AVP, we don't have a callback registered, so just skip */
+		if (avp->avp_model) {
+			struct dict_object * enumval = NULL;
+			
+			/* Get the list of callback for this AVP */
+			CHECK_FCT_DO( ret = fd_dict_disp_cb(DICT_AVP, avp->avp_model, &cb_list), goto out );
+			
+			/* We search enumerated values only in case of non-grouped AVP */
+			if ( avp->avp_public.avp_value ) {
+				struct dict_object * type;
+				/* Check if the AVP has a constant value */
+				CHECK_FCT_DO( ret = fd_dict_search(dict, DICT_TYPE, TYPE_OF_AVP, avp->avp_model, &type, 0), goto out );
+				if (type) {
+					struct dict_enumval_request req;
+					memset(&req, 0, sizeof(struct dict_enumval_request));
+					req.type_obj = type;
+					memcpy( &req.search.enum_value, avp->avp_public.avp_value, sizeof(union avp_value) );
+					CHECK_FCT_DO( ret = fd_dict_search(dict, DICT_ENUMVAL, ENUMVAL_BY_STRUCT, &req, &enumval, 0), goto out );
+				}
+			}
+			
+			/* Call the callbacks */
+			CHECK_FCT_DO( ret = fd_disp_call_cb_int( cb_list, msg, avp, session, action, app, cmd, avp->avp_model, enumval, drop_reason, drop_msg ), goto out );
+			TEST_ACTION_STOP();
+		}
+		/* Go to next AVP */
+		CHECK_FCT_DO(  ret = fd_msg_browse( avp, MSG_BRW_WALK, &avp, NULL ), goto out );
+	}
+		
+	/* Now call command and application callbacks */
+	CHECK_FCT_DO( ret = fd_dict_disp_cb(DICT_COMMAND, cmd, &cb_list), goto out );
+	CHECK_FCT_DO( ret = fd_disp_call_cb_int( cb_list, msg, NULL, session, action, app, cmd, NULL, NULL, drop_reason, drop_msg ), goto out );
+	TEST_ACTION_STOP();
+	
+	if (app) {
+		CHECK_FCT_DO( ret = fd_dict_disp_cb(DICT_APPLICATION, app, &cb_list), goto out );
+		CHECK_FCT_DO( ret = fd_disp_call_cb_int( cb_list, msg, NULL, session, action, app, cmd, NULL, NULL, drop_reason, drop_msg ), goto out );
+		TEST_ACTION_STOP();
+	}
+out:
+	; /* some systems would complain without this */	
+	pthread_cleanup_pop(0);
+	
+	CHECK_POSIX_DO(r2 = pthread_rwlock_unlock(&fd_disp_lock), /* ignore */ );
+	return ret ?: r2;
+}
+
+
diff --git a/libfdproto/ostr.c b/libfdproto/ostr.c
new file mode 100644
index 0000000..0dc9972
--- /dev/null
+++ b/libfdproto/ostr.c
@@ -0,0 +1,561 @@
+/*********************************************************************************************************
+* Software License Agreement (BSD License)                                                               *
+* Author: Sebastien Decugis <sdecugis@freediameter.net>							 *
+*													 *
+* Copyright (c) 2013, WIDE Project and NICT								 *
+* All rights reserved.											 *
+* 													 *
+* Redistribution and use of this software in source and binary forms, with or without modification, are  *
+* permitted provided that the following conditions are met:						 *
+* 													 *
+* * Redistributions of source code must retain the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer.										 *
+*    													 *
+* * Redistributions in binary form must reproduce the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer in the documentation and/or other						 *
+*   materials provided with the distribution.								 *
+* 													 *
+* * Neither the name of the WIDE Project or NICT nor the 						 *
+*   names of its contributors may be used to endorse or 						 *
+*   promote products derived from this software without 						 *
+*   specific prior written permission of WIDE Project and 						 *
+*   NICT.												 *
+* 													 *
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED *
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
+* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR *
+* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 	 *
+* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 	 *
+* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR *
+* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF   *
+* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.								 *
+*********************************************************************************************************/
+
+#include "fdproto-internal.h"
+
+#if (!defined(DIAMID_IDNA_IGNORE) && !defined(DIAMID_IDNA_REJECT))
+/* Process IDNA with stringprep -- See RFC5890 -- and libidn documentation... */
+#include <idna.h> /* idna_to_ascii_8z() */
+#endif /* !defined(DIAMID_IDNA_IGNORE) && !defined(DIAMID_IDNA_REJECT) */
+
+/* Similar to strdup with (must have been verified) os0_t */
+os0_t os0dup_int(os0_t s, size_t l) {
+	os0_t r;
+	CHECK_MALLOC_DO( r = malloc(l+1), return NULL );
+	if (l)
+		memcpy(r, s, l); /* this might be faster than a strcpy or strdup because it can work with 32 or 64b blocks */
+	r[l] = '\0';
+	return r;
+}
+
+/* case sensitive comparison, fast */
+int fd_os_cmp_int(uint8_t * os1, size_t os1sz, uint8_t * os2, size_t os2sz)
+{
+	ASSERT( os1 && os2);
+	if (os1sz < os2sz)
+		return -1;
+	if (os1sz > os2sz)
+		return 1;
+	return os1sz ? memcmp(os1, os2, os1sz) : 0;
+}
+
+/* a local version of tolower() that does not depend on LC_CTYPE locale */
+static inline uint8_t asciitolower(uint8_t a)
+{
+	if ((a >= 'A') && (a <= 'Z'))
+		return a + 32 /* == 'a' - 'A' */;
+	return a;
+}
+
+/* less sensitive to case, slower. */
+/* the semantics of "maybefurther" assume you are searching for os1 in a list of elements ordered, each element passed as os2 */
+int fd_os_almostcasesrch_int(uint8_t * os1, size_t os1sz, uint8_t * os2, size_t os2sz, int *maybefurther)
+{
+	int i;
+	int res = 0;
+	
+	ASSERT( os1 && os2);
+	if (maybefurther)
+		*maybefurther = 0;
+	
+	if (os1sz < os2sz)
+		return -1;
+	
+	if (maybefurther)
+		*maybefurther = 1;
+	
+	if (os1sz > os2sz)
+		return 1;
+	
+	for (i = 0; i < os1sz; i++) {
+		if (os1[i] == os2[i])
+			continue;
+		
+		if (!res) 
+			res = os1[i] < os2[i] ? -1 : 1;
+		
+		if (asciitolower(os1[i]) == asciitolower(os2[i])) 
+			continue;
+		
+		return res;
+	}
+	
+	return 0;
+}
+
+/* Check if the string contains only ASCII */
+int fd_os_is_valid_DiameterIdentity(uint8_t * os, size_t ossz)
+{
+#ifdef DIAMID_IDNA_IGNORE
+	
+	/* Allow anything */
+	
+#else /* DIAMID_IDNA_IGNORE */
+	
+	int i;
+	
+	/* Allow only letters, digits, hyphen, dot */
+	for (i=0; i < ossz; i++) {
+		if (os[i] > 'z')
+			break;
+		if (os[i] >= 'a')
+			continue;
+		if ((os[i] >= 'A') && (os[i] <= 'Z'))
+			continue;
+		if ((os[i] == '-') || (os[i] == '.'))
+			continue;
+		if ((os[i] >= '0') && (os[i] <= '9'))
+			continue;
+		break;
+	}
+	if (i < ossz) {
+		int nb = 1;
+		/* To get a better display, check if the invalid char is UTF-8 */
+		if ((os[i] & 0xE0) == 0xC0 /* 110xxxxx */) {
+			if ((i < ossz - 1) && ((os[i + 1] & 0xC0) == 0x80 /* 10xxxxxx */))
+				nb = 2;
+			goto disp;
+		}
+		if ((os[i] & 0xF0) == 0xE0 /* 1110xxxx */) {
+			if ((i < ossz - 2) && ((os[i + 1] & 0xC0) == 0x80 /* 10xxxxxx */)
+					   && ((os[i + 2] & 0xC0) == 0x80 /* 10xxxxxx */))
+				nb = 3;
+			goto disp;
+		}
+		if ((os[i] & 0xF8) == 0xF0 /* 11110xxx */) {
+			if ((i < ossz - 3) && ((os[i + 1] & 0xC0) == 0x80 /* 10xxxxxx */)
+					   && ((os[i + 2] & 0xC0) == 0x80 /* 10xxxxxx */)
+					   && ((os[i + 3] & 0xC0) == 0x80 /* 10xxxxxx */))
+				nb = 4;
+			goto disp;
+		}
+		if ((os[i] & 0xFC) == 0xF8 /* 111110xx */) {
+			if ((i < ossz - 4) && ((os[i + 1] & 0xC0) == 0x80 /* 10xxxxxx */)
+					   && ((os[i + 2] & 0xC0) == 0x80 /* 10xxxxxx */)
+					   && ((os[i + 3] & 0xC0) == 0x80 /* 10xxxxxx */)
+					   && ((os[i + 4] & 0xC0) == 0x80 /* 10xxxxxx */))
+				nb = 5;
+			goto disp;
+		}
+		if ((os[i] & 0xFE) == 0xFC /* 1111110x */) {
+			if ((i < ossz - 5) && ((os[i + 1] & 0xC0) == 0x80 /* 10xxxxxx */)
+					   && ((os[i + 2] & 0xC0) == 0x80 /* 10xxxxxx */)
+					   && ((os[i + 3] & 0xC0) == 0x80 /* 10xxxxxx */)
+					   && ((os[i + 4] & 0xC0) == 0x80 /* 10xxxxxx */)
+					   && ((os[i + 5] & 0xC0) == 0x80 /* 10xxxxxx */))
+				nb = 6;
+			goto disp;
+		}
+		/* otherwise, we just display the hex code */
+		TRACE_DEBUG(INFO, "Invalid character (0x%hhX) at offset %d in DiameterIdentity '%.*s'", os[i], i+1, (int)ossz, os);
+		return 0;
+disp:
+		TRACE_DEBUG(INFO, "Invalid character '%.*s' at offset %d in DiameterIdentity '%.*s'", nb, os + i, i+1, (int)ossz, os);
+		return 0;
+	}
+	
+#endif /* DIAMID_IDNA_IGNORE */
+	
+	return 1;
+}
+
+/* The following function validates a string as a Diameter Identity or applies the IDNA transformation on it 
+ if *inoutsz is != 0 on entry, *id may not be \0-terminated.
+ memory has the following meaning: 0: *id can be realloc'd. 1: *id must be malloc'd on output (was static)
+*/
+int fd_os_validate_DiameterIdentity(char ** id, size_t * inoutsz, int memory)
+{
+#if !defined(DIAMID_IDNA_IGNORE) && !defined(DIAMID_IDNA_REJECT)
+	int gotsize = 0;
+#endif /* defined(DIAMID_IDNA_IGNORE) || defined(DIAMID_IDNA_REJECT) */
+	
+	TRACE_ENTRY("%p %p", id, inoutsz);
+	CHECK_PARAMS( id && *id && inoutsz );
+	
+	if (!*inoutsz)
+		*inoutsz = strlen(*id);
+#if !defined(DIAMID_IDNA_IGNORE) && !defined(DIAMID_IDNA_REJECT)
+	else
+		gotsize = 1;
+#endif /* defined(DIAMID_IDNA_IGNORE) || defined(DIAMID_IDNA_REJECT) */
+	
+#ifndef DIAMID_IDNA_IGNORE
+	
+	if (!fd_os_is_valid_DiameterIdentity((os0_t)*id, *inoutsz)) {
+	
+#ifdef DIAMID_IDNA_REJECT
+		
+		TRACE_DEBUG(INFO, "The string '%s' is not a valid DiameterIdentity!", *id);
+		TRACE_DEBUG(INFO, "Returning EINVAL since fD is compiled with option DIAMID_IDNA_REJECT.");
+		return EINVAL;
+	
+#else /* DIAMID_IDNA_REJECT */
+	
+		char *processed;
+		int ret;
+		
+		if (gotsize) { /* make it \0-terminated */
+			if (memory) {
+				CHECK_MALLOC( *id = os0dup(*id, *inoutsz) );
+				memory = 0;
+			} else {
+				CHECK_MALLOC( *id = realloc(*id, *inoutsz + 1) );
+				(*id)[*inoutsz] = '0';
+			}
+		}
+		
+		ret = idna_to_ascii_8z ( *id, &processed, IDNA_USE_STD3_ASCII_RULES );
+		if (ret == IDNA_SUCCESS) {
+			TRACE_DEBUG(INFO, "The string '%s' is not a valid DiameterIdentity, it was changed to '%s'", *id, processed);
+			if (memory == 0)
+				free(*id);
+			*id = processed;
+			*inoutsz = strlen(processed);
+			/* Done! */
+		} else {
+			TRACE_DEBUG(INFO, "The string '%s' is not a valid DiameterIdentity and cannot be sanitanized: %s", *id, idna_strerror (ret));
+			return EINVAL;
+		}
+	
+#endif /* DIAMID_IDNA_REJECT */
+	} else
+#endif /* ! DIAMID_IDNA_IGNORE */
+	{
+		if (memory == 1) {
+			CHECK_MALLOC( *id = os0dup(*id, *inoutsz) );
+		}
+	}
+	return 0;
+}
+
+/* Analyze a DiameterURI and return its components. 
+  Return EINVAL if the URI is not valid. 
+  *diamid is malloc'd on function return and must be freed (it is processed by fd_os_validate_DiameterIdentity).
+  *secure is 0 (no security) or 1 (security enabled) on return.
+  *port is 0 (default) or a value in host byte order on return.
+  *transport is 0 (default) or IPPROTO_* on return.
+  *proto is 0 (default) or 'd' (diameter), 'r' (radius), or 't' (tacacs+) on return.
+  */
+int fd_os_parse_DiameterURI(uint8_t * uri, size_t urisz, DiamId_t * diamid, size_t * diamidlen, int * secure, uint16_t * port, int * transport, char *proto)
+{
+	size_t offset = 0;
+	DiamId_t fqdn = NULL;
+	size_t   fqdnlen;
+	TRACE_ENTRY("%p %zd %p %p %p %p %p %p", uri, urisz, diamid, diamidlen, secure, port, transport, proto);
+	CHECK_PARAMS( uri && urisz );
+	
+	CHECK_PARAMS( urisz > 7 ); /* "aaa" + "://" + something else at least */
+	
+	/* Initialize values */
+	if (secure)
+		*secure = 0;
+	if (port)
+		*port = 0;
+	if (transport)
+		*transport = 0;
+	if (proto)
+		*proto = 0;
+	
+	/* Check the beginning */
+	if (memcmp( uri, "aaa", 3)) {
+		TRACE_DEBUG(INFO, "Invalid DiameterURI prefix: got '%.*s', expected 'aaa'", 3, uri);
+		return EINVAL;
+	}
+	offset += 3;
+	
+	/* Secure? */
+	if (uri[offset] == (uint8_t)'s') {
+		if (secure)
+			*secure = 1;
+		offset += 1;
+	}
+	
+	/* Remaining of URI marker */
+	if (memcmp( uri + offset, "://", 3)) {
+		TRACE_DEBUG(INFO, "Invalid DiameterURI prefix: got '%.*s', expected 'aaa://' or 'aaas://'", (int)offset + 3, uri);
+		return EINVAL;
+	}
+	offset += 3;
+	
+	/* This is the start of the FQDN */
+	fqdn = (DiamId_t)uri + offset;
+	for ( ; offset < urisz ; offset++ ) {
+		/* Stop only when we find ':' or ';' */
+		if ((uri[offset] == (uint8_t)':') || (uri[offset] == (uint8_t)';'))
+			break;
+	}
+	fqdnlen = offset - (fqdn - (DiamId_t)uri);
+	CHECK_FCT(fd_os_validate_DiameterIdentity(&fqdn, &fqdnlen, 1));
+	if (diamid)
+		*diamid = fqdn;
+	else
+		free(fqdn);
+	if (diamidlen)
+		*diamidlen = fqdnlen;
+	
+	if (offset == urisz)
+		return 0; /* Finished */
+	
+	/* Is there a port ? */
+	if (uri[offset] == ':') {
+		uint16_t p = 0;
+		do {
+			offset++;
+
+			if (offset == urisz)
+				break;
+
+			uint32_t t = (uint32_t)((char)uri[offset] - '0');
+			if (t > 9)
+				break; /* we did not get a digit */
+
+			t += p * 10; /* the port is specified in decimal base */
+			
+			if (t >= (1<<16)) {
+				TRACE_DEBUG(INFO, "Invalid DiameterURI: port value is too big.");
+				return EINVAL;
+			}
+
+			p = t;
+		} while (1);
+
+		if (port)
+			*port = p;
+	}
+	
+	if (offset == urisz)
+		return 0; /* Finished */
+	
+	/* Is there a transport? */
+	if ( (urisz - offset > CONSTSTRLEN(";transport=")) 
+		&& !strncasecmp((char *)uri + offset, ";transport=", CONSTSTRLEN(";transport=")) ) {
+	
+		offset += CONSTSTRLEN(";transport=");
+
+		if (urisz - offset < 3) {
+			TRACE_DEBUG(INFO, "Invalid DiameterURI: transport string is too short, ignored.");
+			return 0;
+		}		
+		if (!strncasecmp((char *)uri + offset, "tcp", CONSTSTRLEN("tcp"))) {
+			if (transport)
+				*transport = IPPROTO_TCP;
+			offset += CONSTSTRLEN("tcp");
+			goto after_transport;
+		}
+		if (!strncasecmp((char *)uri + offset, "udp", CONSTSTRLEN("udp"))) {
+			if (transport)
+				*transport = IPPROTO_UDP;
+			offset += CONSTSTRLEN("udp");
+			goto after_transport;
+		}
+		if ((urisz - offset > 3) && !strncasecmp((char *)uri + offset, "sctp", CONSTSTRLEN("sctp"))) {
+			if (transport) {
+#ifndef DISABLE_SCTP
+				*transport = IPPROTO_SCTP;
+#else /* DISABLE_SCTP */
+				TRACE_DEBUG(INFO, "Received DiameterURI with 'transport=sctp' but DISABLE_SCTP was selected");
+				*transport = 0;
+#endif /* DISABLE_SCTP */
+			}
+			offset += CONSTSTRLEN("sctp");
+			goto after_transport;
+		}
+		
+		TRACE_DEBUG(INFO, "Invalid DiameterURI: transport string is not recognized ('%.*s').", (int)(urisz - offset), uri + offset);
+		return EINVAL;
+	}
+after_transport:
+	if (offset == urisz)
+		return 0; /* Finished */
+	
+	/* Is there a protocol? */
+	if ( ((urisz - offset) > CONSTSTRLEN(";protocol=")) 
+		&& (!strncasecmp((char *)uri + offset, ";protocol=", CONSTSTRLEN(";protocol="))) ) {
+	
+		offset += CONSTSTRLEN(";protocol=");
+
+		if ( ((urisz - offset) >= CONSTSTRLEN("diameter")) 
+		    && (!strncasecmp((char *)uri + offset, "diameter", CONSTSTRLEN("diameter"))) ) {
+			if (proto)
+				*proto = 'd';
+			offset += CONSTSTRLEN("diameter");
+			goto after_proto;
+		}
+		
+		if ( ((urisz - offset) >= CONSTSTRLEN("radius")) 
+		    && (!strncasecmp((char *)uri + offset, "radius", CONSTSTRLEN("radius"))) ) {
+			if (proto)
+				*proto = 'r';
+			offset += CONSTSTRLEN("radius");
+			goto after_proto;
+		}
+		
+		if ( ((urisz - offset) >= CONSTSTRLEN("tacacs+")) 
+		    && (!strncasecmp((char *)uri + offset, "tacacs+", CONSTSTRLEN("tacacs+"))) ) {
+			if (proto)
+				*proto = 't';
+			offset += CONSTSTRLEN("tacacs+");
+			goto after_proto;
+		}
+		
+		TRACE_DEBUG(INFO, "Invalid DiameterURI: protocol string is not recognized ('%.*s').", (int)(urisz - offset), uri + offset);
+		return EINVAL;
+		
+	}
+after_proto:
+	if (offset == urisz)
+		return 0; /* Finished */
+	
+	TRACE_DEBUG(INFO, "Invalid DiameterURI: final part of string is not recognized ('%.*s').", (int)(urisz - offset), uri + offset);
+	return EINVAL;
+}
+
+
+/********************************************************************************************************/
+/* Hash function -- credits to Austin Appleby, thank you ^^ */
+/* See http://murmurhash.googlepages.com for more information on this function */
+
+/* the strings are NOT always aligned properly (ex: received in RADIUS message), so we use the aligned MurmurHash2 function as needed */
+#define _HASH_MIX(h,k,m) { k *= m; k ^= k >> r; k *= m; h *= m; h ^= k; }
+uint32_t fd_os_hash ( uint8_t * string, size_t len )
+{
+	uint32_t hash = len;
+	uint8_t * data = string;
+	
+	const unsigned int m = 0x5bd1e995;
+	const int r = 24;
+	int align = (long)string & 3;
+	
+	if (!align || (len < 4)) {
+		/* In case data is aligned, MurmurHash2 function */
+		while(len >= 4)
+		{
+			/* Mix 4 bytes at a time into the hash */
+			uint32_t k = *(uint32_t *)data;	/* We don't care about the byte order */
+
+			_HASH_MIX(hash, k, m);
+
+			data += 4;
+			len -= 4;
+		}
+
+		/* Handle the last few bytes of the input */
+		switch(len) {
+			case 3: hash ^= data[2] << 16;
+			case 2: hash ^= data[1] << 8;
+			case 1: hash ^= data[0];
+	        		hash *= m;
+		}
+		
+	} else {
+		/* Unaligned data, use alignment-safe slower version */
+		
+		/* Pre-load the temp registers */
+		uint32_t t = 0, d = 0;
+		switch(align)
+		{
+			case 1: t |= data[2] << 16;
+			case 2: t |= data[1] << 8;
+			case 3: t |= data[0];
+		}
+		t <<= (8 * align);
+
+		data += 4-align;
+		len -= 4-align;
+		
+		/* From this point, "data" can be read by chunks of 4 bytes */
+		
+		int sl = 8 * (4-align);
+		int sr = 8 * align;
+
+		/* Mix */
+		while(len >= 4)
+		{
+			uint32_t k;
+			
+			d = *(unsigned int *)data;
+			k = (t >> sr) | (d << sl);
+
+			_HASH_MIX(hash, k, m);
+
+			t = d;
+
+			data += 4;
+			len -= 4;
+		}
+
+		/* Handle leftover data in temp registers */
+		d = 0;
+		if(len >= align)
+		{
+			uint32_t k;
+			
+			switch(align)
+			{
+			case 3: d |= data[2] << 16;
+			case 2: d |= data[1] << 8;
+			case 1: d |= data[0];
+			}
+
+			k = (t >> sr) | (d << sl);
+			_HASH_MIX(hash, k, m);
+
+			data += align;
+			len -= align;
+
+			/* Handle tail bytes */
+
+			switch(len)
+			{
+			case 3: hash ^= data[2] << 16;
+			case 2: hash ^= data[1] << 8;
+			case 1: hash ^= data[0];
+					hash *= m;
+			};
+		}
+		else
+		{
+			switch(len)
+			{
+			case 3: d |= data[2] << 16;
+			case 2: d |= data[1] << 8;
+			case 1: d |= data[0];
+			case 0: hash ^= (t >> sr) | (d << sl);
+					hash *= m;
+			}
+		}
+
+
+	}
+
+	/* Do a few final mixes of the hash to ensure the last few
+	   bytes are well-incorporated. */
+	hash ^= hash >> 13;
+	hash *= m;
+	hash ^= hash >> 15;
+
+	return hash;
+} 
+
diff --git a/libfdproto/portability.c b/libfdproto/portability.c
new file mode 100644
index 0000000..7111cc3
--- /dev/null
+++ b/libfdproto/portability.c
@@ -0,0 +1,70 @@
+/*********************************************************************************************************
+* Software License Agreement (BSD License)                                                               *
+* Author: Sebastien Decugis <sdecugis@freediameter.net>							 *
+*													 *
+* Copyright (c) 2012, WIDE Project and NICT								 *
+* All rights reserved.											 *
+* 													 *
+* Redistribution and use of this software in source and binary forms, with or without modification, are  *
+* permitted provided that the following conditions are met:						 *
+* 													 *
+* * Redistributions of source code must retain the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer.										 *
+*    													 *
+* * Redistributions in binary form must reproduce the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer in the documentation and/or other						 *
+*   materials provided with the distribution.								 *
+* 													 *
+* * Neither the name of the WIDE Project or NICT nor the 						 *
+*   names of its contributors may be used to endorse or 						 *
+*   promote products derived from this software without 						 *
+*   specific prior written permission of WIDE Project and 						 *
+*   NICT.												 *
+* 													 *
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED *
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
+* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR *
+* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 	 *
+* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 	 *
+* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR *
+* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF   *
+* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.								 *
+*********************************************************************************************************/
+
+#include "fdproto-internal.h"
+
+/* Replacement for clock_gettime for the Mac OS */
+#ifndef HAVE_CLOCK_GETTIME
+int clock_gettime(int clk_id, struct timespec* ts)
+{
+	struct timeval tv;
+	gettimeofday (&tv, NULL);
+	ts->tv_sec = tv.tv_sec;
+	ts->tv_nsec = tv.tv_usec * 1000;
+	return 0;
+}
+#endif /* HAVE_CLOCK_GETTIME */
+
+/* Replacement for strndup for the Mac OS */
+#ifndef HAVE_STRNDUP
+char * strndup (char *str, size_t len)
+{
+	char * output;
+	size_t outlen;
+	
+	output = memchr(str, 0, len);
+	if (output == NULL) {
+		outlen = len;
+	} else {
+		outlen = output - str;
+	}
+	
+	CHECK_MALLOC_DO( output = malloc (outlen + 1), return NULL );
+
+	output[outlen] = '\0';
+	memcpy (output, str, outlen);
+	return output;
+}
+#endif /* HAVE_STRNDUP */
diff --git a/libfdproto/rt_data.c b/libfdproto/rt_data.c
new file mode 100644
index 0000000..f205ef3
--- /dev/null
+++ b/libfdproto/rt_data.c
@@ -0,0 +1,338 @@
+/*********************************************************************************************************
+* Software License Agreement (BSD License)                                                               *
+* Author: Sebastien Decugis <sdecugis@freediameter.net>							 *
+*													 *
+* Copyright (c) 2013, WIDE Project and NICT								 *
+* All rights reserved.											 *
+* 													 *
+* Redistribution and use of this software in source and binary forms, with or without modification, are  *
+* permitted provided that the following conditions are met:						 *
+* 													 *
+* * Redistributions of source code must retain the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer.										 *
+*    													 *
+* * Redistributions in binary form must reproduce the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer in the documentation and/or other						 *
+*   materials provided with the distribution.								 *
+* 													 *
+* * Neither the name of the WIDE Project or NICT nor the 						 *
+*   names of its contributors may be used to endorse or 						 *
+*   promote products derived from this software without 						 *
+*   specific prior written permission of WIDE Project and 						 *
+*   NICT.												 *
+* 													 *
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED *
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
+* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR *
+* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 	 *
+* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 	 *
+* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR *
+* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF   *
+* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.								 *
+*********************************************************************************************************/
+
+/* Routing module helpers.
+ * 
+ * This file provides support for the rt_data structure manipulation.
+ */
+
+#include "fdproto-internal.h"
+
+/* Structure that contains the routing data for a message */
+struct rt_data {
+	int		extracted;	/* if 0, candidates is ordered by diamid, otherwise the order is unspecified. This also counts the number of times the message was (re-)sent, as a side effect */
+	struct fd_list	candidates;	/* All the candidates. Items are struct rtd_candidate. */
+	struct fd_list	errors;		/* All errors received from other peers for this message */
+};
+
+/* Items of the errors list */
+struct rtd_error {
+	struct fd_list	chain;	/* link in the list, ordered by nexthop (fd_os_cmp) */
+	DiamId_t 	nexthop;/* the peer the message was sent to */
+	size_t		nexthoplen; /* cached string length */
+	DiamId_t	erh;	/* the origin of the error */
+	size_t		erhlen; /* cached string length */
+	uint32_t	code;	/* the error code */
+};
+
+/* Create a new structure to store routing data */
+int  fd_rtd_init(struct rt_data ** rtd)
+{
+	struct rt_data *new;
+	TRACE_ENTRY("%p", rtd);
+	CHECK_PARAMS(rtd);
+	
+	/* Alloc the structure */
+	CHECK_MALLOC( new = malloc(sizeof(struct rt_data)) );
+	memset(new, 0, sizeof(struct rt_data) );
+	fd_list_init(&new->candidates, new);
+	fd_list_init(&new->errors, new);
+	
+	*rtd = new;
+	return 0;
+}
+
+/* Destroy the routing data */
+void fd_rtd_free(struct rt_data ** rtd)
+{
+	struct rt_data *old;
+	
+	TRACE_ENTRY("%p", rtd);
+	CHECK_PARAMS_DO(rtd, return );
+	
+	old = *rtd;
+	*rtd = NULL;
+	
+	while (!FD_IS_LIST_EMPTY(&old->candidates)) {
+		struct rtd_candidate * c = (struct rtd_candidate *) old->candidates.next;
+		
+		fd_list_unlink(&c->chain);
+		free(c->diamid);
+		free(c->realm);
+		free(c);
+	}
+	
+	while (!FD_IS_LIST_EMPTY(&old->errors)) {
+		struct rtd_error * c = (struct rtd_error *) old->errors.next;
+		
+		fd_list_unlink(&c->chain);
+		free(c->nexthop);
+		free(c->erh);
+		free(c);
+	}
+	
+	free(old);
+	
+	return;
+}
+
+/* Add a peer to the candidates list. The source is our local peer list, so no need to care for the case here. */
+int  fd_rtd_candidate_add(struct rt_data * rtd, DiamId_t peerid, size_t peeridlen, DiamId_t realm, size_t realmlen)
+{
+	struct fd_list * prev;
+	struct rtd_candidate * new;
+	
+	TRACE_ENTRY("%p %p %zd %p %zd", rtd, peerid, peeridlen, realm, realmlen);
+	CHECK_PARAMS(rtd && peerid && peeridlen);
+	
+	/* Since the peers are ordered when they are added (fd_g_activ_peers) we search for the position from the end -- this should be efficient */
+	for (prev = rtd->candidates.prev; prev != &rtd->candidates; prev = prev->prev) {
+		struct rtd_candidate * cp = (struct rtd_candidate *) prev;
+		int cmp = fd_os_cmp(peerid, peeridlen, cp->diamid, cp->diamidlen);
+		if (cmp > 0)
+			break;
+		if (cmp == 0)
+			/* The candidate is already in the list */
+			return 0;
+	}
+	
+	/* Create the new entry */
+	CHECK_MALLOC( new = malloc(sizeof(struct rtd_candidate)) );
+	memset(new, 0, sizeof(struct rtd_candidate) );
+	fd_list_init(&new->chain, new);
+	CHECK_MALLOC( new->diamid = os0dup(peerid, peeridlen) )
+	new->diamidlen = peeridlen;
+	if (realm) {
+		CHECK_MALLOC( new->realm = os0dup(realm, realmlen) )
+		new->realmlen = realmlen;
+	}
+	
+	/* insert in the list at the correct position */
+	fd_list_insert_after(prev, &new->chain);
+	
+	return 0;
+}
+
+/* Remove a peer from the candidates (if it is found). Case insensitive search since the names are received from other peers */
+void fd_rtd_candidate_del(struct rt_data * rtd, uint8_t * id, size_t idsz)
+{
+	struct fd_list * li;
+	
+	TRACE_ENTRY("%p %p %zd", rtd, id, idsz);
+	CHECK_PARAMS_DO( rtd && id && idsz, return );
+	
+	if (!fd_os_is_valid_DiameterIdentity(id, idsz))
+		/* it cannot be in the list */
+		return;
+	
+	for (li = rtd->candidates.next; li != &rtd->candidates; li = li->next) {
+		struct rtd_candidate * c = (struct rtd_candidate *) li;
+		int cont;
+		int cmp = fd_os_almostcasesrch(id, idsz, c->diamid, c->diamidlen, &cont);
+		
+		if (!cmp) {
+			/* Found it! Remove it */
+			fd_list_unlink(&c->chain);
+			free(c->diamid);
+			free(c->realm);
+			free(c);
+			break;
+		}
+		
+		if (cont)
+			continue;
+		
+		/* The list is guaranteed to be ordered only if not extracted */
+		if (! rtd->extracted)
+			break;
+	}
+	
+	return;
+}
+
+/* If a peer returned a protocol error for this message, save it so that we don't try to send it there again.
+ Case insensitive search since the names are received from other peers*/
+int  fd_rtd_error_add(struct rt_data * rtd, DiamId_t sentto, size_t senttolen, uint8_t * origin, size_t originsz, uint32_t rcode, struct fd_list ** candidates, int * sendingattemtps)
+{
+	struct fd_list * li;
+	int match = 0;
+	
+	TRACE_ENTRY("%p %p %zd %p %zd %u %p %p", rtd, sentto, senttolen, origin, originsz, rcode, candidates, sendingattemtps);
+	CHECK_PARAMS( rtd && sentto && senttolen ); /* origin may be NULL */
+	
+	/* First add the new error entry */
+	for (li = rtd->errors.next; li != &rtd->errors; li = li->next) {
+		struct rtd_error * e = (struct rtd_error *) li;
+		int cmp = fd_os_cmp(sentto, senttolen, e->nexthop, e->nexthoplen);
+		if (cmp > 0)
+			continue;
+		if (!cmp)
+			match = 1;
+		break;
+	}
+	
+	/* If we already had this entry, we should not have sent the message again to this peer... anyway, let's close our eyes. */
+	/* in the normal case, we save the error */
+	if (!match) {
+		/* Add a new entry in the error list */
+		struct rtd_error * new;
+		CHECK_MALLOC( new = malloc(sizeof(struct rtd_error)) );
+		memset(new, 0, sizeof(struct rtd_error));
+		fd_list_init(&new->chain, NULL);
+
+		CHECK_MALLOC(new->nexthop = os0dup(sentto, senttolen));
+		new->nexthoplen = senttolen;
+		
+		if (origin) {
+			if (!originsz) {
+				originsz=strlen((char *)origin);
+			} else {
+				if (!fd_os_is_valid_DiameterIdentity(origin, originsz)){
+					TRACE_DEBUG(FULL, "Received error %d from peer with invalid Origin-Host AVP, not saved", rcode);
+					origin = NULL;
+					goto after_origin;
+				}
+			}
+			CHECK_MALLOC( new->erh = (DiamId_t)os0dup(origin, originsz) );
+			new->erhlen = originsz;
+		}
+after_origin:
+		new->code = rcode;
+		fd_list_insert_before(li, &new->chain);
+	}
+	
+	/* Finally, remove this (these) peers from the candidate list */
+	fd_rtd_candidate_del(rtd, (os0_t)sentto, senttolen);
+	if (origin)
+		fd_rtd_candidate_del(rtd, origin, originsz);
+	
+	if (candidates)
+		*candidates = &rtd->candidates;
+	
+	if (sendingattemtps)
+		*sendingattemtps = rtd->extracted;
+	
+	/* Done! */
+	return 0;
+}
+
+/* Only retrieve the number of times this message has been processed by the routing-out mechanism (i.e. number of times it was failed over) */
+int  fd_rtd_get_nb_attempts(struct rt_data * rtd, int * sendingattemtps)
+{
+	TRACE_ENTRY("%p %p", rtd, sendingattemtps);
+	CHECK_PARAMS( rtd && sendingattemtps );
+	
+	*sendingattemtps = rtd->extracted;
+	
+	/* Done! */
+	return 0;
+}
+
+/* Extract the list of valid candidates, and initialize their scores */
+void fd_rtd_candidate_extract(struct rt_data * rtd, struct fd_list ** candidates, int ini_score)
+{
+	struct fd_list * li;
+	
+	TRACE_ENTRY("%p %p", rtd, candidates);
+	CHECK_PARAMS_DO( candidates, return );
+	CHECK_PARAMS_DO( rtd, { *candidates = NULL; return; } );
+	
+	*candidates = &rtd->candidates;
+	
+	/* Reset all scores to INITIAL score */
+	for (li = rtd->candidates.next; li != &rtd->candidates; li = li->next) {
+		struct rtd_candidate * c = (struct rtd_candidate *) li;
+		c->score = ini_score;
+	}
+	
+	rtd->extracted += 1;
+	return;
+}
+
+/* Reorder the list of peers. If several peer have the same highest score, they are randomized. */
+int  fd_rtd_candidate_reorder(struct fd_list * candidates)
+{
+	struct fd_list unordered = FD_LIST_INITIALIZER(unordered), *li;
+	struct fd_list highest = FD_LIST_INITIALIZER(highest);
+	int hs = -1;
+	
+	TRACE_ENTRY("%p", candidates);
+	CHECK_PARAMS( candidates );
+	
+	/* First, move all items from candidates to the undordered list */
+	fd_list_move_end(&unordered, candidates);
+	
+	/* Now extract each element from unordered and add it back to list ordered by score */
+	while (!FD_IS_LIST_EMPTY(&unordered)) {
+		struct rtd_candidate * c = (struct rtd_candidate *) unordered.next;
+		
+		fd_list_unlink(&c->chain);
+		
+		/* If this candidate has a higher score than the previous ones */
+		if (c->score > hs) {
+			/* Then we move the previous high score items at end of the list */
+			fd_list_move_end(candidates, &highest);
+			
+			/* And the new high score is set */
+			hs = c->score;
+		}
+		
+		/* If this candidate equals the higher score, add it into highest list at a random place */
+		if (c->score == hs) {
+			if (rand() & 1) {
+				fd_list_insert_after(&highest, &c->chain);
+			} else {
+				fd_list_insert_before(&highest, &c->chain);
+			}
+		/* Otherwise, insert at normal place in the list */
+		} else {
+			/* Find the position in ordered candidates list */
+			for (li = candidates->next; li != candidates; li = li->next) {
+				struct rtd_candidate * cnext = (struct rtd_candidate *) li;
+				if (cnext->score >= c->score)
+					break;
+			}
+
+			/* Add the element there */
+			fd_list_insert_before(li, &c->chain);
+		}
+	}
+	
+	/* Now simply move back all the "highest" candidates at the end of the list */
+	fd_list_move_end(candidates, &highest);
+	
+	return 0;
+}
+
diff --git a/libfdproto/sessions.c b/libfdproto/sessions.c
new file mode 100644
index 0000000..b6c94fa
--- /dev/null
+++ b/libfdproto/sessions.c
@@ -0,0 +1,940 @@
+/*********************************************************************************************************
+* Software License Agreement (BSD License)                                                               *
+* Author: Sebastien Decugis <sdecugis@freediameter.net>							 *
+*													 *
+* Copyright (c) 2013, WIDE Project and NICT								 *
+* All rights reserved.											 *
+* 													 *
+* Redistribution and use of this software in source and binary forms, with or without modification, are  *
+* permitted provided that the following conditions are met:						 *
+* 													 *
+* * Redistributions of source code must retain the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer.										 *
+*    													 *
+* * Redistributions in binary form must reproduce the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer in the documentation and/or other						 *
+*   materials provided with the distribution.								 *
+* 													 *
+* * Neither the name of the WIDE Project or NICT nor the 						 *
+*   names of its contributors may be used to endorse or 						 *
+*   promote products derived from this software without 						 *
+*   specific prior written permission of WIDE Project and 						 *
+*   NICT.												 *
+* 													 *
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED *
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
+* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR *
+* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 	 *
+* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 	 *
+* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR *
+* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF   *
+* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.								 *
+*********************************************************************************************************/
+
+/* Sessions module.
+ * 
+ * Basic functionalities to help implementing User sessions state machines from RFC3588.
+ */
+
+#include "fdproto-internal.h"
+
+/*********************** Parameters **********************/
+
+/* Size of the hash table containing the session objects (pow of 2. ex: 6 => 2^6 = 64). must be between 0 and 31. */
+#ifndef SESS_HASH_SIZE
+#define SESS_HASH_SIZE	6
+#endif /* SESS_HASH_SIZE */
+
+/* Default lifetime of a session, in seconds. (31 days = 2678400 seconds) */
+#ifndef SESS_DEFAULT_LIFETIME
+#define SESS_DEFAULT_LIFETIME	2678400
+#endif /* SESS_DEFAULT_LIFETIME */
+
+/********************** /Parameters **********************/
+
+/* Eyescatchers definitions */
+#define SH_EYEC 0x53554AD1
+#define SD_EYEC 0x5355D474
+#define SI_EYEC 0x53551D
+
+/* Macro to check an object is valid */
+#define VALIDATE_SH( _obj ) ( ((_obj) != NULL) && ( ((struct session_handler *)(_obj))->eyec == SH_EYEC) )
+#define VALIDATE_SI( _obj ) ( ((_obj) != NULL) && ( ((struct session         *)(_obj))->eyec == SI_EYEC) )
+
+
+/* Handlers registered by users of the session module */
+struct session_handler {
+	int		  eyec;	/* An eye catcher also used to ensure the object is valid, must be SH_EYEC */
+	int		  id;	/* A unique integer to identify this handler */
+	void 		(*cleanup)(struct sess_state *, os0_t, void *); /* The cleanup function to be called for cleaning a state */
+	session_state_dump state_dump; /* dumper function */
+	void             *opaque; /* a value that is passed as is to the cleanup callback */
+};
+
+static int 		hdl_id = 0;				/* A global counter to initialize the id field */
+static pthread_mutex_t	hdl_lock = PTHREAD_MUTEX_INITIALIZER;	/* lock to protect hdl_id; we could use atomic operations otherwise (less portable) */
+
+
+/* Data structures linked from the sessions, containing the applications states */
+struct state {
+	int			 eyec;	/* Must be SD_EYEC */
+	struct sess_state	*state;	/* The state registered by the application, never NULL (or the whole object is deleted) */
+	struct fd_list		 chain;	/* Chaining in the list of session's states ordered by hdl->id */
+	union {
+		struct session_handler	*hdl;	/* The handler for which this state was registered */
+		os0_t 			 sid;	/* For deleted state, the sid of the session it belong to */
+	};
+};
+
+/* Session object, one for each value of Session-Id AVP */
+struct session {
+	int 		eyec;	/* Eyecatcher, SI_EYEC */
+	
+	os0_t		sid;	/* The \0-terminated Session-Id */
+	size_t		sidlen; /* cached length of sid */
+	uint32_t	hash;	/* computed hash of sid */
+	struct fd_list	chain_h;/* chaining in the hash table of sessions. */
+	
+	struct timespec	timeout;/* Timeout date for the session */
+	struct fd_list	expire;	/* List of expiring sessions, ordered by timeouts. */
+	
+	pthread_mutex_t stlock;	/* A lock to protect the list of states associated with this session */
+	struct fd_list	states;	/* Sentinel for the list of states of this session. */
+	int		msg_cnt;/* Reference counter for the messages pointing to this session */
+	int		is_destroyed; /* boolean telling if fd_sess_detroy has been called on this */
+};
+
+/* Sessions hash table, to allow fast sid to session retrieval */
+static struct {
+	struct fd_list	sentinel;	/* sentinel element for this sublist. The sublist is ordered by hash value, then fd_os_cmp(sid). */
+	pthread_mutex_t lock;		/* the mutex for this sublist -- we might probably change it to rwlock for a little optimization */
+} sess_hash [ 1 << SESS_HASH_SIZE ] ;
+#define H_MASK( __hash ) ((__hash) & (( 1 << SESS_HASH_SIZE ) - 1))
+#define H_LIST( _hash ) (&(sess_hash[H_MASK(_hash)].sentinel))
+#define H_LOCK( _hash ) (&(sess_hash[H_MASK(_hash)].lock    ))
+
+static uint32_t		sess_cnt = 0; /* counts all active session (that are in the expiry list) */
+
+/* The following are used to generate sid values that are eternaly unique */
+static uint32_t   	sid_h;	/* initialized to the current time in fd_sess_init */
+static uint32_t   	sid_l;	/* incremented each time a session id is created */
+static pthread_mutex_t 	sid_lock = PTHREAD_MUTEX_INITIALIZER;
+
+/* Expiring sessions management */
+static struct fd_list	exp_sentinel = FD_LIST_INITIALIZER(exp_sentinel);	/* list of sessions ordered by their timeout date */
+static pthread_mutex_t	exp_lock = PTHREAD_MUTEX_INITIALIZER;	/* lock protecting the list. */
+static pthread_cond_t	exp_cond = PTHREAD_COND_INITIALIZER;	/* condvar used by the expiry mecahinsm. */
+static pthread_t	exp_thr = (pthread_t)NULL; 	/* The expiry thread that handles cleanup of expired sessions */
+
+/* Hierarchy of the locks, to avoid deadlocks:
+ *  hash lock > state lock > expiry lock
+ * i.e. state lock can be taken while holding the hash lock, but not while holding the expiry lock.
+ * As well, the hash lock cannot be taken while holding a state lock.
+ */
+
+/********************************************************************************************************/
+
+/* Initialize a session object. It is not linked now. sid must be already malloc'ed. The hash has already been computed. */
+static struct session * new_session(os0_t sid, size_t sidlen, uint32_t hash)
+{
+	struct session * sess;
+	
+	TRACE_ENTRY("%p %zd", sid, sidlen);
+	CHECK_PARAMS_DO( sid && sidlen, return NULL );
+	
+	CHECK_MALLOC_DO( sess = malloc(sizeof(struct session)), return NULL );
+	memset(sess, 0, sizeof(struct session));
+	
+	sess->eyec = SI_EYEC;
+	
+	sess->sid  = sid;
+	sess->sidlen = sidlen;
+	sess->hash = hash;
+	fd_list_init(&sess->chain_h, sess);
+	
+	CHECK_SYS_DO( clock_gettime(CLOCK_REALTIME, &sess->timeout), return NULL );
+	sess->timeout.tv_sec += SESS_DEFAULT_LIFETIME;
+	fd_list_init(&sess->expire, sess);
+	
+	CHECK_POSIX_DO( pthread_mutex_init(&sess->stlock, NULL), return NULL );
+	fd_list_init(&sess->states, sess);
+	
+	return sess;
+}
+
+/* destroy the session object. It should really be already unlinked... */
+static void del_session(struct session * s)
+{
+	ASSERT(FD_IS_LIST_EMPTY(&s->states));
+	free(s->sid);
+	fd_list_unlink(&s->chain_h);
+	fd_list_unlink(&s->expire);
+	CHECK_POSIX_DO( pthread_mutex_destroy(&s->stlock), /* continue */ );
+	free(s);
+}
+	
+/* The expiry thread */
+static void * exp_fct(void * arg)
+{
+	fd_log_threadname ( "Session/expire" );
+	TRACE_ENTRY( "" );
+	
+	
+	do {
+		struct timespec	now;
+		struct session * first;
+		
+		CHECK_POSIX_DO( pthread_mutex_lock(&exp_lock),  break );
+		pthread_cleanup_push( fd_cleanup_mutex, &exp_lock );
+again:		
+		/* Check if there are expiring sessions available */
+		if (FD_IS_LIST_EMPTY(&exp_sentinel)) {
+			/* Just wait for a change or cancelation */
+			CHECK_POSIX_DO( pthread_cond_wait( &exp_cond, &exp_lock ), break /* this might not pop the cleanup handler, but since we ASSERT(0), it is not the big issue... */ );
+			/* Restart the loop on wakeup */
+			goto again;
+		}
+		
+		/* Get the pointer to the session that expires first */
+		first = (struct session *)(exp_sentinel.next->o);
+		ASSERT( VALIDATE_SI(first) );
+		
+		/* Get the current time */
+		CHECK_SYS_DO(  clock_gettime(CLOCK_REALTIME, &now),  break  );
+
+		/* If first session is not expired, we just wait until it happens */
+		if ( TS_IS_INFERIOR( &now, &first->timeout ) ) {
+			
+			CHECK_POSIX_DO2(  pthread_cond_timedwait( &exp_cond, &exp_lock, &first->timeout ),  
+					ETIMEDOUT, /* ETIMEDOUT is a normal error, continue */,
+					/* on other error, */ break );
+	
+			/* on wakeup, loop */
+			goto again;
+		}
+		
+		/* Now, the first session in the list is expired; destroy it */
+		pthread_cleanup_pop( 0 );
+		CHECK_POSIX_DO( pthread_mutex_unlock(&exp_lock),  break );
+		
+		CHECK_FCT_DO( fd_sess_destroy( &first ), break );
+		
+	} while (1);
+	
+	TRACE_DEBUG(INFO, "A system error occurred in session module! Expiry thread is terminating...");
+	ASSERT(0);
+	return NULL;
+}
+	
+	
+
+/********************************************************************************************************/
+
+/* Initialize the session module */
+int fd_sess_init(void)
+{
+	int i;
+	
+	TRACE_ENTRY( "" );
+	
+	/* Initialize the global counters */
+	sid_h = (uint32_t) time(NULL);
+	sid_l = 0;
+	
+	/* Initialize the hash table */
+	for (i = 0; i < sizeof(sess_hash) / sizeof(sess_hash[0]); i++) {
+		fd_list_init( &sess_hash[i].sentinel, NULL );
+		CHECK_POSIX(  pthread_mutex_init(&sess_hash[i].lock, NULL)  );
+	}
+	
+	return 0;
+}
+
+/* Run this when initializations are complete. */
+int fd_sess_start(void)
+{
+	/* Start session garbage collector (expiry) */
+	CHECK_POSIX(  pthread_create(&exp_thr, NULL, exp_fct, NULL)  );
+	
+	return 0;
+}
+
+/* Terminate */
+void fd_sess_fini(void)
+{
+	TRACE_ENTRY("");
+	CHECK_FCT_DO( fd_thr_term(&exp_thr), /* continue */ );
+	
+	/* Destroy all sessions in the hash table, and the hash table itself? -- How to do it without a race condition ? */
+	
+	return;
+}
+
+/* Create a new handler */
+int fd_sess_handler_create ( struct session_handler ** handler, void (*cleanup)(struct sess_state *, os0_t, void *), session_state_dump dumper, void * opaque )
+{
+	struct session_handler *new;
+	
+	TRACE_ENTRY("%p %p", handler, cleanup);
+	
+	CHECK_PARAMS( handler && cleanup );
+	
+	CHECK_MALLOC( new = malloc(sizeof(struct session_handler)) );
+	memset(new, 0, sizeof(struct session_handler));
+	
+	CHECK_POSIX( pthread_mutex_lock(&hdl_lock) );
+	new->id = ++hdl_id;
+	CHECK_POSIX( pthread_mutex_unlock(&hdl_lock) );
+	
+	new->eyec = SH_EYEC;
+	new->cleanup = cleanup;
+	new->state_dump = dumper;
+	new->opaque = opaque;
+	
+	*handler = new;
+	return 0;
+}
+
+/* Destroy a handler, and all states attached to this handler. This operation is very slow but we don't care since it's rarely used. 
+ * Note that it's better to call this function after all sessions have been deleted... */
+int fd_sess_handler_destroy ( struct session_handler ** handler, void ** opaque )
+{
+	struct session_handler * del;
+	/* place to save the list of states to be cleaned up. We do it after finding them to avoid deadlocks. the "o" field becomes a copy of the sid. */
+	struct fd_list deleted_states = FD_LIST_INITIALIZER( deleted_states );
+	int i;
+	
+	TRACE_ENTRY("%p", handler);
+	CHECK_PARAMS( handler && VALIDATE_SH(*handler) );
+	
+	del = *handler;
+	*handler = NULL;
+	
+	del->eyec = 0xdead; /* The handler is not valid anymore for any other operation */
+	
+	/* Now find all sessions with data registered for this handler, and move this data to the deleted_states list. */
+	for (i = 0; i < sizeof(sess_hash) / sizeof(sess_hash[0]); i++) {
+		struct fd_list * li_si;
+		CHECK_POSIX(  pthread_mutex_lock(&sess_hash[i].lock)  );
+		
+		for (li_si = sess_hash[i].sentinel.next; li_si != &sess_hash[i].sentinel; li_si = li_si->next) { /* for each session in the hash line */
+			struct fd_list * li_st;
+			struct session * sess = (struct session *)(li_si->o);
+			CHECK_POSIX(  pthread_mutex_lock(&sess->stlock)  );
+			for (li_st = sess->states.next; li_st != &sess->states; li_st = li_st->next) { /* for each state in this session */
+				struct state * st = (struct state *)(li_st->o);
+				/* The list is ordered */
+				if (st->hdl->id < del->id)
+					continue;
+				if (st->hdl->id == del->id) {
+					/* This state belongs to the handler we are deleting, move the item to the deleted_states list */
+					fd_list_unlink(&st->chain);
+					st->sid = sess->sid;
+					fd_list_insert_before(&deleted_states, &st->chain);
+				}
+				break;
+			}
+			CHECK_POSIX(  pthread_mutex_unlock(&sess->stlock)  );
+		}
+		CHECK_POSIX(  pthread_mutex_unlock(&sess_hash[i].lock)  );
+	}
+	
+	/* Now, delete all states after calling their cleanup handler */
+	while (!FD_IS_LIST_EMPTY(&deleted_states)) {
+		struct state * st = (struct state *)(deleted_states.next->o);
+		TRACE_DEBUG(FULL, "Calling cleanup handler for session '%s' and data %p", st->sid, st->state);
+		(*del->cleanup)(st->state, st->sid, del->opaque);
+		fd_list_unlink(&st->chain);
+		free(st);
+	}
+	
+	if (opaque)
+		*opaque = del->opaque;
+	
+	/* Free the handler */
+	free(del);
+	
+	return 0;
+}
+
+
+
+/* Create a new session object with the default timeout value, and link it. The refcount is increased by 1, whether the session existed or not */
+int fd_sess_new ( struct session ** session, DiamId_t diamid, size_t diamidlen, uint8_t * opt, size_t optlen )
+{
+	os0_t  sid = NULL;
+	size_t sidlen;
+	uint32_t hash;
+	struct session * sess;
+	struct fd_list * li;
+	int found = 0;
+	int ret = 0;
+	
+	TRACE_ENTRY("%p %p %zd %p %zd", session, diamid, diamidlen, opt, optlen);
+	CHECK_PARAMS( session && (diamid || opt) );
+
+	if (diamid) {	
+		if (!diamidlen) {
+			diamidlen = strlen(diamid);
+		} 
+		/* We check if the string is a valid DiameterIdentity */
+		CHECK_PARAMS( fd_os_is_valid_DiameterIdentity((uint8_t *)diamid, diamidlen) );
+	} else {
+		diamidlen = 0;
+	}
+	if (opt) {	
+		if (!optlen) {
+			optlen = strlen((char *)opt);
+		} else {
+			CHECK_PARAMS( fd_os_is_valid_os0(opt, optlen) );
+		}
+	} else {
+		optlen = 0;
+	}
+		
+	/* Ok, first create the identifier for the string */
+	if (diamid == NULL) {
+		/* opt is the full string */
+		CHECK_MALLOC( sid = os0dup(opt, optlen) );
+		sidlen = optlen;
+	} else {
+		uint32_t sid_h_cpy;
+		uint32_t sid_l_cpy;
+		/* "<diamId>;<high32>;<low32>[;opt]" */
+		sidlen = diamidlen;
+		sidlen += 22; /* max size of ';<high32>;<low32>' */
+		if (opt)
+			sidlen += 1 + optlen; /* ';opt' */
+		sidlen++; /* space for the final \0 also */
+		CHECK_MALLOC( sid = malloc(sidlen) );
+		
+		CHECK_POSIX( pthread_mutex_lock(&sid_lock) );
+		if ( ++sid_l == 0 ) /* overflow */
+			++sid_h;
+		sid_h_cpy = sid_h;
+		sid_l_cpy = sid_l;
+		CHECK_POSIX( pthread_mutex_unlock(&sid_lock) );
+		
+		if (opt) {
+			sidlen = snprintf((char*)sid, sidlen, "%.*s;%u;%u;%.*s", (int)diamidlen, diamid, sid_h_cpy, sid_l_cpy, (int)optlen, opt);
+		} else {
+			sidlen = snprintf((char*)sid, sidlen, "%.*s;%u;%u", (int)diamidlen, diamid, sid_h_cpy, sid_l_cpy);
+		}
+	}
+	
+	hash = fd_os_hash(sid, sidlen);
+	
+	/* Now find the place to add this object in the hash table. */
+	CHECK_POSIX( pthread_mutex_lock( H_LOCK(hash) ) );
+	pthread_cleanup_push( fd_cleanup_mutex, H_LOCK(hash) );
+	
+	for (li = H_LIST(hash)->next; li != H_LIST(hash); li = li->next) {
+		int cmp;
+		struct session * s = (struct session *)(li->o);
+		
+		/* The list is ordered by hash and sid (in case of collisions) */
+		if (s->hash < hash)
+			continue;
+		if (s->hash > hash)
+			break;
+		
+		cmp = fd_os_cmp(s->sid, s->sidlen, sid, sidlen);
+		if (cmp < 0)
+			continue;
+		if (cmp > 0)
+			break;
+		
+		/* A session with the same sid was already in the hash table */
+		found = 1;
+		*session = s;
+		break;
+	}
+	
+	/* If the session did not exist, we can create it & link it in global tables */
+	if (!found) {
+		CHECK_MALLOC_DO(sess = new_session(sid, sidlen, hash),
+			{
+				ret = ENOMEM;
+				free(sid);
+				goto out;
+			} );
+	
+		fd_list_insert_before(li, &sess->chain_h); /* hash table */
+		sess->msg_cnt++;
+	} else {
+		free(sid);
+		
+		CHECK_POSIX( pthread_mutex_lock(&(*session)->stlock) ); 
+		(*session)->msg_cnt++;
+		CHECK_POSIX( pthread_mutex_unlock(&(*session)->stlock) ); 
+		
+		/* it was found: was it previously destroyed? */
+		if ((*session)->is_destroyed == 0) {
+			ret = EALREADY;
+			goto out;
+		} else {
+			/* the session was marked destroyed, let's re-activate it. */
+			sess = *session;
+			sess->is_destroyed = 0;
+			
+			/* update the expiry time */
+			CHECK_SYS_DO( clock_gettime(CLOCK_REALTIME, &sess->timeout), { ASSERT(0); } );
+			sess->timeout.tv_sec += SESS_DEFAULT_LIFETIME;
+		}
+	}
+		
+	/* We must insert in the expiry list */
+	CHECK_POSIX( pthread_mutex_lock( &exp_lock ) );
+	pthread_cleanup_push( fd_cleanup_mutex, &exp_lock );
+
+	/* Find the position in that list. We take it in reverse order */
+	for (li = exp_sentinel.prev; li != &exp_sentinel; li = li->prev) {
+		struct session * s = (struct session *)(li->o);
+		if (TS_IS_INFERIOR( &s->timeout, &sess->timeout ) )
+			break;
+	}
+	fd_list_insert_after( li, &sess->expire );
+	sess_cnt++;
+
+	/* We added a new expiring element, we must signal */
+	if (li == &exp_sentinel) {
+		CHECK_POSIX_DO( pthread_cond_signal(&exp_cond), { ASSERT(0); } ); /* if it fails, we might not pop the cleanup handlers, but this should not happen -- and we'd have a serious problem otherwise */
+	}
+
+	/* We're done with the locked part */
+	pthread_cleanup_pop(0);
+	CHECK_POSIX_DO( pthread_mutex_unlock( &exp_lock ), { ASSERT(0); } ); /* if it fails, we might not pop the cleanup handler, but this should not happen -- and we'd have a serious problem otherwise */
+
+out:
+	;
+	pthread_cleanup_pop(0);
+	CHECK_POSIX( pthread_mutex_unlock( H_LOCK(hash) ) );
+	
+	if (ret) /* in case of error */
+		return ret;
+	
+	*session = sess;
+	return 0;
+}
+
+/* Find or create a session -- the msg refcount is increased */
+int fd_sess_fromsid_msg ( uint8_t * sid, size_t len, struct session ** session, int * new)
+{
+	int ret;
+	
+	TRACE_ENTRY("%p %zd %p %p", sid, len, session, new);
+	CHECK_PARAMS( sid && session );
+	
+	if (!fd_os_is_valid_os0(sid,len)) {
+		TRACE_DEBUG(INFO, "Warning: a Session-Id value contains \\0 chars... (len:%zd, begin:'%.*s') => Debug messages may be truncated.", len, (int)len, sid);
+	}
+	
+	/* All the work is done in sess_new */
+	ret = fd_sess_new ( session, NULL, 0, sid, len );
+	switch (ret) {
+		case 0:
+		case EALREADY:
+			break;
+		
+		default:
+			CHECK_FCT(ret);
+	}
+	
+	if (new)
+		*new = ret ? 0 : 1;
+	
+	return 0;
+}
+
+/* Get the sid of a session */
+int fd_sess_getsid ( struct session * session, os0_t * sid, size_t * sidlen )
+{
+	TRACE_ENTRY("%p %p", session, sid);
+	
+	CHECK_PARAMS( VALIDATE_SI(session) && sid );
+	
+	*sid = session->sid;
+	if (sidlen)
+		*sidlen = session->sidlen;
+	
+	return 0;
+}
+
+/* Change the timeout value of a session */
+int fd_sess_settimeout( struct session * session, const struct timespec * timeout )
+{
+	struct fd_list * li;
+	
+	TRACE_ENTRY("%p %p", session, timeout);
+	CHECK_PARAMS( VALIDATE_SI(session) && timeout );
+	
+	/* Lock -- do we need to lock the hash table as well? I don't think so... */
+	CHECK_POSIX( pthread_mutex_lock( &exp_lock ) );
+	pthread_cleanup_push( fd_cleanup_mutex, &exp_lock );
+	
+	/* Update the timeout */
+	fd_list_unlink(&session->expire);
+	memcpy(&session->timeout, timeout, sizeof(struct timespec));
+	
+	/* Find the new position in expire list. We take it in normal order */
+	for (li = exp_sentinel.next; li != &exp_sentinel; li = li->next) {
+		struct session * s = (struct session *)(li->o);
+
+		if (TS_IS_INFERIOR( &s->timeout, &session->timeout ) )
+			continue;
+
+		break;
+	}
+	fd_list_insert_before( li, &session->expire );
+
+	/* We added a new expiring element, we must signal if it was in first position */
+	if (session->expire.prev == &exp_sentinel) {
+		CHECK_POSIX_DO( pthread_cond_signal(&exp_cond), { ASSERT(0); /* so that we don't have a pending cancellation handler */ } );
+	}
+
+	/* We're done */
+	pthread_cleanup_pop(0);
+	CHECK_POSIX( pthread_mutex_unlock( &exp_lock ) );
+	
+	return 0;
+}
+
+/* Destroy the states associated to a session, and mark it destroyed. */
+int fd_sess_destroy ( struct session ** session )
+{
+	struct session * sess;
+	int destroy_now;
+	os0_t sid;
+	int ret = 0;
+	
+	/* place to save the list of states to be cleaned up. We do it after finding them to avoid deadlocks. the "o" field becomes a copy of the sid. */
+	struct fd_list deleted_states = FD_LIST_INITIALIZER( deleted_states );
+	
+	TRACE_ENTRY("%p", session);
+	CHECK_PARAMS( session && VALIDATE_SI(*session) );
+	
+	sess = *session;
+	*session = NULL;
+	
+	/* Lock the hash line */
+	CHECK_POSIX( pthread_mutex_lock( H_LOCK(sess->hash) ) );
+	pthread_cleanup_push( fd_cleanup_mutex, H_LOCK(sess->hash) );
+	
+	/* Unlink from the expiry list */
+	CHECK_POSIX_DO( pthread_mutex_lock( &exp_lock ), { ASSERT(0); /* otherwise cleanup handler is not pop'd */ } );
+	if (!FD_IS_LIST_EMPTY(&sess->expire)) {
+		sess_cnt--;
+		fd_list_unlink( &sess->expire ); /* no need to signal the condition here */
+	}
+	CHECK_POSIX_DO( pthread_mutex_unlock( &exp_lock ), { ASSERT(0); /* otherwise cleanup handler is not pop'd */ } );
+	
+	/* Now move all states associated to this session into deleted_states */
+	CHECK_POSIX_DO( pthread_mutex_lock( &sess->stlock ), { ASSERT(0); /* otherwise cleanup handler is not pop'd */ } );
+	while (!FD_IS_LIST_EMPTY(&sess->states)) {
+		struct state * st = (struct state *)(sess->states.next->o);
+		fd_list_unlink(&st->chain);
+		fd_list_insert_before(&deleted_states, &st->chain);
+	}
+	CHECK_POSIX_DO( pthread_mutex_unlock( &sess->stlock ), { ASSERT(0); /* otherwise cleanup handler is not pop'd */ } );
+	
+	/* Mark the session as destroyed */
+	destroy_now = (sess->msg_cnt == 0);
+	if (destroy_now) {
+		fd_list_unlink( &sess->chain_h );
+		sid = sess->sid;
+	} else {
+		sess->is_destroyed = 1;
+		CHECK_MALLOC_DO( sid = os0dup(sess->sid, sess->sidlen), ret = ENOMEM );
+	}
+	pthread_cleanup_pop(0);
+	CHECK_POSIX( pthread_mutex_unlock( H_LOCK(sess->hash) ) );
+	
+	if (ret)
+		return ret;
+	
+	/* Now, really delete the states */
+	while (!FD_IS_LIST_EMPTY(&deleted_states)) {
+		struct state * st = (struct state *)(deleted_states.next->o);
+		fd_list_unlink(&st->chain);
+		TRACE_DEBUG(FULL, "Calling handler %p cleanup for state %p registered with session '%s'", st->hdl, st, sid);
+		(*st->hdl->cleanup)(st->state, sid, st->hdl->opaque);
+		free(st);
+	}
+	
+	/* Finally, destroy the session itself, if it is not referrenced by any message anymore */
+	if (destroy_now) {
+		del_session(sess);
+	} else {
+		free(sid);
+	}
+	
+	return 0;
+}
+
+/* Destroy a session if it is not used */
+int fd_sess_reclaim ( struct session ** session )
+{
+	struct session * sess;
+	uint32_t hash;
+	int destroy_now = 0;
+	
+	TRACE_ENTRY("%p", session);
+	CHECK_PARAMS( session && VALIDATE_SI(*session) );
+	
+	sess = *session;
+	hash = sess->hash;
+	*session = NULL;
+	
+	CHECK_POSIX( pthread_mutex_lock( H_LOCK(hash) ) );
+	pthread_cleanup_push( fd_cleanup_mutex, H_LOCK(hash) );
+	CHECK_POSIX_DO( pthread_mutex_lock( &sess->stlock ), { ASSERT(0); /* otherwise, cleanup not poped on FreeBSD */ } );
+	pthread_cleanup_push( fd_cleanup_mutex, &sess->stlock );
+	CHECK_POSIX_DO( pthread_mutex_lock( &exp_lock ), { ASSERT(0); /* otherwise, cleanup not poped on FreeBSD */ } );
+	
+	/* We only do something if the states list is empty */
+	if (FD_IS_LIST_EMPTY(&sess->states)) {
+		/* In this case, we do as in destroy */
+		fd_list_unlink( &sess->expire );
+		destroy_now = (sess->msg_cnt == 0);
+		if (destroy_now) {
+			fd_list_unlink(&sess->chain_h);
+		} else {
+			/* just mark it as destroyed, it will be freed when the last message stops referencing it */
+			sess->is_destroyed = 1;
+		}
+	}
+	
+	CHECK_POSIX_DO( pthread_mutex_unlock( &exp_lock ), { ASSERT(0); /* otherwise, cleanup not poped on FreeBSD */ } );
+	pthread_cleanup_pop(0);
+	CHECK_POSIX_DO( pthread_mutex_unlock( &sess->stlock ), { ASSERT(0); /* otherwise, cleanup not poped on FreeBSD */ } );
+	pthread_cleanup_pop(0);
+	CHECK_POSIX( pthread_mutex_unlock( H_LOCK(hash) ) );
+	
+	if (destroy_now)
+		del_session(sess);
+	
+	return 0;
+}
+
+/* Save a state information with a session */
+int fd_sess_state_store ( struct session_handler * handler, struct session * session, struct sess_state ** state )
+{
+	struct state *new;
+	struct fd_list * li;
+	int already = 0;
+	int ret = 0;
+	
+	TRACE_ENTRY("%p %p %p", handler, session, state);
+	CHECK_PARAMS( handler && VALIDATE_SH(handler) && session && VALIDATE_SI(session) && (!session->is_destroyed) && state );
+	
+	/* Lock the session state list */
+	CHECK_POSIX( pthread_mutex_lock(&session->stlock) );
+	pthread_cleanup_push( fd_cleanup_mutex, &session->stlock );
+			
+	/* Create the new state object */
+	CHECK_MALLOC_DO(new = malloc(sizeof(struct state)), { ret = ENOMEM; goto out; } );
+	memset(new, 0, sizeof(struct state));
+	
+	new->eyec = SD_EYEC;
+	new->state= *state;
+	fd_list_init(&new->chain, new);
+	new->hdl = handler;
+	
+	/* find place for this state in the list */
+	for (li = session->states.next; li != &session->states; li = li->next) {
+		struct state * st = (struct state *)(li->o);
+		/* The list is ordered by handler's id */
+		if (st->hdl->id < handler->id)
+			continue;
+		
+		if (st->hdl->id == handler->id) {
+			TRACE_DEBUG(INFO, "A state was already stored for session '%s' and handler '%p', at location %p", session->sid, st->hdl, st->state);
+			already = EALREADY;
+		}
+		
+		break;
+	}
+	
+	if (!already) {
+		fd_list_insert_before(li, &new->chain);
+		*state = NULL;
+	} else {
+		free(new);
+	}
+out:
+	;	
+	pthread_cleanup_pop(0);
+	CHECK_POSIX( pthread_mutex_unlock(&session->stlock) );
+	
+	return ret ?: already;
+}
+
+/* Get the data back */
+int fd_sess_state_retrieve ( struct session_handler * handler, struct session * session, struct sess_state ** state )
+{
+	struct fd_list * li;
+	struct state * st = NULL;
+	
+	TRACE_ENTRY("%p %p %p", handler, session, state);
+	CHECK_PARAMS( handler && VALIDATE_SH(handler) && session && VALIDATE_SI(session) && state );
+	
+	*state = NULL;
+	
+	/* Lock the session state list */
+	CHECK_POSIX( pthread_mutex_lock(&session->stlock) );
+	pthread_cleanup_push( fd_cleanup_mutex, &session->stlock );
+	
+	/* find the state in the list */
+	for (li = session->states.next; li != &session->states; li = li->next) {
+		st = (struct state *)(li->o);
+		
+		/* The list is ordered by handler's id */
+		if (st->hdl->id > handler->id)
+			break;
+	}
+	
+	/* If we found the state */
+	if (st && (st->hdl == handler)) {
+		fd_list_unlink(&st->chain);
+		*state = st->state;
+		free(st);
+	}
+	
+	pthread_cleanup_pop(0);
+	CHECK_POSIX( pthread_mutex_unlock(&session->stlock) );
+	
+	return 0;
+}
+
+/* For the messages module */
+int fd_sess_fromsid ( uint8_t * sid, size_t len, struct session ** session, int * new)
+{
+	TRACE_ENTRY("%p %zd %p %p", sid, len, session, new);
+	CHECK_PARAMS( sid && len && session );
+	
+	/* Get the session object */
+	CHECK_FCT( fd_sess_fromsid_msg ( sid, len, session, new) );
+	
+	/* Decrease the refcount */
+	CHECK_POSIX( pthread_mutex_lock(&(*session)->stlock) );
+	(*session)->msg_cnt--; /* was increased in fd_sess_new */
+	CHECK_POSIX( pthread_mutex_unlock(&(*session)->stlock) );
+		
+	/* Done */
+	return 0;
+}
+
+int fd_sess_ref_msg ( struct session * session )
+{
+	TRACE_ENTRY("%p", session);
+	CHECK_PARAMS( VALIDATE_SI(session) );
+
+	/* Update the msg refcount */
+	CHECK_POSIX( pthread_mutex_lock(&session->stlock) );
+	session->msg_cnt++;
+	CHECK_POSIX( pthread_mutex_unlock(&session->stlock) );
+	
+	return 0;
+}
+
+int fd_sess_reclaim_msg ( struct session ** session )
+{
+	int reclaim;
+	uint32_t hash;
+	
+	TRACE_ENTRY("%p", session);
+	CHECK_PARAMS( session && VALIDATE_SI(*session) );
+	
+	/* Lock the hash line to avoid possibility that session is freed while we are reclaiming */
+	hash = (*session)->hash;
+	CHECK_POSIX( pthread_mutex_lock( H_LOCK(hash)) );
+	pthread_cleanup_push( fd_cleanup_mutex, H_LOCK(hash) ); 
+
+	/* Update the msg refcount */
+	CHECK_POSIX( pthread_mutex_lock(&(*session)->stlock) );
+	reclaim = (*session)->msg_cnt;
+	(*session)->msg_cnt = reclaim - 1;
+	CHECK_POSIX( pthread_mutex_unlock(&(*session)->stlock) );
+	
+	/* Ok, now unlock the hash line */
+	pthread_cleanup_pop( 0 );
+	CHECK_POSIX( pthread_mutex_unlock( H_LOCK(hash) ) );
+	
+	/* and reclaim if no message references the session anymore */
+	if (reclaim == 1) {
+		CHECK_FCT(fd_sess_reclaim ( session ));
+	} else {
+		*session = NULL;
+	}
+	return 0;
+}
+
+
+
+/* Dump functions */
+DECLARE_FD_DUMP_PROTOTYPE(fd_sess_dump, struct session * session, int with_states)
+{
+	FD_DUMP_HANDLE_OFFSET();
+	
+	CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "{session}(@%p): ", session), return NULL);
+	
+	if (!VALIDATE_SI(session)) {
+		CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "INVALID/NULL"), return NULL);
+	} else {
+		char timebuf[30];
+		struct tm tm;
+
+		strftime(timebuf, sizeof(timebuf), "%D,%T", localtime_r( &session->timeout.tv_sec , &tm ));
+		CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "'%s'(%zd) h:%x m:%d d:%d to:%s.%06ld",
+							session->sid, session->sidlen, session->hash, session->msg_cnt, session->is_destroyed,
+							timebuf, session->timeout.tv_nsec/1000), 
+				 return NULL);
+		
+		if (with_states) {
+			struct fd_list * li;
+			CHECK_POSIX_DO( pthread_mutex_lock(&session->stlock), /* ignore */ );
+			pthread_cleanup_push( fd_cleanup_mutex, &session->stlock );
+			
+			for (li = session->states.next; li != &session->states; li = li->next) {
+				struct state * st = (struct state *)(li->o);
+				CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "\n  {state i:%d}(@%p): ", st->hdl->id, st), return NULL);
+				if (st->hdl->state_dump) {
+					CHECK_MALLOC_DO( (*st->hdl->state_dump)( FD_DUMP_STD_PARAMS, st->state), 
+							fd_dump_extend( FD_DUMP_STD_PARAMS, "[dumper error]"));
+				} else {
+					CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "<%p>", st->state), return NULL);
+				}
+			}
+			
+			pthread_cleanup_pop(0);
+			CHECK_POSIX_DO( pthread_mutex_unlock(&session->stlock), /* ignore */ );
+		}
+	}
+	
+	return *buf;
+}
+
+DECLARE_FD_DUMP_PROTOTYPE(fd_sess_dump_hdl, struct session_handler * handler)
+{
+	FD_DUMP_HANDLE_OFFSET();
+	
+	CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "{sesshdl}(@%p): ", handler), return NULL);
+	
+	if (!VALIDATE_SH(handler)) {
+		CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "INVALID/NULL"), return NULL);
+	} else {
+		CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "i:%d cl:%p d:%p o:%p", handler->id, handler->cleanup, handler->state_dump, handler->opaque), return NULL);
+	}
+	return *buf;
+}	
+
+int fd_sess_getcount(uint32_t *cnt)
+{
+	CHECK_PARAMS(cnt);
+	CHECK_POSIX( pthread_mutex_lock( &exp_lock ) );
+	*cnt = sess_cnt;
+	CHECK_POSIX( pthread_mutex_unlock( &exp_lock ) );
+	return 0;
+}
diff --git a/libfdproto/utils.c b/libfdproto/utils.c
new file mode 100644
index 0000000..f2440cf
--- /dev/null
+++ b/libfdproto/utils.c
@@ -0,0 +1,84 @@
+/*********************************************************************************************************
+* Software License Agreement (BSD License)                                                               *
+* Author: Sebastien Decugis <sdecugis@freediameter.net>							 *
+*													 *
+* Copyright (c) 2013, WIDE Project and NICT								 *
+* All rights reserved.											 *
+* 													 *
+* Redistribution and use of this software in source and binary forms, with or without modification, are  *
+* permitted provided that the following conditions are met:						 *
+* 													 *
+* * Redistributions of source code must retain the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer.										 *
+*    													 *
+* * Redistributions in binary form must reproduce the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer in the documentation and/or other						 *
+*   materials provided with the distribution.								 *
+* 													 *
+* * Neither the name of the WIDE Project or NICT nor the 						 *
+*   names of its contributors may be used to endorse or 						 *
+*   promote products derived from this software without 						 *
+*   specific prior written permission of WIDE Project and 						 *
+*   NICT.												 *
+* 													 *
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED *
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
+* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR *
+* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 	 *
+* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 	 *
+* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR *
+* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF   *
+* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.								 *
+*********************************************************************************************************/
+
+#include "fdproto-internal.h"
+
+DECLARE_FD_DUMP_PROTOTYPE(fd_sa_dump, sSA * sa, int flags) 
+{
+	char addrbuf[INET6_ADDRSTRLEN];
+	char servbuf[32];
+	int rc;
+	FD_DUMP_HANDLE_OFFSET();
+	
+	servbuf[0] = 0;
+	
+	if (sa) {
+		if (sSAport(sa)) {
+			rc = getnameinfo(sa, sSAlen( sa ), addrbuf, sizeof(addrbuf), servbuf, sizeof(servbuf), flags);
+		} else {
+			rc = getnameinfo(sa, sSAlen( sa ), addrbuf, sizeof(addrbuf), NULL, 0, flags);
+		}
+		if (rc) {
+			CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "%s", gai_strerror(rc)), return NULL);
+		} else {
+			if (servbuf[0]) {
+				CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "%s(%s)", &addrbuf[0], &servbuf[0]), return NULL);
+			} else {
+				CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "%s", &addrbuf[0]), return NULL);
+			}
+		}
+	} else {
+		CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "(NULL / ANY)"), return NULL);
+	}
+	return *buf;
+}
+
+void fd_sa_sdump_numeric(char * buf /* must be at least sSA_DUMP_STRLEN */, sSA * sa)
+{
+	char addrbuf[INET6_ADDRSTRLEN];
+	char servbuf[32];
+	
+	if (sa) {
+		int rc = getnameinfo(sa, sSAlen( sa ), addrbuf, sizeof(addrbuf), servbuf, sizeof(servbuf), NI_NUMERICHOST | NI_NUMERICSERV);
+		if (rc) {
+			snprintf(buf, sSA_DUMP_STRLEN, "%s", gai_strerror(rc));
+		} else {
+			snprintf(buf, sSA_DUMP_STRLEN, "%s(%s)", addrbuf, servbuf);
+		}
+	} else {
+		snprintf(buf, sSA_DUMP_STRLEN, "(NULL / ANY)");
+	}
+	
+}
diff --git a/libfdproto/version.c b/libfdproto/version.c
new file mode 100644
index 0000000..48dcf8f
--- /dev/null
+++ b/libfdproto/version.c
@@ -0,0 +1,47 @@
+/*********************************************************************************************************
+* Software License Agreement (BSD License)                                                               *
+* Author: Sebastien Decugis <sdecugis@freediameter.net>							 *
+*													 *
+* Copyright (c) 2013, WIDE Project and NICT								 *
+* All rights reserved.											 *
+* 													 *
+* Redistribution and use of this software in source and binary forms, with or without modification, are  *
+* permitted provided that the following conditions are met:						 *
+* 													 *
+* * Redistributions of source code must retain the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer.										 *
+*    													 *
+* * Redistributions in binary form must reproduce the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer in the documentation and/or other						 *
+*   materials provided with the distribution.								 *
+* 													 *
+* * Neither the name of the WIDE Project or NICT nor the 						 *
+*   names of its contributors may be used to endorse or 						 *
+*   promote products derived from this software without 						 *
+*   specific prior written permission of WIDE Project and 						 *
+*   NICT.												 *
+* 													 *
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED *
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
+* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR *
+* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 	 *
+* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 	 *
+* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR *
+* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF   *
+* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.								 *
+*********************************************************************************************************/
+
+#include "fdproto-internal.h"
+#include <freeDiameter/version.h>
+
+#ifdef FD_PROJECT_VERSION_HG
+# define FD_LIBFDPROTO_VERSION \
+	_stringize(FD_PROJECT_VERSION_MAJOR) "." _stringize(FD_PROJECT_VERSION_MINOR) "." _stringize(FD_PROJECT_VERSION_REV) "-" FD_PROJECT_VERSION_HG_VAL
+#else
+# define FD_LIBFDPROTO_VERSION \
+	_stringize(FD_PROJECT_VERSION_MAJOR) "." _stringize(FD_PROJECT_VERSION_MINOR) "." _stringize(FD_PROJECT_VERSION_REV)
+#endif
+
+const char fd_libproto_version[] = FD_LIBFDPROTO_VERSION;
diff --git a/test.txt b/test.txt
deleted file mode 100644
index 079f188..0000000
--- a/test.txt
+++ /dev/null
@@ -1 +0,0 @@
-push test
diff --git a/test2.txt b/test2.txt
deleted file mode 100644
index 323b371..0000000
--- a/test2.txt
+++ /dev/null
@@ -1 +0,0 @@
-this is push test2
diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt
new file mode 100644
index 0000000..eaaaa94
--- /dev/null
+++ b/tests/CMakeLists.txt
@@ -0,0 +1,117 @@
+# Test directory
+PROJECT("freeDiameter tests" C)
+
+# give the possibility to configure the timeout duration for the tests
+OPTION(TEST_TIMEOUT "Timeout for the tests, in seconds (default: 120)?")
+IF(TEST_TIMEOUT)
+	ADD_DEFINITIONS(-DTEST_TIMEOUT=${TEST_TIMEOUT})
+ENDIF(TEST_TIMEOUT)
+
+# default command line for the tests
+OPTION(OPT_TEST_ARGUMENTS "Specify the default arguments for the tests" OFF)
+IF(OPT_TEST_ARGUMENTS)
+	SET(TEST_ARGUMENTS ${OPT_TEST_ARGUMENTS})
+ELSE(OPT_TEST_ARGUMENTS)
+	SET(TEST_ARGUMENTS "")
+ENDIF(OPT_TEST_ARGUMENTS)
+
+
+#############################
+# List the test cases
+SET(TEST_LIST
+	testsctp
+	testostr
+	testfifo
+	testpeers
+	testdict
+	testmesg
+	testmesg_stress
+	testsess
+	testdisp
+	testcnx
+	testloadext
+)
+
+#############################
+# Some parameters for the tests
+
+ADD_DEFINITIONS(-DTEST_DEBUG)
+ADD_DEFINITIONS(-DBUILD_DIR="${CMAKE_BINARY_DIR}")
+
+INCLUDE_DIRECTORIES( "../libfdproto" )
+INCLUDE_DIRECTORIES( "../libfdcore" )
+INCLUDE_DIRECTORIES(${LFDCORE_INCLUDES})
+
+
+SET(testcnx_ADDITIONAL_LIB  ${CLOCK_GETTIME_LIBS})
+SET(testfifo_ADDITIONAL_LIB ${CLOCK_GETTIME_LIBS})
+SET(testsess_ADDITIONAL_LIB ${CLOCK_GETTIME_LIBS})
+SET(testloadext_ADDITIONAL_LIB ${CMAKE_DL_LIBS})
+SET(testmesg_stress_ADDITIONAL_LIB ${CLOCK_GETTIME_LIBS} ${CMAKE_DL_LIBS})
+
+##############################
+# App_acct test
+
+IF(BUILD_APP_ACCT OR ALL_EXTENSIONS)
+	OPTION(TEST_APP_ACCT "Test app_acct extension? (Requires a configured database, see testappacct.c for details)" OFF)
+	IF(TEST_APP_ACCT)
+	
+		OPTION(TEST_APP_ACCT_CONNINFO "The connection string to the database")
+		IF(TEST_APP_ACCT_CONNINFO)
+			ADD_DEFINITIONS(-DTEST_CONNINFO="${TEST_APP_ACCT_CONNINFO}")
+		ENDIF(TEST_APP_ACCT_CONNINFO)
+	
+		SET(TEST_LIST ${TEST_LIST} testappacct)
+
+		# Extension dependencies
+		FIND_PACKAGE(PostgreSQL REQUIRED)
+		INCLUDE_DIRECTORIES(${POSTGRESQL_INCLUDE_DIR})
+		SET(testappacct_ADDITIONAL_LIB ${POSTGRESQL_LIBRARIES})
+
+		# List of source files, copied from the extension CMakeLists.
+		BISON_FILE(../extensions/app_acct/acct_conf.y)
+		FLEX_FILE(../extensions/app_acct/acct_conf.l)
+		#SET_SOURCE_FILES_PROPERTIES(lex.acct_conf.c acct_conf.tab.c PROPERTIES COMPILE_FLAGS "-I ${CMAKE_CURRENT_SOURCE_DIR}")
+		
+		SET( APP_ACCT_SRC
+			app_acct.h
+			app_acct.c
+			acct_db.c
+			acct_records.c
+		)
+		SET( APP_ACCT_SRC_GEN
+			lex.acct_conf.c
+			acct_conf.tab.c
+			acct_conf.tab.h
+		)
+
+		# The extension headers
+		INCLUDE_DIRECTORIES( "../extensions/app_acct" )
+
+		SET(testappacct_ADDITIONAL "")
+
+		FOREACH( SRC_FILE ${APP_ACCT_SRC})
+		   SET(testappacct_ADDITIONAL ${testappacct_ADDITIONAL} "../extensions/app_acct/${SRC_FILE}")
+		ENDFOREACH(SRC_FILE)
+
+		FOREACH( SRC_FILE ${APP_ACCT_SRC_GEN})
+		   SET(testappacct_ADDITIONAL ${testappacct_ADDITIONAL} "${CMAKE_CURRENT_BINARY_DIR}/../extensions/app_acct/${SRC_FILE}")
+		ENDFOREACH(SRC_FILE)
+
+	ENDIF(TEST_APP_ACCT)
+ENDIF(BUILD_APP_ACCT OR ALL_EXTENSIONS)
+
+
+#############################
+# Compile each test
+FOREACH( TEST ${TEST_LIST} )
+   ADD_EXECUTABLE(${TEST} ${TEST}.c tests.h ${${TEST}_ADDITIONAL})
+   TARGET_LINK_LIBRARIES(${TEST} libfdproto libfdcore ${GNUTLS_LIBRARIES} ${GCRYPT_LIBRARY} ${${TEST}_ADDITIONAL_LIB})
+   ADD_TEST(${TEST} ${EXECUTABLE_OUTPUT_PATH}/${TEST} ${TEST_ARGUMENTS})
+ENDFOREACH( TEST )
+
+
+####
+## INSTALL section ##
+
+# we do not install the tests
diff --git a/tests/testappacct.c b/tests/testappacct.c
new file mode 100644
index 0000000..2ec94f3
--- /dev/null
+++ b/tests/testappacct.c
@@ -0,0 +1,278 @@
+/*********************************************************************************************************
+* Software License Agreement (BSD License)                                                               *
+* Author: Sebastien Decugis <sdecugis@freediameter.net>							 *
+*													 *
+* Copyright (c) 2013, WIDE Project and NICT								 *
+* All rights reserved.											 *
+* 													 *
+* Redistribution and use of this software in source and binary forms, with or without modification, are  *
+* permitted provided that the following conditions are met:						 *
+* 													 *
+* * Redistributions of source code must retain the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer.										 *
+*    													 *
+* * Redistributions in binary form must reproduce the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer in the documentation and/or other						 *
+*   materials provided with the distribution.								 *
+* 													 *
+* * Neither the name of the WIDE Project or NICT nor the 						 *
+*   names of its contributors may be used to endorse or 						 *
+*   promote products derived from this software without 						 *
+*   specific prior written permission of WIDE Project and 						 *
+*   NICT.												 *
+* 													 *
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED *
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
+* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR *
+* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 	 *
+* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 	 *
+* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR *
+* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF   *
+* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.								 *
+*********************************************************************************************************/
+
+#include "tests.h"
+
+/* The connection string to the database */
+#ifndef TEST_CONNINFO
+#error "Please specify the conninfo information"
+#endif /* TEST_CONNINFO */
+
+/* The table used for tests. This table will receive the following instructions:
+DROP TABLE <table>;
+CREATE TABLE <table>
+(
+  recorded_on timestamp with time zone NOT NULL,
+  "Accounting-Record-Type" integer,
+  "Session-Id" bytea,
+  "Accounting-Record-Number" integer,
+  "Route-Record1" bytea,
+  "Route-Record2" bytea,
+  "Route-Record3" bytea,
+  "Route-Record4" bytea
+);
+*/
+#define TABLE "incoming_test"
+
+#include "app_acct.h"
+#include <libpq-fe.h>
+
+static int add_avp_in_conf(char * avpname, int multi) 
+{
+	struct acct_conf_avp *new;
+	struct dict_object * dict;
+	struct dict_avp_data dictdata;
+
+	/* Validate the avp name first */
+	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, avpname, &dict, ENOENT) );
+	CHECK_FCT( fd_dict_getval( dict, &dictdata ));
+
+	/* Create a new entry */
+	CHECK_MALLOC( new = malloc(sizeof(struct acct_conf_avp)) );
+	memset(new, 0, sizeof(struct acct_conf_avp));
+	fd_list_init(&new->chain, NULL);
+	new->avpname = avpname;
+	new->avpobj = dict;
+	new->avptype = dictdata.avp_basetype;
+	new->multi = multi;
+
+	/* Add this new entry at the end of the list */
+	fd_list_insert_before( &acct_config->avps, &new->chain );
+	
+	return 0;
+}
+
+#define LOCAL_ID	"test.app.acct"
+#define LOCAL_REALM	"app.acct"
+
+/* Main test routine */
+int main(int argc, char *argv[])
+{
+	extern pthread_key_t connk; /* in acct_db.c */
+	PGconn *conn;
+	extern int fd_ext_init(int major, int minor, char * conffile); /* defined in include's extension.h */
+	extern void fd_ext_fini(void); /* defined in the extension itself */
+	struct msg * msg;
+	os0_t sess_bkp;
+	size_t sess_bkp_len;
+	
+	/* First, initialize the daemon modules */
+	INIT_FD();
+	fd_g_config->cnf_diamid = strdup(LOCAL_ID);
+	fd_g_config->cnf_diamid_len = CONSTSTRLEN(LOCAL_ID);
+	fd_g_config->cnf_diamrlm = strdup(LOCAL_REALM);
+	fd_g_config->cnf_diamrlm_len = CONSTSTRLEN(LOCAL_REALM);
+	
+	CHECK( 0, fd_queues_init()  );
+	CHECK( 0, fd_msg_init()  );
+	CHECK( 0, fd_rtdisp_init()  );
+	
+	/* Initialize the extension configuration for the test */
+	{
+		CHECK( 0, acct_conf_init() );
+		acct_config->conninfo = strdup(TEST_CONNINFO);
+		acct_config->tablename = strdup(TABLE);
+		acct_config->tsfield = strdup("recorded_on");
+		CHECK( 0, add_avp_in_conf(strdup("Session-Id"), 0) );
+		CHECK( 0, add_avp_in_conf(strdup("Accounting-Record-Type"), 0) );
+		CHECK( 0, add_avp_in_conf(strdup("Accounting-Record-Number"), 0) );
+		CHECK( 0, add_avp_in_conf(strdup("Route-Record"), 4) );
+		
+		/* Now, call the one of the extension */
+		CHECK( 0, fd_ext_init(FD_PROJECT_VERSION_MAJOR, FD_PROJECT_VERSION_MINOR,NULL) );
+		conn = pthread_getspecific(connk);
+	}
+	
+	/* Drop and recreate the table for the test */
+	{
+		PGresult * res;
+		CHECK( CONNECTION_OK, PQstatus(conn) );
+		
+		res = PQexec(conn, "DROP TABLE " TABLE ";");
+		CHECK( PGRES_COMMAND_OK, PQresultStatus(res) );
+		PQclear(res);
+		
+		res = PQexec(conn, "CREATE TABLE " TABLE " ( "
+					"  recorded_on timestamp with time zone NOT NULL, "
+					"  \"Accounting-Record-Type\" integer, "
+					"  \"Session-Id\" bytea, "
+					"  \"Accounting-Record-Number\" integer, "
+					"  \"Route-Record1\" bytea, "
+					"  \"Route-Record2\" bytea, "
+					"  \"Route-Record3\" bytea, "
+					"  \"Route-Record4\" bytea "
+					");"
+				);
+		CHECK( PGRES_COMMAND_OK, PQresultStatus(res) );
+		PQclear(res);
+	}
+	
+	/* OK, we are ready to test now. Create an ACR message that will pass the ABNF check */
+	{
+		struct dict_object * d = NULL;
+		struct avp *avp = NULL;
+		union avp_value avp_val;
+
+		/* Now find the ACR dictionary object */
+		CHECK( 0, fd_dict_search ( fd_g_config->cnf_dict, DICT_COMMAND, CMD_BY_NAME, "Accounting-Request", &d, ENOENT ) );
+
+		/* Create the instance */
+		CHECK( 0, fd_msg_new ( d, MSGFL_ALLOC_ETEID, &msg ) );
+		
+		/* App id */
+		{
+			struct msg_hdr * h;
+			CHECK( 0, fd_msg_hdr( msg, &h ) );
+			h->msg_appl = 3;
+		}
+		
+		/* sid */
+		{
+			struct session * sess = NULL;
+			os0_t s;
+			CHECK( 0, fd_sess_new( &sess, fd_g_config->cnf_diamid, fd_g_config->cnf_diamid_len, NULL, 0) );
+			CHECK( 0, fd_sess_getsid(sess, &s, &sess_bkp_len) );
+			CHECK( 1, (sess_bkp = os0dup(s, sess_bkp_len)) ? 1 : 0);
+
+			CHECK( 0, fd_dict_search ( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Session-Id", &d, ENOENT ) );
+			CHECK( 0, fd_msg_avp_new ( d, 0, &avp ) );
+			memset(&avp_val, 0, sizeof(avp_val));
+			avp_val.os.data = sess_bkp;
+			avp_val.os.len = sess_bkp_len;
+			CHECK( 0, fd_msg_avp_setvalue ( avp, &avp_val ) );
+			CHECK( 0, fd_msg_avp_add ( msg, MSG_BRW_FIRST_CHILD, avp) );
+		}
+		
+		/* Origin-* */
+		CHECK( 0, fd_msg_add_origin(msg, 1) );
+		
+		/* Destination-Realm */
+		{
+			CHECK( 0, fd_dict_search ( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Destination-Realm", &d, ENOENT ) );
+			CHECK( 0, fd_msg_avp_new ( d, 0, &avp ) );
+			memset(&avp_val, 0, sizeof(avp_val));
+			avp_val.os.data = (unsigned char *)fd_g_config->cnf_diamrlm;
+			avp_val.os.len = fd_g_config->cnf_diamrlm_len;
+			CHECK( 0, fd_msg_avp_setvalue ( avp, &avp_val ) );
+			CHECK( 0, fd_msg_avp_add ( msg, MSG_BRW_LAST_CHILD, avp) );
+		}
+		
+		/* Accounting-Record-Type */
+		{
+			CHECK( 0, fd_dict_search ( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Accounting-Record-Type", &d, ENOENT ) );
+			CHECK( 0, fd_msg_avp_new ( d, 0, &avp ) );
+			memset(&avp_val, 0, sizeof(avp_val));
+			avp_val.u32 = 2;
+			CHECK( 0, fd_msg_avp_setvalue ( avp, &avp_val ) );
+			CHECK( 0, fd_msg_avp_add ( msg, MSG_BRW_LAST_CHILD, avp) );
+		}
+		
+		/* Accounting-Record-Number */
+		{
+			CHECK( 0, fd_dict_search ( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Accounting-Record-Number", &d, ENOENT ) );
+			CHECK( 0, fd_msg_avp_new ( d, 0, &avp ) );
+			memset(&avp_val, 0, sizeof(avp_val));
+			avp_val.u32 = 2;
+			CHECK( 0, fd_msg_avp_setvalue ( avp, &avp_val ) );
+			CHECK( 0, fd_msg_avp_add ( msg, MSG_BRW_LAST_CHILD, avp) );
+		}
+		
+		/* Route-Record */
+		{
+			CHECK( 0, fd_dict_search ( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Route-Record", &d, ENOENT ) );
+			CHECK( 0, fd_msg_avp_new ( d, 0, &avp ) );
+			memset(&avp_val, 0, sizeof(avp_val));
+			avp_val.os.data = (unsigned char *)"peer1";
+			avp_val.os.len = strlen((char *)avp_val.os.data);
+			CHECK( 0, fd_msg_avp_setvalue ( avp, &avp_val ) );
+			CHECK( 0, fd_msg_avp_add ( msg, MSG_BRW_LAST_CHILD, avp) );
+			
+			CHECK( 0, fd_msg_avp_new ( d, 0, &avp ) );
+			memset(&avp_val, 0, sizeof(avp_val));
+			avp_val.os.data = (unsigned char *)"peer2";
+			avp_val.os.len = strlen((char *)avp_val.os.data);
+			CHECK( 0, fd_msg_avp_setvalue ( avp, &avp_val ) );
+			CHECK( 0, fd_msg_avp_add ( msg, MSG_BRW_LAST_CHILD, avp) );
+		}
+		
+		/* Source */
+		CHECK( 0, fd_msg_source_set( msg, "peer3", CONSTSTRLEN("peer3") ) );
+		CHECK( 0, fd_msg_source_setrr( msg, "peer3", CONSTSTRLEN("peer3"), fd_g_config->cnf_dict ) );
+	}
+	
+	/* Now, have the daemon handle this */
+	CHECK( 0, fd_fifo_post(fd_g_incoming, &msg) );
+	
+	/* It is picked by the dispatch module, the extension handles the query, inserts the records in the DB, send creates the answer.
+	   Once the answer is ready, it is sent to "peer3" which is not available of course; then the message is simply destroyed.
+	   We wait 1 second for this to happen... */
+	sleep(1);
+	
+	/* Now, check the record was actually registered properly */
+	{
+		PGresult * res;
+		uint8_t * bs;
+		char * es;
+		size_t l;
+		
+		res = PQexec(conn, "SELECT \"Session-Id\" from " TABLE ";");
+		CHECK( PGRES_TUPLES_OK, PQresultStatus(res) );
+		
+		/* We also check that the Session-Id we retrieve is the same as what we generated earlier (not trashed in the process) */
+		es = PQgetvalue(res, 0, 0);
+		bs = PQunescapeBytea((uint8_t *)es, &l);
+		
+		CHECK( 0, fd_os_cmp(bs, l, sess_bkp, sess_bkp_len) );
+		
+		PQclear(res);
+		PQfreemem(bs);
+	}  
+
+	/* That's all for the tests yet */
+	free(sess_bkp);
+	
+	PASSTEST();
+} 
+	
diff --git a/tests/testcnx.c b/tests/testcnx.c
new file mode 100644
index 0000000..e1826c9
--- /dev/null
+++ b/tests/testcnx.c
@@ -0,0 +1,2009 @@
+/*********************************************************************************************************
+* Software License Agreement (BSD License)                                                               *
+* Author: Sebastien Decugis <sdecugis@freediameter.net>							 *
+*													 *
+* Copyright (c) 2013, WIDE Project and NICT								 *
+* All rights reserved.											 *
+* 													 *
+* Redistribution and use of this software in source and binary forms, with or without modification, are  *
+* permitted provided that the following conditions are met:						 *
+* 													 *
+* * Redistributions of source code must retain the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer.										 *
+*    													 *
+* * Redistributions in binary form must reproduce the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer in the documentation and/or other						 *
+*   materials provided with the distribution.								 *
+* 													 *
+* * Neither the name of the WIDE Project or NICT nor the 						 *
+*   names of its contributors may be used to endorse or 						 *
+*   promote products derived from this software without 						 *
+*   specific prior written permission of WIDE Project and 						 *
+*   NICT.												 *
+* 													 *
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED *
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
+* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR *
+* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 	 *
+* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 	 *
+* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR *
+* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF   *
+* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.								 *
+*********************************************************************************************************/
+
+#include "tests.h"
+
+#ifndef TEST_PORT
+#define TEST_PORT	3868
+#endif /* TEST_PORT */
+
+#ifndef NB_STREAMS
+#define NB_STREAMS	10
+#endif /* NB_STREAMS */
+
+#ifndef GNUTLS_DEFAULT_PRIORITY
+# define GNUTLS_DEFAULT_PRIORITY "NORMAL"
+#endif /* GNUTLS_DEFAULT_PRIORITY */
+
+#ifndef GNUTLS_DEFAULT_DHBITS
+# define GNUTLS_DEFAULT_DHBITS 1024
+#endif /* GNUTLS_DEFAULT_DHBITS */
+
+
+/* The cryptographic data */
+static char ca_data[] =		"-----BEGIN CERTIFICATE-----\n"
+				"MIIEqjCCA5KgAwIBAgIJANKgDwdlDYQDMA0GCSqGSIb3DQEBBQUAMIGUMQswCQYD\n"
+				"VQQGEwJKUDEOMAwGA1UECAwFVG9reW8xEDAOBgNVBAcMB0tvZ2FuZWkxDTALBgNV\n"
+				"BAoMBFdJREUxDzANBgNVBAsMBkFBQSBXRzEfMB0GA1UEAwwWY2hhdnJvdXguY293\n"
+				"YWRkaWN0Lm9yZzEiMCAGCSqGSIb3DQEJARYTc2RlY3VnaXNAbmljdC5nby5qcDAe\n"
+				"Fw0wOTEwMDUwODUxNDRaFw0xOTEwMDMwODUxNDRaMIGUMQswCQYDVQQGEwJKUDEO\n"
+				"MAwGA1UECAwFVG9reW8xEDAOBgNVBAcMB0tvZ2FuZWkxDTALBgNVBAoMBFdJREUx\n"
+				"DzANBgNVBAsMBkFBQSBXRzEfMB0GA1UEAwwWY2hhdnJvdXguY293YWRkaWN0Lm9y\n"
+				"ZzEiMCAGCSqGSIb3DQEJARYTc2RlY3VnaXNAbmljdC5nby5qcDCCASIwDQYJKoZI\n"
+				"hvcNAQEBBQADggEPADCCAQoCggEBAM5c6w4NnngTvGNWcJzbo0Kklp+kvUNQNgGu\n"
+				"myvz826qPp07HTSyJrIcgFnuYDR0Nd130Ot9u5osqpQhHTvolxDE87Tii8i3hJSj\n"
+				"TTY9K0ZwGb4AZ6QkuyMXS1jtOY657HqjpGZqT/2Syh0i7dM/hqSXFw0SPbyq+W1H\n"
+				"SVFWa1CTkPywFWAzwdr5WKah77uZ1dxWqgPgUdcZOiIQtLRp5n3fg40Nwso5YdwS\n"
+				"64+ebBX1pkhrCQ8AGc8O61Ep1JTXcO7jqQmPgzjiN+FeostI1Dp73S3MqleTAHjR\n"
+				"hqZ77VF7nkroMM9btMHJBaxnfwc2ewULUJwnuOiGWrvMq/9Z4J8CAwEAAaOB/DCB\n"
+				"+TAdBgNVHQ4EFgQUkqpVn7N3gmiJ7X5zQ2bki+7qv4UwgckGA1UdIwSBwTCBvoAU\n"
+				"kqpVn7N3gmiJ7X5zQ2bki+7qv4WhgZqkgZcwgZQxCzAJBgNVBAYTAkpQMQ4wDAYD\n"
+				"VQQIDAVUb2t5bzEQMA4GA1UEBwwHS29nYW5laTENMAsGA1UECgwEV0lERTEPMA0G\n"
+				"A1UECwwGQUFBIFdHMR8wHQYDVQQDDBZjaGF2cm91eC5jb3dhZGRpY3Qub3JnMSIw\n"
+				"IAYJKoZIhvcNAQkBFhNzZGVjdWdpc0BuaWN0LmdvLmpwggkA0qAPB2UNhAMwDAYD\n"
+				"VR0TBAUwAwEB/zANBgkqhkiG9w0BAQUFAAOCAQEAJy0XLk8j8YLSTt2/VMy9TAUx\n"
+				"esXUiZj0Ung+gkr7A1K0NnwYxDzG2adMhf13upHoydu2ErLMmD6F77x+QuY/q7nc\n"
+				"ZvO0tvcoAP6ToSDwiypU5dnTmnfkgwVwzFkNCi1sGRosEm8c/c/8MfK0I0nVdj1/\n"
+				"BIkIG7tTDVi9JvkWYl0UlSKWTZKrntVwCmscfC02DGb+GoLbO9+QmiNM5Y3yOYZ4\n"
+				"Pc7SSoKLL0rwJBmpPNs7boYsweeSuCAVu0shRfgC90odXcej2EN5ETfCuU1evXNW\n"
+				"5cA+zZsDK/nWJwxBaW0CxAHX579FElFWlK4+BnzhZRdDhmJDnN5dh4ekJGM6Lg==\n"
+				"-----END CERTIFICATE-----\n";
+				
+/* Client:
+				Certificate:
+				    Data:
+        				Version: 3 (0x2)
+        				Serial Number: 5 (0x5)
+        				Signature Algorithm: sha1WithRSAEncryption
+        				Issuer: C=JP, ST=Tokyo, L=Koganei, O=WIDE, OU=AAA WG, CN=chavroux.cowaddict.org/emailAddress=sdecugis@nict.go.jp
+        				Validity
+        				    Not Before: Oct 27 04:04:05 2009 GMT
+        				    Not After : Oct 25 04:04:05 2019 GMT
+        				Subject: C=JP, ST=Tokyo, L=Koganei, O=WIDE, OU=AAA WG, CN=client.test/emailAddress=client@test
+        				Subject Public Key Info:
+        				    Public Key Algorithm: rsaEncryption
+        				    RSA Public Key: (1024 bit)
+                				Modulus (1024 bit):
+                				    00:bd:eb:50:1e:9d:7a:cd:9d:bb:e7:bc:4e:38:4a:
+                				    b2:cc:9e:b4:89:77:01:ef:d1:c6:19:29:00:fe:ce:
+                				    3c:62:05:13:b1:8c:ff:31:7a:0f:c1:2e:4b:3c:0c:
+                				    40:1e:36:4e:76:da:0a:64:43:fc:1e:ea:0c:97:b2:
+                				    57:9c:9c:8c:90:bd:eb:23:7b:b8:b7:5c:03:ed:6f:
+                				    48:55:8a:88:08:38:c5:cd:33:b7:ab:a8:3a:6f:7f:
+                				    13:10:65:a5:50:b9:f4:8b:cc:2e:e9:79:58:a6:11:
+                				    f0:58:45:41:ef:36:b3:35:cb:14:ec:82:0c:ad:11:
+                				    6a:ea:64:ef:28:a2:6e:47:45
+                				Exponent: 65537 (0x10001)
+        				X509v3 extensions:
+        				    X509v3 Basic Constraints: 
+                				CA:FALSE
+        				    Netscape Comment: 
+                				OpenSSL Generated Certificate
+        				    X509v3 Subject Key Identifier: 
+                				BE:B3:89:4F:9D:8F:6C:20:C4:D0:3E:6A:05:11:82:50:54:49:70:A2
+        				    X509v3 Authority Key Identifier: 
+                				keyid:92:AA:55:9F:B3:77:82:68:89:ED:7E:73:43:66:E4:8B:EE:EA:BF:85
+
+				    Signature Algorithm: sha1WithRSAEncryption
+        				a3:88:f5:15:b5:ad:20:60:a1:85:19:3f:b9:5e:1e:be:31:7f:
+        				84:7a:c2:18:3a:63:6a:67:1f:46:86:4d:10:d6:1d:ad:a2:c8:
+        				0b:95:33:fa:e4:05:f4:b8:70:34:77:f7:85:6e:70:46:ac:39:
+        				54:a9:5f:ea:5e:d1:33:bb:c9:a3:42:81:41:90:25:b5:92:8b:
+        				e8:6e:3e:97:06:dd:9a:cc:29:61:34:5a:d3:1c:5d:ad:d1:a3:
+        				eb:6a:47:b4:d0:c2:17:89:e1:e2:2d:36:18:50:1a:e7:d4:fc:
+        				38:2e:47:0b:39:50:87:2f:aa:07:64:f8:9a:4d:47:01:da:10:
+        				d8:97:c7:a6:13:bc:0e:ca:63:c1:f2:09:fb:f8:6a:a4:5f:08:
+        				b5:ad:ed:4f:71:b9:89:7f:43:27:85:72:e7:8d:a8:4a:cc:f6:
+        				36:ca:8a:ae:82:b5:a8:42:41:99:87:84:7c:f0:90:fd:ca:96:
+        				37:a2:e0:d9:fa:dd:a4:c9:f1:50:b7:e5:e6:8f:af:83:8c:23:
+        				b6:20:cc:66:e3:08:60:13:02:8f:42:3a:07:91:a7:38:b2:72:
+        				16:fd:bd:a9:60:f0:e2:9f:23:f3:c0:99:e3:17:bc:00:7c:b3:
+        				89:9c:ea:fa:3e:f6:69:a1:98:c2:ec:46:da:70:b6:f9:c3:93:
+        				a7:fc:36:dd
+*/
+static char client_cert_data[] ="-----BEGIN CERTIFICATE-----\n"
+				"MIIDiTCCAnGgAwIBAgIBBTANBgkqhkiG9w0BAQUFADCBlDELMAkGA1UEBhMCSlAx\n"
+				"DjAMBgNVBAgMBVRva3lvMRAwDgYDVQQHDAdLb2dhbmVpMQ0wCwYDVQQKDARXSURF\n"
+				"MQ8wDQYDVQQLDAZBQUEgV0cxHzAdBgNVBAMMFmNoYXZyb3V4LmNvd2FkZGljdC5v\n"
+				"cmcxIjAgBgkqhkiG9w0BCQEWE3NkZWN1Z2lzQG5pY3QuZ28uanAwHhcNMDkxMDI3\n"
+				"MDQwNDA1WhcNMTkxMDI1MDQwNDA1WjCBgTELMAkGA1UEBhMCSlAxDjAMBgNVBAgM\n"
+				"BVRva3lvMRAwDgYDVQQHDAdLb2dhbmVpMQ0wCwYDVQQKDARXSURFMQ8wDQYDVQQL\n"
+				"DAZBQUEgV0cxFDASBgNVBAMMC2NsaWVudC50ZXN0MRowGAYJKoZIhvcNAQkBFgtj\n"
+				"bGllbnRAdGVzdDCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAvetQHp16zZ27\n"
+				"57xOOEqyzJ60iXcB79HGGSkA/s48YgUTsYz/MXoPwS5LPAxAHjZOdtoKZEP8HuoM\n"
+				"l7JXnJyMkL3rI3u4t1wD7W9IVYqICDjFzTO3q6g6b38TEGWlULn0i8wu6XlYphHw\n"
+				"WEVB7zazNcsU7IIMrRFq6mTvKKJuR0UCAwEAAaN7MHkwCQYDVR0TBAIwADAsBglg\n"
+				"hkgBhvhCAQ0EHxYdT3BlblNTTCBHZW5lcmF0ZWQgQ2VydGlmaWNhdGUwHQYDVR0O\n"
+				"BBYEFL6ziU+dj2wgxNA+agURglBUSXCiMB8GA1UdIwQYMBaAFJKqVZ+zd4Joie1+\n"
+				"c0Nm5Ivu6r+FMA0GCSqGSIb3DQEBBQUAA4IBAQCjiPUVta0gYKGFGT+5Xh6+MX+E\n"
+				"esIYOmNqZx9Ghk0Q1h2tosgLlTP65AX0uHA0d/eFbnBGrDlUqV/qXtEzu8mjQoFB\n"
+				"kCW1kovobj6XBt2azClhNFrTHF2t0aPrake00MIXieHiLTYYUBrn1Pw4LkcLOVCH\n"
+				"L6oHZPiaTUcB2hDYl8emE7wOymPB8gn7+GqkXwi1re1PcbmJf0MnhXLnjahKzPY2\n"
+				"yoqugrWoQkGZh4R88JD9ypY3ouDZ+t2kyfFQt+Xmj6+DjCO2IMxm4whgEwKPQjoH\n"
+				"kac4snIW/b2pYPDinyPzwJnjF7wAfLOJnOr6PvZpoZjC7EbacLb5w5On/Dbd\n"
+				"-----END CERTIFICATE-----\n";
+static char client_priv_data[] ="-----BEGIN RSA PRIVATE KEY-----\n"
+				"MIICXgIBAAKBgQC961AenXrNnbvnvE44SrLMnrSJdwHv0cYZKQD+zjxiBROxjP8x\n"
+				"eg/BLks8DEAeNk522gpkQ/we6gyXslecnIyQvesje7i3XAPtb0hViogIOMXNM7er\n"
+				"qDpvfxMQZaVQufSLzC7peVimEfBYRUHvNrM1yxTsggytEWrqZO8oom5HRQIDAQAB\n"
+				"AoGBAIYnsOLPby3LnC5n8AEHkyHDgdgQvsd/MSYYtuFHIZRD7dNfu+xhQru9TdvO\n"
+				"84Pj7K07/FczRuc3gUmu6wBv/UIP9To15RHZh+/n537nybGus5S4IYKVvap477To\n"
+				"0rQDf9ec27iw77gxb7moQ9Otuxwbv0h0Z+1EVLI8d8jHOq0BAkEA9YNr0R+7KXBS\n"
+				"48yT43g5HpOFkTZzNXWVdpSvYGneb56wslk5Eatp235I4uz/a7Rej5v99W0M3nSe\n"
+				"/AgHfYn75QJBAMYH/pBx/WkrLj+pPaARlNwInCIC5zUhr6B0IKCt2tvy5eyuc5sd\n"
+				"AoTFaU+cSI+ZqsRzY8jMKkonktxBg48oJ+ECQQCt4AtlqcFVkbVCm8pJGQXq/7Ni\n"
+				"qlthiwr1Vkv2TkQ4bPza8pGWT/3Cc2ePPyWN08n8jw+G11p72cAW4mDbqfN5AkEA\n"
+				"mNYKrkiLn+NnqlJf8W4gSUGL3uQGtYbuGRQHKnuDckWhFm39YzWcgAQsJvkjN1EN\n"
+				"7thvpsWLzfeE7ODTPGVtgQJATObxYJOt6rms3fAStwuXW3ET77TA1ja4XsUEe5Yu\n"
+				"JpcQOruJb9XwndqzNbL0dSUePb9gFiBCGKYOyreNTTRTmw==\n"
+				"-----END RSA PRIVATE KEY-----\n";
+				
+/* Server:
+				Certificate:
+				    Data:
+        				Version: 3 (0x2)
+        				Serial Number: 4 (0x4)
+        				Signature Algorithm: sha1WithRSAEncryption
+        				Issuer: C=JP, ST=Tokyo, L=Koganei, O=WIDE, OU=AAA WG, CN=chavroux.cowaddict.org/emailAddress=sdecugis@nict.go.jp
+        				Validity
+        				    Not Before: Oct 27 04:03:39 2009 GMT
+        				    Not After : Oct 25 04:03:39 2019 GMT
+        				Subject: C=JP, ST=Tokyo, L=Koganei, O=WIDE, OU=AAA WG, CN=serv.test/emailAddress=serv@test
+        				Subject Public Key Info:
+        				    Public Key Algorithm: rsaEncryption
+        				    RSA Public Key: (1024 bit)
+                				Modulus (1024 bit):
+                				    00:a6:f7:1c:a9:90:5b:fa:c8:f6:a3:04:0c:d0:8b:
+                				    45:c3:90:f7:2d:c2:c9:d7:bd:66:8a:7c:1c:51:89:
+                				    40:9e:cd:70:57:cb:00:47:a3:e8:76:8b:00:b3:c9:
+                				    c3:0d:b1:b9:2a:08:9f:52:92:82:d3:18:c1:d8:d1:
+                				    b8:1e:fd:71:fe:23:ec:19:e9:6d:9d:fd:ae:88:bc:
+                				    39:44:7a:37:ad:c6:88:d1:64:7c:b1:d4:3c:a9:30:
+                				    c4:de:51:02:c4:48:4f:25:3e:2f:93:ae:25:32:66:
+                				    9a:dc:f4:44:45:ff:7f:12:49:97:0d:01:8d:13:9a:
+                				    d3:8f:9e:2d:62:95:02:0a:c7
+                				Exponent: 65537 (0x10001)
+        				X509v3 extensions:
+        				    X509v3 Basic Constraints: 
+                				CA:FALSE
+        				    Netscape Comment: 
+                				OpenSSL Generated Certificate
+        				    X509v3 Subject Key Identifier: 
+                				0C:33:C4:7F:39:D0:34:FF:F8:61:A1:46:8B:49:1D:A3:57:B3:4D:58
+        				    X509v3 Authority Key Identifier: 
+                				keyid:92:AA:55:9F:B3:77:82:68:89:ED:7E:73:43:66:E4:8B:EE:EA:BF:85
+
+				    Signature Algorithm: sha1WithRSAEncryption
+        				87:f5:49:a6:04:f9:98:9a:f1:1a:68:ce:06:ae:4c:0c:08:eb:
+        				ba:98:e7:3f:df:22:7f:35:88:1d:b7:8a:f3:89:a3:68:0d:53:
+        				45:eb:23:a1:dd:6b:dc:b0:80:58:0c:10:0b:49:74:ea:a8:b6:
+        				8c:2e:c6:73:dc:7a:74:c7:59:3e:79:5a:d2:5c:15:0b:f1:d8:
+        				19:37:2a:c0:22:75:10:3f:4c:e9:a1:e0:eb:b2:9e:09:70:3d:
+        				2a:4c:fe:9c:99:36:4b:aa:6c:e1:8b:9c:aa:e1:29:1f:49:6b:
+        				14:db:12:ae:cf:68:4a:dd:03:e1:3b:ad:79:b4:54:84:1d:bb:
+        				ac:45:c4:85:f1:03:65:65:96:23:ae:e7:97:3c:5c:db:ce:55:
+        				34:5d:c3:73:ec:cd:f6:0f:a5:81:5f:c2:ab:a3:42:fa:36:7f:
+        				83:ef:db:0f:cd:62:0b:ea:d9:4f:73:35:68:5f:23:d5:0a:be:
+        				ff:7f:23:9a:af:0d:a5:f8:3e:3a:f0:63:1c:e1:d2:96:81:cf:
+        				7b:5a:6b:d0:9b:67:56:9e:aa:a9:e8:f1:6c:fb:54:2b:1a:f4:
+        				ef:16:5a:be:1d:a9:c8:d6:cc:f7:42:8c:fe:83:2c:84:8c:80:
+        				fb:1c:88:f6:35:1c:ae:43:72:fa:68:30:9c:25:8b:db:2c:84:
+        				87:76:9d:b9
+*/
+static char server_cert_data[] ="-----BEGIN CERTIFICATE-----\n"
+				"MIIDhDCCAmygAwIBAgIBBDANBgkqhkiG9w0BAQUFADCBlDELMAkGA1UEBhMCSlAx\n"
+				"DjAMBgNVBAgMBVRva3lvMRAwDgYDVQQHDAdLb2dhbmVpMQ0wCwYDVQQKDARXSURF\n"
+				"MQ8wDQYDVQQLDAZBQUEgV0cxHzAdBgNVBAMMFmNoYXZyb3V4LmNvd2FkZGljdC5v\n"
+				"cmcxIjAgBgkqhkiG9w0BCQEWE3NkZWN1Z2lzQG5pY3QuZ28uanAwHhcNMDkxMDI3\n"
+				"MDQwMzM5WhcNMTkxMDI1MDQwMzM5WjB9MQswCQYDVQQGEwJKUDEOMAwGA1UECAwF\n"
+				"VG9reW8xEDAOBgNVBAcMB0tvZ2FuZWkxDTALBgNVBAoMBFdJREUxDzANBgNVBAsM\n"
+				"BkFBQSBXRzESMBAGA1UEAwwJc2Vydi50ZXN0MRgwFgYJKoZIhvcNAQkBFglzZXJ2\n"
+				"QHRlc3QwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAKb3HKmQW/rI9qMEDNCL\n"
+				"RcOQ9y3Cyde9Zop8HFGJQJ7NcFfLAEej6HaLALPJww2xuSoIn1KSgtMYwdjRuB79\n"
+				"cf4j7BnpbZ39roi8OUR6N63GiNFkfLHUPKkwxN5RAsRITyU+L5OuJTJmmtz0REX/\n"
+				"fxJJlw0BjROa04+eLWKVAgrHAgMBAAGjezB5MAkGA1UdEwQCMAAwLAYJYIZIAYb4\n"
+				"QgENBB8WHU9wZW5TU0wgR2VuZXJhdGVkIENlcnRpZmljYXRlMB0GA1UdDgQWBBQM\n"
+				"M8R/OdA0//hhoUaLSR2jV7NNWDAfBgNVHSMEGDAWgBSSqlWfs3eCaIntfnNDZuSL\n"
+				"7uq/hTANBgkqhkiG9w0BAQUFAAOCAQEAh/VJpgT5mJrxGmjOBq5MDAjrupjnP98i\n"
+				"fzWIHbeK84mjaA1TResjod1r3LCAWAwQC0l06qi2jC7Gc9x6dMdZPnla0lwVC/HY\n"
+				"GTcqwCJ1ED9M6aHg67KeCXA9Kkz+nJk2S6ps4YucquEpH0lrFNsSrs9oSt0D4Tut\n"
+				"ebRUhB27rEXEhfEDZWWWI67nlzxc285VNF3Dc+zN9g+lgV/Cq6NC+jZ/g+/bD81i\n"
+				"C+rZT3M1aF8j1Qq+/38jmq8Npfg+OvBjHOHSloHPe1pr0JtnVp6qqejxbPtUKxr0\n"
+				"7xZavh2pyNbM90KM/oMshIyA+xyI9jUcrkNy+mgwnCWL2yyEh3aduQ==\n"
+				"-----END CERTIFICATE-----\n";
+static char server_priv_data[] ="-----BEGIN RSA PRIVATE KEY-----\n"
+				"MIICXQIBAAKBgQCm9xypkFv6yPajBAzQi0XDkPctwsnXvWaKfBxRiUCezXBXywBH\n"
+				"o+h2iwCzycMNsbkqCJ9SkoLTGMHY0bge/XH+I+wZ6W2d/a6IvDlEejetxojRZHyx\n"
+				"1DypMMTeUQLESE8lPi+TriUyZprc9ERF/38SSZcNAY0TmtOPni1ilQIKxwIDAQAB\n"
+				"AoGAZv3Ddm0P79CLIt9asEFY1VvUvSuMqkGwwPfx1/HcJJkBFYapM4fN22G/Gyf3\n"
+				"47ifSWhsLtklTeXVnVMwSh14dJaJQuSEnaFnUUWfjiRbEAXZnMFwAIiaszEZbPap\n"
+				"NUNpcGl06FZrphYAMkjOVUfjCjfOZDAvL4JGpo271Zx4l0ECQQDYoFFQpBCPx0PK\n"
+				"TWUmvatXI/Amo94XkGfofbdeeI8PiAJBO5UI6rmjjIVwsJwO9dQb/IlP1/OnBeJv\n"
+				"p9YW5uixAkEAxVAOKu7mpGu0Q/K2iEUUYDX9YHf253kgkdIDF4iZk4Tcecjoxuru\n"
+				"fIWu9dMtyDVV+HT2X4cNEnO1/oS3kJII9wJBAJkdwDwiqz4lV6o/yFZ4zAoc8dsu\n"
+				"CoZXYMq5SYox5tTQit928OHLn4mVgqBjhPsiEVnyx0+zUZpmE2ZemHm5nxECQHfE\n"
+				"FBVzVYRP6+eil7E3XRrZKqc3qiLunxpkA4RxYebtKnaxwLmdOI1VB9InEQ8JcNmT\n"
+				"BUkOzJx6p+mJ3XJfchkCQQDWmbMYYJajsjlS4YpdUUj7cBSotA6vtkNVHFr0/ak/\n"
+				"S+tLkMNuruaInWizK+BKYTIJLlQDf5u5NTrw41vye5Hv\n"
+				"-----END RSA PRIVATE KEY-----\n";
+
+/* Expired:
+				Certificate:
+				    Data:
+        				Version: 3 (0x2)
+        				Serial Number: 6 (0x6)
+        				Signature Algorithm: sha1WithRSAEncryption
+        				Issuer: C=JP, ST=Tokyo, L=Koganei, O=WIDE, OU=AAA WG, CN=chavroux.cowaddict.org/emailAddress=sdecugis@nict.go.jp
+        				Validity
+        				    Not Before: Oct 27 04:06:35 2009 GMT
+        				    Not After : Oct 28 04:06:35 2009 GMT
+        				Subject: C=JP, ST=Tokyo, L=Koganei, O=WIDE, OU=AAA WG, CN=expired.test/emailAddress=expired@test
+        				Subject Public Key Info:
+        				    Public Key Algorithm: rsaEncryption
+        				    RSA Public Key: (1024 bit)
+                				Modulus (1024 bit):
+                				    00:e3:17:15:54:85:dc:cf:c7:a0:32:4a:49:7d:55:
+                				    75:9b:29:15:db:7e:87:17:d9:0e:65:44:53:d7:19:
+                				    37:27:c7:c6:fe:c6:dc:72:2b:dc:86:1a:ff:24:6c:
+                				    63:3f:75:9c:0a:14:e1:70:06:79:d4:b9:26:d4:68:
+                				    4c:28:38:ba:34:60:56:02:3d:94:55:4a:1f:4e:5a:
+                				    f0:a5:71:4c:3e:71:69:39:ad:bc:aa:55:35:fb:73:
+                				    5b:5f:6c:30:71:8e:8a:b6:a5:06:cc:ee:dd:29:c7:
+                				    52:0d:a7:9c:0f:a1:ba:52:11:e2:1b:b9:74:6b:08:
+                				    87:11:d2:ec:a9:ac:63:63:4f
+                				Exponent: 65537 (0x10001)
+        				X509v3 extensions:
+        				    X509v3 Basic Constraints: 
+                				CA:FALSE
+        				    Netscape Comment: 
+                				OpenSSL Generated Certificate
+        				    X509v3 Subject Key Identifier: 
+                				1C:AF:66:42:5B:AD:AA:A5:9B:D9:AE:3A:C1:5A:AC:2F:CC:CE:22:6C
+        				    X509v3 Authority Key Identifier: 
+                				keyid:92:AA:55:9F:B3:77:82:68:89:ED:7E:73:43:66:E4:8B:EE:EA:BF:85
+
+				    Signature Algorithm: sha1WithRSAEncryption
+        				60:8f:55:55:59:82:0f:64:cb:b8:11:c8:44:ce:bf:69:07:0d:
+        				be:c2:34:be:42:6a:78:15:39:9f:be:8a:17:d6:43:42:c9:7c:
+        				f1:6d:5d:aa:c3:1b:4d:b0:f0:b6:73:46:2a:87:cd:55:56:a3:
+        				6d:cc:de:a8:28:6a:53:85:9e:e5:68:b7:3c:f5:72:13:7b:d0:
+        				21:f2:91:49:35:e0:37:1e:28:19:d5:1b:cc:e1:32:1e:7f:b0:
+        				86:df:43:a4:47:0f:29:0b:eb:51:60:9a:f5:ca:50:f4:2d:59:
+        				cd:fc:50:9d:29:ed:45:98:de:a2:5c:d1:b5:7a:34:ad:7a:73:
+        				48:8b:a2:9b:89:8e:4a:2e:2a:04:19:d6:62:6a:0d:f0:96:f2:
+        				f0:d0:22:77:3b:7f:b1:2a:f4:3b:17:47:5e:38:07:09:65:ad:
+        				1d:ea:46:69:6a:96:b6:6b:3b:5c:cc:6e:30:d7:cb:53:69:59:
+        				c2:63:78:2b:03:d4:d4:f7:17:29:99:9a:43:ff:78:0a:af:42:
+        				c5:b3:8d:09:38:5b:30:70:28:c1:97:ab:fd:7f:87:9a:ec:f2:
+        				97:44:ff:f5:b9:41:30:d1:c6:32:98:69:34:c4:39:30:6f:e2:
+        				d3:b2:70:97:66:ee:41:f5:ae:0f:09:f0:ed:60:96:67:a9:8a:
+        				cd:d6:95:f2
+*/
+static char expired_cert_data[]="-----BEGIN CERTIFICATE-----\n"
+				"MIIDizCCAnOgAwIBAgIBBjANBgkqhkiG9w0BAQUFADCBlDELMAkGA1UEBhMCSlAx\n"
+				"DjAMBgNVBAgMBVRva3lvMRAwDgYDVQQHDAdLb2dhbmVpMQ0wCwYDVQQKDARXSURF\n"
+				"MQ8wDQYDVQQLDAZBQUEgV0cxHzAdBgNVBAMMFmNoYXZyb3V4LmNvd2FkZGljdC5v\n"
+				"cmcxIjAgBgkqhkiG9w0BCQEWE3NkZWN1Z2lzQG5pY3QuZ28uanAwHhcNMDkxMDI3\n"
+				"MDQwNjM1WhcNMDkxMDI4MDQwNjM1WjCBgzELMAkGA1UEBhMCSlAxDjAMBgNVBAgM\n"
+				"BVRva3lvMRAwDgYDVQQHDAdLb2dhbmVpMQ0wCwYDVQQKDARXSURFMQ8wDQYDVQQL\n"
+				"DAZBQUEgV0cxFTATBgNVBAMMDGV4cGlyZWQudGVzdDEbMBkGCSqGSIb3DQEJARYM\n"
+				"ZXhwaXJlZEB0ZXN0MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDjFxVUhdzP\n"
+				"x6AySkl9VXWbKRXbfocX2Q5lRFPXGTcnx8b+xtxyK9yGGv8kbGM/dZwKFOFwBnnU\n"
+				"uSbUaEwoOLo0YFYCPZRVSh9OWvClcUw+cWk5rbyqVTX7c1tfbDBxjoq2pQbM7t0p\n"
+				"x1INp5wPobpSEeIbuXRrCIcR0uyprGNjTwIDAQABo3sweTAJBgNVHRMEAjAAMCwG\n"
+				"CWCGSAGG+EIBDQQfFh1PcGVuU1NMIEdlbmVyYXRlZCBDZXJ0aWZpY2F0ZTAdBgNV\n"
+				"HQ4EFgQUHK9mQlutqqWb2a46wVqsL8zOImwwHwYDVR0jBBgwFoAUkqpVn7N3gmiJ\n"
+				"7X5zQ2bki+7qv4UwDQYJKoZIhvcNAQEFBQADggEBAGCPVVVZgg9ky7gRyETOv2kH\n"
+				"Db7CNL5CangVOZ++ihfWQ0LJfPFtXarDG02w8LZzRiqHzVVWo23M3qgoalOFnuVo\n"
+				"tzz1chN70CHykUk14DceKBnVG8zhMh5/sIbfQ6RHDykL61FgmvXKUPQtWc38UJ0p\n"
+				"7UWY3qJc0bV6NK16c0iLopuJjkouKgQZ1mJqDfCW8vDQInc7f7Eq9DsXR144Bwll\n"
+				"rR3qRmlqlrZrO1zMbjDXy1NpWcJjeCsD1NT3FymZmkP/eAqvQsWzjQk4WzBwKMGX\n"
+				"q/1/h5rs8pdE//W5QTDRxjKYaTTEOTBv4tOycJdm7kH1rg8J8O1glmepis3WlfI=\n"
+				"-----END CERTIFICATE-----\n";
+static char expired_priv_data[]="-----BEGIN RSA PRIVATE KEY-----\n"
+				"MIICXgIBAAKBgQDjFxVUhdzPx6AySkl9VXWbKRXbfocX2Q5lRFPXGTcnx8b+xtxy\n"
+				"K9yGGv8kbGM/dZwKFOFwBnnUuSbUaEwoOLo0YFYCPZRVSh9OWvClcUw+cWk5rbyq\n"
+				"VTX7c1tfbDBxjoq2pQbM7t0px1INp5wPobpSEeIbuXRrCIcR0uyprGNjTwIDAQAB\n"
+				"AoGASwPoDui9XYHTIGm7xwRA+kVjLAOq+qy//aHJlEeHGcP7r1PfpHNqwH4QhGat\n"
+				"jlv6dLYbFld9TVDwS8A8UBkVIPLWnCysd5tF2A4C5akx6ouW6HliW/JheYrgl8AV\n"
+				"PVeR3bm91UbnpC0ABVlw87jp1Ovyr60Suo4jsoJz+CyTa2ECQQD0LJWpnwn1jIlR\n"
+				"DGkLi7F3E70JJcdhTWzBjGFD+Na+/2ZO0MKLhK+O1WUkKa0oi+e5P1JOnGIpTI8c\n"
+				"BJOO415RAkEA7hauapYuqGI/auSPH8/nFB5z1G94RTxo2a5THKcG5MqS/8N3ubFj\n"
+				"i2PPS0lEYVjqoHEsZUsMnDmXp6KDKMAfnwJBAIp+T1UqM8fmsmwaEerOjRXxSCNM\n"
+				"Hk5+T9Vn/jNDjOpAipLhrbbcx4bIWtmsGd8Jm6Fi3RhhcvvhxLorjlZZeEECQQCf\n"
+				"IaPD88sNmlUewdLzhUbCiLQMadCuHflKfRxpyy1tYAQuVFxCTdDlynkzra25ju+K\n"
+				"+vmcXjP4evnk/lbBtt+rAkEAgOr4Apgs3nMppngPV5yFx0NDqH2n8PlEAM1Il4Qs\n"
+				"IuuK18v0KwlUGAfEEmCiNh1e1qkLmD0CnI2QjYAjcLQUhw==\n"
+				"-----END RSA PRIVATE KEY-----\n";
+
+/* Unknown CA certificate :
+				Certificate:
+				    Data:
+        				Version: 3 (0x2)
+        				Serial Number: 1 (0x1)
+        				Signature Algorithm: sha1WithRSAEncryption
+        				Issuer: C=JP, ST=Tokyo, L=Koganei, O=WIDE, OU=AAA WG, CN=chavroux.cowaddict.org/emailAddress=sdecugis@nict.go.jp
+        				Validity
+        				    Not Before: Oct 28 08:04:40 2009 GMT
+        				    Not After : Oct 28 08:04:40 2010 GMT
+        				Subject: C=JP, ST=Tokyo, L=Koganei, O=WIDE, OU=AAA WG, CN=unknown.cs/emailAddress=unknown@ca
+        				Subject Public Key Info:
+        				    Public Key Algorithm: rsaEncryption
+        				    RSA Public Key: (1024 bit)
+                				Modulus (1024 bit):
+                				    00:e6:3a:d5:8a:14:c8:15:d0:f0:5c:03:c3:af:33:
+                				    51:2c:17:b7:65:ac:45:e8:48:2d:ae:70:fd:7c:79:
+                				    3a:c7:80:c8:50:53:d0:19:d8:3a:26:a8:16:4d:4c:
+                				    04:17:09:df:69:9b:59:2b:89:c8:e0:60:bb:1d:37:
+                				    82:d2:3f:17:39:c9:8f:5d:76:e1:0f:6e:08:9a:8f:
+                				    16:4a:ea:83:86:f9:bd:15:14:56:68:87:79:05:f9:
+                				    5f:66:11:bd:22:46:26:64:be:57:16:51:66:41:50:
+                				    ac:f2:b1:ca:d0:38:11:4b:4c:b2:ee:25:36:6e:d3:
+                				    b9:63:72:c4:84:82:1c:2b:27
+                				Exponent: 65537 (0x10001)
+        				X509v3 extensions:
+        				    X509v3 Basic Constraints: 
+                				CA:FALSE
+        				    Netscape Comment: 
+                				OpenSSL Generated Certificate
+        				    X509v3 Subject Key Identifier: 
+                				BA:5A:9D:D2:B0:4B:72:D6:1F:00:11:0B:B5:7B:59:DF:08:38:81:BE
+        				    X509v3 Authority Key Identifier: 
+                				keyid:52:C5:A4:63:B8:DB:AC:F2:92:34:2F:72:56:71:C8:11:8E:76:E6:DF
+
+				    Signature Algorithm: sha1WithRSAEncryption
+        				90:8f:3b:bd:e3:a1:ca:6a:92:a6:fd:f0:64:ae:46:83:32:35:
+        				61:80:57:8b:30:12:70:02:e1:51:d9:87:c8:af:d9:4b:b9:6d:
+        				bf:ab:86:5f:19:1f:dc:af:84:67:bf:3c:bf:33:f3:7c:c6:81:
+        				7b:e4:e9:26:1d:bc:d6:8c:ab:72:94:7f:85:33:95:d9:24:ec:
+        				fd:7b:d2:fd:50:3e:e5:61:4f:75:51:ae:c6:4a:ec:df:cf:aa:
+        				73:a5:08:f7:f3:9a:40:66:48:f0:8e:9b:43:b1:30:f3:e3:c8:
+        				36:3f:68:36:6a:1c:aa:16:40:49:b4:73:9a:71:f1:17:6c:0b:
+        				d3:e1:a7:b7:40:de:2c:3c:36:7c:d4:dd:d6:94:c9:d7:5f:f5:
+        				ae:35:56:e8:cc:65:9c:bb:3d:e8:7a:ca:0e:ed:78:03:41:cb:
+        				fd:80:81:de:f9:de:b2:14:4b:81:24:36:de:29:c1:06:11:86:
+        				8c:a9:b0:0c:c7:57:cf:79:a7:3a:84:0c:27:dc:86:6d:cb:44:
+        				2d:26:dc:7e:fb:17:d6:b2:3d:31:03:d3:f1:ab:5d:91:5d:94:
+        				e4:94:88:70:96:b3:7c:0f:15:fe:c8:c6:4d:99:37:ab:09:0c:
+        				da:ba:b6:0e:fa:5e:bb:4b:ce:04:21:06:09:a9:2c:27:86:76:
+        				cc:ee:73:6f
+*/
+static char notrust_ca_data[] =	"-----BEGIN CERTIFICATE-----\n"
+				"MIIEqjCCA5KgAwIBAgIJAP3UMghSlH9PMA0GCSqGSIb3DQEBBQUAMIGUMQswCQYD\n"
+				"VQQGEwJKUDEOMAwGA1UECAwFVG9reW8xEDAOBgNVBAcMB0tvZ2FuZWkxDTALBgNV\n"
+				"BAoMBFdJREUxDzANBgNVBAsMBkFBQSBXRzEfMB0GA1UEAwwWY2hhdnJvdXguY293\n"
+				"YWRkaWN0Lm9yZzEiMCAGCSqGSIb3DQEJARYTc2RlY3VnaXNAbmljdC5nby5qcDAe\n"
+				"Fw0wOTEwMjgwODAzNDRaFw0xOTEwMjYwODAzNDRaMIGUMQswCQYDVQQGEwJKUDEO\n"
+				"MAwGA1UECAwFVG9reW8xEDAOBgNVBAcMB0tvZ2FuZWkxDTALBgNVBAoMBFdJREUx\n"
+				"DzANBgNVBAsMBkFBQSBXRzEfMB0GA1UEAwwWY2hhdnJvdXguY293YWRkaWN0Lm9y\n"
+				"ZzEiMCAGCSqGSIb3DQEJARYTc2RlY3VnaXNAbmljdC5nby5qcDCCASIwDQYJKoZI\n"
+				"hvcNAQEBBQADggEPADCCAQoCggEBALKW9iSUggF5mbvYe1Xk128Csfiijx+fwH5y\n"
+				"ZqWrHNt0YG/tZSwyCDMWBLXTeuYsntg5y0mcpsrN8v02tvrPiCzDfRPyz3mG68us\n"
+				"DPEEgQ1kqL2Gsti2DUcsdyZcDM+4rgsWRivgOTVyoNimv5f+xgmPYoElkgelLwZK\n"
+				"WxGt1VCebOxP3qZA3hSHWE1hJgL4svful7RD1PbwPzidxJKITyAiJoPKWQA9cjSa\n"
+				"gVzRQ7S4vmYALJn7xe+dMFRcfAK8RMv7/gJF6Rw7zufW0DIZK98KZs6aL0lmMPVk\n"
+				"f31N2uvndf+cjy0n4luwEoXY+TeJZY205lbwHrzR0rH75FSm0RsCAwEAAaOB/DCB\n"
+				"+TAdBgNVHQ4EFgQUUsWkY7jbrPKSNC9yVnHIEY525t8wgckGA1UdIwSBwTCBvoAU\n"
+				"UsWkY7jbrPKSNC9yVnHIEY525t+hgZqkgZcwgZQxCzAJBgNVBAYTAkpQMQ4wDAYD\n"
+				"VQQIDAVUb2t5bzEQMA4GA1UEBwwHS29nYW5laTENMAsGA1UECgwEV0lERTEPMA0G\n"
+				"A1UECwwGQUFBIFdHMR8wHQYDVQQDDBZjaGF2cm91eC5jb3dhZGRpY3Qub3JnMSIw\n"
+				"IAYJKoZIhvcNAQkBFhNzZGVjdWdpc0BuaWN0LmdvLmpwggkA/dQyCFKUf08wDAYD\n"
+				"VR0TBAUwAwEB/zANBgkqhkiG9w0BAQUFAAOCAQEACANo6IR3OQlQaXHJaprVVDvl\n"
+				"oMJC0FRbVCK503sbmWTJL98UqxRdsTZNIL07gXlK0oUKyiNijIXiLG8d5IlUrDxF\n"
+				"H/Vsu6s8k3/PpAUVeiO2oygWqvU5NGvt0jg54MrOJKhYYPWrzbmHty+cAXyoNzOR\n"
+				"+W5RX6HRQgxvZWQq2Ok46VX622R1nNjFmCBYT7I7/gWG+hkbIAoH6d9sULLjpC+B\n"
+				"bI+L/N7ac9/Og8pGIgpUI60Gn5zO93+E+Nhg+1BlcDHGnQD6vFNs8LYp5CCX/Zj1\n"
+				"tWFVXZnx58odaU3M4t9/ZQnkZdx9YJIroETbN0PoqlnSagBjgUvbWwn4YCotCA==\n"
+				"-----END CERTIFICATE-----\n";
+				
+static char notrust_cert_data[]="-----BEGIN CERTIFICATE-----\n"
+				"MIIDhjCCAm6gAwIBAgIBATANBgkqhkiG9w0BAQUFADCBlDELMAkGA1UEBhMCSlAx\n"
+				"DjAMBgNVBAgMBVRva3lvMRAwDgYDVQQHDAdLb2dhbmVpMQ0wCwYDVQQKDARXSURF\n"
+				"MQ8wDQYDVQQLDAZBQUEgV0cxHzAdBgNVBAMMFmNoYXZyb3V4LmNvd2FkZGljdC5v\n"
+				"cmcxIjAgBgkqhkiG9w0BCQEWE3NkZWN1Z2lzQG5pY3QuZ28uanAwHhcNMDkxMDI4\n"
+				"MDgwNDQwWhcNMTAxMDI4MDgwNDQwWjB/MQswCQYDVQQGEwJKUDEOMAwGA1UECAwF\n"
+				"VG9reW8xEDAOBgNVBAcMB0tvZ2FuZWkxDTALBgNVBAoMBFdJREUxDzANBgNVBAsM\n"
+				"BkFBQSBXRzETMBEGA1UEAwwKdW5rbm93bi5jczEZMBcGCSqGSIb3DQEJARYKdW5r\n"
+				"bm93bkBjYTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA5jrVihTIFdDwXAPD\n"
+				"rzNRLBe3ZaxF6EgtrnD9fHk6x4DIUFPQGdg6JqgWTUwEFwnfaZtZK4nI4GC7HTeC\n"
+				"0j8XOcmPXXbhD24Imo8WSuqDhvm9FRRWaId5BflfZhG9IkYmZL5XFlFmQVCs8rHK\n"
+				"0DgRS0yy7iU2btO5Y3LEhIIcKycCAwEAAaN7MHkwCQYDVR0TBAIwADAsBglghkgB\n"
+				"hvhCAQ0EHxYdT3BlblNTTCBHZW5lcmF0ZWQgQ2VydGlmaWNhdGUwHQYDVR0OBBYE\n"
+				"FLpandKwS3LWHwARC7V7Wd8IOIG+MB8GA1UdIwQYMBaAFFLFpGO426zykjQvclZx\n"
+				"yBGOdubfMA0GCSqGSIb3DQEBBQUAA4IBAQCQjzu946HKapKm/fBkrkaDMjVhgFeL\n"
+				"MBJwAuFR2YfIr9lLuW2/q4ZfGR/cr4Rnvzy/M/N8xoF75OkmHbzWjKtylH+FM5XZ\n"
+				"JOz9e9L9UD7lYU91Ua7GSuzfz6pzpQj385pAZkjwjptDsTDz48g2P2g2ahyqFkBJ\n"
+				"tHOacfEXbAvT4ae3QN4sPDZ81N3WlMnXX/WuNVbozGWcuz3oesoO7XgDQcv9gIHe\n"
+				"+d6yFEuBJDbeKcEGEYaMqbAMx1fPeac6hAwn3IZty0QtJtx++xfWsj0xA9Pxq12R\n"
+				"XZTklIhwlrN8DxX+yMZNmTerCQzaurYO+l67S84EIQYJqSwnhnbM7nNv\n"
+				"-----END CERTIFICATE-----\n";
+static char notrust_priv_data[]="-----BEGIN RSA PRIVATE KEY-----\n"
+				"MIICXQIBAAKBgQDmOtWKFMgV0PBcA8OvM1EsF7dlrEXoSC2ucP18eTrHgMhQU9AZ\n"
+				"2DomqBZNTAQXCd9pm1kricjgYLsdN4LSPxc5yY9dduEPbgiajxZK6oOG+b0VFFZo\n"
+				"h3kF+V9mEb0iRiZkvlcWUWZBUKzyscrQOBFLTLLuJTZu07ljcsSEghwrJwIDAQAB\n"
+				"AoGAeRec1SGVE5Rvt5XrSK0vFofq2DlCE6hTDpszWFLTDbe4pDdRDybhfw+Nm15O\n"
+				"EGgK8BrbTcEMvKdkAzv9POQeLDE8JImgesHZFxN3jnkK+b762BGRDt57DzvMJsfj\n"
+				"1LBle+UBnZB1CvjrINvu+tNMVPlUpjIstbpMq0D+s01+ijECQQD8MHTv/M+Uc86u\n"
+				"1SFywgs+eQPQ8g0OoTLxzqo6YhW8FtwLjoRCZx2TNQS5gYBuQrixd/yE0Spfv9aS\n"
+				"UtlAaOc1AkEA6bVufggHVHcgiWqS8CHzb6g/GRxQixVshOsoVLMkCSz04zlwIfXF\n"
+				"c03hh5RJVv7jmuBmhHbayujMgvinw75oawJAQb9oXUDt5Wgj1FTgeYi5YbovEoRo\n"
+				"fw3ruDsHCl2UCQt0ptarCJzVixFhf/ORRi3C9RGxFfdqMrhS+qb62N4AmQJBALYU\n"
+				"T1BLiwJoiWXmLTJ/EP0V9Irov2uMtm5cE6DhrJqlduksz8r1gu7RZ3tMsVLg5Iy+\n"
+				"dcCQJOffNa54caQUTZ8CQQDTs/70Nr6F6ktrtmtU/S7lIitpQJCu9u/SPyBYPmFZ\n"
+				"9Axy6Ee66Php+eWDNP4Ln4axrapD0732wD8DcmGDVHij\n"
+				"-----END RSA PRIVATE KEY-----\n";
+
+/* Diffie-Hellman parameters, generated with GNUTLS certtool:
+certtool --generate-dh-params
+				Generator: 06
+
+				Prime: ea:c3:75:0b:32:cf:d9:17:98:5c:da:d1
+					e0:1d:b9:7c:be:29:60:b0:6f:68:a9:f6
+					8d:75:05:59:69:04:ae:39:7c:2b:74:04
+					3c:e2:da:28:8a:9b:93:aa:67:05:a7:3e
+					06:3e:0d:31:63:88:55:ad:5a:bd:41:22
+					b7:58:a7:45:b3:d5:03:ad:de:3c:8d:69
+					42:bf:84:3d:c1:90:e7:39:6a:4b:87:01
+					19:e5:f3:a4:e5:8e:e2:45:d5:0c:6b:17
+					22:2b:2e:50:83:91:0c:5b:82:fc:72:27
+					49:3b:9f:29:11:53:c7:90:b8:8d:87:73
+					1a:7b:05:ab:cb:30:59:16:71:30:60:1b
+					4c:80:15:3a:a2:d3:47:b7:4a:61:de:64
+					7e:79:de:88:53:b7:7a:c6:a2:9a:bb:55
+					40:2d:7a:71:c7:41:b5:29:df:d7:5c:fb
+					42:e4:d8:5e:0b:99:d3:3c:93:0f:33:51
+					8b:f4:60:e4:c5:b5:58:21:c0:51:c4:43
+					25:7c:37:fe:5c:d3:62:6c:2a:af:a7:2a
+					82:d5:d3:e2:bb:5d:ad:84:15:f6:78:d9
+					d5:a8:f7:f0:48:5c:8d:e0:3d:04:ac:cf
+					aa:34:3f:5d:f2:0d:3d:ee:ec:b8:d8:e8
+					ad:dc:d3:40:59:a0:fd:45:62:47:63:c0
+					bd:f5:df:8b
+*/
+static char dh_params_data[] =  "-----BEGIN DH PARAMETERS-----\n"
+				"MIIBCAKCAQEA6sN1CzLP2ReYXNrR4B25fL4pYLBvaKn2jXUFWWkErjl8K3QEPOLa\n"
+				"KIqbk6pnBac+Bj4NMWOIVa1avUEit1inRbPVA63ePI1pQr+EPcGQ5zlqS4cBGeXz\n"
+				"pOWO4kXVDGsXIisuUIORDFuC/HInSTufKRFTx5C4jYdzGnsFq8swWRZxMGAbTIAV\n"
+				"OqLTR7dKYd5kfnneiFO3esaimrtVQC16ccdBtSnf11z7QuTYXguZ0zyTDzNRi/Rg\n"
+				"5MW1WCHAUcRDJXw3/lzTYmwqr6cqgtXT4rtdrYQV9njZ1aj38EhcjeA9BKzPqjQ/\n"
+				"XfINPe7suNjordzTQFmg/UViR2PAvfXfiwIBBg==\n"
+				"-----END DH PARAMETERS-----\n";
+
+
+/* List server endpoints */
+static struct fd_list eps = FD_LIST_INITIALIZER(eps);
+
+/* Pass parameters to the connect thread */
+struct connect_flags {
+	int	proto;
+	int	expect_failure; /* 0 or 1 */
+};
+
+/* Client's side of the connection established from a separate thread */
+static void * connect_thr(void * arg)
+{
+	struct connect_flags * cf = arg;
+	struct cnxctx * cnx = NULL;
+	
+	fd_log_threadname ( "testcnx:connect" );
+	
+	/* Connect to the server */
+	switch (cf->proto) {
+		case IPPROTO_TCP:
+			{
+				struct fd_endpoint * ep = (struct fd_endpoint *)(eps.next);
+				cnx = fd_cnx_cli_connect_tcp( &ep->sa, sSAlen(&ep->ss) );
+				CHECK( 1, (cnx ? 1 : 0) ^ cf->expect_failure );
+			}
+			break;
+#ifndef DISABLE_SCTP
+		case IPPROTO_SCTP:
+			{
+				cnx = fd_cnx_cli_connect_sctp(0, TEST_PORT, &eps);
+				CHECK( 1, (cnx ? 1 : 0) ^ cf->expect_failure );
+			}
+			break;
+#endif /* DISABLE_SCTP */
+		default:
+			CHECK( 0, 1 );
+	}
+	
+	/* exit */
+	return cnx;
+}
+
+/* Parameters to the handshake thread */
+struct handshake_flags {
+	struct cnxctx * cnx;
+	gnutls_certificate_credentials_t	creds;
+	int algo;
+	int ret;
+};
+
+/* Handshake the client's side */
+static void * handshake_thr(void * arg)
+{
+	struct handshake_flags * hf = arg;
+	fd_log_threadname ( "testcnx:handshake" );
+	hf->ret = fd_cnx_handshake(hf->cnx, GNUTLS_CLIENT, hf->algo, NULL, hf->creds);
+	return NULL;
+}
+
+/* Terminate the client's connection side */
+static void * destroy_thr(void * arg)
+{
+	struct cnxctx * cnx = arg;
+	fd_log_threadname ( "testcnx:destroy" );
+	fd_cnx_destroy(cnx);
+	return NULL;
+}
+	
+/* Main test routine */
+int main(int argc, char *argv[])
+{
+	gnutls_datum_t ca 		= { (uint8_t *)ca_data, 		sizeof(ca_data) 	  };
+	gnutls_datum_t server_cert 	= { (uint8_t *)server_cert_data, 	sizeof(server_cert_data)  };
+	gnutls_datum_t server_priv 	= { (uint8_t *)server_priv_data, 	sizeof(server_priv_data)  };
+	gnutls_datum_t client_cert	= { (uint8_t *)client_cert_data, 	sizeof(client_cert_data)  };
+	gnutls_datum_t client_priv 	= { (uint8_t *)client_priv_data, 	sizeof(client_priv_data)  };
+	gnutls_datum_t expired_cert 	= { (uint8_t *)expired_cert_data, 	sizeof(expired_cert_data) };
+	gnutls_datum_t expired_priv 	= { (uint8_t *)expired_priv_data, 	sizeof(expired_priv_data) };
+	gnutls_datum_t notrust_ca 	= { (uint8_t *)notrust_ca_data, 	sizeof(notrust_ca_data)   };
+	gnutls_datum_t notrust_cert 	= { (uint8_t *)notrust_cert_data, 	sizeof(notrust_cert_data) };
+	gnutls_datum_t notrust_priv 	= { (uint8_t *)notrust_priv_data, 	sizeof(notrust_priv_data) };
+	gnutls_datum_t dh_params	= { (uint8_t *)dh_params_data, 		sizeof(dh_params_data) 	  };
+	
+	/* Listening socket, server side */
+	struct cnxctx * listener;
+#ifndef DISABLE_SCTP
+	struct cnxctx * listener_sctp;
+#endif /* DISABLE_SCTP */
+	
+	/* Server & client connected sockets */
+	struct cnxctx * server_side;
+	struct cnxctx * client_side;
+	
+	pthread_t thr;
+	int ret, i;
+	uint8_t * cer_buf;
+	size_t 	  cer_sz;
+	uint8_t * rcv_buf;
+	size_t 	  rcv_sz;
+	
+	/* First, initialize the daemon modules */
+	INIT_FD();
+	
+	/* Restrain the # of streams */
+	fd_g_config->cnf_sctp_str = NB_STREAMS;
+	
+	/* Set the CA parameter in the config */
+	CHECK_GNUTLS_DO( ret = gnutls_certificate_set_x509_trust_mem( fd_g_config->cnf_sec_data.credentials,
+									 &ca,
+									 GNUTLS_X509_FMT_PEM), );
+	CHECK( 1, ret );
+	
+	#ifdef GNUTLS_VERSION_300
+	{
+		/* We import these CA in the trust list */
+		gnutls_x509_crt_t * calist;
+		unsigned int cacount = 0;
+		
+		CHECK_GNUTLS_DO( ret = gnutls_x509_crt_list_import2(&calist, &cacount, &ca, GNUTLS_X509_FMT_PEM, 
+							GNUTLS_X509_CRT_LIST_FAIL_IF_UNSORTED), );
+		CHECK( 1, cacount );
+
+		CHECK_GNUTLS_DO( ret = gnutls_x509_trust_list_add_cas (fd_g_config->cnf_sec_data.trustlist, calist, cacount, 0), );
+		CHECK( 1, ret );
+	}
+		
+	/* Use certificate verification during the handshake */
+	gnutls_certificate_set_verify_function (fd_g_config->cnf_sec_data.credentials, fd_tls_verify_credentials_2);
+	
+	#endif /* GNUTLS_VERSION_300 */
+							
+	
+	/* Set the server credentials (in config) */
+	CHECK_GNUTLS_DO( ret = gnutls_certificate_set_x509_key_mem( fd_g_config->cnf_sec_data.credentials,
+									&server_cert,
+									&server_priv,
+									GNUTLS_X509_FMT_PEM), );
+	CHECK( GNUTLS_E_SUCCESS, ret );
+	
+	/* Set the default priority */
+	CHECK_GNUTLS_DO( ret = gnutls_priority_init( &fd_g_config->cnf_sec_data.prio_cache, GNUTLS_DEFAULT_PRIORITY, NULL), );
+	CHECK( GNUTLS_E_SUCCESS, ret );
+	
+	/* Set default DH params */
+	CHECK_GNUTLS_DO( ret = gnutls_dh_params_import_pkcs3( fd_g_config->cnf_sec_data.dh_cache, &dh_params, GNUTLS_X509_FMT_PEM), );
+	CHECK( GNUTLS_E_SUCCESS, ret );
+	
+	
+	/* Initialize the server address (this should give a safe loopback address + port, even on non-standard configs) */
+	{
+		struct addrinfo hints, *ai, *aip;
+		memset(&hints, 0, sizeof(hints));
+		hints.ai_flags  = AI_NUMERICSERV;
+		hints.ai_family = AF_INET;
+		CHECK( 0, getaddrinfo("localhost", _stringize(TEST_PORT), &hints, &ai) );
+		aip = ai;
+		while (aip) {
+			CHECK( 0, fd_ep_add_merge( &eps, aip->ai_addr, aip->ai_addrlen, EP_FL_DISC | EP_ACCEPTALL ));
+			aip = aip->ai_next;
+		};
+		freeaddrinfo(ai);
+		
+		CHECK( 0, FD_IS_LIST_EMPTY(&eps) ? 1 : 0 );
+	}
+	
+	/* Start the server(s) */
+	{
+		/* TCP server */
+		listener = fd_cnx_serv_tcp(TEST_PORT, 0, (struct fd_endpoint *)(eps.next));
+		CHECK( 1, listener ? 1 : 0 );
+		
+		/* Accept incoming clients */
+		CHECK( 0, fd_cnx_serv_listen(listener));
+
+#ifndef DISABLE_SCTP
+		/* SCTP server */
+		listener_sctp = fd_cnx_serv_sctp(TEST_PORT, &eps);
+		CHECK( 1, listener_sctp ? 1 : 0 );
+		
+		/* Accept incoming clients */
+		CHECK( 0, fd_cnx_serv_listen(listener_sctp));
+#endif /* DISABLE_SCTP */
+
+	}	
+	
+	/* Initialize the CER message */
+	{
+		struct msg * cer;
+		struct dict_object * model = NULL;
+		struct avp * oh;
+		union avp_value value;
+
+		/* Find the CER dictionary object */
+		CHECK( 0, fd_dict_search ( fd_g_config->cnf_dict, DICT_COMMAND, CMD_BY_NAME, "Capabilities-Exchange-Request", &model, ENOENT ) );
+
+		/* Create the instance */
+		CHECK( 0, fd_msg_new ( model, 0, &cer ) );
+		
+		/* Now find the Origin-Host dictionary object */
+		CHECK( 0, fd_dict_search ( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Origin-Host", &model, ENOENT ) );
+
+		/* Create the instance */
+		CHECK( 0, fd_msg_avp_new ( model, 0, &oh ) );
+		value.os.data = (uint8_t *)"Client.side";
+		value.os.len = strlen((char *)value.os.data);
+		CHECK( 0, fd_msg_avp_setvalue ( oh, &value ) );
+		
+		/* Add the AVP */
+		CHECK( 0, fd_msg_avp_add( cer, MSG_BRW_LAST_CHILD, oh) );
+
+		#if 0
+		/* For debug: dump the object */
+		fd_log_debug("Dumping CER");
+		fd_log_debug("%s", fd_msg_dump_treeview(FD_DUMP_TEST_PARAMS, cer, fd_g_config->cnf_dict, 0, 1));
+		#endif
+		
+		CHECK( 0, fd_msg_bufferize( cer, &cer_buf, &cer_sz ) );
+		CHECK( 0, fd_msg_free(cer) );
+	}
+	
+	/* Simple TCP client / server test (no TLS) */
+	{
+		struct connect_flags cf;
+		
+		memset(&cf, 0, sizeof(cf));
+		cf.proto = IPPROTO_TCP;
+		
+		/* Start the client thread */
+		CHECK( 0, pthread_create(&thr, NULL, connect_thr, &cf) );
+
+		/* Accept the connection of the client */
+		server_side = fd_cnx_serv_accept(listener);
+		CHECK( 1, server_side ? 1 : 0 );
+		CHECK( 0, fd_cnx_start_clear(server_side, 0) );
+		
+		/* Retrieve the client connection object */
+		CHECK( 0, pthread_join( thr, (void *)&client_side ) );
+		CHECK( 1, client_side ? 1 : 0 );
+		CHECK( 0, fd_cnx_start_clear(client_side, 0) );
+		
+		/* Send a message and receive it */
+		CHECK( 0, fd_cnx_send(server_side, cer_buf, cer_sz));
+		CHECK( 0, fd_cnx_receive(client_side, NULL, &rcv_buf, &rcv_sz));
+		CHECK( cer_sz, rcv_sz );
+		CHECK( 0, memcmp( rcv_buf, cer_buf, cer_sz ) );
+		free(rcv_buf);
+		
+		/* Do it in the other direction */
+		CHECK( 0, fd_cnx_send(client_side, cer_buf, cer_sz));
+		CHECK( 0, fd_cnx_receive(server_side, NULL, &rcv_buf, &rcv_sz));
+		CHECK( cer_sz, rcv_sz );
+		CHECK( 0, memcmp( rcv_buf, cer_buf, cer_sz ) );
+		free(rcv_buf);
+		
+		/* Now close the connections */
+		fd_cnx_destroy(client_side);
+		fd_cnx_destroy(server_side);
+	}
+		
+#ifndef DISABLE_SCTP
+	/* Simple SCTP client / server test (no TLS) */
+	{
+		struct connect_flags cf;
+		
+		memset(&cf, 0, sizeof(cf));
+		cf.proto = IPPROTO_SCTP;
+		
+		/* Start the client thread */
+		CHECK( 0, pthread_create(&thr, NULL, connect_thr, &cf) );
+
+		/* Accept the connection of the client */
+		server_side = fd_cnx_serv_accept(listener_sctp);
+		CHECK( 1, server_side ? 1 : 0 );
+		
+		/* Retrieve the client connection object */
+		CHECK( 0, pthread_join( thr, (void *)&client_side ) );
+		CHECK( 1, client_side ? 1 : 0 );
+		
+		CHECK( 0, fd_cnx_start_clear(server_side, 1) );
+		
+		/* Send a message and receive it */
+		CHECK( 0, fd_cnx_send(server_side, cer_buf, cer_sz));
+		CHECK( EINVAL, fd_cnx_receive(client_side, NULL, &rcv_buf, &rcv_sz));
+		CHECK( 0, fd_cnx_start_clear(client_side, 0) );
+		CHECK( 0, fd_cnx_receive(client_side, NULL, &rcv_buf, &rcv_sz));
+		CHECK( cer_sz, rcv_sz );
+		CHECK( 0, memcmp( rcv_buf, cer_buf, cer_sz ) );
+		free(rcv_buf);
+		
+		/* Do it in the other direction */
+		CHECK( 0, fd_cnx_send(client_side, cer_buf, cer_sz));
+		CHECK( 0, fd_cnx_receive(server_side, NULL, &rcv_buf, &rcv_sz));
+		CHECK( cer_sz, rcv_sz );
+		CHECK( 0, memcmp( rcv_buf, cer_buf, cer_sz ) );
+		free(rcv_buf);
+		
+		/* Do it one more time to use another stream */
+		CHECK( 0, fd_cnx_send(client_side, cer_buf, cer_sz));
+		CHECK( 0, fd_cnx_receive(server_side, NULL, &rcv_buf, &rcv_sz));
+		CHECK( cer_sz, rcv_sz );
+		CHECK( 0, memcmp( rcv_buf, cer_buf, cer_sz ) );
+		free(rcv_buf);
+		
+		/* Now close the connection */
+		fd_cnx_destroy(client_side);
+		fd_cnx_destroy(server_side);
+	}
+#endif /* DISABLE_SCTP */
+	
+	/* TCP Client / server emulating old Diameter behavior (handshake after 1 message exchange) */
+	{
+		struct connect_flags cf;
+		struct handshake_flags hf;
+		
+		memset(&cf, 0, sizeof(cf));
+		cf.proto = IPPROTO_TCP;
+		
+		memset(&hf, 0, sizeof(hf));
+		
+		/* Initialize remote certificate */
+		CHECK_GNUTLS_DO( ret = gnutls_certificate_allocate_credentials (&hf.creds), );
+		CHECK( GNUTLS_E_SUCCESS, ret );
+		/* Set the CA */
+		CHECK_GNUTLS_DO( ret = gnutls_certificate_set_x509_trust_mem( hf.creds, &ca, GNUTLS_X509_FMT_PEM), );
+		CHECK( 1, ret );
+		/* Set the key */
+		CHECK_GNUTLS_DO( ret = gnutls_certificate_set_x509_key_mem( hf.creds, &client_cert, &client_priv, GNUTLS_X509_FMT_PEM), );
+		CHECK( GNUTLS_E_SUCCESS, ret );
+		
+		/* Start the client thread */
+		CHECK( 0, pthread_create(&thr, NULL, connect_thr, &cf) );
+
+		/* Accept the connection of the client */
+		server_side = fd_cnx_serv_accept(listener);
+		CHECK( 1, server_side ? 1 : 0 );
+		
+		/* Retrieve the client connection object */
+		CHECK( 0, pthread_join( thr, (void *)&client_side ) );
+		CHECK( 1, client_side ? 1 : 0 );
+		hf.cnx = client_side;
+		
+		/* In legacy Diameter, we exchange first one message (CER / CEA) */
+		
+		CHECK( 0, fd_cnx_start_clear(server_side, 0) );
+		CHECK( 0, fd_cnx_start_clear(client_side, 0) );
+		
+		/* Send a message and receive it */
+		CHECK( 0, fd_cnx_send(server_side, cer_buf, cer_sz));
+		CHECK( 0, fd_cnx_receive(client_side, NULL, &rcv_buf, &rcv_sz));
+		CHECK( cer_sz, rcv_sz );
+		CHECK( 0, memcmp( rcv_buf, cer_buf, cer_sz ) );
+		free(rcv_buf);
+		
+		/* And the supposed reply */
+		CHECK( 0, fd_cnx_send(client_side, cer_buf, cer_sz));
+		CHECK( 0, fd_cnx_receive(server_side, NULL, &rcv_buf, &rcv_sz));
+		CHECK( cer_sz, rcv_sz );
+		CHECK( 0, memcmp( rcv_buf, cer_buf, cer_sz ) );
+		free(rcv_buf);
+		
+		/* At this point in legacy Diameter we start the handshake */
+		CHECK( 0, pthread_create(&thr, NULL, handshake_thr, &hf) );
+		CHECK( 0, fd_cnx_handshake(server_side, GNUTLS_SERVER, ALGO_HANDSHAKE_DEFAULT /* No impact on TCP */, NULL, NULL) );
+		CHECK( 0, pthread_join(thr, NULL) );
+		CHECK( 0, hf.ret );
+		
+		/* Send a few TLS protected message, and replies */
+		for (i = 0; i < 2 * NB_STREAMS; i++) {
+			CHECK( 0, fd_cnx_send(server_side, cer_buf, cer_sz));
+			CHECK( 0, fd_cnx_receive(client_side, NULL, &rcv_buf, &rcv_sz));
+			CHECK( cer_sz, rcv_sz );
+			CHECK( 0, memcmp( rcv_buf, cer_buf, cer_sz ) );
+			free(rcv_buf);
+
+			CHECK( 0, fd_cnx_send(client_side, cer_buf, cer_sz));
+			CHECK( 0, fd_cnx_receive(server_side, NULL, &rcv_buf, &rcv_sz));
+			CHECK( cer_sz, rcv_sz );
+			CHECK( 0, memcmp( rcv_buf, cer_buf, cer_sz ) );
+			free(rcv_buf);
+		}
+		
+		
+		/* Now close the connection */
+		CHECK( 0, pthread_create(&thr, NULL, destroy_thr, client_side) );
+		fd_cnx_destroy(server_side);
+		CHECK( 0, pthread_join(thr, NULL) );
+		
+		/* Free the credentials */
+		gnutls_certificate_free_keys(hf.creds);
+		gnutls_certificate_free_cas(hf.creds);
+		gnutls_certificate_free_credentials(hf.creds);
+	}
+		
+#ifndef DISABLE_SCTP
+	/* SCTP Client / server emulating old Diameter behavior (handshake after 1 message exchange) */
+	{
+		struct connect_flags cf;
+		struct handshake_flags hf;
+		
+		memset(&cf, 0, sizeof(cf));
+		cf.proto = IPPROTO_SCTP;
+		
+		memset(&hf, 0, sizeof(hf));
+		hf.algo = ALGO_HANDSHAKE_3436; /* this is mandatory for old TLS mechanism */
+		
+		/* Initialize remote certificate */
+		CHECK_GNUTLS_DO( ret = gnutls_certificate_allocate_credentials (&hf.creds), );
+		CHECK( GNUTLS_E_SUCCESS, ret );
+		/* Set the CA */
+		CHECK_GNUTLS_DO( ret = gnutls_certificate_set_x509_trust_mem( hf.creds, &ca, GNUTLS_X509_FMT_PEM), );
+		CHECK( 1, ret );
+		/* Set the key */
+		CHECK_GNUTLS_DO( ret = gnutls_certificate_set_x509_key_mem( hf.creds, &client_cert, &client_priv, GNUTLS_X509_FMT_PEM), );
+		CHECK( GNUTLS_E_SUCCESS, ret );
+		
+		/* Start the client thread */
+		CHECK( 0, pthread_create(&thr, NULL, connect_thr, &cf) );
+
+		/* Accept the connection of the client */
+		server_side = fd_cnx_serv_accept(listener_sctp);
+		CHECK( 1, server_side ? 1 : 0 );
+		
+		/* Retrieve the client connection object */
+		CHECK( 0, pthread_join( thr, (void *)&client_side ) );
+		CHECK( 1, client_side ? 1 : 0 );
+		hf.cnx = client_side;
+		
+		/* In legacy Diameter, we exchange first one message (CER / CEA) */
+		
+		CHECK( 0, fd_cnx_start_clear(server_side, 0) );
+		CHECK( 0, fd_cnx_start_clear(client_side, 0) );
+		
+		/* Send a message and receive it */
+		CHECK( 0, fd_cnx_send(server_side, cer_buf, cer_sz));
+		CHECK( 0, fd_cnx_receive(client_side, NULL, &rcv_buf, &rcv_sz));
+		CHECK( cer_sz, rcv_sz );
+		CHECK( 0, memcmp( rcv_buf, cer_buf, cer_sz ) );
+		free(rcv_buf);
+		
+		/* And the supposed reply */
+		CHECK( 0, fd_cnx_send(client_side, cer_buf, cer_sz));
+		CHECK( 0, fd_cnx_receive(server_side, NULL, &rcv_buf, &rcv_sz));
+		CHECK( cer_sz, rcv_sz );
+		CHECK( 0, memcmp( rcv_buf, cer_buf, cer_sz ) );
+		free(rcv_buf);
+		
+		/* At this point in legacy Diameter we start the handshake */
+		CHECK( 0, pthread_create(&thr, NULL, handshake_thr, &hf) );
+		CHECK( 0, fd_cnx_handshake(server_side, GNUTLS_SERVER, ALGO_HANDSHAKE_3436, NULL, NULL) );
+		CHECK( 0, pthread_join(thr, NULL) );
+		CHECK( 0, hf.ret );
+		
+		/* Send a few TLS protected message, and replies */
+		for (i = 0; i < 2 * NB_STREAMS; i++) {
+			CHECK( 0, fd_cnx_send(server_side, cer_buf, cer_sz));
+			CHECK( 0, fd_cnx_receive(client_side, NULL, &rcv_buf, &rcv_sz));
+			CHECK( cer_sz, rcv_sz );
+			CHECK( 0, memcmp( rcv_buf, cer_buf, cer_sz ) );
+			free(rcv_buf);
+
+			CHECK( 0, fd_cnx_send(client_side, cer_buf, cer_sz));
+			CHECK( 0, fd_cnx_receive(server_side, NULL, &rcv_buf, &rcv_sz));
+			CHECK( cer_sz, rcv_sz );
+			CHECK( 0, memcmp( rcv_buf, cer_buf, cer_sz ) );
+			free(rcv_buf);
+		}
+		
+		
+		/* Now close the connection */
+		CHECK( 0, pthread_create(&thr, NULL, destroy_thr, client_side) );
+		fd_cnx_destroy(server_side);
+		CHECK( 0, pthread_join(thr, NULL) );
+		
+		/* Free the credentials */
+		gnutls_certificate_free_keys(hf.creds);
+		gnutls_certificate_free_cas(hf.creds);
+		gnutls_certificate_free_credentials(hf.creds);
+	}
+#endif /* DISABLE_SCTP */
+	
+	/* TCP Client / server emulating new Diameter behavior (handshake at connection directly) */
+	{
+		struct connect_flags cf;
+		struct handshake_flags hf;
+		
+		memset(&cf, 0, sizeof(cf));
+		cf.proto = IPPROTO_TCP;
+		
+		memset(&hf, 0, sizeof(hf));
+		
+		/* Initialize remote certificate */
+		CHECK_GNUTLS_DO( ret = gnutls_certificate_allocate_credentials (&hf.creds), );
+		CHECK( GNUTLS_E_SUCCESS, ret );
+		/* Set the CA */
+		CHECK_GNUTLS_DO( ret = gnutls_certificate_set_x509_trust_mem( hf.creds, &ca, GNUTLS_X509_FMT_PEM), );
+		CHECK( 1, ret );
+		/* Set the key */
+		CHECK_GNUTLS_DO( ret = gnutls_certificate_set_x509_key_mem( hf.creds, &client_cert, &client_priv, GNUTLS_X509_FMT_PEM), );
+		CHECK( GNUTLS_E_SUCCESS, ret );
+		
+		/* Start the client thread */
+		CHECK( 0, pthread_create(&thr, NULL, connect_thr, &cf) );
+
+		/* Accept the connection of the client */
+		server_side = fd_cnx_serv_accept(listener);
+		CHECK( 1, server_side ? 1 : 0 );
+		
+		/* Retrieve the client connection object */
+		CHECK( 0, pthread_join( thr, (void *)&client_side ) );
+		CHECK( 1, client_side ? 1 : 0 );
+		hf.cnx = client_side;
+		
+		/* Start the handshake directly */
+		CHECK( 0, pthread_create(&thr, NULL, handshake_thr, &hf) );
+		CHECK( 0, fd_cnx_handshake(server_side, GNUTLS_SERVER, ALGO_HANDSHAKE_DEFAULT, NULL, NULL) );
+		CHECK( 0, pthread_join(thr, NULL) );
+		CHECK( 0, hf.ret );
+		
+		/* Send a few TLS protected message, and replies */
+		for (i = 0; i < 2 * NB_STREAMS; i++) {
+			CHECK( 0, fd_cnx_send(server_side, cer_buf, cer_sz));
+			CHECK( 0, fd_cnx_receive(client_side, NULL, &rcv_buf, &rcv_sz));
+			CHECK( cer_sz, rcv_sz );
+			CHECK( 0, memcmp( rcv_buf, cer_buf, cer_sz ) );
+			free(rcv_buf);
+
+			CHECK( 0, fd_cnx_send(client_side, cer_buf, cer_sz));
+			CHECK( 0, fd_cnx_receive(server_side, NULL, &rcv_buf, &rcv_sz));
+			CHECK( cer_sz, rcv_sz );
+			CHECK( 0, memcmp( rcv_buf, cer_buf, cer_sz ) );
+			free(rcv_buf);
+		}
+		
+		/* Now close the connection */
+		CHECK( 0, pthread_create(&thr, NULL, destroy_thr, client_side) );
+		fd_cnx_destroy(server_side);
+		CHECK( 0, pthread_join(thr, NULL) );
+		
+		/* Free the credentials */
+		gnutls_certificate_free_keys(hf.creds);
+		gnutls_certificate_free_cas(hf.creds);
+		gnutls_certificate_free_credentials(hf.creds);
+	}
+	
+#ifndef DISABLE_SCTP
+	
+	
+	/* SCTP Client / server emulating new Diameter behavior (DTLS handshake at connection directly) */
+	TODO("Enabled after DTLS implementation");
+	if (0)
+	{
+		struct connect_flags cf;
+		struct handshake_flags hf;
+		
+		memset(&cf, 0, sizeof(cf));
+		cf.proto = IPPROTO_SCTP;
+		
+		memset(&hf, 0, sizeof(hf));
+		
+		/* Initialize remote certificate */
+		CHECK_GNUTLS_DO( ret = gnutls_certificate_allocate_credentials (&hf.creds), );
+		CHECK( GNUTLS_E_SUCCESS, ret );
+		/* Set the CA */
+		CHECK_GNUTLS_DO( ret = gnutls_certificate_set_x509_trust_mem( hf.creds, &ca, GNUTLS_X509_FMT_PEM), );
+		CHECK( 1, ret );
+		/* Set the key */
+		CHECK_GNUTLS_DO( ret = gnutls_certificate_set_x509_key_mem( hf.creds, &client_cert, &client_priv, GNUTLS_X509_FMT_PEM), );
+		CHECK( GNUTLS_E_SUCCESS, ret );
+		
+		/* Start the client thread */
+		CHECK( 0, pthread_create(&thr, NULL, connect_thr, &cf) );
+
+		/* Accept the connection of the client */
+		server_side = fd_cnx_serv_accept(listener_sctp);
+		CHECK( 1, server_side ? 1 : 0 );
+		
+		/* Retrieve the client connection object */
+		CHECK( 0, pthread_join( thr, (void *)&client_side ) );
+		CHECK( 1, client_side ? 1 : 0 );
+		hf.cnx = client_side;
+		
+		/* Start the handshake directly */
+		CHECK( 0, pthread_create(&thr, NULL, handshake_thr, &hf) );
+		CHECK( 0, fd_cnx_handshake(server_side, GNUTLS_SERVER, ALGO_HANDSHAKE_DEFAULT, NULL, NULL) );
+		CHECK( 0, pthread_join(thr, NULL) );
+		CHECK( 0, hf.ret );
+		
+		/* Send a few TLS protected messages, and replies */
+		for (i = 0; i < 2 * NB_STREAMS; i++) {
+			CHECK( 0, fd_cnx_send(server_side, cer_buf, cer_sz));
+			CHECK( 0, fd_cnx_receive(client_side, NULL, &rcv_buf, &rcv_sz));
+			CHECK( cer_sz, rcv_sz );
+			CHECK( 0, memcmp( rcv_buf, cer_buf, cer_sz ) );
+			free(rcv_buf);
+
+			CHECK( 0, fd_cnx_send(client_side, cer_buf, cer_sz));
+			CHECK( 0, fd_cnx_receive(server_side, NULL, &rcv_buf, &rcv_sz));
+			CHECK( cer_sz, rcv_sz );
+			CHECK( 0, memcmp( rcv_buf, cer_buf, cer_sz ) );
+			free(rcv_buf);
+		}
+		
+		
+		/* Now close the connection */
+		CHECK( 0, pthread_create(&thr, NULL, destroy_thr, client_side) );
+		fd_cnx_destroy(server_side);
+		CHECK( 0, pthread_join(thr, NULL) );
+		
+		/* Free the credentials */
+		gnutls_certificate_free_keys(hf.creds);
+		gnutls_certificate_free_cas(hf.creds);
+		gnutls_certificate_free_credentials(hf.creds);
+	}
+	
+	/* SCTP Client / server emulating old intermediary Diameter behavior (TLS handshake at connection directly) */
+	{
+		struct connect_flags cf;
+		struct handshake_flags hf;
+		
+		memset(&cf, 0, sizeof(cf));
+		cf.proto = IPPROTO_SCTP;
+		
+		memset(&hf, 0, sizeof(hf));
+		hf.algo = ALGO_HANDSHAKE_3436; /* this is mandatory for old TLS mechanism */
+		
+		/* Initialize remote certificate */
+		CHECK_GNUTLS_DO( ret = gnutls_certificate_allocate_credentials (&hf.creds), );
+		CHECK( GNUTLS_E_SUCCESS, ret );
+		/* Set the CA */
+		CHECK_GNUTLS_DO( ret = gnutls_certificate_set_x509_trust_mem( hf.creds, &ca, GNUTLS_X509_FMT_PEM), );
+		CHECK( 1, ret );
+		/* Set the key */
+		CHECK_GNUTLS_DO( ret = gnutls_certificate_set_x509_key_mem( hf.creds, &client_cert, &client_priv, GNUTLS_X509_FMT_PEM), );
+		CHECK( GNUTLS_E_SUCCESS, ret );
+		
+		/* Start the client thread */
+		CHECK( 0, pthread_create(&thr, NULL, connect_thr, &cf) );
+
+		/* Accept the connection of the client */
+		server_side = fd_cnx_serv_accept(listener_sctp);
+		CHECK( 1, server_side ? 1 : 0 );
+		
+		/* Retrieve the client connection object */
+		CHECK( 0, pthread_join( thr, (void *)&client_side ) );
+		CHECK( 1, client_side ? 1 : 0 );
+		hf.cnx = client_side;
+		
+		/* Start the handshake directly */
+		CHECK( 0, pthread_create(&thr, NULL, handshake_thr, &hf) );
+		CHECK( 0, fd_cnx_handshake(server_side, GNUTLS_SERVER, ALGO_HANDSHAKE_3436, NULL, NULL) );
+		CHECK( 0, pthread_join(thr, NULL) );
+		CHECK( 0, hf.ret );
+		
+		/* Send a few TLS protected messages, and replies */
+		for (i = 0; i < 2 * NB_STREAMS; i++) {
+			CHECK( 0, fd_cnx_send(server_side, cer_buf, cer_sz));
+			CHECK( 0, fd_cnx_receive(client_side, NULL, &rcv_buf, &rcv_sz));
+			CHECK( cer_sz, rcv_sz );
+			CHECK( 0, memcmp( rcv_buf, cer_buf, cer_sz ) );
+			free(rcv_buf);
+
+			CHECK( 0, fd_cnx_send(client_side, cer_buf, cer_sz));
+			CHECK( 0, fd_cnx_receive(server_side, NULL, &rcv_buf, &rcv_sz));
+			CHECK( cer_sz, rcv_sz );
+			CHECK( 0, memcmp( rcv_buf, cer_buf, cer_sz ) );
+			free(rcv_buf);
+		}
+		
+		
+		/* Now close the connection */
+		CHECK( 0, pthread_create(&thr, NULL, destroy_thr, client_side) );
+		fd_cnx_destroy(server_side);
+		CHECK( 0, pthread_join(thr, NULL) );
+		
+		/* Free the credentials */
+		gnutls_certificate_free_keys(hf.creds);
+		gnutls_certificate_free_cas(hf.creds);
+		gnutls_certificate_free_credentials(hf.creds);
+	}
+#endif /* DISABLE_SCTP */
+	
+	/* Test with different number of streams between server and client */
+#ifndef DISABLE_SCTP
+	/* DTLS / SCTP style */
+	TODO("Enabled after DTLS implementation");
+	if (0)
+	{
+		struct connect_flags cf;
+		struct handshake_flags hf;
+		
+		memset(&cf, 0, sizeof(cf));
+		cf.proto = IPPROTO_SCTP;
+		
+		memset(&hf, 0, sizeof(hf));
+		
+		/* Initialize remote certificate */
+		CHECK_GNUTLS_DO( ret = gnutls_certificate_allocate_credentials (&hf.creds), );
+		CHECK( GNUTLS_E_SUCCESS, ret );
+		/* Set the CA */
+		CHECK_GNUTLS_DO( ret = gnutls_certificate_set_x509_trust_mem( hf.creds, &ca, GNUTLS_X509_FMT_PEM), );
+		CHECK( 1, ret );
+		/* Set the key */
+		CHECK_GNUTLS_DO( ret = gnutls_certificate_set_x509_key_mem( hf.creds, &client_cert, &client_priv, GNUTLS_X509_FMT_PEM), );
+		CHECK( GNUTLS_E_SUCCESS, ret );
+		
+		/* Start the client thread with more streams than the server */
+		fd_g_config->cnf_sctp_str = 2 * NB_STREAMS;
+		CHECK( 0, pthread_create(&thr, NULL, connect_thr, &cf) );
+
+		/* Accept the connection of the client */
+		server_side = fd_cnx_serv_accept(listener_sctp);
+		CHECK( 1, server_side ? 1 : 0 );
+		
+		/* Retrieve the client connection object */
+		CHECK( 0, pthread_join( thr, (void *)&client_side ) );
+		CHECK( 1, client_side ? 1 : 0 );
+		hf.cnx = client_side;
+		
+		/* Start the handshake directly */
+		CHECK( 0, pthread_create(&thr, NULL, handshake_thr, &hf) );
+		CHECK( 0, fd_cnx_handshake(server_side, GNUTLS_SERVER, ALGO_HANDSHAKE_DEFAULT, NULL, NULL) );
+		CHECK( 0, pthread_join(thr, NULL) );
+		CHECK( 0, hf.ret );
+		
+		/* Send a few TLS protected message, and replies */
+		for (i = 0; i < 4 * NB_STREAMS; i++) {
+			CHECK( 0, fd_cnx_send(server_side, cer_buf, cer_sz));
+			CHECK( 0, fd_cnx_receive(client_side, NULL, &rcv_buf, &rcv_sz));
+			CHECK( cer_sz, rcv_sz );
+			CHECK( 0, memcmp( rcv_buf, cer_buf, cer_sz ) );
+			free(rcv_buf);
+
+			CHECK( 0, fd_cnx_send(client_side, cer_buf, cer_sz));
+			CHECK( 0, fd_cnx_receive(server_side, NULL, &rcv_buf, &rcv_sz));
+			CHECK( cer_sz, rcv_sz );
+			CHECK( 0, memcmp( rcv_buf, cer_buf, cer_sz ) );
+			free(rcv_buf);
+		}
+		
+		/* Now close the connection */
+		CHECK( 0, pthread_create(&thr, NULL, destroy_thr, client_side) );
+		fd_cnx_destroy(server_side);
+		CHECK( 0, pthread_join(thr, NULL) );
+		
+		/* Do the same test but with more streams on the server this time */
+		fd_g_config->cnf_sctp_str = NB_STREAMS / 2;
+		CHECK( 0, pthread_create(&thr, NULL, connect_thr, &cf) );
+
+		/* Accept the connection of the client */
+		server_side = fd_cnx_serv_accept(listener_sctp);
+		CHECK( 1, server_side ? 1 : 0 );
+		
+		/* Retrieve the client connection object */
+		CHECK( 0, pthread_join( thr, (void *)&client_side ) );
+		CHECK( 1, client_side ? 1 : 0 );
+		hf.cnx = client_side;
+		
+		/* Start the handshake directly */
+		CHECK( 0, pthread_create(&thr, NULL, handshake_thr, &hf) );
+		CHECK( 0, fd_cnx_handshake(server_side, GNUTLS_SERVER, ALGO_HANDSHAKE_DEFAULT, NULL, NULL) );
+		CHECK( 0, pthread_join(thr, NULL) );
+		CHECK( 0, hf.ret );
+		
+		/* Send a few TLS protected message, and replies */
+		for (i = 0; i < 2 * NB_STREAMS; i++) {
+			CHECK( 0, fd_cnx_send(server_side, cer_buf, cer_sz));
+			CHECK( 0, fd_cnx_receive(client_side, NULL, &rcv_buf, &rcv_sz));
+			CHECK( cer_sz, rcv_sz );
+			CHECK( 0, memcmp( rcv_buf, cer_buf, cer_sz ) );
+			free(rcv_buf);
+
+			CHECK( 0, fd_cnx_send(client_side, cer_buf, cer_sz));
+			CHECK( 0, fd_cnx_receive(server_side, NULL, &rcv_buf, &rcv_sz));
+			CHECK( cer_sz, rcv_sz );
+			CHECK( 0, memcmp( rcv_buf, cer_buf, cer_sz ) );
+			free(rcv_buf);
+		}
+		
+		/* Now close the connection */
+		CHECK( 0, pthread_create(&thr, NULL, destroy_thr, client_side) );
+		fd_cnx_destroy(server_side);
+		CHECK( 0, pthread_join(thr, NULL) );
+		
+		
+		/* Free the credentials */
+		gnutls_certificate_free_keys(hf.creds);
+		gnutls_certificate_free_cas(hf.creds);
+		gnutls_certificate_free_credentials(hf.creds);
+	}
+	
+	/* TLS / SCTP style */
+	{
+		struct connect_flags cf;
+		struct handshake_flags hf;
+		
+		memset(&cf, 0, sizeof(cf));
+		cf.proto = IPPROTO_SCTP;
+		
+		memset(&hf, 0, sizeof(hf));
+		hf.algo = ALGO_HANDSHAKE_3436;
+		
+		/* Initialize remote certificate */
+		CHECK_GNUTLS_DO( ret = gnutls_certificate_allocate_credentials (&hf.creds), );
+		CHECK( GNUTLS_E_SUCCESS, ret );
+		/* Set the CA */
+		CHECK_GNUTLS_DO( ret = gnutls_certificate_set_x509_trust_mem( hf.creds, &ca, GNUTLS_X509_FMT_PEM), );
+		CHECK( 1, ret );
+		/* Set the key */
+		CHECK_GNUTLS_DO( ret = gnutls_certificate_set_x509_key_mem( hf.creds, &client_cert, &client_priv, GNUTLS_X509_FMT_PEM), );
+		CHECK( GNUTLS_E_SUCCESS, ret );
+		
+		/* Start the client thread with more streams than the server */
+		fd_g_config->cnf_sctp_str = 2 * NB_STREAMS;
+		CHECK( 0, pthread_create(&thr, NULL, connect_thr, &cf) );
+
+		/* Accept the connection of the client */
+		server_side = fd_cnx_serv_accept(listener_sctp);
+		CHECK( 1, server_side ? 1 : 0 );
+		
+		/* Retrieve the client connection object */
+		CHECK( 0, pthread_join( thr, (void *)&client_side ) );
+		CHECK( 1, client_side ? 1 : 0 );
+		hf.cnx = client_side;
+		
+		/* Start the handshake directly */
+		CHECK( 0, pthread_create(&thr, NULL, handshake_thr, &hf) );
+		CHECK( 0, fd_cnx_handshake(server_side, GNUTLS_SERVER, ALGO_HANDSHAKE_3436, NULL, NULL) );
+		CHECK( 0, pthread_join(thr, NULL) );
+		CHECK( 0, hf.ret );
+		
+		/* Send a few TLS protected message, and replies */
+		for (i = 0; i < 4 * NB_STREAMS; i++) {
+			CHECK( 0, fd_cnx_send(server_side, cer_buf, cer_sz));
+			CHECK( 0, fd_cnx_receive(client_side, NULL, &rcv_buf, &rcv_sz));
+			CHECK( cer_sz, rcv_sz );
+			CHECK( 0, memcmp( rcv_buf, cer_buf, cer_sz ) );
+			free(rcv_buf);
+
+			CHECK( 0, fd_cnx_send(client_side, cer_buf, cer_sz));
+			CHECK( 0, fd_cnx_receive(server_side, NULL, &rcv_buf, &rcv_sz));
+			CHECK( cer_sz, rcv_sz );
+			CHECK( 0, memcmp( rcv_buf, cer_buf, cer_sz ) );
+			free(rcv_buf);
+		}
+		
+		/* Now close the connection */
+		CHECK( 0, pthread_create(&thr, NULL, destroy_thr, client_side) );
+		fd_cnx_destroy(server_side);
+		CHECK( 0, pthread_join(thr, NULL) );
+		
+		/* Do the same test but with more streams on the server this time */
+		fd_g_config->cnf_sctp_str = NB_STREAMS / 2;
+		CHECK( 0, pthread_create(&thr, NULL, connect_thr, &cf) );
+
+		/* Accept the connection of the client */
+		server_side = fd_cnx_serv_accept(listener_sctp);
+		CHECK( 1, server_side ? 1 : 0 );
+		
+		/* Retrieve the client connection object */
+		CHECK( 0, pthread_join( thr, (void *)&client_side ) );
+		CHECK( 1, client_side ? 1 : 0 );
+		hf.cnx = client_side;
+		
+		/* Start the handshake directly */
+		CHECK( 0, pthread_create(&thr, NULL, handshake_thr, &hf) );
+		CHECK( 0, fd_cnx_handshake(server_side, GNUTLS_SERVER, ALGO_HANDSHAKE_3436, NULL, NULL) );
+		CHECK( 0, pthread_join(thr, NULL) );
+		CHECK( 0, hf.ret );
+		
+		/* Send a few TLS protected message, and replies */
+		for (i = 0; i < 2 * NB_STREAMS; i++) {
+			CHECK( 0, fd_cnx_send(server_side, cer_buf, cer_sz));
+			CHECK( 0, fd_cnx_receive(client_side, NULL, &rcv_buf, &rcv_sz));
+			CHECK( cer_sz, rcv_sz );
+			CHECK( 0, memcmp( rcv_buf, cer_buf, cer_sz ) );
+			free(rcv_buf);
+
+			CHECK( 0, fd_cnx_send(client_side, cer_buf, cer_sz));
+			CHECK( 0, fd_cnx_receive(server_side, NULL, &rcv_buf, &rcv_sz));
+			CHECK( cer_sz, rcv_sz );
+			CHECK( 0, memcmp( rcv_buf, cer_buf, cer_sz ) );
+			free(rcv_buf);
+		}
+		
+		/* Now close the connection */
+		CHECK( 0, pthread_create(&thr, NULL, destroy_thr, client_side) );
+		fd_cnx_destroy(server_side);
+		CHECK( 0, pthread_join(thr, NULL) );
+		
+		
+		/* Free the credentials */
+		gnutls_certificate_free_keys(hf.creds);
+		gnutls_certificate_free_cas(hf.creds);
+		gnutls_certificate_free_credentials(hf.creds);
+	}
+	
+#endif /* DISABLE_SCTP */
+	
+	
+	/* Basic operation tested successfully, now test we detect error conditions */
+
+	/* Untrusted certificate, TCP */
+	{
+		struct connect_flags cf;
+		struct handshake_flags hf;
+		
+		memset(&cf, 0, sizeof(cf));
+		cf.proto = IPPROTO_TCP;
+		
+		memset(&hf, 0, sizeof(hf));
+		
+		/* Initialize remote certificate */
+		CHECK_GNUTLS_DO( ret = gnutls_certificate_allocate_credentials (&hf.creds), );
+		CHECK( GNUTLS_E_SUCCESS, ret );
+		/* Set the CA */
+		CHECK_GNUTLS_DO( ret = gnutls_certificate_set_x509_trust_mem( hf.creds, &notrust_ca, GNUTLS_X509_FMT_PEM), );
+		CHECK_GNUTLS_DO( ret = gnutls_certificate_set_x509_trust_mem( hf.creds, &ca, GNUTLS_X509_FMT_PEM), );
+		CHECK( 1, ret );
+		/* Set the key */
+		CHECK_GNUTLS_DO( ret = gnutls_certificate_set_x509_key_mem( hf.creds, &notrust_cert, &notrust_priv, GNUTLS_X509_FMT_PEM), );
+		CHECK( GNUTLS_E_SUCCESS, ret );
+		
+		/* Start the client thread */
+		CHECK( 0, pthread_create(&thr, NULL, connect_thr, &cf) );
+
+		/* Accept the connection of the client */
+		server_side = fd_cnx_serv_accept(listener);
+		CHECK( 1, server_side ? 1 : 0 );
+		
+		/* Retrieve the client connection object */
+		CHECK( 0, pthread_join( thr, (void *)&client_side ) );
+		CHECK( 1, client_side ? 1 : 0 );
+		hf.cnx = client_side;
+		
+		/* Start the handshake directly */
+		CHECK( 0, pthread_create(&thr, NULL, handshake_thr, &hf) );
+		CHECK( EINVAL, fd_cnx_handshake(server_side, GNUTLS_SERVER, ALGO_HANDSHAKE_DEFAULT, NULL, NULL) );
+		fd_cnx_destroy(server_side);
+		
+		CHECK( 0, pthread_join(thr, NULL) );
+		
+		/* Now close the connection */
+		CHECK( 0, pthread_create(&thr, NULL, destroy_thr, client_side) );
+		CHECK( 0, pthread_join(thr, NULL) );
+		
+		/* Free the credentials */
+		gnutls_certificate_free_keys(hf.creds);
+		gnutls_certificate_free_cas(hf.creds);
+		gnutls_certificate_free_credentials(hf.creds);
+	}
+	
+	/* Same in SCTP */
+#ifndef DISABLE_SCTP
+	/* DTLS */
+	TODO("Enabled after DTLS implementation");
+	if (0)
+	{
+		struct connect_flags cf;
+		struct handshake_flags hf;
+		
+		memset(&cf, 0, sizeof(cf));
+		cf.proto = IPPROTO_SCTP;
+		
+		memset(&hf, 0, sizeof(hf));
+		
+		/* Initialize remote certificate */
+		CHECK_GNUTLS_DO( ret = gnutls_certificate_allocate_credentials (&hf.creds), );
+		CHECK( GNUTLS_E_SUCCESS, ret );
+		/* Set the CA */
+		CHECK_GNUTLS_DO( ret = gnutls_certificate_set_x509_trust_mem( hf.creds, &notrust_ca, GNUTLS_X509_FMT_PEM), );
+		CHECK_GNUTLS_DO( ret = gnutls_certificate_set_x509_trust_mem( hf.creds, &ca, GNUTLS_X509_FMT_PEM), );
+		CHECK( 1, ret );
+		/* Set the key */
+		CHECK_GNUTLS_DO( ret = gnutls_certificate_set_x509_key_mem( hf.creds, &notrust_cert, &notrust_priv, GNUTLS_X509_FMT_PEM), );
+		CHECK( GNUTLS_E_SUCCESS, ret );
+		
+		/* Start the client thread */
+		CHECK( 0, pthread_create(&thr, NULL, connect_thr, &cf) );
+
+		/* Accept the connection of the client */
+		server_side = fd_cnx_serv_accept(listener_sctp);
+		CHECK( 1, server_side ? 1 : 0 );
+		
+		/* Retrieve the client connection object */
+		CHECK( 0, pthread_join( thr, (void *)&client_side ) );
+		CHECK( 1, client_side ? 1 : 0 );
+		hf.cnx = client_side;
+		
+		/* Start the handshake directly */
+		CHECK( 0, pthread_create(&thr, NULL, handshake_thr, &hf) );
+		CHECK( EINVAL, fd_cnx_handshake(server_side, GNUTLS_SERVER, ALGO_HANDSHAKE_DEFAULT, NULL, NULL) );
+		fd_cnx_destroy(server_side);
+		CHECK( 0, pthread_join(thr, NULL) );
+		
+		/* Now close the connection */
+		CHECK( 0, pthread_create(&thr, NULL, destroy_thr, client_side) );
+		CHECK( 0, pthread_join(thr, NULL) );
+		
+		/* Free the credentials */
+		gnutls_certificate_free_keys(hf.creds);
+		gnutls_certificate_free_cas(hf.creds);
+		gnutls_certificate_free_credentials(hf.creds);
+	}
+	
+	/* TLS */
+	{
+		struct connect_flags cf;
+		struct handshake_flags hf;
+		
+		memset(&cf, 0, sizeof(cf));
+		cf.proto = IPPROTO_SCTP;
+		
+		memset(&hf, 0, sizeof(hf));
+		hf.algo = ALGO_HANDSHAKE_3436;
+		
+		/* Initialize remote certificate */
+		CHECK_GNUTLS_DO( ret = gnutls_certificate_allocate_credentials (&hf.creds), );
+		CHECK( GNUTLS_E_SUCCESS, ret );
+		/* Set the CA */
+		CHECK_GNUTLS_DO( ret = gnutls_certificate_set_x509_trust_mem( hf.creds, &notrust_ca, GNUTLS_X509_FMT_PEM), );
+		CHECK_GNUTLS_DO( ret = gnutls_certificate_set_x509_trust_mem( hf.creds, &ca, GNUTLS_X509_FMT_PEM), );
+		CHECK( 1, ret );
+		/* Set the key */
+		CHECK_GNUTLS_DO( ret = gnutls_certificate_set_x509_key_mem( hf.creds, &notrust_cert, &notrust_priv, GNUTLS_X509_FMT_PEM), );
+		CHECK( GNUTLS_E_SUCCESS, ret );
+		
+		/* Start the client thread */
+		CHECK( 0, pthread_create(&thr, NULL, connect_thr, &cf) );
+
+		/* Accept the connection of the client */
+		server_side = fd_cnx_serv_accept(listener_sctp);
+		CHECK( 1, server_side ? 1 : 0 );
+		
+		/* Retrieve the client connection object */
+		CHECK( 0, pthread_join( thr, (void *)&client_side ) );
+		CHECK( 1, client_side ? 1 : 0 );
+		hf.cnx = client_side;
+		
+		/* Start the handshake directly */
+		CHECK( 0, pthread_create(&thr, NULL, handshake_thr, &hf) );
+		CHECK( EINVAL, fd_cnx_handshake(server_side, GNUTLS_SERVER, ALGO_HANDSHAKE_3436, NULL, NULL) );
+		fd_cnx_destroy(server_side);
+		CHECK( 0, pthread_join(thr, NULL) );
+		
+		/* Now close the connection */
+		CHECK( 0, pthread_create(&thr, NULL, destroy_thr, client_side) );
+		CHECK( 0, pthread_join(thr, NULL) );
+		
+		/* Free the credentials */
+		gnutls_certificate_free_keys(hf.creds);
+		gnutls_certificate_free_cas(hf.creds);
+		gnutls_certificate_free_credentials(hf.creds);
+	}
+#endif /* DISABLE_SCTP */
+	
+	/* Expired certificate */
+	{
+		struct connect_flags cf;
+		struct handshake_flags hf;
+		
+		memset(&cf, 0, sizeof(cf));
+		cf.proto = IPPROTO_TCP;
+		
+		memset(&hf, 0, sizeof(hf));
+		
+		/* Initialize remote certificate */
+		CHECK_GNUTLS_DO( ret = gnutls_certificate_allocate_credentials (&hf.creds), );
+		CHECK( GNUTLS_E_SUCCESS, ret );
+		/* Set the CA */
+		CHECK_GNUTLS_DO( ret = gnutls_certificate_set_x509_trust_mem( hf.creds, &ca, GNUTLS_X509_FMT_PEM), );
+		CHECK( 1, ret );
+		/* Set the key */
+		CHECK_GNUTLS_DO( ret = gnutls_certificate_set_x509_key_mem( hf.creds, &expired_cert, &expired_priv, GNUTLS_X509_FMT_PEM), );
+		CHECK( GNUTLS_E_SUCCESS, ret );
+		
+		/* Start the client thread */
+		CHECK( 0, pthread_create(&thr, NULL, connect_thr, &cf) );
+
+		/* Accept the connection of the client */
+		server_side = fd_cnx_serv_accept(listener);
+		CHECK( 1, server_side ? 1 : 0 );
+		
+		/* Retrieve the client connection object */
+		CHECK( 0, pthread_join( thr, (void *)&client_side ) );
+		CHECK( 1, client_side ? 1 : 0 );
+		hf.cnx = client_side;
+		
+		/* Start the handshake directly */
+		CHECK( 0, pthread_create(&thr, NULL, handshake_thr, &hf) );
+		CHECK( EINVAL, fd_cnx_handshake(server_side, GNUTLS_SERVER, ALGO_HANDSHAKE_DEFAULT, NULL, NULL) );
+		fd_cnx_destroy(server_side);
+		CHECK( 0, pthread_join(thr, NULL) );
+		
+		/* Now close the connection */
+		CHECK( 0, pthread_create(&thr, NULL, destroy_thr, client_side) );
+		CHECK( 0, pthread_join(thr, NULL) );
+		
+		/* Free the credentials */
+		gnutls_certificate_free_keys(hf.creds);
+		gnutls_certificate_free_cas(hf.creds);
+		gnutls_certificate_free_credentials(hf.creds);
+	}
+	
+	/* Non matching hostname */
+	
+	{
+		struct connect_flags cf;
+		struct handshake_flags hf;
+		
+		memset(&cf, 0, sizeof(cf));
+		cf.proto = IPPROTO_TCP;
+		
+		memset(&hf, 0, sizeof(hf));
+		
+		/* Initialize remote certificate */
+		CHECK_GNUTLS_DO( ret = gnutls_certificate_allocate_credentials (&hf.creds), );
+		CHECK( GNUTLS_E_SUCCESS, ret );
+		/* Set the CA */
+		CHECK_GNUTLS_DO( ret = gnutls_certificate_set_x509_trust_mem( hf.creds, &ca, GNUTLS_X509_FMT_PEM), );
+		CHECK( 1, ret );
+		/* Set the key */
+		CHECK_GNUTLS_DO( ret = gnutls_certificate_set_x509_key_mem( hf.creds, &client_cert, &client_priv, GNUTLS_X509_FMT_PEM), );
+		CHECK( GNUTLS_E_SUCCESS, ret );
+		
+		/* Start the client thread */
+		CHECK( 0, pthread_create(&thr, NULL, connect_thr, &cf) );
+
+		/* Accept the connection of the client */
+		server_side = fd_cnx_serv_accept(listener);
+		CHECK( 1, server_side ? 1 : 0 );
+		
+		/* Retrieve the client connection object */
+		CHECK( 0, pthread_join( thr, (void *)&client_side ) );
+		CHECK( 1, client_side ? 1 : 0 );
+		hf.cnx = client_side;
+		
+		/* Set the correct hostname we expect from the client (in the server) */
+		fd_cnx_sethostname(server_side, "client.test");
+		
+		/* Start the handshake, check it is successful */
+		CHECK( 0, pthread_create(&thr, NULL, handshake_thr, &hf) );
+		CHECK( 0, fd_cnx_handshake(server_side, GNUTLS_SERVER, ALGO_HANDSHAKE_DEFAULT, NULL, NULL) );
+		CHECK( 0, pthread_join(thr, NULL) );
+		CHECK( 0, hf.ret );
+		
+		/* Now close the connection */
+		CHECK( 0, pthread_create(&thr, NULL, destroy_thr, client_side) );
+		fd_cnx_destroy(server_side);
+		CHECK( 0, pthread_join(thr, NULL) );
+		
+		/* Do it again with an invalid hostname */
+		CHECK( 0, pthread_create(&thr, NULL, connect_thr, &cf) );
+
+		/* Accept the connection of the client */
+		server_side = fd_cnx_serv_accept(listener);
+		CHECK( 1, server_side ? 1 : 0 );
+		
+		/* Retrieve the client connection object */
+		CHECK( 0, pthread_join( thr, (void *)&client_side ) );
+		CHECK( 1, client_side ? 1 : 0 );
+		hf.cnx = client_side;
+		
+		/* Set the correct hostname we expect from the client (in the server) */
+		fd_cnx_sethostname(server_side, "nomatch.test");
+		
+		/* Start the handshake, check it is successful */
+		CHECK( 0, pthread_create(&thr, NULL, handshake_thr, &hf) );
+		CHECK( EINVAL, fd_cnx_handshake(server_side, GNUTLS_SERVER, ALGO_HANDSHAKE_DEFAULT, NULL, NULL) );
+		fd_cnx_destroy(server_side);
+		CHECK( 0, pthread_join(thr, NULL) );
+		
+		/* Now close the connection */
+		CHECK( 0, pthread_create(&thr, NULL, destroy_thr, client_side) );
+		CHECK( 0, pthread_join(thr, NULL) );
+		
+		/* Free the credentials */
+		gnutls_certificate_free_keys(hf.creds);
+		gnutls_certificate_free_cas(hf.creds);
+		gnutls_certificate_free_credentials(hf.creds);
+	}
+	
+	/* Test the other functions of the module */
+	{
+		struct connect_flags cf;
+		struct handshake_flags hf;
+		char * str;
+		const gnutls_datum_t *cert_list;
+		unsigned int cert_list_size;
+		struct fifo * myfifo = NULL;
+		struct timespec now;
+		int ev_code;
+		
+		memset(&cf, 0, sizeof(cf));
+		cf.proto = IPPROTO_TCP;
+		
+		memset(&hf, 0, sizeof(hf));
+		
+		/* Initialize remote certificate */
+		CHECK_GNUTLS_DO( ret = gnutls_certificate_allocate_credentials (&hf.creds), );
+		CHECK( GNUTLS_E_SUCCESS, ret );
+		/* Set the CA */
+		CHECK_GNUTLS_DO( ret = gnutls_certificate_set_x509_trust_mem( hf.creds, &ca, GNUTLS_X509_FMT_PEM), );
+		CHECK( 1, ret );
+		/* Set the key */
+		CHECK_GNUTLS_DO( ret = gnutls_certificate_set_x509_key_mem( hf.creds, &client_cert, &client_priv, GNUTLS_X509_FMT_PEM), );
+		CHECK( GNUTLS_E_SUCCESS, ret );
+		
+		/* Start the client thread */
+		CHECK( 0, pthread_create(&thr, NULL, connect_thr, &cf) );
+
+		/* Accept the connection of the client */
+		server_side = fd_cnx_serv_accept(listener);
+		CHECK( 1, server_side ? 1 : 0 );
+		
+		/* Retrieve the client connection object */
+		CHECK( 0, pthread_join( thr, (void *)&client_side ) );
+		CHECK( 1, client_side ? 1 : 0 );
+		hf.cnx = client_side;
+		
+		/* Start the handshake */
+		CHECK( 0, pthread_create(&thr, NULL, handshake_thr, &hf) );
+		CHECK( 0, fd_cnx_handshake(server_side, GNUTLS_SERVER, ALGO_HANDSHAKE_DEFAULT, NULL, NULL) );
+		CHECK( 0, pthread_join(thr, NULL) );
+		CHECK( 0, hf.ret );
+		
+		/* Test some simple functions */
+		
+		/* fd_cnx_getid */
+		str = fd_cnx_getid(server_side);
+		CHECK( 1, str ? 1 : 0 );
+		CHECK( 1, (str[0] != '\0') ? 1 : 0 );
+		
+		/* fd_cnx_getproto */
+		i = fd_cnx_getproto(server_side);
+		CHECK( IPPROTO_TCP, i);
+		
+		/* fd_cnx_getTLS */
+		i = fd_cnx_getTLS(server_side);
+		CHECK( 1, i ? 1 : 0 );
+		
+		/* fd_cnx_getcred */
+		CHECK( 0, fd_cnx_getcred(server_side, &cert_list, &cert_list_size) );
+		CHECK( 1, (cert_list_size > 0) ? 1 : 0 );
+		/* We could also verify that the cert_list really contains the client_cert and ca certificates */
+		
+		/* fd_cnx_getremoteid */
+		str = fd_cnx_getremoteid(server_side);
+		CHECK( 1, str ? 1 : 0 );
+		CHECK( 1, (str[0] != '\0') ? 1 : 0 );
+		
+		/* fd_cnx_recv_setaltfifo */
+		CHECK( 0, fd_cnx_send(client_side, cer_buf, cer_sz));
+		CHECK( 0, fd_fifo_new(&myfifo, 0) );
+		CHECK( 0, fd_cnx_recv_setaltfifo(server_side, myfifo) );
+		CHECK( 0, clock_gettime(CLOCK_REALTIME, &now) );
+		do {
+			CHECK( 0, fd_event_timedget(myfifo, &now, ETIMEDOUT, &ev_code, NULL, (void *)&rcv_buf) );
+			free(rcv_buf);
+		} while (ev_code != FDEVP_CNX_MSG_RECV);
+		
+		/* Now close the connection */
+		CHECK( 0, pthread_create(&thr, NULL, destroy_thr, client_side) );
+		fd_cnx_destroy(server_side);
+		CHECK( 0, pthread_join(thr, NULL) );
+		
+		fd_event_destroy(&myfifo, free);
+		
+		/* Free the credentials */
+		gnutls_certificate_free_keys(hf.creds);
+		gnutls_certificate_free_cas(hf.creds);
+		gnutls_certificate_free_credentials(hf.creds);
+	}
+	
+#ifndef DISABLE_SCTP
+	/* And re-test with a SCTP connection */
+	TODO("Enabled after DTLS implementation");
+	if (0)
+	{
+		struct connect_flags cf;
+		struct handshake_flags hf;
+		char * str;
+		const gnutls_datum_t *cert_list;
+		unsigned int cert_list_size;
+		struct fifo * myfifo = NULL;
+		struct timespec now;
+		int ev_code;
+		
+		memset(&cf, 0, sizeof(cf));
+		cf.proto = IPPROTO_SCTP;
+		
+		memset(&hf, 0, sizeof(hf));
+		
+		/* Initialize remote certificate */
+		CHECK_GNUTLS_DO( ret = gnutls_certificate_allocate_credentials (&hf.creds), );
+		CHECK( GNUTLS_E_SUCCESS, ret );
+		/* Set the CA */
+		CHECK_GNUTLS_DO( ret = gnutls_certificate_set_x509_trust_mem( hf.creds, &ca, GNUTLS_X509_FMT_PEM), );
+		CHECK( 1, ret );
+		/* Set the key */
+		CHECK_GNUTLS_DO( ret = gnutls_certificate_set_x509_key_mem( hf.creds, &client_cert, &client_priv, GNUTLS_X509_FMT_PEM), );
+		CHECK( GNUTLS_E_SUCCESS, ret );
+		
+		/* Start the client thread */
+		CHECK( 0, pthread_create(&thr, NULL, connect_thr, &cf) );
+
+		/* Accept the connection of the client */
+		server_side = fd_cnx_serv_accept(listener_sctp);
+		CHECK( 1, server_side ? 1 : 0 );
+		
+		/* Retrieve the client connection object */
+		CHECK( 0, pthread_join( thr, (void *)&client_side ) );
+		CHECK( 1, client_side ? 1 : 0 );
+		hf.cnx = client_side;
+		
+		/* Start the handshake */
+		CHECK( 0, pthread_create(&thr, NULL, handshake_thr, &hf) );
+		CHECK( 0, fd_cnx_handshake(server_side, GNUTLS_SERVER, ALGO_HANDSHAKE_DEFAULT, NULL, NULL) );
+		CHECK( 0, pthread_join(thr, NULL) );
+		CHECK( 0, hf.ret );
+		
+		/* Test some simple functions */
+		
+		/* fd_cnx_getid */
+		str = fd_cnx_getid(server_side);
+		CHECK( 1, str ? 1 : 0 );
+		CHECK( 1, (str[0] != '\0') ? 1 : 0 );
+		
+		/* fd_cnx_getproto */
+		i = fd_cnx_getproto(server_side);
+		CHECK( IPPROTO_SCTP, i);
+		
+		/* fd_cnx_getTLS */
+		i = fd_cnx_getTLS(server_side);
+		CHECK( 1, i ? 1 : 0 );
+		
+		/* fd_cnx_getcred */
+		CHECK( 0, fd_cnx_getcred(server_side, &cert_list, &cert_list_size) );
+		CHECK( 1, (cert_list_size > 0) ? 1 : 0 );
+		/* We could also verify that the cert_list really contains the client_cert and ca certificates */
+		
+		/* fd_cnx_getremoteid */
+		str = fd_cnx_getremoteid(server_side);
+		CHECK( 1, str ? 1 : 0 );
+		CHECK( 1, (str[0] != '\0') ? 1 : 0 );
+		
+		/* fd_cnx_recv_setaltfifo */
+		CHECK( 0, fd_cnx_send(client_side, cer_buf, cer_sz));
+		CHECK( 0, fd_fifo_new(&myfifo, 0) );
+		CHECK( 0, fd_cnx_recv_setaltfifo(server_side, myfifo) );
+		CHECK( 0, clock_gettime(CLOCK_REALTIME, &now) );
+		do {
+			CHECK( 0, fd_event_timedget(myfifo, &now, ETIMEDOUT, &ev_code, NULL, (void *)&rcv_buf) );
+			free(rcv_buf);
+		} while (ev_code != FDEVP_CNX_MSG_RECV);
+		
+		/* Now close the connection */
+		CHECK( 0, pthread_create(&thr, NULL, destroy_thr, client_side) );
+		fd_cnx_destroy(server_side);
+		CHECK( 0, pthread_join(thr, NULL) );
+		
+		fd_event_destroy(&myfifo, free);
+		
+		/* Free the credentials */
+		gnutls_certificate_free_keys(hf.creds);
+		gnutls_certificate_free_cas(hf.creds);
+		gnutls_certificate_free_credentials(hf.creds);
+	}
+	
+	/* TLS */
+	{
+		struct connect_flags cf;
+		struct handshake_flags hf;
+		char * str;
+		const gnutls_datum_t *cert_list;
+		unsigned int cert_list_size;
+		struct fifo * myfifo = NULL;
+		struct timespec now;
+		int ev_code;
+		
+		memset(&cf, 0, sizeof(cf));
+		cf.proto = IPPROTO_SCTP;
+		
+		memset(&hf, 0, sizeof(hf));
+		hf.algo = ALGO_HANDSHAKE_3436;
+		
+		/* Initialize remote certificate */
+		CHECK_GNUTLS_DO( ret = gnutls_certificate_allocate_credentials (&hf.creds), );
+		CHECK( GNUTLS_E_SUCCESS, ret );
+		/* Set the CA */
+		CHECK_GNUTLS_DO( ret = gnutls_certificate_set_x509_trust_mem( hf.creds, &ca, GNUTLS_X509_FMT_PEM), );
+		CHECK( 1, ret );
+		/* Set the key */
+		CHECK_GNUTLS_DO( ret = gnutls_certificate_set_x509_key_mem( hf.creds, &client_cert, &client_priv, GNUTLS_X509_FMT_PEM), );
+		CHECK( GNUTLS_E_SUCCESS, ret );
+		
+		/* Start the client thread */
+		CHECK( 0, pthread_create(&thr, NULL, connect_thr, &cf) );
+
+		/* Accept the connection of the client */
+		server_side = fd_cnx_serv_accept(listener_sctp);
+		CHECK( 1, server_side ? 1 : 0 );
+		
+		/* Retrieve the client connection object */
+		CHECK( 0, pthread_join( thr, (void *)&client_side ) );
+		CHECK( 1, client_side ? 1 : 0 );
+		hf.cnx = client_side;
+		
+		/* Start the handshake */
+		CHECK( 0, pthread_create(&thr, NULL, handshake_thr, &hf) );
+		CHECK( 0, fd_cnx_handshake(server_side, GNUTLS_SERVER, ALGO_HANDSHAKE_3436, NULL, NULL) );
+		CHECK( 0, pthread_join(thr, NULL) );
+		CHECK( 0, hf.ret );
+		
+		/* Test some simple functions */
+		
+		/* fd_cnx_getid */
+		str = fd_cnx_getid(server_side);
+		CHECK( 1, str ? 1 : 0 );
+		CHECK( 1, (str[0] != '\0') ? 1 : 0 );
+		
+		/* fd_cnx_getproto */
+		i = fd_cnx_getproto(server_side);
+		CHECK( IPPROTO_SCTP, i);
+		
+		/* fd_cnx_getTLS */
+		i = fd_cnx_getTLS(server_side);
+		CHECK( 1, i ? 1 : 0 );
+		
+		/* fd_cnx_getcred */
+		CHECK( 0, fd_cnx_getcred(server_side, &cert_list, &cert_list_size) );
+		CHECK( 1, (cert_list_size > 0) ? 1 : 0 );
+		/* We could also verify that the cert_list really contains the client_cert and ca certificates */
+		
+		/* fd_cnx_getremoteid */
+		str = fd_cnx_getremoteid(server_side);
+		CHECK( 1, str ? 1 : 0 );
+		CHECK( 1, (str[0] != '\0') ? 1 : 0 );
+		
+		/* fd_cnx_recv_setaltfifo */
+		CHECK( 0, fd_cnx_send(client_side, cer_buf, cer_sz));
+		CHECK( 0, fd_fifo_new(&myfifo, 0) );
+		CHECK( 0, fd_cnx_recv_setaltfifo(server_side, myfifo) );
+		CHECK( 0, clock_gettime(CLOCK_REALTIME, &now) );
+		do {
+			CHECK( 0, fd_event_timedget(myfifo, &now, ETIMEDOUT, &ev_code, NULL, (void *)&rcv_buf) );
+			free(rcv_buf);
+		} while (ev_code != FDEVP_CNX_MSG_RECV);
+		
+		/* Now close the connection */
+		CHECK( 0, pthread_create(&thr, NULL, destroy_thr, client_side) );
+		fd_cnx_destroy(server_side);
+		CHECK( 0, pthread_join(thr, NULL) );
+		
+		fd_event_destroy(&myfifo, free);
+		
+		/* Free the credentials */
+		gnutls_certificate_free_keys(hf.creds);
+		gnutls_certificate_free_cas(hf.creds);
+		gnutls_certificate_free_credentials(hf.creds);
+	}
+#endif /* DISABLE_SCTP */
+	
+
+	/* Destroy the servers */
+	{
+		fd_cnx_destroy(listener);
+#ifndef DISABLE_SCTP
+		fd_cnx_destroy(listener_sctp);
+#endif /* DISABLE_SCTP */
+	}
+	
+	/* Check that connection attempt fails then */
+	{
+		struct connect_flags cf;
+		
+		memset(&cf, 0, sizeof(cf));
+		cf.proto = IPPROTO_TCP;
+		cf.expect_failure = 1;
+		
+		/* Start the client thread, that should fail */
+		CHECK( 0, pthread_create(&thr, NULL, connect_thr, &cf) );
+		CHECK( 0, pthread_join( thr, (void *)&client_side ) );
+		CHECK( 0, client_side ? 1 : 0 );
+	}
+		
+#ifndef DISABLE_SCTP
+	{
+		struct connect_flags cf;
+		
+		memset(&cf, 0, sizeof(cf));
+		cf.proto = IPPROTO_SCTP;
+		cf.expect_failure = 1;
+		
+		/* Start the client thread, that should fail */
+		CHECK( 0, pthread_create(&thr, NULL, connect_thr, &cf) );
+		CHECK( 0, pthread_join( thr, (void *)&client_side ) );
+		CHECK( 0, client_side ? 1 : 0 );
+	}
+#endif /* DISABLE_SCTP */
+	
+	
+	/* That's all for the tests yet */
+	PASSTEST();
+} 
+	
diff --git a/tests/testdict.c b/tests/testdict.c
new file mode 100644
index 0000000..d45d52e
--- /dev/null
+++ b/tests/testdict.c
@@ -0,0 +1,211 @@
+/*********************************************************************************************************
+* Software License Agreement (BSD License)                                                               *
+* Author: Sebastien Decugis <sdecugis@freediameter.net>							 *
+*													 *
+* Copyright (c) 2013, WIDE Project and NICT								 *
+* All rights reserved.											 *
+* 													 *
+* Redistribution and use of this software in source and binary forms, with or without modification, are  *
+* permitted provided that the following conditions are met:						 *
+* 													 *
+* * Redistributions of source code must retain the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer.										 *
+*    													 *
+* * Redistributions in binary form must reproduce the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer in the documentation and/or other						 *
+*   materials provided with the distribution.								 *
+* 													 *
+* * Neither the name of the WIDE Project or NICT nor the 						 *
+*   names of its contributors may be used to endorse or 						 *
+*   promote products derived from this software without 						 *
+*   specific prior written permission of WIDE Project and 						 *
+*   NICT.												 *
+* 													 *
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED *
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
+* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR *
+* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 	 *
+* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 	 *
+* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR *
+* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF   *
+* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.								 *
+*********************************************************************************************************/
+
+#include "tests.h"
+
+/* Test for the dict_iterate_rules function */
+int iter_test(void * data, struct dict_rule_data * rule)
+{
+	struct dict_avp_data avpdata;
+	(*(int *)data)++;
+	
+	CHECK( 0, fd_dict_getval ( rule->rule_avp, &avpdata ) );
+	TRACE_DEBUG(FULL, "rule #%d: avp '%s'", *(int *)data, avpdata.avp_name);
+	return 0;
+}
+
+/* Main test routine */
+int main(int argc, char *argv[])
+{
+	/* First, initialize the daemon modules */
+	INIT_FD();
+	
+	/* Test creating and searching all types of objects */
+	{
+		struct dict_object * obj1 = NULL;
+		struct dict_object * obj2 = NULL;
+		struct dict_object * obj3 = NULL;
+
+		vendor_id_t vendor_id = 735671;
+		struct dict_vendor_data vendor1_data = { 735671, "Vendor test 1" };
+		struct dict_vendor_data vendor2_data = { 735672, "Vendor test 2" };
+		struct dict_application_data app1_data = { 735674, "Application test 1" };
+		
+		
+		/* Create two vendors */
+		CHECK( 0, fd_dict_new ( fd_g_config->cnf_dict, DICT_VENDOR, &vendor1_data , NULL, &obj1 ) );
+		CHECK( 0, fd_dict_new ( fd_g_config->cnf_dict, DICT_VENDOR, &vendor2_data , NULL, NULL ) );
+		
+		/* Check we always retrieve the correct vendor object */
+		CHECK( 0, fd_dict_search ( fd_g_config->cnf_dict, DICT_VENDOR, VENDOR_BY_ID, &vendor_id, &obj2, ENOENT ) );
+		CHECK( obj1, obj2);
+		CHECK( 0, fd_dict_search ( fd_g_config->cnf_dict, DICT_VENDOR, VENDOR_BY_NAME, "Vendor test 1", &obj2, ENOENT ) );
+		CHECK( obj1, obj2);
+		
+		/* Check the error conditions */
+		CHECK( 0, fd_dict_search ( fd_g_config->cnf_dict, DICT_VENDOR, VENDOR_BY_ID, &vendor_id, NULL, ENOENT ) );
+		
+		vendor_id = 735673; /* Not defined */
+		CHECK( ENOENT, fd_dict_search ( fd_g_config->cnf_dict, DICT_VENDOR, VENDOR_BY_ID, &vendor_id, NULL, ENOENT ) );
+		CHECK( ENOENT, fd_dict_search ( fd_g_config->cnf_dict, DICT_VENDOR, VENDOR_BY_NAME, "Vendor test 3", NULL, ENOENT ) );
+		CHECK( ENOENT, fd_dict_search ( fd_g_config->cnf_dict, DICT_VENDOR, VENDOR_BY_ID, &vendor_id, &obj2, ENOENT ) );
+		CHECK( ENOENT, fd_dict_search ( fd_g_config->cnf_dict, DICT_VENDOR, VENDOR_BY_NAME, "Vendor test 3", &obj2, ENOENT ) );
+		CHECK( ENOTSUP, fd_dict_search ( fd_g_config->cnf_dict, DICT_VENDOR, VENDOR_BY_NAME, "Vendor test 3", &obj2, ENOTSUP ) );
+		
+		/* Check the get_* functions */
+		CHECK( 0, fd_dict_getval ( obj1, &vendor1_data ) );
+		CHECK( 735671, vendor1_data.vendor_id );
+		CHECK( 0, strcmp(vendor1_data.vendor_name, "Vendor test 1") );
+		/* error conditions */
+		CHECK( EINVAL, fd_dict_getval ( (struct dict_object *)"not an object", &vendor1_data ) );
+		
+		/* Create the application with vendor1 as parent */
+		CHECK( EINVAL, fd_dict_new ( fd_g_config->cnf_dict, DICT_APPLICATION, &app1_data , (struct dict_object *)"bad object", &obj2 ) );
+		CHECK( 0, fd_dict_new ( fd_g_config->cnf_dict, DICT_APPLICATION, &app1_data , obj1, &obj2 ) );
+		
+		CHECK( 0, fd_dict_search ( fd_g_config->cnf_dict, DICT_VENDOR, VENDOR_OF_APPLICATION, obj2, &obj3, ENOENT ) );
+		CHECK( obj1, obj3);
+		
+		/* Creating and searching the other objects is already done in dictionary initialization */
+	}
+
+	/* Test creation of the "Example-AVP" grouped AVP from the RFC */
+	{
+		int nbr = 0;
+		struct dict_object * origin_host_avp = NULL;
+		struct dict_object * session_id_avp = NULL;
+		struct dict_object * example_avp_avp = NULL;
+		struct dict_rule_data rule_data = { NULL, RULE_REQUIRED, -1, -1 };
+		struct dict_avp_data example_avp_data = { 999999, 0, "Example-AVP", AVP_FLAG_VENDOR , 0, AVP_TYPE_GROUPED };
+
+		CHECK( 0, fd_dict_search ( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Origin-Host", &origin_host_avp, ENOENT ) );
+		CHECK( 0, fd_dict_search ( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Session-Id", &session_id_avp, ENOENT ) );
+		
+		CHECK( 0, fd_dict_new ( fd_g_config->cnf_dict, DICT_AVP, &example_avp_data , NULL, &example_avp_avp ) );
+		
+		rule_data.rule_avp = origin_host_avp;
+		rule_data.rule_min = 1;
+		rule_data.rule_max = 1;
+		CHECK( 0, fd_dict_new ( fd_g_config->cnf_dict, DICT_RULE, &rule_data, example_avp_avp, NULL ) );
+		
+		rule_data.rule_avp = session_id_avp;
+		rule_data.rule_min = 1;
+		rule_data.rule_max = -1;
+		CHECK( 0, fd_dict_new ( fd_g_config->cnf_dict, DICT_RULE, &rule_data, example_avp_avp, NULL ) );
+		
+		CHECK( 0, fd_dict_iterate_rules ( example_avp_avp, &nbr, iter_test) );
+		CHECK( 2, nbr );
+	}
+	
+	/* Test list function */
+	{
+		struct fd_list * li = NULL;
+		struct fd_list * sentinel = NULL;
+		enum dict_object_type	type;
+		struct dict_object * defvnd=NULL;
+		vendor_id_t vid = 0;
+		int first = 1;
+		
+		CHECK( 0, fd_dict_getlistof(VENDOR_BY_ID, fd_g_config->cnf_dict, &sentinel));
+		
+		for (li = sentinel; (li != sentinel) || (first != 0); li = li->next) {
+			first = 0;
+			CHECK(0, fd_dict_gettype(li->o, &type));
+			CHECK(DICT_VENDOR, type);
+#if 0
+			struct dict_vendor_data data;
+			CHECK( 0, fd_dict_getval(li->o, &data) );
+			printf("%d : %s\n", data.vendor_id, data.vendor_name);
+#endif
+		}
+		
+		CHECK( 0, fd_dict_search(fd_g_config->cnf_dict, DICT_VENDOR, VENDOR_BY_ID, &vid, &defvnd, ENOENT) );
+		
+		CHECK( 0, fd_dict_getlistof(AVP_BY_NAME, defvnd, &sentinel));
+		for (li = sentinel->next; li != sentinel; li = li->next) {
+			CHECK(0, fd_dict_gettype(li->o, &type));
+			CHECK(DICT_AVP, type);
+#if 0
+			struct dict_avp_data data;
+			CHECK( 0, fd_dict_getval(li->o, &data) );
+			printf("%d : %s\n", data.avp_code, data.avp_name);
+#endif
+		}
+	}
+
+	/* Test delete function */
+	{
+		struct fd_list * li = NULL;
+		struct fd_list * sentinel = NULL;
+		struct dict_object * obj=NULL;
+		vendor_id_t vid = 0;
+		int count = 0, cntbkp;
+		
+		CHECK( 0, fd_dict_search(fd_g_config->cnf_dict, DICT_VENDOR, VENDOR_BY_ID, &vid, &obj, ENOENT) );
+		
+		CHECK( EINVAL, fd_dict_delete(obj) );
+			
+		
+		CHECK( 0, fd_dict_getlistof(AVP_BY_NAME, obj, &sentinel));
+		obj = NULL;
+		
+		for (li = sentinel->next; li != sentinel; li = li->next) {
+			struct dict_avp_data data;
+			CHECK( 0, fd_dict_getval(li->o, &data) );
+			count++;
+			if (data.avp_basetype != AVP_TYPE_GROUPED)
+				obj = li->o;
+		}
+		
+		CHECK(1, obj ? 1 : 0 );
+#if 1
+		fd_log_debug("%s", fd_dict_dump_object(FD_DUMP_TEST_PARAMS, obj));
+#endif
+		CHECK( 0, fd_dict_delete(obj) );
+		cntbkp = count;
+		count = 0;
+		for (li = sentinel->next; li != sentinel; li = li->next) {
+			count++;
+		}
+		CHECK( 1, cntbkp - count );
+		
+	}
+	
+	LOG_D( "Dictionary at the end of %s: %s", __FILE__, fd_dict_dump(FD_DUMP_TEST_PARAMS, fd_g_config->cnf_dict) ?: "error");
+	
+	/* That's all for the tests yet */
+	PASSTEST();
+} 
+	
diff --git a/tests/testdisp.c b/tests/testdisp.c
new file mode 100644
index 0000000..7625a69
--- /dev/null
+++ b/tests/testdisp.c
@@ -0,0 +1,729 @@
+/*********************************************************************************************************
+* Software License Agreement (BSD License)                                                               *
+* Author: Sebastien Decugis <sdecugis@freediameter.net>							 *
+*													 *
+* Copyright (c) 2013, WIDE Project and NICT								 *
+* All rights reserved.											 *
+* 													 *
+* Redistribution and use of this software in source and binary forms, with or without modification, are  *
+* permitted provided that the following conditions are met:						 *
+* 													 *
+* * Redistributions of source code must retain the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer.										 *
+*    													 *
+* * Redistributions in binary form must reproduce the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer in the documentation and/or other						 *
+*   materials provided with the distribution.								 *
+* 													 *
+* * Neither the name of the WIDE Project or NICT nor the 						 *
+*   names of its contributors may be used to endorse or 						 *
+*   promote products derived from this software without 						 *
+*   specific prior written permission of WIDE Project and 						 *
+*   NICT.												 *
+* 													 *
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED *
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
+* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR *
+* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 	 *
+* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 	 *
+* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR *
+* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF   *
+* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.								 *
+*********************************************************************************************************/
+
+#include "tests.h"
+	
+#define Define_cb( __int, __extra )												\
+int cb_##__int( struct msg ** msg, struct avp * avp, struct session * session, void * opaque, enum disp_action * action )	\
+{																\
+	CHECK( 1, msg ? 1 : 0 );												\
+	CHECK( 1, action ? 1 : 0 );												\
+	CHECK( sess, session );													\
+	if (opaque) {														\
+		CHECK( 1, opaque == g_opaque ? 1 : 0 );										\
+	}															\
+	*action = DISP_ACT_CONT;												\
+	cbcalled[__int] += 1;													\
+	do {															\
+		__extra ;													\
+	} while (0);														\
+	return 0;														\
+}
+
+#define NB_CB	10
+char cbcalled[NB_CB];
+struct session * sess;
+void * g_opaque = (void *)"test";
+
+/* cb_0 */  Define_cb( 0, );
+/* cb_1 */  Define_cb( 1, );
+/* cb_2 */  Define_cb( 2, );
+/* cb_3 */  Define_cb( 3, );
+/* cb_4 */  Define_cb( 4, );
+/* cb_5 */  Define_cb( 5, );
+/* cb_6 */  Define_cb( 6, return 12345 );
+/* cb_7 */  Define_cb( 7, { CHECK( 1, avp ? 1 : 0 ); } );
+/* cb_8 */  Define_cb( 8, { CHECK( 0, fd_msg_free( *msg ) ); *msg = NULL; } );
+/* cb_9 */  Define_cb( 9, *action = DISP_ACT_SEND );
+/* max: cb_<NB_CB - 1> */
+
+/* Create a new message containing what we want */
+struct msg * new_msg(int appid, struct dict_object * cmd, struct dict_object * avp1, struct dict_object * avp2, int val)
+{
+	struct msg *new;
+	struct avp *avp;
+	union avp_value value;
+	struct msg_hdr * msg_hdr = NULL;
+	
+	CHECK( 0, fd_msg_new ( cmd, 0, &new ) );
+	CHECK( 0, fd_msg_hdr ( new, &msg_hdr ) );
+	msg_hdr->msg_appl = appid;
+	
+	if (avp1) {
+		CHECK( 0, fd_msg_avp_new ( avp1, 0, &avp ) );
+		value.u32 = 0;
+		CHECK( 0, fd_msg_avp_setvalue ( avp, &value ) );
+		CHECK( 0, fd_msg_avp_add ( new, MSG_BRW_LAST_CHILD, avp ) );
+	}
+	
+	if (avp2) {
+		CHECK( 0, fd_msg_avp_new ( avp2, 0, &avp ) );
+		value.u32 = val;
+		CHECK( 0, fd_msg_avp_setvalue ( avp, &value ) );
+		CHECK( 0, fd_msg_avp_add ( new, MSG_BRW_LAST_CHILD, avp ) );
+	}
+	
+	return new;	
+}
+
+/* Main test routine */
+int main(int argc, char *argv[])
+{
+	struct dict_object * app1, * app2;
+	struct dict_object * cmd1, * cmd2;
+	struct dict_object * avp1, * avp2; /* avp2 is enumerated; they are both unsigned32 types */
+	struct dict_object * enu1, * enu2;
+	struct msg * msg = NULL, *error;
+	enum disp_action action;
+	struct disp_hdl * hdl[NB_CB];
+	struct disp_when when;
+	char * ec, *em;
+	
+	/* First, initialize the daemon modules */
+	INIT_FD();
+	
+	/* Create a dummy session, we don't use it anyway */
+	#define DUMMY_SID "test.disp"
+	CHECK( 0, fd_sess_new( &sess, DUMMY_SID, CONSTSTRLEN(DUMMY_SID), NULL, 0 ) );
+	
+	memset(&when, 0xff, sizeof(when)); /* check that we don't use un-initialized parts */
+	
+	/* Initialize dictionary objects */
+	{
+		struct dict_object * enutype;
+		struct dict_application_data app1_data = { 1, "Application test 1" };
+		struct dict_application_data app2_data = { 2, "Application test 2" };
+		struct dict_cmd_data cmd1_data = { 1, "Command test 1 (req)", CMD_FLAG_REQUEST,	CMD_FLAG_REQUEST };
+		struct dict_cmd_data cmd2_data = { 1, "Command test 2 (ans)", CMD_FLAG_REQUEST,	0 };
+		struct dict_type_data type_data = { AVP_TYPE_UNSIGNED32, "Type test", NULL, NULL };
+		struct dict_avp_data avp1_data = { 10001, 0, "AVP test 1", 0, 0, AVP_TYPE_UNSIGNED32 };
+		struct dict_avp_data avp2_data = { 10002, 0, "AVP test 2", 0, 0, AVP_TYPE_UNSIGNED32 };
+		struct dict_enumval_data enu1_data = { "ENU test 1", { .u32 = 1 }};
+		struct dict_enumval_data enu2_data = { "ENU test 2", { .u32 = 2 }};
+		
+		CHECK( 0, fd_dict_new ( fd_g_config->cnf_dict, DICT_APPLICATION, &app1_data, NULL, &app1 ) );
+		CHECK( 0, fd_dict_new ( fd_g_config->cnf_dict, DICT_APPLICATION, &app2_data, NULL, &app2 ) );
+		CHECK( 0, fd_dict_new ( fd_g_config->cnf_dict, DICT_COMMAND, &cmd1_data, NULL, &cmd1 ) );
+		CHECK( 0, fd_dict_new ( fd_g_config->cnf_dict, DICT_COMMAND, &cmd2_data, NULL, &cmd2 ) );
+		CHECK( 0, fd_dict_new ( fd_g_config->cnf_dict, DICT_TYPE, &type_data, NULL, &enutype ) );
+		CHECK( 0, fd_dict_new ( fd_g_config->cnf_dict, DICT_AVP, &avp1_data, NULL,    &avp1 ) );
+		CHECK( 0, fd_dict_new ( fd_g_config->cnf_dict, DICT_AVP, &avp2_data, enutype, &avp2 ) );
+		CHECK( 0, fd_dict_new ( fd_g_config->cnf_dict, DICT_ENUMVAL, &enu1_data, enutype, &enu1 ) );
+		CHECK( 0, fd_dict_new ( fd_g_config->cnf_dict, DICT_ENUMVAL, &enu2_data, enutype, &enu2 ) );
+	}
+	
+	/* Register first handler, very simple test */
+	{
+		CHECK( 0, fd_disp_register( cb_0, DISP_HOW_ANY, NULL, NULL, &hdl[0] ) );
+		CHECK( 1, hdl[0] ? 1 : 0 );
+		CHECK( 0, fd_disp_unregister( &hdl[0], NULL ) );
+		CHECK( NULL, hdl[0] );
+		CHECK( 0, fd_disp_register( cb_0, DISP_HOW_ANY, NULL, NULL, &hdl[0] ) );
+	
+		/* Check this handler is called for a message */
+		msg = new_msg( 0, cmd1, avp1, NULL, 0 );
+		memset(cbcalled, 0, sizeof(cbcalled));
+		CHECK( 0, fd_msg_dispatch ( &msg, sess, &action, &ec, &em, &error ) );
+		CHECK( 1, cbcalled[0] );
+		CHECK( DISP_ACT_CONT, action );
+		
+		/* Delete the message */
+		CHECK( 0, fd_msg_free( msg ) );
+		CHECK( 0, fd_disp_unregister( &hdl[0], NULL ) );
+	}
+	
+	/* Handlers for applications */
+	{
+		CHECK( 0, fd_disp_register( cb_0, DISP_HOW_ANY, &when, NULL, &hdl[0] ) );
+		when.app = app1;
+		CHECK( 0, fd_disp_register( cb_1, DISP_HOW_APPID, &when, NULL, &hdl[1] ) );
+		when.app = app2;
+		CHECK( 0, fd_disp_register( cb_2, DISP_HOW_APPID, &when, NULL, &hdl[2] ) );
+		when.avp = avp2;
+		CHECK( 0, fd_disp_register( cb_3, DISP_HOW_APPID, &when, NULL, &hdl[3] ) );
+		when.avp = avp1;
+		CHECK( 0, fd_disp_register( cb_4, DISP_HOW_APPID, &when, NULL, &hdl[4] ) );
+	
+		/* Check the callbacks are called as appropriate */
+		memset(cbcalled, 0, sizeof(cbcalled));
+		msg = new_msg( 0, cmd1, avp1, NULL, 0 );
+		CHECK( 0, fd_msg_dispatch ( &msg, sess, &action, &ec, &em, &error ) );
+		CHECK( 1, cbcalled[0] );
+		CHECK( 0, cbcalled[1] );
+		CHECK( 0, cbcalled[2] );
+		CHECK( 0, cbcalled[3] );
+		CHECK( 0, cbcalled[4] );
+		CHECK( DISP_ACT_CONT, action );
+		CHECK( 0, fd_msg_free( msg ) );
+		
+		memset(cbcalled, 0, sizeof(cbcalled));
+		msg = new_msg( 1, cmd1, avp1, NULL, 0 );
+		CHECK( 0, fd_msg_dispatch ( &msg, sess, &action, &ec, &em, &error ) );
+		CHECK( 1, cbcalled[0] );
+		CHECK( 1, cbcalled[1] );
+		CHECK( 0, cbcalled[2] );
+		CHECK( 0, cbcalled[3] );
+		CHECK( 0, cbcalled[4] );
+		CHECK( DISP_ACT_CONT, action );
+		CHECK( 0, fd_msg_free( msg ) );
+		
+		memset(cbcalled, 0, sizeof(cbcalled));
+		msg = new_msg( 2, cmd1, avp1, NULL, 0 );
+		CHECK( 0, fd_msg_dispatch ( &msg, sess, &action, &ec, &em, &error ) );
+		CHECK( 1, cbcalled[0] );
+		CHECK( 0, cbcalled[1] );
+		CHECK( 1, cbcalled[2] );
+		CHECK( 1, cbcalled[3] );
+		CHECK( 1, cbcalled[4] );
+		CHECK( DISP_ACT_CONT, action );
+		CHECK( 0, fd_msg_free( msg ) );
+		
+		CHECK( 0, fd_disp_unregister( &hdl[0], NULL ) );
+		CHECK( 0, fd_disp_unregister( &hdl[1], NULL ) );
+		CHECK( 0, fd_disp_unregister( &hdl[2], NULL ) );
+		CHECK( 0, fd_disp_unregister( &hdl[3], NULL ) );
+		CHECK( 0, fd_disp_unregister( &hdl[4], NULL ) );
+	}
+	
+	/* Handlers for commands */
+	{
+		when.app = NULL;
+		when.command = NULL;
+		CHECK( 0, fd_disp_register( cb_0, DISP_HOW_ANY, &when, NULL, &hdl[0] ) );
+		CHECK( EINVAL, fd_disp_register( cb_1, DISP_HOW_CC, &when, NULL, &hdl[1] ) );
+		when.command = cmd1;
+		CHECK( 0, fd_disp_register( cb_1, DISP_HOW_CC, &when, NULL, &hdl[1] ) ); /* cmd1 */
+		when.app = app2;
+		CHECK( 0, fd_disp_register( cb_2, DISP_HOW_CC, &when, NULL, &hdl[2] ) ); /* app2 + cmd1 */
+		when.command = cmd2;
+		when.app = NULL;
+		when.avp = avp1;
+		CHECK( 0, fd_disp_register( cb_3, DISP_HOW_CC, &when, NULL, &hdl[3] ) ); /* cmd2 (avp1 ignored) */
+		
+		/* Check the callbacks are called as appropriate */
+		memset(cbcalled, 0, sizeof(cbcalled));
+		msg = new_msg( 0, cmd1, avp1, NULL, 0 );
+		CHECK( 0, fd_msg_dispatch ( &msg, sess, &action, &ec, &em, &error ) );
+		CHECK( 1, cbcalled[0] );
+		CHECK( 1, cbcalled[1] );
+		CHECK( 0, cbcalled[2] );
+		CHECK( 0, cbcalled[3] );
+		CHECK( DISP_ACT_CONT, action );
+		CHECK( 0, fd_msg_free( msg ) );
+		
+		memset(cbcalled, 0, sizeof(cbcalled));
+		msg = new_msg( 2, cmd1, avp1, NULL, 0 );
+		CHECK( 0, fd_msg_dispatch ( &msg, sess, &action, &ec, &em, &error ) );
+		CHECK( 1, cbcalled[0] );
+		CHECK( 1, cbcalled[1] );
+		CHECK( 1, cbcalled[2] );
+		CHECK( 0, cbcalled[3] );
+		CHECK( DISP_ACT_CONT, action );
+		CHECK( 0, fd_msg_free( msg ) );
+		
+		memset(cbcalled, 0, sizeof(cbcalled));
+		msg = new_msg( 2, cmd2, avp1, NULL, 0 );
+		CHECK( 0, fd_msg_dispatch ( &msg, sess, &action, &ec, &em, &error ) );
+		CHECK( 1, cbcalled[0] );
+		CHECK( 0, cbcalled[1] );
+		CHECK( 0, cbcalled[2] );
+		CHECK( 1, cbcalled[3] );
+		CHECK( DISP_ACT_CONT, action );
+		CHECK( 0, fd_msg_free( msg ) );
+		
+		memset(cbcalled, 0, sizeof(cbcalled));
+		msg = new_msg( 1, cmd2, NULL, avp2, 0 );
+		CHECK( 0, fd_msg_dispatch ( &msg, sess, &action, &ec, &em, &error ) );
+		CHECK( 1, cbcalled[0] );
+		CHECK( 0, cbcalled[1] );
+		CHECK( 0, cbcalled[2] );
+		CHECK( 1, cbcalled[3] );
+		CHECK( DISP_ACT_CONT, action );
+		CHECK( 0, fd_msg_free( msg ) );
+		
+		CHECK( 0, fd_disp_unregister( &hdl[0], NULL ) );
+		CHECK( 0, fd_disp_unregister( &hdl[1], NULL ) );
+		CHECK( 0, fd_disp_unregister( &hdl[2], NULL ) );
+		CHECK( 0, fd_disp_unregister( &hdl[3], NULL ) );
+	}
+	
+	/* Handlers for AVPs */
+	{
+		when.app = NULL;
+		when.command = NULL;
+		when.avp = NULL;
+	
+		CHECK( 0, fd_disp_register( cb_0, DISP_HOW_ANY, &when, NULL, &hdl[0] ) ); /* all */
+		CHECK( EINVAL, fd_disp_register( cb_1, DISP_HOW_AVP, &when, NULL, &hdl[1] ) );
+		
+		when.avp = avp1;
+		CHECK( 0, fd_disp_register( cb_1, DISP_HOW_AVP, &when, NULL, &hdl[1] ) ); /* avp1 */
+		
+		when.command = cmd1;
+		CHECK( 0, fd_disp_register( cb_2, DISP_HOW_AVP, &when, NULL, &hdl[2] ) ); /* avp1 + cmd1 */
+		
+		when.command = NULL;
+		when.app = app1;
+		CHECK( 0, fd_disp_register( cb_3, DISP_HOW_AVP, &when, NULL, &hdl[3] ) ); /* avp1 + app1 */
+		
+		when.command = cmd1;
+		CHECK( 0, fd_disp_register( cb_4, DISP_HOW_AVP, &when, NULL, &hdl[4] ) ); /* avp1 + cmd1 + app1 */
+		
+		when.app = NULL;
+		when.command = NULL;
+		when.avp = avp2;
+		when.value = enu1;
+		CHECK( 0, fd_disp_register( cb_5, DISP_HOW_AVP, &when, NULL, &hdl[5] ) ); /* avp2 */
+		
+		when.value = enu2;
+		CHECK( 0, fd_disp_register( cb_7, DISP_HOW_AVP, &when, NULL, &hdl[6] ) ); /* avp2 */
+		
+		
+		
+		/* Check the callbacks are called as appropriate */
+		memset(cbcalled, 0, sizeof(cbcalled));
+		msg = new_msg( 0, cmd1, NULL, NULL, 0 );
+		CHECK( 0, fd_msg_dispatch ( &msg, sess, &action, &ec, &em, &error ) );
+		CHECK( 1, cbcalled[0] );
+		CHECK( 0, cbcalled[1] );
+		CHECK( 0, cbcalled[2] );
+		CHECK( 0, cbcalled[3] );
+		CHECK( 0, cbcalled[4] );
+		CHECK( 0, cbcalled[5] );
+		CHECK( DISP_ACT_CONT, action );
+		CHECK( 0, fd_msg_free( msg ) );
+		
+		memset(cbcalled, 0, sizeof(cbcalled));
+		msg = new_msg( 0, cmd1, avp1, NULL, 0 );
+		CHECK( 0, fd_msg_dispatch ( &msg, sess, &action, &ec, &em, &error ) );
+		CHECK( 1, cbcalled[0] );
+		CHECK( 1, cbcalled[1] );
+		CHECK( 1, cbcalled[2] );
+		CHECK( 0, cbcalled[3] );
+		CHECK( 0, cbcalled[4] );
+		CHECK( 0, cbcalled[5] );
+		CHECK( DISP_ACT_CONT, action );
+		CHECK( 0, fd_msg_free( msg ) );
+		
+		memset(cbcalled, 0, sizeof(cbcalled));
+		msg = new_msg( 1, cmd2, avp1, NULL, 0 );
+		CHECK( 0, fd_msg_dispatch ( &msg, sess, &action, &ec, &em, &error ) );
+		CHECK( 1, cbcalled[0] );
+		CHECK( 1, cbcalled[1] );
+		CHECK( 0, cbcalled[2] );
+		CHECK( 1, cbcalled[3] );
+		CHECK( 0, cbcalled[4] );
+		CHECK( 0, cbcalled[5] );
+		CHECK( DISP_ACT_CONT, action );
+		CHECK( 0, fd_msg_free( msg ) );
+		
+		memset(cbcalled, 0, sizeof(cbcalled));
+		msg = new_msg( 1, cmd1, avp1, NULL, 0 );
+		CHECK( 0, fd_msg_dispatch ( &msg, sess, &action, &ec, &em, &error ) );
+		CHECK( 1, cbcalled[0] );
+		CHECK( 1, cbcalled[1] );
+		CHECK( 1, cbcalled[2] );
+		CHECK( 1, cbcalled[3] );
+		CHECK( 1, cbcalled[4] );
+		CHECK( 0, cbcalled[5] );
+		CHECK( DISP_ACT_CONT, action );
+		CHECK( 0, fd_msg_free( msg ) );
+		
+		memset(cbcalled, 0, sizeof(cbcalled));
+		msg = new_msg( 1, cmd1, avp1, avp2, 0 );
+		CHECK( 0, fd_msg_dispatch ( &msg, sess, &action, &ec, &em, &error ) );
+		CHECK( 1, cbcalled[0] );
+		CHECK( 1, cbcalled[1] );
+		CHECK( 1, cbcalled[2] );
+		CHECK( 1, cbcalled[3] );
+		CHECK( 1, cbcalled[4] );
+		CHECK( 1, cbcalled[5] );
+		CHECK( 1, cbcalled[7] );
+		CHECK( DISP_ACT_CONT, action );
+		CHECK( 0, fd_msg_free( msg ) );
+		
+		memset(cbcalled, 0, sizeof(cbcalled));
+		msg = new_msg( 1, cmd1, NULL, avp2, 1 );
+		CHECK( 0, fd_msg_dispatch ( &msg, sess, &action, &ec, &em, &error ) );
+		CHECK( 1, cbcalled[0] );
+		CHECK( 0, cbcalled[1] );
+		CHECK( 0, cbcalled[2] );
+		CHECK( 0, cbcalled[3] );
+		CHECK( 0, cbcalled[4] );
+		CHECK( 1, cbcalled[5] );
+		CHECK( 1, cbcalled[7] );
+		CHECK( DISP_ACT_CONT, action );
+		CHECK( 0, fd_msg_free( msg ) );
+		
+		memset(cbcalled, 0, sizeof(cbcalled));
+		msg = new_msg( 1, cmd1, NULL, avp2, 2 );
+		CHECK( 0, fd_msg_dispatch ( &msg, sess, &action, &ec, &em, &error ) );
+		CHECK( 1, cbcalled[0] );
+		CHECK( 0, cbcalled[1] );
+		CHECK( 0, cbcalled[2] );
+		CHECK( 0, cbcalled[3] );
+		CHECK( 0, cbcalled[4] );
+		CHECK( 1, cbcalled[5] );
+		CHECK( 1, cbcalled[7] );
+		CHECK( DISP_ACT_CONT, action );
+		CHECK( 0, fd_msg_free( msg ) );
+		
+		CHECK( 0, fd_disp_unregister( &hdl[0], NULL ) );
+		CHECK( 0, fd_disp_unregister( &hdl[1], NULL ) );
+		CHECK( 0, fd_disp_unregister( &hdl[2], NULL ) );
+		CHECK( 0, fd_disp_unregister( &hdl[3], NULL ) );
+		CHECK( 0, fd_disp_unregister( &hdl[4], NULL ) );
+		CHECK( 0, fd_disp_unregister( &hdl[5], NULL ) );
+		CHECK( 0, fd_disp_unregister( &hdl[6], NULL ) );
+	}
+		
+	/* Handlers for enum values */
+	{
+		when.app = NULL;
+		when.command = NULL;
+		when.avp = NULL;
+		when.value = NULL;
+		
+		CHECK( 0, fd_disp_register( cb_0, DISP_HOW_ANY, &when, NULL, &hdl[0] ) ); /* all */
+		CHECK( EINVAL, fd_disp_register( cb_1, DISP_HOW_AVP_ENUMVAL, &when, NULL, &hdl[1] ) );
+		when.value = enu1;
+		CHECK( EINVAL, fd_disp_register( cb_1, DISP_HOW_AVP_ENUMVAL, &when, NULL, &hdl[1] ) );
+		when.avp = avp1;
+		CHECK( EINVAL, fd_disp_register( cb_1, DISP_HOW_AVP_ENUMVAL, &when, NULL, &hdl[1] ) );
+		when.avp = avp2;
+		CHECK( 0, fd_disp_register( cb_1, DISP_HOW_AVP_ENUMVAL, &when, NULL, &hdl[1] ) ); /* avp2, enu1 */
+		
+		when.command = cmd1;
+		CHECK( 0, fd_disp_register( cb_2, DISP_HOW_AVP_ENUMVAL, &when, NULL, &hdl[2] ) ); /* avp2, enu1 + cmd1 */
+		
+		when.command = NULL;
+		when.app = app1;
+		when.value = enu2;
+		CHECK( 0, fd_disp_register( cb_3, DISP_HOW_AVP_ENUMVAL, &when, NULL, &hdl[3] ) ); /* avp2, enu2 + app1 */
+		
+		/* Check the callbacks are called as appropriate */
+		memset(cbcalled, 0, sizeof(cbcalled));
+		msg = new_msg( 0, cmd1, avp1, NULL, 0 );
+		CHECK( 0, fd_msg_dispatch ( &msg, sess, &action, &ec, &em, &error ) );
+		CHECK( 1, cbcalled[0] );
+		CHECK( 0, cbcalled[1] );
+		CHECK( 0, cbcalled[2] );
+		CHECK( 0, cbcalled[3] );
+		CHECK( DISP_ACT_CONT, action );
+		CHECK( 0, fd_msg_free( msg ) );
+		
+		memset(cbcalled, 0, sizeof(cbcalled));
+		msg = new_msg( 1, cmd2, avp1, avp2, 0 );
+		CHECK( 0, fd_msg_dispatch ( &msg, sess, &action, &ec, &em, &error ) );
+		CHECK( 1, cbcalled[0] );
+		CHECK( 0, cbcalled[1] );
+		CHECK( 0, cbcalled[2] );
+		CHECK( 0, cbcalled[3] );
+		CHECK( DISP_ACT_CONT, action );
+		CHECK( 0, fd_msg_free( msg ) );
+		
+		memset(cbcalled, 0, sizeof(cbcalled));
+		msg = new_msg( 1, cmd2, avp1, avp2, 1 );
+		CHECK( 0, fd_msg_dispatch ( &msg, sess, &action, &ec, &em, &error ) );
+		CHECK( 1, cbcalled[0] );
+		CHECK( 1, cbcalled[1] );
+		CHECK( 0, cbcalled[2] );
+		CHECK( 0, cbcalled[3] );
+		CHECK( DISP_ACT_CONT, action );
+		CHECK( 0, fd_msg_free( msg ) );
+		
+		memset(cbcalled, 0, sizeof(cbcalled));
+		msg = new_msg( 1, cmd2, avp1, avp2, 2 );
+		CHECK( 0, fd_msg_dispatch ( &msg, sess, &action, &ec, &em, &error ) );
+		CHECK( 1, cbcalled[0] );
+		CHECK( 0, cbcalled[1] );
+		CHECK( 0, cbcalled[2] );
+		CHECK( 1, cbcalled[3] );
+		CHECK( DISP_ACT_CONT, action );
+		CHECK( 0, fd_msg_free( msg ) );
+		
+		memset(cbcalled, 0, sizeof(cbcalled));
+		msg = new_msg( 1, cmd1, avp1, avp2, 1 );
+		CHECK( 0, fd_msg_dispatch ( &msg, sess, &action, &ec, &em, &error ) );
+		CHECK( 1, cbcalled[0] );
+		CHECK( 1, cbcalled[1] );
+		CHECK( 1, cbcalled[2] );
+		CHECK( 0, cbcalled[3] );
+		CHECK( DISP_ACT_CONT, action );
+		CHECK( 0, fd_msg_free( msg ) );
+		
+		memset(cbcalled, 0, sizeof(cbcalled));
+		msg = new_msg( 1, cmd2, avp1, avp2, 1 );
+		{
+			struct avp *avp;
+			union avp_value value;
+			CHECK( 0, fd_msg_avp_new ( avp2, 0, &avp ) );
+			value.u32 = 2;
+			CHECK( 0, fd_msg_avp_setvalue ( avp, &value ) );
+			CHECK( 0, fd_msg_avp_add ( msg, MSG_BRW_LAST_CHILD, avp ) );
+		}
+		CHECK( 0, fd_msg_dispatch ( &msg, sess, &action, &ec, &em, &error ) );
+		CHECK( 1, cbcalled[0] );
+		CHECK( 1, cbcalled[1] );
+		CHECK( 0, cbcalled[2] );
+		CHECK( 1, cbcalled[3] );
+		CHECK( DISP_ACT_CONT, action );
+		CHECK( 0, fd_msg_free( msg ) );
+		
+		CHECK( 0, fd_disp_unregister( &hdl[0], NULL ) );
+		CHECK( 0, fd_disp_unregister( &hdl[1], NULL ) );
+		CHECK( 0, fd_disp_unregister( &hdl[2], NULL ) );
+		CHECK( 0, fd_disp_unregister( &hdl[3], NULL ) );
+	}
+	
+	/* Test behavior of handlers */
+	{
+		CHECK( 0, fd_disp_register( cb_0, DISP_HOW_ANY, &when, NULL, &hdl[0] ) );
+		CHECK( 0, fd_disp_register( cb_1, DISP_HOW_ANY, &when, NULL, &hdl[1] ) );
+		CHECK( 0, fd_disp_register( cb_6, DISP_HOW_ANY, &when, NULL, &hdl[2] ) );
+		CHECK( 0, fd_disp_register( cb_2, DISP_HOW_ANY, &when, NULL, &hdl[3] ) );
+		CHECK( 0, fd_disp_register( cb_3, DISP_HOW_ANY, &when, NULL, &hdl[4] ) );
+		
+		memset(cbcalled, 0, sizeof(cbcalled));
+		msg = new_msg( 1, cmd1, avp1, avp2, 1 );
+		CHECK( 0, fd_msg_dispatch ( &msg, sess, &action, &ec, &em, &error ) );
+		CHECK( 1, cbcalled[0] );
+		CHECK( 1, cbcalled[1] );
+		CHECK( 1, cbcalled[6] );
+		CHECK( 0, cbcalled[2] );
+		CHECK( 0, cbcalled[3] );
+		CHECK( 0, msg ? 1 : 0);
+		CHECK( 1, em ? 1 : 0);
+		CHECK( 0, fd_msg_free( error ) );
+		
+		CHECK( 0, fd_disp_unregister( &hdl[0], NULL ) );
+		CHECK( 0, fd_disp_unregister( &hdl[1], NULL ) );
+		CHECK( 0, fd_disp_unregister( &hdl[2], NULL ) );
+		CHECK( 0, fd_disp_unregister( &hdl[3], NULL ) );
+		CHECK( 0, fd_disp_unregister( &hdl[4], NULL ) );
+		
+		CHECK( 0, fd_disp_register( cb_0, DISP_HOW_ANY, &when, NULL, &hdl[0] ) );
+		CHECK( 0, fd_disp_register( cb_1, DISP_HOW_ANY, &when, NULL, &hdl[1] ) );
+		CHECK( 0, fd_disp_register( cb_8, DISP_HOW_ANY, &when, NULL, &hdl[2] ) );
+		CHECK( 0, fd_disp_register( cb_2, DISP_HOW_ANY, &when, NULL, &hdl[3] ) );
+		CHECK( 0, fd_disp_register( cb_3, DISP_HOW_ANY, &when, NULL, &hdl[4] ) );
+		
+		memset(cbcalled, 0, sizeof(cbcalled));
+		msg = new_msg( 1, cmd1, avp1, avp2, 1 );
+		CHECK( 0, fd_msg_dispatch ( &msg, sess, &action, &ec, &em, &error ) );
+		CHECK( 1, cbcalled[0] );
+		CHECK( 1, cbcalled[1] );
+		CHECK( 1, cbcalled[8] );
+		CHECK( 0, cbcalled[2] );
+		CHECK( 0, cbcalled[3] );
+		CHECK( NULL, msg );
+		CHECK( NULL, em );
+		
+		CHECK( 0, fd_disp_unregister( &hdl[0], NULL ) );
+		CHECK( 0, fd_disp_unregister( &hdl[1], NULL ) );
+		CHECK( 0, fd_disp_unregister( &hdl[2], NULL ) );
+		CHECK( 0, fd_disp_unregister( &hdl[3], NULL ) );
+		CHECK( 0, fd_disp_unregister( &hdl[4], NULL ) );
+		
+		CHECK( 0, fd_disp_register( cb_0, DISP_HOW_ANY, &when, NULL, &hdl[0] ) );
+		CHECK( 0, fd_disp_register( cb_1, DISP_HOW_ANY, &when, NULL, &hdl[1] ) );
+		CHECK( 0, fd_disp_register( cb_9, DISP_HOW_ANY, &when, NULL, &hdl[2] ) );
+		CHECK( 0, fd_disp_register( cb_2, DISP_HOW_ANY, &when, NULL, &hdl[3] ) );
+		CHECK( 0, fd_disp_register( cb_3, DISP_HOW_ANY, &when, NULL, &hdl[4] ) );
+		
+		memset(cbcalled, 0, sizeof(cbcalled));
+		msg = new_msg( 1, cmd1, avp1, avp2, 1 );
+		CHECK( 0, fd_msg_dispatch ( &msg, sess, &action, &ec, &em, &error ) );
+		CHECK( 1, cbcalled[0] );
+		CHECK( 1, cbcalled[1] );
+		CHECK( 1, cbcalled[9] );
+		CHECK( 0, cbcalled[2] );
+		CHECK( 0, cbcalled[3] );
+		CHECK( DISP_ACT_SEND, action );
+		CHECK( 0, fd_msg_free( msg ) );
+		
+		CHECK( 0, fd_disp_unregister( &hdl[0], NULL ) );
+		CHECK( 0, fd_disp_unregister( &hdl[1], NULL ) );
+		CHECK( 0, fd_disp_unregister( &hdl[2], NULL ) );
+		CHECK( 0, fd_disp_unregister( &hdl[3], NULL ) );
+		CHECK( 0, fd_disp_unregister( &hdl[4], NULL ) );
+	}
+		
+	/* Test order of handlers */
+	{
+		when.app = app2;
+		when.command = cmd2;
+		when.avp = avp2;
+		when.value = enu2;
+		
+		CHECK( 0, fd_disp_register( cb_0, DISP_HOW_ANY, &when, NULL, &hdl[0] ) );
+		CHECK( 0, fd_disp_register( cb_1, DISP_HOW_AVP_ENUMVAL, &when, NULL, &hdl[1] ) );
+		CHECK( 0, fd_disp_register( cb_2, DISP_HOW_AVP, &when, NULL, &hdl[2] ) );
+		CHECK( 0, fd_disp_register( cb_3, DISP_HOW_CC, &when, NULL, &hdl[3] ) );
+		CHECK( 0, fd_disp_register( cb_4, DISP_HOW_APPID, &when, NULL, &hdl[4] ) );
+		
+		memset(cbcalled, 0, sizeof(cbcalled));
+		msg = new_msg( 2, cmd2, avp1, avp2, 2 );
+		CHECK( 0, fd_msg_dispatch ( &msg, sess, &action, &ec, &em, &error ) );
+		CHECK( 1, cbcalled[0] );
+		CHECK( 1, cbcalled[1] );
+		CHECK( 1, cbcalled[2] );
+		CHECK( 1, cbcalled[3] );
+		CHECK( 1, cbcalled[4] );
+		CHECK( 0, cbcalled[9] );
+		CHECK( 0, fd_msg_free( msg ) );
+		
+		CHECK( 0, fd_disp_register( cb_9, DISP_HOW_ANY, &when, NULL, &hdl[5] ) );
+		memset(cbcalled, 0, sizeof(cbcalled));
+		msg = new_msg( 2, cmd2, avp1, avp2, 2 );
+		CHECK( 0, fd_msg_dispatch ( &msg, sess, &action, &ec, &em, &error ) );
+		CHECK( 1, cbcalled[0] );
+		CHECK( 0, cbcalled[1] );
+		CHECK( 0, cbcalled[2] );
+		CHECK( 0, cbcalled[3] );
+		CHECK( 0, cbcalled[4] );
+		CHECK( 1, cbcalled[9] );
+		CHECK( 0, fd_msg_free( msg ) );
+		CHECK( 0, fd_disp_unregister( &hdl[5], NULL ) );
+		
+		CHECK( 0, fd_disp_register( cb_9, DISP_HOW_AVP_ENUMVAL, &when, NULL, &hdl[5] ) );
+		memset(cbcalled, 0, sizeof(cbcalled));
+		msg = new_msg( 2, cmd2, avp1, avp2, 2 );
+		CHECK( 0, fd_msg_dispatch ( &msg, sess, &action, &ec, &em, &error ) );
+		CHECK( 1, cbcalled[0] );
+		CHECK( 1, cbcalled[1] );
+		CHECK( 1, cbcalled[2] );
+		CHECK( 0, cbcalled[3] );
+		CHECK( 0, cbcalled[4] );
+		CHECK( 1, cbcalled[9] );
+		CHECK( 0, fd_msg_free( msg ) );
+		CHECK( 0, fd_disp_unregister( &hdl[5], NULL ) );
+		
+		CHECK( 0, fd_disp_register( cb_9, DISP_HOW_AVP, &when, NULL, &hdl[5] ) );
+		memset(cbcalled, 0, sizeof(cbcalled));
+		msg = new_msg( 2, cmd2, avp1, avp2, 2 );
+		CHECK( 0, fd_msg_dispatch ( &msg, sess, &action, &ec, &em, &error ) );
+		CHECK( 1, cbcalled[0] );
+		CHECK( 1, cbcalled[1] );
+		CHECK( 1, cbcalled[2] );
+		CHECK( 0, cbcalled[3] );
+		CHECK( 0, cbcalled[4] );
+		CHECK( 1, cbcalled[9] );
+		CHECK( 0, fd_msg_free( msg ) );
+		CHECK( 0, fd_disp_unregister( &hdl[5], NULL ) );
+		
+		CHECK( 0, fd_disp_register( cb_9, DISP_HOW_CC, &when, NULL, &hdl[5] ) );
+		memset(cbcalled, 0, sizeof(cbcalled));
+		msg = new_msg( 2, cmd2, avp1, avp2, 2 );
+		CHECK( 0, fd_msg_dispatch ( &msg, sess, &action, &ec, &em, &error ) );
+		CHECK( 1, cbcalled[0] );
+		CHECK( 1, cbcalled[1] );
+		CHECK( 1, cbcalled[2] );
+		CHECK( 1, cbcalled[3] );
+		CHECK( 0, cbcalled[4] );
+		CHECK( 1, cbcalled[9] );
+		CHECK( 0, fd_msg_free( msg ) );
+		CHECK( 0, fd_disp_unregister( &hdl[5], NULL ) );
+		
+		CHECK( 0, fd_disp_register( cb_9, DISP_HOW_APPID, &when, NULL, &hdl[5] ) );
+		memset(cbcalled, 0, sizeof(cbcalled));
+		msg = new_msg( 2, cmd2, avp1, avp2, 2 );
+		CHECK( 0, fd_msg_dispatch ( &msg, sess, &action, &ec, &em, &error ) );
+		CHECK( 1, cbcalled[0] );
+		CHECK( 1, cbcalled[1] );
+		CHECK( 1, cbcalled[2] );
+		CHECK( 1, cbcalled[3] );
+		CHECK( 1, cbcalled[4] );
+		CHECK( 1, cbcalled[9] );
+		CHECK( 0, fd_msg_free( msg ) );
+		CHECK( 0, fd_disp_unregister( &hdl[5], NULL ) );
+		
+		CHECK( 0, fd_disp_unregister( &hdl[0], NULL ) );
+		CHECK( 0, fd_disp_unregister( &hdl[1], NULL ) );
+		CHECK( 0, fd_disp_unregister( &hdl[2], NULL ) );
+		CHECK( 0, fd_disp_unregister( &hdl[3], NULL ) );
+		CHECK( 0, fd_disp_unregister( &hdl[4], NULL ) );
+	}			
+	
+	/* Test application support advertisement */
+	{
+		struct dict_object * vnd;
+		struct dict_vendor_data vnd_data = { 1, "Vendor test" };
+		struct fd_app * app;
+		
+		CHECK( 0, fd_dict_new ( fd_g_config->cnf_dict, DICT_VENDOR, &vnd_data, NULL, &vnd ) );
+		
+		CHECK( EINVAL, fd_disp_app_support ( vnd, NULL, 1, 0 ) );
+		CHECK( EINVAL, fd_disp_app_support ( app1, NULL, 0, 0 ) );
+		CHECK( 0, fd_disp_app_support ( app1, NULL, 1, 0 ) );
+		CHECK( 0, fd_disp_app_support ( app1, NULL, 0, 1 ) );
+		CHECK( 0, fd_disp_app_support ( app2, vnd, 1, 0 ) );
+		
+		app = (struct fd_app *)(fd_g_config->cnf_apps.next);
+		CHECK( 1, app->appid );
+		CHECK( 1, app->flags.auth );
+		CHECK( 1, app->flags.acct );
+		app = (struct fd_app *)(fd_g_config->cnf_apps.prev);
+		CHECK( 2, app->appid );
+		CHECK( 1, app->flags.auth );
+		CHECK( 0, app->flags.acct );
+		
+		#if 0
+		fd_log_debug("%s", fd_conf_dump(FD_DUMP_TEST_PARAMS));
+		#endif
+	}
+	
+	/* Test opaque pointer management */
+	{
+		void * ptr;
+		CHECK( 0, fd_disp_register( cb_0, DISP_HOW_ANY, NULL, g_opaque, &hdl[0] ) );
+	
+		/* Check this handler is called for a message */
+		msg = new_msg( 0, cmd1, avp1, NULL, 0 );
+		memset(cbcalled, 0, sizeof(cbcalled));
+		CHECK( 0, fd_msg_dispatch ( &msg, sess, &action, &ec, &em, &error ) );
+		CHECK( 1, cbcalled[0] );
+		CHECK( DISP_ACT_CONT, action );
+		
+		/* Delete the message */
+		CHECK( 0, fd_msg_free( msg ) );
+		CHECK( 0, fd_disp_unregister( &hdl[0], &ptr ) );
+		CHECK( 1, ptr == g_opaque ? 1 : 0 );
+	}
+	
+	/* That's all for the tests yet */
+	PASSTEST();
+} 
+	
diff --git a/tests/testfifo.c b/tests/testfifo.c
new file mode 100644
index 0000000..c1c7cf1
--- /dev/null
+++ b/tests/testfifo.c
@@ -0,0 +1,579 @@
+/*********************************************************************************************************
+* Software License Agreement (BSD License)                                                               *
+* Author: Sebastien Decugis <sdecugis@freediameter.net>							 *
+*													 *
+* Copyright (c) 2013, WIDE Project and NICT								 *
+* All rights reserved.											 *
+* 													 *
+* Redistribution and use of this software in source and binary forms, with or without modification, are  *
+* permitted provided that the following conditions are met:						 *
+* 													 *
+* * Redistributions of source code must retain the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer.										 *
+*    													 *
+* * Redistributions in binary form must reproduce the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer in the documentation and/or other						 *
+*   materials provided with the distribution.								 *
+* 													 *
+* * Neither the name of the WIDE Project or NICT nor the 						 *
+*   names of its contributors may be used to endorse or 						 *
+*   promote products derived from this software without 						 *
+*   specific prior written permission of WIDE Project and 						 *
+*   NICT.												 *
+* 													 *
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED *
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
+* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR *
+* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 	 *
+* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 	 *
+* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR *
+* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF   *
+* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.								 *
+*********************************************************************************************************/
+
+#include "tests.h"
+#include <unistd.h>
+#include <limits.h>
+
+/* Wrapper for pthread_barrier stuff on Mac OS X */
+#ifndef HAVE_PTHREAD_BAR
+
+#define PTHREAD_BARRIER_SERIAL_THREAD 1
+typedef struct {
+	int count;
+	int entered;
+	int serial;
+	pthread_mutex_t mutex;
+	pthread_cond_t cond;
+} pthread_barrier_t;
+
+int pthread_barrier_init(pthread_barrier_t * barrier, int * barrier_attr, int count)
+{
+	memset(barrier, 0, sizeof(pthread_barrier_t));
+	barrier->count = count;
+	pthread_mutex_init(&barrier->mutex, NULL);
+	pthread_cond_init(&barrier->cond, NULL);
+	return 0;
+}
+
+int pthread_barrier_destroy(pthread_barrier_t * barrier)
+{
+	pthread_mutex_destroy(&barrier->mutex);
+	pthread_cond_destroy(&barrier->cond);
+	return 0;
+}
+
+int pthread_barrier_wait(pthread_barrier_t * barrier)
+{
+	int ret = 0;
+	int serial;
+	pthread_mutex_lock(&barrier->mutex);
+	serial = barrier->serial;
+	
+	/* first thread gets the special value */
+	if (barrier->entered++ == 0) 
+		ret = PTHREAD_BARRIER_SERIAL_THREAD;
+	
+	/* Count was achieved? */
+	if (barrier->entered == barrier->count) {
+		/* Ok, increase serial, reset number of threads, and signal everyone */
+		barrier->entered = 0;
+		barrier->serial++;
+		pthread_cond_broadcast(&barrier->cond);
+	} else {
+		do {
+			pthread_cond_wait(&barrier->cond, &barrier->mutex);
+		} while (barrier->serial == serial);
+		/* this protects against spurious wakes */
+	}
+	pthread_mutex_unlock(&barrier->mutex);
+	return 0;
+}
+
+#endif /* HAVE_PTHREAD_BAR */
+
+/* Structure for testing threshold function */
+static struct thrh_test {
+	struct fifo *   queue; /* pointer to the queue */
+	int		h_calls; /* number of calls of h_cb */
+	int		l_calls; /* number of calls of l_cb */
+} thrh_td;
+
+/* Callbacks for threasholds test */
+void thrh_cb_h(struct fifo *queue, void **data)
+{
+	if (thrh_td.h_calls == thrh_td.l_calls) {
+		CHECK( NULL, *data );
+		*data = &thrh_td;
+	} else {
+		CHECK( *data, &thrh_td );
+	}
+	CHECK( queue, thrh_td.queue );
+	
+	/* Update the count */
+	thrh_td.h_calls ++;
+}
+void thrh_cb_l(struct fifo *queue, void **data)
+{
+	CHECK( 1, data ? 1 : 0 );
+	CHECK( *data, &thrh_td );
+
+	/* Check the queue parameter is correct */
+	CHECK( queue, thrh_td.queue );
+	
+	/* Update the count */
+	thrh_td.l_calls ++;
+	/* Cleanup the data ptr if needed */
+	if (thrh_td.l_calls == thrh_td.h_calls)
+		*data = NULL;
+	/* done */
+}
+
+
+/* Structure that is passed to the test function */
+struct test_data {
+	struct fifo     * queue; /* pointer to the queue */
+	pthread_barrier_t * bar;   /* if not NULL, barrier to synchronize before getting messages */
+	struct timespec   * ts;	   /* if not NULL, use a timedget instead of a get */
+	int		    nbr;   /* number of messages to retrieve from the queue */
+};
+
+/* The test function, to be threaded */
+static void * test_fct(void * data)
+{
+	int ret = 0, i;
+	struct msg * msg = NULL;
+	struct test_data * td = (struct test_data *) data;
+	
+	if (td->bar != NULL) {
+		ret = pthread_barrier_wait(td->bar);
+		if (ret != PTHREAD_BARRIER_SERIAL_THREAD) {
+			CHECK( 0, ret);
+		} else {
+			CHECK( PTHREAD_BARRIER_SERIAL_THREAD, ret); /* just for the traces */
+		}
+	}
+	
+	for (i=0; i< td->nbr; i++) {
+		if (td->ts != NULL) {
+			CHECK( 0, fd_fifo_timedget(td->queue, &msg, td->ts) );
+		} else {
+			CHECK( 0, fd_fifo_get(td->queue, &msg) );
+		}
+	}
+	
+	return NULL;
+}
+
+/* The test function, to be threaded */
+static int iter  = 0;
+static void * test_fct2(void * data)
+{
+	int i;
+	int * item;
+	struct test_data * td = (struct test_data *) data;
+	
+	for (i=0; i< td->nbr; i++) {
+		item = malloc(sizeof(int));
+		CHECK( 1, item ? 1 : 0 );
+		*item = i;
+		CHECK( 0, fd_fifo_post(td->queue, &item) );
+		iter++;
+	}
+	
+	return NULL;
+}
+
+
+/* Main test routine */
+int main(int argc, char *argv[])
+{
+	struct timespec ts;
+	
+	struct msg * msg1 = NULL;
+	struct msg * msg2 = NULL;
+	struct msg * msg3 = NULL;
+	
+	/* First, initialize the daemon modules */
+	INIT_FD();
+	
+	/* Prolog: create the messages */
+	{
+		struct dict_object * acr_model = NULL;
+		struct dict_object * cer_model = NULL;
+		struct dict_object * dwr_model = NULL;
+
+		CHECK( 0, fd_dict_search ( fd_g_config->cnf_dict, DICT_COMMAND, CMD_BY_NAME, "Accounting-Request", 			&acr_model, ENOENT ) );
+		CHECK( 0, fd_dict_search ( fd_g_config->cnf_dict, DICT_COMMAND, CMD_BY_NAME, "Capabilities-Exchange-Request", 	&cer_model, ENOENT ) );
+		CHECK( 0, fd_dict_search ( fd_g_config->cnf_dict, DICT_COMMAND, CMD_BY_NAME, "Device-Watchdog-Request",		&dwr_model, ENOENT ) );
+		CHECK( 0, fd_msg_new ( acr_model, 0, &msg1 ) );
+		CHECK( 0, fd_msg_new ( cer_model, 0, &msg2 ) );
+		CHECK( 0, fd_msg_new ( dwr_model, 0, &msg3 ) );
+	}
+	
+	/* Basic operation */
+	{
+		struct fifo * queue = NULL;
+		struct msg * msg  = NULL;
+		int max;
+		long long count;
+		
+		/* Create the queue */
+		CHECK( 0, fd_fifo_new(&queue, 0) );
+		
+		/* Check the count is 0 */
+		CHECK( 0, fd_fifo_length(queue) );
+		
+		/* Now enqueue */
+		msg = msg1;
+		CHECK( 0, fd_fifo_post(queue, &msg) );
+		msg = msg2;
+		CHECK( 0, fd_fifo_post(queue, &msg) );
+		msg = msg3;
+		CHECK( 0, fd_fifo_post(queue, &msg) );
+		
+		/* Check the count is 3 */
+		CHECK( 3, fd_fifo_length(queue) );
+		
+		/* Retrieve the first message using fd_fifo_get */
+		CHECK( 0, fd_fifo_get(queue, &msg) );
+		CHECK( msg1, msg);
+		CHECK( 2, fd_fifo_length(queue) );
+		
+		/* Retrieve the second message using fd_fifo_timedget */
+		CHECK(0, clock_gettime(CLOCK_REALTIME, &ts));
+		ts.tv_sec += 1; /* Set the timeout to 1 second */
+		CHECK( 0, fd_fifo_timedget(queue, &msg, &ts) );
+		CHECK( msg2, msg);
+		CHECK( 1, fd_fifo_length(queue) );
+		
+		/* Retrieve the third message using meq_tryget */
+		CHECK( 0, fd_fifo_tryget(queue, &msg) );
+		CHECK( msg3, msg);
+		CHECK( 0, fd_fifo_length(queue) );
+		
+		/* Check that another meq_tryget does not block */
+		CHECK( EWOULDBLOCK, fd_fifo_tryget(queue, &msg) );
+		CHECK( 0, fd_fifo_length(queue) );
+		
+		/* Check the timedget actually timesout */
+		CHECK(0, clock_gettime(CLOCK_REALTIME, &ts));
+		ts.tv_nsec += 1000000; /* 1 millisecond */
+		if (ts.tv_nsec >= 1000000000L) {
+			ts.tv_nsec -= 1000000000L;
+			ts.tv_sec += 1;
+		}
+		CHECK( ETIMEDOUT, fd_fifo_timedget(queue, &msg, &ts) );
+		CHECK( 0, fd_fifo_length(queue) );
+		
+		/* Post & get another message */
+		msg = msg1;
+		CHECK( 0, fd_fifo_post(queue, &msg) );
+		CHECK( 0, fd_fifo_timedget(queue, &msg, &ts) );
+		CHECK( msg1, msg);		
+		
+		/* Check some statistics */
+		CHECK( 0, fd_fifo_getstats(queue, NULL, NULL, &max, &count, NULL, NULL, NULL) );
+		CHECK( 3, max );
+		CHECK( 4, count );	
+		
+		/* We're done for basic tests */
+		CHECK( 0, fd_fifo_del(&queue) );
+	}
+	
+	/* Test robustness, ensure no messages are lost */
+	{
+#define NBR_MSG		200
+#define NBR_THREADS	60
+		struct fifo  		*queue = NULL;
+		pthread_barrier_t	 bar;
+		struct test_data	 td_1;
+		struct test_data	 td_2;
+		struct msg   		*msgs[NBR_MSG * NBR_THREADS * 2], *msg;
+		pthread_t  		 thr [NBR_THREADS * 2];
+		struct dict_object	*dwr_model = NULL;
+		int			 i;
+		int			 nbr_threads;
+#ifdef _POSIX_THREAD_THREADS_MAX
+		nbr_threads = _POSIX_THREAD_THREADS_MAX;
+#else /* _POSIX_THREAD_THREADS_MAX */
+		nbr_threads = sysconf(_SC_THREAD_THREADS_MAX);
+#endif /* _POSIX_THREAD_THREADS_MAX */
+		if ((nbr_threads <= 0) || (nbr_threads > NBR_THREADS * 2)) {
+			nbr_threads = NBR_THREADS;
+		} else {
+			TRACE_DEBUG(INFO, "Local limit on number of threads: %d", nbr_threads);
+			/* The local limit is below NBR_THREADS */
+			nbr_threads = (nbr_threads / 2) - 1;
+			/* Ensure we create at least a few threads! */
+			CHECK( 1, nbr_threads >= 10 ? 1 : 0 );
+		}
+		
+		/* Create the queue */
+		CHECK( 0, fd_fifo_new(&queue, 0) );
+		
+		/* Create the barrier */
+		CHECK( 0, pthread_barrier_init(&bar, NULL, nbr_threads * 2 + 1) );
+		
+		/* Initialize the ts */
+		CHECK(0, clock_gettime(CLOCK_REALTIME, &ts));
+		ts.tv_sec += 20; /* Set the timeout to 20 second */
+		
+		/* Create the messages */
+		CHECK( 0, fd_dict_search ( fd_g_config->cnf_dict, DICT_COMMAND, CMD_BY_NAME, "Device-Watchdog-Request",		&dwr_model, ENOENT ) );
+		for (i = 0; i < NBR_MSG * nbr_threads * 2; i++) {
+			CHECK( 0, fd_msg_new ( dwr_model, 0, &msgs[i] ) );
+		}
+		
+		/* Initialize the test data structures */
+		td_1.queue = queue;
+		td_1.bar = &bar;
+		td_1.ts  = &ts;
+		td_1.nbr = NBR_MSG;
+		td_2.queue = queue;
+		td_2.bar = &bar;
+		td_2.ts  = NULL;
+		td_2.nbr = NBR_MSG;
+		
+		/* Create the threads */
+		for (i=0; i < nbr_threads * 2; i++) {
+			CHECK( 0, pthread_create( &thr[i], NULL, test_fct, (i & 1) ? &td_1 : &td_2 ) );
+		}
+		
+		/* Synchronize everyone */
+		{
+			int ret = pthread_barrier_wait(&bar);
+			if (ret != PTHREAD_BARRIER_SERIAL_THREAD) {
+				CHECK( 0, ret);
+			} else {
+				CHECK( PTHREAD_BARRIER_SERIAL_THREAD, ret); /* for trace only */
+			}
+		}
+		
+		/* Now post all the messages */
+		for (i=0; i < NBR_MSG * nbr_threads * 2; i++) {
+			msg = msgs[i];
+			CHECK( 0, fd_fifo_post(queue, &msg) );
+		}
+		
+		/* Join all threads. This blocks if messages are lost... */
+		for (i=0; i < nbr_threads * 2; i++) {
+			CHECK( 0, pthread_join( thr[i], NULL ) );
+		}
+		
+		/* Check the count of the queue is back to 0 */
+		CHECK( 0, fd_fifo_length(queue) );
+		
+		/* Destroy this queue and the messages */
+		CHECK( 0, fd_fifo_del(&queue) );
+		for (i=0; i < NBR_MSG * nbr_threads * 2; i++) {
+			CHECK( 0, fd_msg_free(  msgs[i] ) );
+		}
+	}
+	
+	/* Test thread cancelation */
+	{
+		struct fifo      	*queue = NULL;
+		pthread_barrier_t	 bar;
+		struct test_data	 td;
+		pthread_t		 th;
+		
+		/* Create the queue */
+		CHECK( 0, fd_fifo_new(&queue, 0) );
+		
+		/* Create the barrier */
+		CHECK( 0, pthread_barrier_init(&bar, NULL, 2) );
+		
+		/* Initialize the ts */
+		CHECK(0, clock_gettime(CLOCK_REALTIME, &ts));
+		ts.tv_sec += 10; /* Set the timeout to 10 second */
+		
+		/* Initialize the test data structures */
+		td.queue = queue;
+		td.bar = &bar;
+		td.ts  = &ts;
+		td.nbr = 1;
+		
+		/* Create the thread */
+		CHECK( 0, pthread_create( &th, NULL, test_fct, &td ) );
+		
+		/* Wait for the thread to be running */
+		{
+			int ret = pthread_barrier_wait(&bar);
+			if (ret != PTHREAD_BARRIER_SERIAL_THREAD) {
+				CHECK( 0, ret);
+			} else {
+				CHECK( PTHREAD_BARRIER_SERIAL_THREAD, ret );
+			}
+		}
+		
+		/* Now cancel the thread */
+		CHECK( 0, pthread_cancel( th ) );
+		
+		/* Join it */
+		CHECK( 0, pthread_join( th, NULL ) );
+		
+		/* Do the same with the other function */
+		td.ts  = NULL;
+		
+		/* Create the thread */
+		CHECK( 0, pthread_create( &th, NULL, test_fct, &td ) );
+		
+		/* Wait for the thread to be running */
+		{
+			int ret = pthread_barrier_wait(&bar);
+			if (ret != PTHREAD_BARRIER_SERIAL_THREAD) {
+				CHECK( 0, ret);
+			} else {
+				CHECK( PTHREAD_BARRIER_SERIAL_THREAD, ret );
+			}
+		}
+		
+		/* Now cancel the thread */
+		CHECK( 0, pthread_cancel( th ) );
+		
+		/* Join it */
+		CHECK( 0, pthread_join( th, NULL ) );
+		
+		/* Destroy the queue */
+		CHECK( 0, fd_fifo_del(&queue) );
+	}
+	
+	/* Test the threashold function */
+	{
+		struct fifo * queue = NULL;
+		int i;
+		struct msg * msg  = NULL;
+		
+		/* Create the queue */
+		CHECK( 0, fd_fifo_new(&queue, 0) );
+		
+		/* Prepare the test data */
+		memset(&thrh_td, 0, sizeof(thrh_td));
+		thrh_td.queue = queue;
+		
+		/* Set the thresholds for the queue */
+		CHECK( 0, fd_fifo_setthrhd ( queue, NULL, 6, thrh_cb_h, 4, thrh_cb_l ) );
+		
+		/* Post 5 messages, no cb must be called. */
+		for (i=0; i<5; i++) {
+			msg = msg1;
+			CHECK( 0, fd_fifo_post(queue, &msg) );
+		} /* 5 msg in queue */
+		CHECK( 0, thrh_td.h_calls );
+		CHECK( 0, thrh_td.l_calls );
+		
+		/* Get all these messages, and check again */
+		for (i=0; i<5; i++) {
+			CHECK( 0, fd_fifo_get(queue, &msg) );
+		} /* 0 msg in queue */
+		CHECK( 0, thrh_td.h_calls );
+		CHECK( 0, thrh_td.l_calls );
+		
+		/* Now, post 6 messages, the high threashold */
+		for (i=0; i<6; i++) {
+			msg = msg1;
+			CHECK( 0, fd_fifo_post(queue, &msg) );
+		} /* 6 msg in queue */
+		CHECK( 1, thrh_td.h_calls );
+		CHECK( 0, thrh_td.l_calls );
+		
+		/* Remove 2 messages, to reach the low threshold */
+		for (i=0; i<2; i++) {
+			CHECK( 0, fd_fifo_get(queue, &msg) );
+		} /* 4 msg in queue */
+		CHECK( 1, thrh_td.h_calls );
+		CHECK( 1, thrh_td.l_calls );
+		
+		/* Come again at the high threshold */
+		for (i=0; i<2; i++) {
+			msg = msg1;
+			CHECK( 0, fd_fifo_post(queue, &msg) );
+		} /* 6 msg in queue */
+		CHECK( 2, thrh_td.h_calls );
+		CHECK( 1, thrh_td.l_calls );
+		
+		/* Suppose the queue continues to grow */
+		for (i=0; i<6; i++) {
+			msg = msg1;
+			CHECK( 0, fd_fifo_post(queue, &msg) );
+		} /* 12 msg in queue */
+		CHECK( 3, thrh_td.h_calls );
+		CHECK( 1, thrh_td.l_calls );
+		for (i=0; i<5; i++) {
+			msg = msg1;
+			CHECK( 0, fd_fifo_post(queue, &msg) );
+		} /* 17 msg in queue */
+		CHECK( 3, thrh_td.h_calls );
+		CHECK( 1, thrh_td.l_calls );
+		
+		/* Now the queue goes back to 0 messages */
+		for (i=0; i<17; i++) {
+			CHECK( 0, fd_fifo_get(queue, &msg) );
+		} /* 0 msg in queue */
+		CHECK( 3, thrh_td.h_calls );
+		CHECK( 3, thrh_td.l_calls );
+		
+		/* We're done for this test */
+		CHECK( 0, fd_fifo_del(&queue) );
+	}
+	
+	/* Test max queue limit */
+	{
+		struct fifo      	*queue = NULL;
+		struct test_data	 td;
+		pthread_t		 th;
+		int *			item, i;
+		
+		/* Create the queue */
+		CHECK( 0, fd_fifo_new(&queue, 10) );
+		
+		/* Initialize the test data structures */
+		td.queue = queue;
+		td.nbr = 15;
+		
+		CHECK( 0, pthread_create( &th, NULL, test_fct2, &td ) );
+		
+		usleep(100000); /* 100 millisec */
+		
+		CHECK( 10, iter );
+		
+		CHECK( 0, fd_fifo_tryget(queue, &item) );
+		CHECK( 0, *item);
+		free(item);
+		
+		usleep(100000); /* 100 millisec */
+		
+		CHECK( 11, iter );
+		
+		for (i=1; i<4; i++) {
+			CHECK( 0, fd_fifo_get(queue, &item) );
+			CHECK( i, *item);
+			free(item);
+		}
+		
+		usleep(100000); /* 100 millisec */
+		
+		CHECK( 14, iter );
+		
+		for (; i < td.nbr; i++) {
+			CHECK( 0, fd_fifo_tryget(queue, &item) );
+			CHECK( i, *item);
+			free(item);
+		}
+		
+		CHECK( 0, pthread_join( th, NULL ) );
+		CHECK( 15, iter );
+		
+	}
+	
+	/* Delete the messages */
+	CHECK( 0, fd_msg_free( msg1 ) );
+	CHECK( 0, fd_msg_free( msg2 ) );
+	CHECK( 0, fd_msg_free( msg3 ) );
+
+	/* That's all for the tests yet */
+	PASSTEST();
+} 
diff --git a/tests/testloadext.c b/tests/testloadext.c
new file mode 100644
index 0000000..452737f
--- /dev/null
+++ b/tests/testloadext.c
@@ -0,0 +1,100 @@
+/*********************************************************************************************************
+* Software License Agreement (BSD License)                                                               *
+* Author: Sebastien Decugis <sdecugis@freediameter.net>							 *
+*													 *
+* Copyright (c) 2011, WIDE Project and NICT								 *
+* All rights reserved.											 *
+* 													 *
+* Redistribution and use of this software in source and binary forms, with or without modification, are  *
+* permitted provided that the following conditions are met:						 *
+* 													 *
+* * Redistributions of source code must retain the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer.										 *
+*    													 *
+* * Redistributions in binary form must reproduce the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer in the documentation and/or other						 *
+*   materials provided with the distribution.								 *
+* 													 *
+* * Neither the name of the WIDE Project or NICT nor the 						 *
+*   names of its contributors may be used to endorse or 						 *
+*   promote products derived from this software without 						 *
+*   specific prior written permission of WIDE Project and 						 *
+*   NICT.												 *
+* 													 *
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED *
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
+* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR *
+* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 	 *
+* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 	 *
+* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR *
+* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF   *
+* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.								 *
+*********************************************************************************************************/
+
+#include "tests.h"
+
+#ifndef BUILD_DIR
+#error "Missing BUILD_DIR information"
+#endif /* BUILD_DIR */
+
+#include <sys/types.h>
+#include <dirent.h>
+#include <libgen.h>
+#include <dlfcn.h>
+
+/* Main test routine */
+int main(int argc, char *argv[])
+{
+	DIR *dir;
+	struct dirent *dp;
+	char fullname[512];
+	int pathlen;
+
+	/* First, initialize the daemon modules */
+	INIT_FD();
+	CHECK( 0, fd_queues_init()  );
+	CHECK( 0, fd_msg_init()  );
+	CHECK( 0, fd_rtdisp_init()  );
+	
+	/* Find all extensions which have been compiled along the test */
+	TRACE_DEBUG(INFO, "Loading from: '%s'", BUILD_DIR "/extensions");
+	CHECK( 0, (dir = opendir (BUILD_DIR "/extensions")) == NULL ? 1 : 0 );
+	pathlen = snprintf(fullname, sizeof(fullname), BUILD_DIR "/extensions/");
+	
+	while ((dp = readdir (dir)) != NULL) {
+		char * dot = strrchr(dp->d_name, '.');
+		if (dot && !(strcmp(dot, ".fdx"))) {
+			/* We found a file with name *.fdx, attempt to load it */
+			void *hdl, * ep;
+			snprintf(fullname + pathlen, sizeof(fullname) - pathlen, "%s", dp->d_name);
+			
+			TRACE_DEBUG(INFO, "Extension: '%s'", dp->d_name);
+			
+			/* load */
+			hdl = dlopen(fullname, RTLD_NOW | RTLD_GLOBAL);
+			if (!hdl) {
+				TRACE_DEBUG(INFO, "Unable to load '%s': %s.", fullname, dlerror());
+			}
+			CHECK( 0, hdl == NULL ? 1 : 0 );
+			
+			/* resolve entry */
+			ep = dlsym( hdl, "fd_ext_init" );
+			if (!ep) {
+				TRACE_DEBUG(INFO, "No 'fd_ext_init' entry point in '%s': %s.", fullname, dlerror());
+			}
+			CHECK( 0, ep == NULL ? 1 : 0 );
+			
+			/* Done, now unload */
+#ifndef SKIP_DLCLOSE
+			CHECK( 0, dlclose(hdl) );
+#endif /* SKIP_DLCLOSE */
+		}
+	}
+	
+	CHECK( 0, closedir(dir) );
+	
+	PASSTEST();
+} 
+	
diff --git a/tests/testmesg.c b/tests/testmesg.c
new file mode 100644
index 0000000..5525ff4
--- /dev/null
+++ b/tests/testmesg.c
@@ -0,0 +1,1455 @@
+/*********************************************************************************************************
+* Software License Agreement (BSD License)                                                               *
+* Author: Sebastien Decugis <sdecugis@freediameter.net>							 *
+*													 *
+* Copyright (c) 2015, WIDE Project and NICT								 *
+* All rights reserved.											 *
+* 													 *
+* Redistribution and use of this software in source and binary forms, with or without modification, are  *
+* permitted provided that the following conditions are met:						 *
+* 													 *
+* * Redistributions of source code must retain the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer.										 *
+*    													 *
+* * Redistributions in binary form must reproduce the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer in the documentation and/or other						 *
+*   materials provided with the distribution.								 *
+* 													 *
+* * Neither the name of the WIDE Project or NICT nor the 						 *
+*   names of its contributors may be used to endorse or 						 *
+*   promote products derived from this software without 						 *
+*   specific prior written permission of WIDE Project and 						 *
+*   NICT.												 *
+* 													 *
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED *
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
+* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR *
+* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 	 *
+* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 	 *
+* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR *
+* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF   *
+* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.								 *
+*********************************************************************************************************/
+
+#include "tests.h"
+
+/* Main test routine */
+int main(int argc, char *argv[])
+{
+	struct msg * acr = NULL;
+	struct avp * pi = NULL, *avp1, *avp2;
+	unsigned char * buf = NULL;
+	
+	/* First, initialize the daemon modules */
+	INIT_FD();
+	
+	/* Create the message object from model */
+	{
+		struct dict_object * acr_model = NULL;
+
+		/* Now find the ACR dictionary object */
+		CHECK( 0, fd_dict_search ( fd_g_config->cnf_dict, DICT_COMMAND, CMD_BY_NAME, "Accounting-Request", &acr_model, ENOENT ) );
+
+		/* Create the instance, using the templates */
+		CHECK( 0, fd_msg_new ( acr_model, 0, &acr ) );
+
+		/* Check there is no child */
+		CHECK( ENOENT, fd_msg_browse ( acr, MSG_BRW_FIRST_CHILD, NULL, NULL) );
+		
+		#if 0
+		/* For debug: dump the object */
+		fd_log_debug("Dumping Accounting-Request empty message:");
+		fd_log_debug("%s", fd_msg_dump_treeview(FD_DUMP_TEST_PARAMS, acr, fd_g_config->cnf_dict, 0, 1));
+		#endif
+	}
+	
+	/* Create the Proxy-Info AVP from model */
+	{
+		struct dict_object * pi_model = NULL;
+
+		/* Now find the ACR dictionary object */
+		CHECK( 0, fd_dict_search ( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Proxy-Info", &pi_model, ENOENT ) );
+
+		/* Create the instance, using the templates */
+		CHECK( 0, fd_msg_avp_new ( pi_model, 0, &pi ) );
+
+		#if 0
+		/* For debug: dump the object */
+		fd_log_debug("Dumping Proxy-Info AVP");
+		fd_log_debug("%s", fd_msg_dump_treeview(FD_DUMP_TEST_PARAMS, pi, fd_g_config->cnf_dict, 0, 1));
+		fd_log_debug("Dumping dictionary model");
+		fd_log_debug("%s", fd_dict_dump_object(FD_DUMP_TEST_PARAMS, pi_model));
+		#endif
+		
+	}
+	
+	/* Get a reference to the current last AVP in the message */
+	{
+		int diff = 0;
+		
+		CHECK( 0, fd_msg_avp_new ( NULL, 0, &avp1 ) );
+		CHECK( 0, fd_msg_avp_add ( acr, MSG_BRW_LAST_CHILD, avp1) );
+		
+		CHECK( 0, fd_msg_browse ( acr, MSG_BRW_LAST_CHILD, &avp2, &diff) );
+		CHECK( 1, diff );
+		CHECK( avp1, avp2 );
+		
+		/* Check that we cannot add this AVP to another object since it is already linked */
+		CHECK( EINVAL, fd_msg_avp_add( pi, MSG_BRW_LAST_CHILD, avp1) );
+	}
+
+	/* Now add the Proxy-Info AVP at the end of the message */
+	{
+		CHECK( 0, fd_msg_avp_add( acr, MSG_BRW_LAST_CHILD, pi) );
+		#if 0
+		/* For debug: dump the object */
+		fd_log_debug("Dumping Accounting-Request with Proxy-Info AVP at the end");
+		fd_log_debug("%s", fd_msg_dump_treeview(FD_DUMP_TEST_PARAMS, acr, fd_g_config->cnf_dict, 0, 1));
+		#endif
+	}
+	
+	/* Check the last child is now the proxy-Info */
+	{
+		CHECK( 0, fd_msg_browse ( acr, MSG_BRW_LAST_CHILD, &avp2, NULL) );
+		CHECK( pi, avp2 );
+	}
+	
+	/* Check that the avp before the proxy-info is the previous last one */
+	{
+		int diff = 0;
+		CHECK( 0, fd_msg_browse ( pi, MSG_BRW_PREV, &avp2, &diff) );
+		CHECK( avp1, avp2 );
+		CHECK( 0, diff);
+	}
+	
+	/* Check that there are no AVP after the proxy-info */
+	CHECK( ENOENT, fd_msg_browse ( pi, MSG_BRW_NEXT, NULL, NULL) );
+	
+	/* Test the fd_msg_free function unlinks the object properly */
+	{
+		struct dict_object * rr_model = NULL;
+
+		/* Now find the dictionary object */
+		CHECK( 0, fd_dict_search ( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Route-Record", &rr_model, ENOENT ) );
+
+		/* Create the instance, using the templates */
+		CHECK( 0, fd_msg_avp_new ( rr_model, 0, &avp1 ) );
+		
+		/* Add the AVP at the end of the message */
+		CHECK( 0, fd_msg_avp_add( pi, MSG_BRW_NEXT, avp1) );
+		
+		/* Check the last AVP of the message is now this one */
+		CHECK( 0, fd_msg_browse ( acr, MSG_BRW_LAST_CHILD, &avp2, NULL) );
+		CHECK( avp1, avp2 );
+		
+		/* Now delete it */
+		CHECK( 0, fd_msg_free( avp1 ) );
+		
+		/* Check the last AVP of the message is back to pi */
+		CHECK( 0, fd_msg_browse ( acr, MSG_BRW_LAST_CHILD, &avp2, NULL) );
+		CHECK( pi, avp2 );
+		
+		/* Delete the whole message */
+		CHECK( 0, fd_msg_free( acr ) );
+	}
+	
+	/* Recreate the message object */
+	{
+		struct dict_object * acr_model = NULL;
+
+		/* Now find the ACR dictionary object */
+		CHECK( 0, fd_dict_search ( fd_g_config->cnf_dict, DICT_COMMAND, CMD_BY_NAME, "Accounting-Request", &acr_model, ENOENT ) );
+
+		/* Create the instance, using the templates */
+		CHECK( 0, fd_msg_new ( acr_model, 0, &acr ) );
+	}
+	
+	/* Now let's create some additional Dictionary objects for the test */
+	{
+		/* The constant values used here are totally arbitrary chosen */
+		struct dict_object * vendor;
+		{
+			struct dict_vendor_data vendor_data = { 73565, "Vendor test" };
+			CHECK( 0, fd_dict_new ( fd_g_config->cnf_dict, DICT_VENDOR, &vendor_data , NULL, &vendor ) );
+		}
+		
+		{
+			struct dict_application_data app_data = { 73566, "Application test" };
+			CHECK( 0, fd_dict_new ( fd_g_config->cnf_dict, DICT_APPLICATION, &app_data , vendor, NULL ) );
+		}
+		
+		{
+			struct dict_avp_data avp_data = { 73567, 0, "AVP Test - no vendor - f32", 0, 0, AVP_TYPE_FLOAT32 };
+			CHECK( 0, fd_dict_new ( fd_g_config->cnf_dict, DICT_AVP, &avp_data , NULL, NULL ) );
+		}
+		
+		{
+			struct dict_avp_data avp_data = { 139103, 0, "AVP Test - no vendor - f64", 0, 0, AVP_TYPE_FLOAT64 };
+			CHECK( 0, fd_dict_new ( fd_g_config->cnf_dict, DICT_AVP, &avp_data , NULL, NULL ) );
+		}
+		
+		{ 
+			struct dict_object  * type = NULL;
+			struct dict_type_data type_data = { AVP_TYPE_INTEGER64, "Int64 test" };
+			struct dict_avp_data  avp_data = { 73568, 73565, "AVP Test - i64", AVP_FLAG_VENDOR, AVP_FLAG_VENDOR, AVP_TYPE_INTEGER64 };
+			CHECK( 0, fd_dict_new ( fd_g_config->cnf_dict, DICT_TYPE, &type_data , NULL, &type ) );
+			CHECK( 0, fd_dict_new ( fd_g_config->cnf_dict, DICT_AVP, &avp_data , type, NULL ) );
+		}
+		
+		{
+			struct dict_object     * type = NULL;
+			struct dict_type_data    type_data = { AVP_TYPE_INTEGER32, "Enum32 test" };
+			struct dict_enumval_data val1 = { "i32 const test (val 1)", { .i32 = 1 } };
+			struct dict_enumval_data val2 = { "i32 const test (val 2)", { .i32 = 2 } };
+			struct dict_enumval_data val3 = { "i32 const test (val -5)",{ .i32 = -5 } };
+			struct dict_avp_data     avp_data = { 73569, 73565, "AVP Test - enumi32", AVP_FLAG_VENDOR, AVP_FLAG_VENDOR, AVP_TYPE_INTEGER32 };
+			
+			CHECK( 0, fd_dict_new ( fd_g_config->cnf_dict, DICT_TYPE, &type_data , NULL, &type ) );
+			CHECK( 0, fd_dict_new ( fd_g_config->cnf_dict, DICT_AVP, &avp_data , type, NULL ) );
+			CHECK( 0, fd_dict_new ( fd_g_config->cnf_dict, DICT_ENUMVAL, &val1 , type, NULL ) );
+			CHECK( 0, fd_dict_new ( fd_g_config->cnf_dict, DICT_ENUMVAL, &val2 , type, NULL ) );
+			CHECK( 0, fd_dict_new ( fd_g_config->cnf_dict, DICT_ENUMVAL, &val3 , type, NULL ) );
+		}
+			
+		{ 
+			struct dict_object  * type = NULL;
+			struct dict_type_data type_data = { AVP_TYPE_OCTETSTRING, "OS test" };
+			struct dict_avp_data  avp_data = { 73570, 73565, "AVP Test - os", AVP_FLAG_VENDOR, AVP_FLAG_VENDOR, AVP_TYPE_OCTETSTRING };
+			CHECK( 0, fd_dict_new ( fd_g_config->cnf_dict, DICT_TYPE, &type_data , NULL, &type ) );
+			CHECK( 0, fd_dict_new ( fd_g_config->cnf_dict, DICT_AVP, &avp_data , type, NULL ) );
+		}
+		
+		{
+			struct dict_object     * type = NULL;
+			struct dict_type_data    type_data = { AVP_TYPE_OCTETSTRING, "OS enum test" };
+			struct dict_enumval_data val1 = { "os const test (Test)", { .os = { (unsigned char *)"Test", 4 } } };
+			struct dict_enumval_data val2 = { "os const test (waaad)", { .os = { (unsigned char *)"waaad", 5 } } };
+			struct dict_enumval_data val3 = { "os const test (waa)", { .os = { (unsigned char *)"waaad", 3 } } };
+			struct dict_avp_data     avp_data = { 73571, 73565, "AVP Test - enumos", AVP_FLAG_VENDOR, AVP_FLAG_VENDOR, AVP_TYPE_OCTETSTRING };
+			
+			CHECK( 0, fd_dict_new ( fd_g_config->cnf_dict, DICT_TYPE, &type_data , NULL, &type ) );
+			CHECK( 0, fd_dict_new ( fd_g_config->cnf_dict, DICT_AVP, &avp_data , type, NULL ) );
+			CHECK( 0, fd_dict_new ( fd_g_config->cnf_dict, DICT_ENUMVAL, &val1 , type, NULL ) );
+			CHECK( 0, fd_dict_new ( fd_g_config->cnf_dict, DICT_ENUMVAL, &val2 , type, NULL ) );
+			CHECK( 0, fd_dict_new ( fd_g_config->cnf_dict, DICT_ENUMVAL, &val3 , type, NULL ) );
+		}
+		
+		{
+			struct dict_object * gavp = NULL;
+			struct dict_avp_data avp_data = { 73572, 73565, "AVP Test - grouped", AVP_FLAG_VENDOR, AVP_FLAG_VENDOR, AVP_TYPE_GROUPED };
+			
+			CHECK( 0, fd_dict_new ( fd_g_config->cnf_dict, DICT_AVP, &avp_data , NULL, &gavp ) );
+			
+			/* Macro to search AVP and create a rule */		
+			#define ADD_RULE( _parent, _vendor, _avpname, _pos, _min, _max, _ord ) {		\
+				struct dict_object * _avp = NULL;						\
+				struct dict_avp_request _req = { (_vendor), 0, (_avpname) };			\
+				struct dict_rule_data _data;							\
+				CHECK( 0, fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME_AND_VENDOR, &_req, &_avp, ENOENT));\
+				_data.rule_avp = _avp;								\
+				_data.rule_position = (_pos);							\
+				_data.rule_order = (_ord);							\
+				_data.rule_min = (_min);							\
+				_data.rule_max = (_max);							\
+				CHECK( 0, fd_dict_new ( fd_g_config->cnf_dict, DICT_RULE, &_data , (_parent), NULL ) );	\
+			}
+			
+			ADD_RULE(gavp, 73565, "AVP Test - os", RULE_OPTIONAL,   -1, -1,  0);
+			
+		}
+			
+		{
+			struct dict_object  * application = NULL;
+			struct dict_object  * command = NULL;
+			struct dict_cmd_data  cmd_data = { 73573, "Test-Command-Request", CMD_FLAG_REQUEST, CMD_FLAG_REQUEST };
+			
+			CHECK( 0, fd_dict_search ( fd_g_config->cnf_dict, DICT_APPLICATION, APPLICATION_BY_NAME, "Application test", &application, ENOENT ) );
+			CHECK( 0, fd_dict_new ( fd_g_config->cnf_dict, DICT_COMMAND, &cmd_data , application, &command ) );
+			ADD_RULE(command, 0,     "AVP Test - no vendor - f32", 	RULE_FIXED_HEAD, -1,  1,  1);
+			ADD_RULE(command, 73565, "AVP Test - i64",		RULE_REQUIRED,   -1, -1,  0);
+			ADD_RULE(command, 73565, "AVP Test - enumi32", 		RULE_OPTIONAL,   -1, -1,  0);
+			ADD_RULE(command, 73565, "AVP Test - os", 		RULE_OPTIONAL,   -1, -1,  0);
+			ADD_RULE(command, 73565, "AVP Test - enumos", 		RULE_OPTIONAL,   -1, -1,  0);
+			ADD_RULE(command, 73565, "AVP Test - grouped", 		RULE_OPTIONAL,   -1, -1,  0);
+		}
+		
+		{
+			struct dict_object  * application = NULL;
+			struct dict_object  * command = NULL;
+			struct dict_cmd_data  cmd_data = { 73573, "Test-Command-Answer", CMD_FLAG_REQUEST, 0 };
+			
+			CHECK( 0, fd_dict_search ( fd_g_config->cnf_dict, DICT_APPLICATION, APPLICATION_BY_NAME, "Application test", &application, ENOENT ) );
+			CHECK( 0, fd_dict_new ( fd_g_config->cnf_dict, DICT_COMMAND, &cmd_data , application, &command ) );
+		}
+		
+		{
+			struct dict_object  * gavp = NULL;
+			struct dict_avp_data  avp_data = { 73574, 73565, "AVP Test - rules", AVP_FLAG_VENDOR, AVP_FLAG_VENDOR, AVP_TYPE_GROUPED };
+			
+			CHECK( 0, fd_dict_new ( fd_g_config->cnf_dict, DICT_AVP, &avp_data , NULL, &gavp ) );
+			
+			ADD_RULE(gavp,     0, "AVP Test - no vendor - f32", RULE_FIXED_HEAD,   0, 1, 1);
+			ADD_RULE(gavp, 73565, "AVP Test - i64", 	    RULE_FIXED_HEAD,  -1, 1, 2);
+			ADD_RULE(gavp, 73565, "AVP Test - enumi32", 	    RULE_FIXED_HEAD,  -1, 1, 3);
+			ADD_RULE(gavp, 73565, "AVP Test - os", 	    	    RULE_REQUIRED,     2, 3, 0);
+			ADD_RULE(gavp, 73565, "AVP Test - enumos",     	    RULE_OPTIONAL,     0, 1, 0);
+			ADD_RULE(gavp, 73565, "AVP Test - grouped",         RULE_FIXED_TAIL,  -1, 1, 1);
+			/* ABNF : 
+				< no vendor - f32 >
+				< i64 >
+				< enumi32 >
+			    2*3 { os }
+			     *1 [ enumos ]
+				< grouped >
+						*/
+			#if 0
+			fd_log_debug("%s", fd_dict_dump_object(FD_DUMP_TEST_PARAMS, gavp));
+			#endif
+		}
+
+		{ 
+			struct dict_object  * type = NULL;
+			struct dict_type_data type_data = { AVP_TYPE_OCTETSTRING, "OS test2", NULL, NULL, NULL, fd_dictfct_CharInOS_check, "@." };
+			struct dict_avp_data  avp_data = { 73575, 73565, "AVP Test - os2", AVP_FLAG_VENDOR, AVP_FLAG_VENDOR, AVP_TYPE_OCTETSTRING };
+			CHECK( 0, fd_dict_new ( fd_g_config->cnf_dict, DICT_TYPE, &type_data , NULL, &type ) );
+			CHECK( 0, fd_dict_new ( fd_g_config->cnf_dict, DICT_AVP, &avp_data , type, NULL ) );
+		}
+		
+		#if 0
+		{
+			fd_log_debug("%s", fd_dict_dump_object(FD_DUMP_TEST_PARAMS, vendor));
+		}
+		#endif
+	}
+	
+	/* Now create some values and check the length is correctly handled */
+	{
+		struct dict_object * cmd_model = NULL;
+		struct msg         * msg = NULL;
+		struct dict_object * avp_model = NULL;
+		struct avp         * avp = NULL;
+		union avp_value      value;
+		
+		CHECK( 0, fd_dict_search ( fd_g_config->cnf_dict, DICT_COMMAND, CMD_BY_NAME, "Test-Command-Request", &cmd_model, ENOENT ) );
+		
+		/* Check an error is trigged if the AVP has no value set */
+		{
+			CHECK( 0, fd_dict_search ( fd_g_config->cnf_dict, DICT_AVP,     AVP_BY_NAME,     "AVP Test - no vendor - f32", &avp_model, ENOENT ) );
+			
+			CHECK( 0, fd_msg_new ( cmd_model, 0, &msg ) );
+			CHECK( 0, fd_msg_avp_new ( avp_model, 0, &avp ) );
+			
+			CHECK( 0, fd_msg_avp_add ( msg, MSG_BRW_FIRST_CHILD, avp ) );
+			
+			CHECK( EINVAL, fd_msg_update_length ( avp ) );
+			CHECK( EINVAL, fd_msg_update_length ( msg ) );
+			
+			CHECK( 0, fd_msg_free( msg ) );
+		}
+		
+		/* Check the sizes are handled properly */
+		{
+			struct avp * avpi = NULL;
+			struct avp * avpch = NULL;
+			struct avp_hdr * avpdata = NULL;
+			struct msg_hdr * msgdata = NULL;
+			#define ADD_AVP( _parent, _position, _avpi, _avpvendor, _avpname) {			\
+				struct dict_object * _avp = NULL;						\
+				struct dict_avp_request _req = { (_avpvendor), 0, (_avpname) };			\
+				CHECK( 0, fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME_AND_VENDOR, &_req, &_avp, ENOENT));\
+				CHECK( 0, fd_msg_avp_new ( _avp, 0, &_avpi ) );					\
+				CHECK( 0, fd_msg_avp_add ( (_parent), (_position), _avpi ) );			\
+			}
+			/* Create a message with many AVP inside */
+			CHECK( 0, fd_msg_new ( cmd_model, 0, &msg ) );
+			CHECK( 0, fd_msg_hdr ( msg, &msgdata ) );
+			
+			/* Avp no vendor, float32 => size = 12 */
+			ADD_AVP( msg, MSG_BRW_LAST_CHILD, avpi, 0,     "AVP Test - no vendor - f32" );
+			value.f32 = 3.1415;
+			CHECK( 0, fd_msg_avp_setvalue ( avpi, &value ) );
+			CHECK( 0, fd_msg_update_length ( avpi ) );
+			#if 0
+			fd_log_debug("AVP no vendor, value 3.1415:");
+			fd_log_debug("%s", fd_msg_dump_treeview(FD_DUMP_TEST_PARAMS, avpi, fd_g_config->cnf_dict, 0, 0));
+			#endif
+			CHECK( 0, fd_msg_avp_hdr ( avpi, &avpdata ) );
+			CHECK( 12, avpdata->avp_len );
+			
+			/* Check what happens when we delete the value */
+			CHECK( 0, fd_msg_avp_setvalue ( avpi, NULL ) );
+			CHECK( EINVAL, fd_msg_update_length ( avpi ) );
+			CHECK( 0, fd_msg_avp_setvalue ( avpi, &value ) );
+			
+			/* Add a vendor AVP, integer64 => size = 20 */
+			ADD_AVP( msg, MSG_BRW_LAST_CHILD, avpi, 73565, "AVP Test - i64" );
+			value.i64 = 0x123456789abcdeLL;
+			CHECK( 0, fd_msg_avp_setvalue ( avpi, &value ) );
+			CHECK( 0, fd_msg_update_length ( avpi ) );
+			#if 0
+			fd_log_debug("AVP vendor, value 0x123456789abcdeL:");
+			fd_log_debug("%s", fd_msg_dump_treeview(FD_DUMP_TEST_PARAMS, avpi, fd_g_config->cnf_dict, 0, 0));
+			#endif
+			CHECK( 0, fd_msg_avp_hdr ( avpi, &avpdata ) );
+			CHECK( 20, avpdata->avp_len );
+			
+			/* Check the size of the message is 20 (header) + 12 + 20 = 52 */
+			CHECK( 0, fd_msg_update_length ( msg ) );
+			CHECK( 52, msgdata->msg_length );
+			
+			/* Add an AVP with an enum value */
+			ADD_AVP( msg, MSG_BRW_LAST_CHILD, avpi, 73565, "AVP Test - enumi32" );
+			{
+				struct dict_object * type_model = NULL;
+				struct dict_object * value_model = NULL;
+				struct dict_enumval_request request;
+				
+				CHECK( 0, fd_msg_model ( avpi, &avp_model ) );
+				CHECK( 0, fd_dict_search ( fd_g_config->cnf_dict, DICT_TYPE, TYPE_OF_AVP, avp_model, &type_model, ENOENT ) );
+				memset(&request, 0, sizeof(request));
+				request.type_obj = type_model;
+				request.search.enum_name = "i32 const test (val 2)";
+				CHECK( 0, fd_dict_search ( fd_g_config->cnf_dict, DICT_ENUMVAL, ENUMVAL_BY_STRUCT, &request, &value_model, ENOENT ) );
+				CHECK( 0, fd_dict_getval ( value_model, &request.search ) );
+				CHECK( 0, fd_msg_avp_setvalue ( avpi, &request.search.enum_value ) );
+				#if 0
+				fd_log_debug("AVP enum i32, value 2 (from const):");
+				fd_log_debug("%s", fd_msg_dump_treeview(FD_DUMP_TEST_PARAMS, avpi, fd_g_config->cnf_dict, 0, 0));
+				#endif
+			}
+			
+			/* Add an AVP with an enum value, negative */
+			ADD_AVP( msg, MSG_BRW_LAST_CHILD, avpi, 73565, "AVP Test - enumi32" );
+			{
+				struct dict_object  * type_model = NULL;
+				struct dict_object  * value_model = NULL;
+				struct dict_enumval_request request;
+				
+				CHECK( 0, fd_msg_model ( avpi, &avp_model ) );
+				CHECK( 0, fd_dict_search ( fd_g_config->cnf_dict, DICT_TYPE, TYPE_OF_AVP, avp_model, &type_model, ENOENT ) );
+				memset(&request, 0, sizeof(request));
+				request.type_obj = type_model;
+				request.search.enum_name = "i32 const test (val -5)";
+				CHECK( 0, fd_dict_search ( fd_g_config->cnf_dict, DICT_ENUMVAL, ENUMVAL_BY_STRUCT, &request, &value_model, ENOENT ) );
+				CHECK( 0, fd_dict_getval ( value_model, &request.search ) );
+				CHECK( 0, fd_msg_avp_setvalue ( avpi, &request.search.enum_value ) );
+				#if 0
+				fd_log_debug("AVP enum i32, value -5 (from const):");
+				fd_log_debug("%s", fd_msg_dump_treeview(FD_DUMP_TEST_PARAMS, avpi, fd_g_config->cnf_dict, 0, 0));
+				#endif
+				/* Check the size is correct ( 12 for header + 4 for value ) */
+				CHECK( 0, fd_msg_update_length ( avpi ) );
+				CHECK( 0, fd_msg_avp_hdr ( avpi, &avpdata ) );
+				CHECK( 16, avpdata->avp_len );
+			}
+			
+			/* Now add a value which is not a constant into an enumerated AVP */
+			ADD_AVP( msg, MSG_BRW_LAST_CHILD, avpi, 73565, "AVP Test - enumi32" );
+			value.i32 = -10;
+			CHECK( 0, fd_msg_avp_setvalue ( avpi, &value ) );
+			CHECK( 0, fd_msg_update_length ( avpi ) );
+			#if 0
+			fd_log_debug("AVP vendor enum i32, value -10 (not const):");
+			fd_log_debug("%s", fd_msg_dump_treeview(FD_DUMP_TEST_PARAMS, avpi, fd_g_config->cnf_dict, 0, 0));
+			#endif
+			
+			/* Add an octetstring AVP */
+			ADD_AVP( msg, MSG_BRW_LAST_CHILD, avpi, 73565, "AVP Test - os" );
+			{
+				unsigned char buf[90];
+				memcpy(&buf, "This\0 is a buffer of dat\a. It is not a string so we can have any c\0ntr\0l character here...\0\0", 89);
+				value.os.data = buf;
+				value.os.len = 89;
+				CHECK( 0, fd_msg_avp_setvalue ( avpi, &value ) );
+				memset(&buf, 0, sizeof(buf)); /* Test that the OS value is really copied */
+				CHECK( 0, fd_msg_update_length ( avpi ) );
+				#if 0
+				fd_log_debug("AVP octet string, 'This\\0 is a b...'");
+				fd_log_debug("%s", fd_msg_dump_treeview(FD_DUMP_TEST_PARAMS, avpi, fd_g_config->cnf_dict, 0, 0));
+				#endif
+				CHECK( 0, fd_msg_avp_hdr ( avpi, &avpdata ) );
+				CHECK( 101, avpdata->avp_len );
+				CHECK( 'T', avpdata->avp_value->os.data[0] );
+				CHECK( 'i', avpdata->avp_value->os.data[6] );
+			}
+
+			/* Check the size of the message is 20 (header) + 12 + 20 + 16 * 3 + 101 + 3 (padding) = 204 */
+			CHECK( 0, fd_msg_update_length ( msg ) );
+			CHECK( 204, msgdata->msg_length );
+			
+			/* Add an octetstring from an enumerated constant */
+			ADD_AVP( msg, MSG_BRW_LAST_CHILD, avpi, 73565, "AVP Test - enumos" );
+			{
+				struct dict_object  * type_model = NULL;
+				struct dict_object  * value_model = NULL;
+				struct dict_enumval_request request;
+				
+				CHECK( 0, fd_msg_model ( avpi, &avp_model ) );
+				CHECK( 0, fd_dict_search ( fd_g_config->cnf_dict, DICT_TYPE, TYPE_OF_AVP, avp_model, &type_model, ENOENT ) );
+				memset(&request, 0, sizeof(request));
+				request.type_obj = type_model;
+				request.search.enum_name = "os const test (waaad)";
+				CHECK( 0, fd_dict_search ( fd_g_config->cnf_dict, DICT_ENUMVAL, ENUMVAL_BY_STRUCT, &request, &value_model, ENOENT ) );
+				CHECK( 0, fd_dict_getval ( value_model, &request.search ) );
+				CHECK( 0, fd_msg_avp_setvalue ( avpi, &request.search.enum_value ) );
+				#if 0
+				fd_log_debug("AVP Enumuerated OctetString (from const):");
+				fd_log_debug("%s", fd_msg_dump_treeview(FD_DUMP_TEST_PARAMS, avpi, fd_g_config->cnf_dict, 0, 0));
+				#endif
+				/* Check the size is correct ( 12 for header + 5 for value ) */
+				CHECK( 0, fd_msg_update_length ( avpi ) );
+				CHECK( 0, fd_msg_avp_hdr ( avpi, &avpdata ) );
+				CHECK( 17, avpdata->avp_len );
+			}
+				
+			/* Add an octetstring from an enumerated constant */
+			ADD_AVP( msg, MSG_BRW_LAST_CHILD, avpi, 73565, "AVP Test - enumos" );
+			{
+				struct dict_object  * type_model = NULL;
+				struct dict_object  * value_model = NULL;
+				struct dict_enumval_request request;
+				
+				CHECK( 0, fd_msg_model ( avpi, &avp_model ) );
+				CHECK( 0, fd_dict_search ( fd_g_config->cnf_dict, DICT_TYPE, TYPE_OF_AVP, avp_model, &type_model, ENOENT ) );
+				memset(&request, 0, sizeof(request));
+				request.type_obj = type_model;
+				request.search.enum_name = "os const test (waa)";
+				CHECK( 0, fd_dict_search ( fd_g_config->cnf_dict, DICT_ENUMVAL, ENUMVAL_BY_STRUCT, &request, &value_model, ENOENT ) );
+				CHECK( 0, fd_dict_getval ( value_model, &request.search ) );
+				CHECK( 0, fd_msg_avp_setvalue ( avpi, &request.search.enum_value ) );
+				#if 0
+				fd_log_debug("AVP Enumuerated OctetString (from const):");
+				fd_log_debug("%s", fd_msg_dump_treeview(FD_DUMP_TEST_PARAMS, avpi, fd_g_config->cnf_dict, 0, 0));
+				#endif
+				/* Check the size is correct ( 12 for header + 3 for value ) */
+				CHECK( 0, fd_msg_update_length ( avpi ) );
+				CHECK( 0, fd_msg_avp_hdr ( avpi, &avpdata ) );
+				CHECK( 15, avpdata->avp_len );
+			}
+				
+
+			/* Check the size of the message is 20 (header) + 12 + 20 + 16 * 3 + (101 + 3) + (17 + 3) + (15 + 1) = 240 */
+			CHECK( 0, fd_msg_update_length ( msg ) );
+			CHECK( 240, msgdata->msg_length );
+			
+			/* Now test the grouped AVPs */	
+			ADD_AVP( msg, MSG_BRW_LAST_CHILD, avpi, 73565, "AVP Test - grouped" );
+			  ADD_AVP( avpi, MSG_BRW_LAST_CHILD, avpch, 73565, "AVP Test - os" );
+			  {
+				value.os.data = (unsigned char *)"12345678";
+				value.os.len = 8;
+				CHECK( 0, fd_msg_avp_setvalue ( avpch, &value ) );
+				#if 0
+				fd_log_debug("AVP octet string, '1234678'");
+				fd_log_debug("%s", fd_msg_dump_treeview(FD_DUMP_TEST_PARAMS, avpch, fd_g_config->cnf_dict, 0, 0));
+				#endif
+				CHECK( 0, fd_msg_update_length ( avpch ) );
+				CHECK( 0, fd_msg_avp_hdr ( avpch, &avpdata ) );
+				CHECK( 20, avpdata->avp_len );
+			  }
+			  ADD_AVP( avpi, MSG_BRW_LAST_CHILD, avpch, 73565, "AVP Test - os" );
+			  {
+				value.os.data = (unsigned char *)"123456789";
+				value.os.len = 9;
+				CHECK( 0, fd_msg_avp_setvalue ( avpch, &value ) );
+				#if 0
+				fd_log_debug("AVP octet string, '12346789'");
+				fd_log_debug("%s", fd_msg_dump_treeview(FD_DUMP_TEST_PARAMS, avpch, fd_g_config->cnf_dict, 0, 0));
+				#endif
+			  }
+			
+			/* Check the size is updated recursively: (gavp hdr: 12) + (avp1: 20) + (avp2: 21 + 3) = 56 */
+			CHECK( 0, fd_msg_update_length ( avpi ) );
+			CHECK( 0, fd_msg_avp_hdr ( avpi, &avpdata ) );
+			CHECK( 56, avpdata->avp_len );
+			
+			/* Add another similar grouped AVP, to have lot of padding */
+			ADD_AVP( msg, MSG_BRW_LAST_CHILD, avpi, 73565, "AVP Test - grouped" );
+			  ADD_AVP( avpi, MSG_BRW_LAST_CHILD, avpch, 73565, "AVP Test - os" );
+			  {
+				value.os.data = (unsigned char *)"1";
+				value.os.len = 1;
+				CHECK( 0, fd_msg_avp_setvalue ( avpch, &value ) );
+			  }
+			  ADD_AVP( avpi, MSG_BRW_LAST_CHILD, avpch, 73565, "AVP Test - os" );
+			  {
+				value.os.data = (unsigned char *)"1234567";
+				value.os.len = 7;
+				CHECK( 0, fd_msg_avp_setvalue ( avpch, &value ) );
+			  }
+			
+			/* Now check the global size of the message, if padding is correctly handled */
+			/* size = 20 (header) + 12 + 20 + 16 * 3 + (101 + 3) + (17 + 3) + (15 + 1) 
+			 *        + ( 12 + ( 20 + 21) + 3 )         # padding for the grouped AVP = 3
+			 *        + ( 12 + ( (13 + 3) + 19 ) + 1 )  # and 1 for this one
+			 * size = 240 + 56 + 48 = 344
+			 */
+			CHECK( 0, fd_msg_update_length ( msg ) );
+			#if 0
+			fd_log_debug("%s", fd_msg_dump_treeview(FD_DUMP_TEST_PARAMS, msg, fd_g_config->cnf_dict, 0, 1));
+			#endif
+			CHECK( 344, msgdata->msg_length );
+			
+			/* Set the application to the test application: 73566 */
+			msgdata->msg_appl = 73566;
+			
+			/* Set the hop-by-hop ID to a random value: 0x4b44b41d */
+			msgdata->msg_hbhid = 0x4b44b41d;
+			/* Set the end-to-end ID to a random value: 0xe2ee2e1d */
+			msgdata->msg_eteid = 0xe2ee2e1d;
+		}
+		
+		/* Test the msg_bufferize function */
+		{
+			
+			CHECK( 0, fd_msg_bufferize( msg, &buf, NULL ) );
+			
+			/* Test the first bytes */
+			CHECK( 0x01, buf[0] ); /* Version */
+			CHECK( 0x00, buf[1] ); /* Length: 344 = 0x000158 */
+			CHECK( 0x01, buf[2] );
+			CHECK( 0x58, buf[3] );
+			CHECK( 0x80, buf[4] ); /* flags: only "R" is set. */
+			CHECK( 0x01, buf[5] ); /* Command code: 73573 = 0x011F65 */
+			CHECK( 0x1F, buf[6] );
+			CHECK( 0x65, buf[7] );
+			CHECK( 0x00, buf[8] ); /* App ID: 73566 = 0x00011F5E */
+			CHECK( 0x01, buf[9] ); 
+			CHECK( 0x1F, buf[10] );
+			CHECK( 0x5E, buf[11] );
+			CHECK( 0x4b, buf[12] ); /* hop-by-hop id: 0x4b44b41d */
+			CHECK( 0x44, buf[13] );
+			CHECK( 0xb4, buf[14] );
+			CHECK( 0x1d, buf[15] );
+			CHECK( 0xe2, buf[16] ); /* end-to-end id: 0xe2ee2e1d */
+			CHECK( 0xee, buf[17] );
+			CHECK( 0x2e, buf[18] );
+			CHECK( 0x1d, buf[19] );
+			
+			CHECK( 0x00, buf[20] ); /* First AVP (AVP Test - no vendor - f32) begin: code 73567 = 0x00011F5F */
+			CHECK( 0x01, buf[21] );
+			CHECK( 0x1F, buf[22] );
+			CHECK( 0x5F, buf[23] );
+			CHECK( 0x00, buf[24] ); /* flags: 0 */
+			CHECK( 0x00, buf[25] ); /* length: 12 = 0x00000c */
+			CHECK( 0x00, buf[26] );
+			CHECK( 0x0C, buf[27] );
+			CHECK( 0x40, buf[28] ); /* Value: 3.1415:  sign = '+' => most significant bit = 0 */
+			CHECK( 0x49, buf[29] ); /* 2 <= 3.1415 < 4 => exponent = 1 => biaised (on 8 bits) = (decimal) 128 = (binary) 100 0000 0 */
+			CHECK( 0x0e, buf[30] ); /* significand = (decimal) 1.57075 = (binary) 1.100 1001 0000 1110 0101 0110 */
+			CHECK( 0x56, buf[31] ); /* total => 0100 0000 0100 1001 0000 1110 0101 0110 = (hexa) 40 49 0e 56*/
+			
+			/* The other AVPs will be tested by successful parsing... */
+		}
+		
+		/* Now free the message, we keep only the buffer. */
+		CHECK( 0, fd_msg_free( msg ) );
+		
+	}
+	
+	/* Test the parsing of buffers and messages */
+	{
+		unsigned char * buf_cpy = NULL;
+		struct msg * msg;
+		
+		#define CPYBUF() {			\
+			buf_cpy = malloc(344);		\
+			CHECK( buf_cpy ? 1 : 0, 1);	\
+			memcpy(buf_cpy, buf, 344);	\
+		}
+		
+		/* Test the msg_parse_buffer function */
+		{
+			CPYBUF();
+			CHECK( EBADMSG, fd_msg_parse_buffer( &buf_cpy, 340, &msg) );
+			
+			CPYBUF();
+			CHECK( 0, fd_msg_parse_buffer( &buf_cpy, 344, &msg) );
+			#if 0
+			fd_log_debug("%s", fd_msg_dump_treeview(FD_DUMP_TEST_PARAMS, msg, fd_g_config->cnf_dict, 0, 1));
+			#endif
+			
+			/* reinit the msg */
+			CHECK( 0, fd_msg_free ( msg ) );
+				
+		}
+		
+		/* Test the fd_msg_search_avp function */
+		{
+			struct dict_object * avp_model;
+			struct avp 	   * found;
+			struct avp_hdr     * avpdata = NULL;
+			
+			/* Now find the ACR dictionary object */
+			CHECK( 0, fd_dict_search ( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "AVP Test - no vendor - f32", &avp_model, ENOENT ) );
+			
+			CPYBUF();
+			CHECK( 0, fd_msg_parse_buffer( &buf_cpy, 344, &msg) );
+			
+			/* Search this AVP instance in the msg */
+			CHECK( 0, fd_msg_search_avp( msg, avp_model, &found ) );
+			
+			/* Check the AVP value is 3.1415 */
+			CHECK( 0, fd_msg_avp_hdr ( found, &avpdata ) );
+			CHECK( 3.1415F, avpdata->avp_value->f32 );
+			
+			/* reinit the msg */
+			CHECK( 0, fd_msg_free ( msg ) );
+				
+		}
+		
+		/* Test the msg_parse_dict function */
+		{
+			/* Test with an unknown command code */
+			{
+				CPYBUF();
+				
+				/* Change the command-code */
+				buf_cpy[5] = 0x11;
+				CHECK( 0, fd_msg_parse_buffer( &buf_cpy, 344, &msg) );
+				CHECK( ENOTSUP, fd_msg_parse_dict( msg, fd_g_config->cnf_dict, NULL ) );
+				
+				/* reset */
+				CHECK( 0, fd_msg_free ( msg ) );
+			}
+			
+			/* Test with an unknown Mandatory AVP */
+			{
+				CPYBUF();
+				
+				buf_cpy[20] = 0x11;	/* New AVP code = 0x11011F5F, undefined */
+				buf_cpy[24] = 0x40; 	/* Add the 'M' flag */
+				
+				/* Check that we cannot support this message now */
+				CHECK( 0, fd_msg_parse_buffer( &buf_cpy, 344, &msg) );
+				CHECK( ENOTSUP, fd_msg_parse_dict( msg, fd_g_config->cnf_dict, NULL ) );
+				
+				/* reset */
+				CHECK( 0, fd_msg_free ( msg ) );
+			}
+			
+			/* Test with an unknown optional AVP */
+			{
+				CPYBUF();
+				
+				buf_cpy[20] = 0x11;	/* New AVP code = 0x11011F5F, undefined */
+				
+				/* Check that we can support this message now */
+				CHECK( 0, fd_msg_parse_buffer( &buf_cpy, 344, &msg) );
+				CHECK( 0, fd_msg_parse_dict( msg, fd_g_config->cnf_dict, NULL ) );
+				
+				#if 0
+				fd_log_debug("%s", fd_msg_dump_treeview(FD_DUMP_TEST_PARAMS, msg, fd_g_config->cnf_dict, 0, 1));
+				#endif
+				
+				/* reset */
+				CHECK( 0, fd_msg_free ( msg ) );
+			}
+			
+			/* Test with an invalid AVP (definition mismatch with the dictionary) */
+			{
+				CPYBUF();
+				
+				buf_cpy[21] = 0x02;	/* New AVP code = 0x00021F5F, f64 type in the dictionary */
+				
+				
+				/* Check that we cannot support this message now */
+				CHECK( 0, fd_msg_parse_buffer( &buf_cpy, 344, &msg) );
+				CHECK( EBADMSG, fd_msg_parse_dict( msg, fd_g_config->cnf_dict, NULL ) );
+				
+				/* reset */
+				CHECK( 0, fd_msg_free ( msg ) );
+			}
+			
+			/* Test with a type verifier */
+			{
+				struct fd_pei error_info;
+				CPYBUF();
+				buf_cpy[103] = 0x67;	/* Replaced AVP code = 0x00011F67, OS test2 type in the dictionary */
+				
+				/* Check that we cannot support this message now */
+				CHECK( 0, fd_msg_parse_buffer( &buf_cpy, 344, &msg) );
+				CHECK( EBADMSG, fd_msg_parse_dict( msg, fd_g_config->cnf_dict, NULL ) );
+				
+				/* reset */
+				CHECK( 0, fd_msg_free ( msg ) );
+
+				CPYBUF();
+				buf_cpy[103] = 0x67;	/* Replaced AVP code = 0x00011F67, OS test2 type in the dictionary */
+				
+				/* Check error reporting works */
+				CHECK( 0, fd_msg_parse_buffer( &buf_cpy, 344, &msg) );
+				CHECK( EBADMSG, fd_msg_parse_dict( msg, fd_g_config->cnf_dict, &error_info ) );
+				
+				#if 1
+				fd_log_debug("Error reported: %s\n in AVP: %s", error_info.pei_message, fd_msg_dump_treeview(FD_DUMP_TEST_PARAMS, error_info.pei_avp, fd_g_config->cnf_dict, 0, 1));
+				#endif
+				
+				/* reset */
+				CHECK( 0, fd_msg_free ( msg ) );
+				
+				CPYBUF();
+				buf_cpy[103] = 0x67;	/* Replaced AVP code = 0x00011F67, OS test2 type in the dictionary */
+				buf_cpy[130] = '@';
+				buf_cpy[140] = '.';     /* now we comply to the constraints */
+				
+				/* Check that we cannot support this message now */
+				CHECK( 0, fd_msg_parse_buffer( &buf_cpy, 344, &msg) );
+				CHECK( 0, fd_msg_parse_dict( msg, fd_g_config->cnf_dict, NULL ) );
+				
+				/* reset */
+				CHECK( 0, fd_msg_free ( msg ) );
+				
+				
+			}
+			
+			{
+				unsigned char * buftmp = NULL;
+				struct msg * error;
+				/* Check the parse or error works as expected */
+				CPYBUF();
+				
+				buf_cpy[21] = 0x02;	/* New AVP code = 0x00021F5F, f64 type in the dictionary */
+				
+				/* Check that we cannot support this message now */
+				CHECK( 0, fd_msg_init() );
+				CHECK( 0, fd_msg_parse_buffer( &buf_cpy, 344, &msg) );
+				CHECK( EBADMSG, fd_msg_parse_or_error( &msg, &error ) );
+				CHECK( NULL, msg );
+				msg = error;
+				
+				CHECK( 0, fd_msg_bufferize( msg, &buftmp, NULL ) );				
+				
+				fd_log_debug("%s", fd_msg_dump_treeview(FD_DUMP_TEST_PARAMS, msg, fd_g_config->cnf_dict, 0, 1));
+				
+				TODO("Check the Failed-AVP is as expected");
+				
+				
+				/* reset */
+				CHECK( 0, fd_msg_free ( msg ) );
+				free(buftmp);
+			}
+			
+			
+			CHECK( 0, fd_msg_parse_buffer( &buf, 344, &msg) );
+			CHECK( 0, fd_msg_parse_dict( msg, fd_g_config->cnf_dict, NULL ) );
+			#if 0
+			fd_log_debug("%s", fd_msg_dump_treeview(FD_DUMP_TEST_PARAMS, msg, fd_g_config->cnf_dict, 0, 1));
+			#endif
+		}
+		
+		/* Now test the msg_parse_rule function */
+		{
+			struct fd_pei pei;
+			
+			CHECK( 0, fd_msg_parse_rules( msg, fd_g_config->cnf_dict, &pei ) );
+			
+			/* Use the "AVP Test - rules" AVP to test the rules */
+			{
+				struct avp * tavp = NULL;
+				struct avp * tempavp = NULL;
+				struct avp * childavp = NULL;
+				
+				ADD_AVP( msg, MSG_BRW_LAST_CHILD, tavp, 73565, "AVP Test - rules" );
+				
+				/* Create a conforming message first */
+				ADD_AVP( tavp, MSG_BRW_LAST_CHILD, childavp,     0, "AVP Test - no vendor - f32" );
+				ADD_AVP( tavp, MSG_BRW_LAST_CHILD, childavp, 73565, "AVP Test - i64" );
+				ADD_AVP( tavp, MSG_BRW_LAST_CHILD, childavp, 73565, "AVP Test - enumi32" );
+				ADD_AVP( tavp, MSG_BRW_LAST_CHILD, childavp, 73565, "AVP Test - os" );
+				ADD_AVP( tavp, MSG_BRW_LAST_CHILD, childavp, 73565, "AVP Test - os" );
+				ADD_AVP( tavp, MSG_BRW_LAST_CHILD, childavp, 73565, "AVP Test - grouped" );
+				
+				/* Check the message is still conform */
+				CHECK( 0, fd_msg_parse_rules( msg, fd_g_config->cnf_dict, &pei ) );
+				
+				/* The first avp is optional in fixed position, so remove it and check the message is still OK */
+				CHECK( 0, fd_msg_browse ( tavp, MSG_BRW_FIRST_CHILD, &childavp, NULL) );
+				CHECK( 0, fd_msg_free ( childavp ) );
+				CHECK( 0, fd_msg_parse_rules( msg, fd_g_config->cnf_dict, &pei ) );
+				ADD_AVP( tavp, MSG_BRW_FIRST_CHILD, childavp,     0, "AVP Test - no vendor - f32" );
+				
+				
+				/* Now break some rules and check it is detected */
+				#define CHECK_CONFLICT( _msg, _error, _conflictavp_name, _conflictavp_vnd )		{	\
+					struct fd_pei _pei;									\
+					CHECK( EBADMSG,  fd_msg_parse_rules( _msg, fd_g_config->cnf_dict, &_pei ) );		\
+					if (_error) {										\
+						CHECK( 0, strcmp( _error, _pei.pei_errcode ) );					\
+					}											\
+					if ((_conflictavp_name) == NULL) {							\
+						CHECK( NULL, _pei.pei_avp);							\
+					} else {										\
+						struct dict_avp_request _req = { (_conflictavp_vnd), 0, (_conflictavp_name) };	\
+						struct dict_object *    _avp;							\
+						struct dict_object * _conflict;							\
+						CHECK( 1, (_pei.pei_avp) ? 1 : 0 );						\
+						CHECK( 0, fd_msg_model( _pei.pei_avp, &_conflict ) );				\
+						CHECK( 0, fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME_AND_VENDOR, &_req, &_avp, ENOENT));	\
+						CHECK( _avp, _conflict );							\
+					}											\
+				}
+
+			/* ABNF : 
+				< no vendor - f32 >
+				< i64 >
+				< enumi32 >
+			    2*3 { os }
+			     *1 [ enumos ]
+				< grouped >
+						*/
+				{
+					/* Test the FIXED_HEAD rules positions: add another AVP before the third */
+					CHECK( 0, fd_msg_browse ( tavp, MSG_BRW_FIRST_CHILD, &tempavp, NULL) ); /* tempavp is the novendor avp */
+					CHECK( 0, fd_msg_browse ( tempavp, MSG_BRW_NEXT, &tempavp, NULL) );     /* tempavp is the i64 avp */
+					ADD_AVP( tempavp, MSG_BRW_NEXT, childavp, 73565, "AVP Test - os" );
+					
+					CHECK_CONFLICT( msg, "DIAMETER_MISSING_AVP", "AVP Test - enumi32", 73565 );
+					
+					/* Now remove this AVP */
+					CHECK( 0, fd_msg_free ( childavp ) );
+				}
+				{
+					/* Remove the third AVP, same rule must conflict */
+					CHECK( 0, fd_msg_browse ( tempavp, MSG_BRW_NEXT, &childavp, NULL) );     /* childavp is the enumi32 avp */
+					CHECK( 0, fd_msg_free ( childavp ) );
+					
+					CHECK_CONFLICT( msg, "DIAMETER_MISSING_AVP", "AVP Test - enumi32", 73565 );
+					
+					/* Add the AVP back */
+					ADD_AVP( tempavp, MSG_BRW_NEXT, childavp, 73565, "AVP Test - enumi32" );
+				}
+				
+				{
+					/* Test the minimum value in the REQUIRED rule: delete one of the os AVPs */
+					CHECK( 0, fd_msg_browse ( childavp, MSG_BRW_NEXT, &tempavp, NULL) );     /* tempavp is the os avp */
+					CHECK( 0, fd_msg_free ( tempavp ) );
+					
+					CHECK_CONFLICT( msg, "DIAMETER_MISSING_AVP", "AVP Test - os", 73565 ); /* The rule requires at least 2 AVP, we have only 1 */
+					
+					/* Now add this AVP */
+					ADD_AVP( childavp, MSG_BRW_NEXT, tempavp, 73565, "AVP Test - os" );
+				}
+				{
+					/* Test the maximum value in the REQUIRED rule: add more of the os AVPs */
+					ADD_AVP( childavp, MSG_BRW_NEXT, tempavp, 73565, "AVP Test - os" );
+					ADD_AVP( childavp, MSG_BRW_NEXT, tempavp, 73565, "AVP Test - os" );
+					
+					CHECK_CONFLICT( msg, "DIAMETER_AVP_OCCURS_TOO_MANY_TIMES", "AVP Test - os", 73565 ); /* The rule requires at most 3 AVP, we have 4 */
+					
+					/* Now delete these AVP */
+					CHECK( 0, fd_msg_free ( tempavp ) );
+					CHECK( 0, fd_msg_browse ( childavp, MSG_BRW_NEXT, &tempavp, NULL) );
+					CHECK( 0, fd_msg_free ( tempavp ) );
+				}
+				
+				{
+					/* Test the maximum value in the OPTIONAL rule: add 2 enumos AVPs */
+					ADD_AVP( childavp, MSG_BRW_NEXT, tempavp, 73565, "AVP Test - enumos" );
+					
+					/* The message is still conform */
+					CHECK( 0, fd_msg_parse_rules( msg, fd_g_config->cnf_dict, &pei ) );
+					
+					/* Now break the rule */
+					ADD_AVP( childavp, MSG_BRW_NEXT, tempavp, 73565, "AVP Test - enumos" );
+					
+					CHECK_CONFLICT( msg, "DIAMETER_AVP_OCCURS_TOO_MANY_TIMES", "AVP Test - enumos", 73565 );
+					
+					/* Now delete this AVP */
+					CHECK( 0, fd_msg_free ( tempavp ) );
+				}
+				
+				{
+					/* Test the RULE_FIXED_TAIL rules positions: add another AVP at the end */
+					ADD_AVP( tavp, MSG_BRW_LAST_CHILD, childavp, 73565, "AVP Test - os" );
+					
+					CHECK_CONFLICT( msg, "DIAMETER_MISSING_AVP", "AVP Test - grouped", 73565 );
+					
+					/* Now remove this AVP */
+					CHECK( 0, fd_msg_free ( childavp ) );
+				}
+			}
+		}
+		
+		/* Test the fd_msg_new_answer_from_req function */
+		{
+			struct dict_object * cmd_model = NULL;
+			struct msg         * msg = NULL;
+			struct avp * pi1, *pi2, *avp;
+			char * host1="host1", * host2="host2";
+			union avp_value      value;
+			struct msg_hdr * msgdata = NULL;
+			
+			CHECK( 0, fd_dict_search ( fd_g_config->cnf_dict, DICT_COMMAND, CMD_BY_NAME, "Test-Command-Request", &cmd_model, ENOENT ) );
+			
+			/* Test default behavior without flags */
+			{ 
+				/* Create a message with some AVPs inside */
+				CHECK( 0, fd_msg_new ( cmd_model, 0, &msg ) );
+				CHECK( 0, fd_msg_hdr ( msg, &msgdata ) );
+				
+				/* Add a session id */
+				CHECK( 0, fd_msg_new_session( msg, (os0_t)"testmsg", strlen("testmsg") ) );
+				
+				/* Create two instances of Proxy-Info */
+				ADD_AVP( msg, MSG_BRW_LAST_CHILD, pi1, 0, "Proxy-Info");
+				ADD_AVP( msg, MSG_BRW_LAST_CHILD, pi2, 0, "Proxy-Info");
+
+				ADD_AVP( pi1, MSG_BRW_LAST_CHILD, avp, 0, "Proxy-State");
+				value.os.data = (os0_t)"ps_pi1";
+				value.os.len = strlen((char *)value.os.data);
+				CHECK( 0, fd_msg_avp_setvalue ( avp, &value ) );
+				
+				ADD_AVP( pi2, MSG_BRW_LAST_CHILD, avp, 0, "Proxy-State");
+				value.os.data = (os0_t)"pi2_state";
+				value.os.len = strlen((char *)value.os.data);
+				CHECK( 0, fd_msg_avp_setvalue ( avp, &value ) );
+				
+				ADD_AVP( pi1, MSG_BRW_FIRST_CHILD, avp, 0, "Proxy-Host");
+				value.os.data = (os0_t)host1;
+				value.os.len = strlen(host1);
+				CHECK( 0, fd_msg_avp_setvalue ( avp, &value ) );
+				
+				ADD_AVP( pi2, MSG_BRW_LAST_CHILD, avp, 0, "Proxy-Host");
+				value.os.data = (os0_t)host2;
+				value.os.len = strlen(host2);
+				CHECK( 0, fd_msg_avp_setvalue ( avp, &value ) );
+				
+				ADD_AVP( pi2, MSG_BRW_LAST_CHILD, avp, 73565, "AVP Test - i64");
+				value.i64 = 0x123456789abcdeLL;
+				CHECK( 0, fd_msg_avp_setvalue ( avp, &value ) );
+				
+				
+				/* Now call the fd_msg_new_answer_from_req function */
+				CHECK( 0, fd_msg_new_answer_from_req ( fd_g_config->cnf_dict, &msg, 0 ) );
+				
+				/* Check there is a Session-Id AVP */
+				{
+					struct session * sess;
+					int new;
+					CHECK( 0, fd_msg_sess_get(fd_g_config->cnf_dict, msg, &sess, &new) );
+					CHECK( 1, sess == NULL ? 0 : 1 );
+					CHECK( 0, new ? 1 : 0 );
+				}
+				
+				/* Check there are two Proxy-Info with the two hosts */
+				{
+					int got_h1 = 0, got_h2=0;
+					CHECK( 0, fd_msg_browse ( msg, MSG_BRW_FIRST_CHILD, &avp, NULL) );
+					while(avp) {
+						struct avp_hdr * avpdata = NULL;
+						CHECK( 0, fd_msg_avp_hdr ( avp, &avpdata ) );
+						if (avpdata->avp_code == AC_PROXY_INFO) {
+							struct avp * iavp;
+							CHECK( 0, fd_msg_browse ( avp, MSG_BRW_FIRST_CHILD, &iavp, NULL) );
+							while(iavp) {
+								struct avp_hdr * iavpdata = NULL;
+								CHECK( 0, fd_msg_avp_hdr ( iavp, &iavpdata ) );
+								if (iavpdata->avp_code == AC_PROXY_HOST) {
+									if (!memcmp(host1, iavpdata->avp_value->os.data, strlen(host1)))
+										got_h1++;
+									if (!memcmp(host2, iavpdata->avp_value->os.data, strlen(host2)))
+										got_h2++;
+								}
+								CHECK( 0, fd_msg_browse ( iavp, MSG_BRW_NEXT, &iavp, NULL) );
+							}
+						}
+						
+						CHECK( 0, fd_msg_browse ( avp, MSG_BRW_NEXT, &avp, NULL) );
+					}
+					
+					CHECK(1, got_h1);
+					CHECK(1, got_h2);
+				}
+				
+				/* Now test the behavior of fd_msg_rescode_set with a grouped AVP */
+				CHECK( 0, fd_msg_rescode_set(msg, "DIAMETER_AVP_OCCURS_TOO_MANY_TIMES", NULL, pi1, 1) );
+				
+				fd_log_debug("%s", fd_msg_dump_treeview(FD_DUMP_TEST_PARAMS, msg, fd_g_config->cnf_dict, 0, 1));
+				
+				TODO("Check the Failed-AVP is as expected");
+			}
+			
+		}
+	}
+	
+	/* Test the msg_avp_value_interpret and msg_avp_value_encode functions. use the Address type and Host-IP-Address AVPs */
+	{
+		struct dict_object * cer_model = NULL;
+		struct msg * cer = NULL;
+		
+		struct dict_object * hia_model = NULL;
+		struct avp *avp4, *avp6;
+		#define TEST_IP4 "192.168.100.101"
+		char buf4[INET_ADDRSTRLEN];
+		#define	TEST_IP6 "1111:2222:3333:4444:1234:5678:9abc:def0"
+		char buf6[INET6_ADDRSTRLEN];
+		
+		struct sockaddr_storage ss;
+		struct sockaddr_in  sin,  *psin;
+		struct sockaddr_in6 sin6, *psin6;
+		
+		/* Find the CER dictionary object */
+		CHECK( 0, fd_dict_search ( fd_g_config->cnf_dict, DICT_COMMAND, CMD_BY_NAME, "Capabilities-Exchange-Request", &cer_model, ENOENT ) );
+
+		/* Now find the Host-IP-Address dictionary object */
+		CHECK( 0, fd_dict_search ( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Host-IP-Address", &hia_model, ENOENT ) );
+
+		/* Create the msg instance */
+		CHECK( 0, fd_msg_new ( cer_model, 0, &cer ) );
+
+		/* Create the avp instances */
+		CHECK( 0, fd_msg_avp_new ( hia_model, 0, &avp4 ) );
+		CHECK( 0, fd_msg_avp_new ( hia_model, 0, &avp6 ) );
+		
+		/* Set the value of the IP avp */
+		sin.sin_family = AF_INET;
+		CHECK( 1, inet_pton( AF_INET, TEST_IP4, &sin.sin_addr.s_addr ) );
+		CHECK( 0, fd_msg_avp_value_encode ( &sin, avp4 ) );
+		
+		/* Set the value of the IP6 avp */
+		sin6.sin6_family = AF_INET6;
+		CHECK( 1, inet_pton( AF_INET6, TEST_IP6, &sin6.sin6_addr.s6_addr ) );
+		CHECK( 0, fd_msg_avp_value_encode ( &sin6, avp6 ) );
+		
+		/* Add these AVPs in the message */
+		CHECK( 0, fd_msg_avp_add( cer, MSG_BRW_LAST_CHILD, avp4) );
+		CHECK( 0, fd_msg_avp_add( cer, MSG_BRW_LAST_CHILD, avp6) );
+		
+		/* Create the buffer for this message */
+		CHECK( 0, fd_msg_bufferize( cer, &buf, NULL ) );
+		
+		/* Now free the message, we keep only the buffer. */
+		CHECK( 0, fd_msg_free( cer ) );
+		
+		/* Check the content of the buffer is correct (skip command header) */
+		CHECK( 0x00, buf[20] ); /* First AVP (IP4) begins: code 257 = 0x00000101 */
+		CHECK( 0x00, buf[21] );
+		CHECK( 0x01, buf[22] );
+		CHECK( 0x01, buf[23] );
+		CHECK( 0x40, buf[24] ); /* flags: M */
+		CHECK( 0x00, buf[25] ); /* length: 8+6 = 0x00000e */
+		CHECK( 0x00, buf[26] );
+		CHECK( 0x0E, buf[27] );
+		CHECK( 0x00, buf[28] ); /* Value: AddressType 1 */
+		CHECK( 0x01, buf[29] ); 
+		CHECK(  192, buf[30] ); /* 192.168.100.101 */
+		CHECK(  168, buf[31] ); 
+		CHECK(  100, buf[32] ); 
+		CHECK(  101, buf[33] );
+		
+		CHECK( 0x00, buf[34] ); /* Padding */
+		CHECK( 0x00, buf[35] );
+		
+		CHECK( 0x00, buf[36] ); /* Second AVP (IP6) begins: code 257 = 0x00000101 */
+		CHECK( 0x00, buf[37] );
+		CHECK( 0x01, buf[38] );
+		CHECK( 0x01, buf[39] );
+		CHECK( 0x40, buf[40] ); /* flags: M */
+		CHECK( 0x00, buf[41] ); /* length: 8+18 = 0x00001a */
+		CHECK( 0x00, buf[42] );
+		CHECK( 0x1A, buf[43] );
+		CHECK( 0x00, buf[44] ); /* Value: AddressType 2 */
+		CHECK( 0x02, buf[45] ); 
+		CHECK( 0x11, buf[46] ); /* 1111:2222:3333:4444:1234:5678:9abc:def0 */
+		CHECK( 0x11, buf[47] ); 
+		CHECK( 0x22, buf[48] ); 
+		CHECK( 0x22, buf[49] );
+		CHECK( 0x33, buf[50] );
+		CHECK( 0x33, buf[51] );
+		CHECK( 0x44, buf[52] );
+		CHECK( 0x44, buf[53] );
+		CHECK( 0x12, buf[54] );
+		CHECK( 0x34, buf[55] );
+		CHECK( 0x56, buf[56] );
+		CHECK( 0x78, buf[57] );
+		CHECK( 0x9a, buf[58] );
+		CHECK( 0xbc, buf[59] );
+		CHECK( 0xde, buf[60] );
+		CHECK( 0xf0, buf[61] );
+		
+		/* Ok, now let's recreate the message */
+		CHECK( 0, fd_msg_parse_buffer( &buf, 64, &cer) );
+		CHECK( 0, fd_msg_parse_dict( cer, fd_g_config->cnf_dict, NULL ) );
+		
+		/* Get the pointers to the first and last AVP */
+		CHECK( 0, fd_msg_browse( cer, MSG_BRW_FIRST_CHILD, &avp4, NULL) );
+		CHECK( 0, fd_msg_browse( cer, MSG_BRW_LAST_CHILD,  &avp6, NULL) );
+		
+		/* Try and interpret the data in the AVPs */
+		CHECK( 0, fd_msg_avp_value_interpret ( avp4, &ss ) );
+		psin = (struct sockaddr_in *)&ss;
+		CHECK( AF_INET, psin->sin_family );
+		CHECK( 0, (inet_ntop( AF_INET, &psin->sin_addr.s_addr, buf4, sizeof(buf4) ) == NULL) ? errno : 0 );
+		CHECK( 0, strcmp( buf4, TEST_IP4 ) );
+		
+		CHECK( 0, fd_msg_avp_value_interpret ( avp6, &ss ) );
+		psin6 = (struct sockaddr_in6 *)&ss;
+		CHECK( AF_INET6, psin6->sin6_family );
+		CHECK( 0, (inet_ntop( AF_INET6, &psin6->sin6_addr.s6_addr, buf6, sizeof(buf6) ) == NULL) ? errno : 0 );
+		CHECK( 0, strcasecmp( buf6, TEST_IP6 ) );
+		
+		/* Ok, it's done */
+		CHECK( 0, fd_msg_free( cer ) );
+	}
+	
+	/* Check proper encoding / decoding for all basic types of AVP */
+	{
+		{
+			struct dict_avp_data avp_data = { 91001, 0, "AVP Test 2 - os", 0, 0, AVP_TYPE_OCTETSTRING };
+			CHECK( 0, fd_dict_new ( fd_g_config->cnf_dict, DICT_AVP, &avp_data , NULL, NULL ) );
+		}
+		{
+			struct dict_avp_data avp_data = { 91002, 0, "AVP Test 2 - i32", 0, 0, AVP_TYPE_INTEGER32 };
+			CHECK( 0, fd_dict_new ( fd_g_config->cnf_dict, DICT_AVP, &avp_data , NULL, NULL ) );
+		}
+		{
+			struct dict_avp_data avp_data = { 91003, 0, "AVP Test 2 - i64", 0, 0, AVP_TYPE_INTEGER64 };
+			CHECK( 0, fd_dict_new ( fd_g_config->cnf_dict, DICT_AVP, &avp_data , NULL, NULL ) );
+		}
+		{
+			struct dict_avp_data avp_data = { 91004, 0, "AVP Test 2 - u32", 0, 0, AVP_TYPE_UNSIGNED32 };
+			CHECK( 0, fd_dict_new ( fd_g_config->cnf_dict, DICT_AVP, &avp_data , NULL, NULL ) );
+		}
+		{
+			struct dict_avp_data avp_data = { 91005, 0, "AVP Test 2 - u64", 0, 0, AVP_TYPE_UNSIGNED64 };
+			CHECK( 0, fd_dict_new ( fd_g_config->cnf_dict, DICT_AVP, &avp_data , NULL, NULL ) );
+		}
+		{
+			struct dict_avp_data avp_data = { 91006, 0, "AVP Test 2 - f32", 0, 0, AVP_TYPE_FLOAT32 };
+			CHECK( 0, fd_dict_new ( fd_g_config->cnf_dict, DICT_AVP, &avp_data , NULL, NULL ) );
+		}
+		{
+			struct dict_avp_data avp_data = { 91007, 0, "AVP Test 2 - f64", 0, 0, AVP_TYPE_FLOAT64 };
+			CHECK( 0, fd_dict_new ( fd_g_config->cnf_dict, DICT_AVP, &avp_data , NULL, NULL ) );
+		}
+		
+		{
+			struct dict_object * cmd_model = NULL;
+			struct msg         * msg = NULL;
+			struct avp         * avp = NULL;
+			union avp_value      value;
+			struct avp         * avpi = NULL;
+			struct avp_hdr     * avpdata = NULL;
+			struct msg_hdr     * msgdata = NULL;
+
+			CHECK( 0, fd_dict_search ( fd_g_config->cnf_dict, DICT_COMMAND, CMD_BY_NAME, "Test-Command-Request", &cmd_model, ENOENT ) );
+
+			/* Create a message */
+			CHECK( 0, fd_msg_new ( cmd_model, 0, &msg ) );
+			CHECK( 0, fd_msg_hdr ( msg, &msgdata ) );
+			
+			ADD_AVP( msg, MSG_BRW_LAST_CHILD, avpi, 0, 	"AVP Test 2 - os" );
+			value.os.data = (unsigned char *) "waaad";
+			value.os.len = 6;
+			CHECK( 0, fd_msg_avp_setvalue ( avpi, &value ) );
+
+			ADD_AVP( msg, MSG_BRW_LAST_CHILD, avpi, 0,	"AVP Test 2 - i32" );
+			value.i32 = 0x123456;
+			CHECK( 0, fd_msg_avp_setvalue ( avpi, &value ) );
+
+			ADD_AVP( msg, MSG_BRW_LAST_CHILD, avpi, 0,	"AVP Test 2 - i32" );
+			value.i32 = -0x123456;
+			CHECK( 0, fd_msg_avp_setvalue ( avpi, &value ) );
+
+			ADD_AVP( msg, MSG_BRW_LAST_CHILD, avpi, 0,	"AVP Test 2 - i64" );
+			value.i64 = 0x11223344556677LL;
+			CHECK( 0, fd_msg_avp_setvalue ( avpi, &value ) );
+
+			ADD_AVP( msg, MSG_BRW_LAST_CHILD, avpi, 0,	"AVP Test 2 - i64" );
+			value.i64 = -0x11223344556677LL;
+			CHECK( 0, fd_msg_avp_setvalue ( avpi, &value ) );
+
+			ADD_AVP( msg, MSG_BRW_LAST_CHILD, avpi, 0,	"AVP Test 2 - u32" );
+			value.u32 = 0xFEDCBA98;
+			CHECK( 0, fd_msg_avp_setvalue ( avpi, &value ) );
+
+			ADD_AVP( msg, MSG_BRW_LAST_CHILD, avpi, 0,	"AVP Test 2 - u64" );
+			value.u64 = 0x123456789abcdef0LL;
+			CHECK( 0, fd_msg_avp_setvalue ( avpi, &value ) );
+
+			ADD_AVP( msg, MSG_BRW_LAST_CHILD, avpi, 0,	"AVP Test 2 - f32" );
+			value.f32 = 2097153.0F;
+			CHECK( 0, fd_msg_avp_setvalue ( avpi, &value ) );
+
+			ADD_AVP( msg, MSG_BRW_LAST_CHILD, avpi, 0,	"AVP Test 2 - f64" );
+			value.f64 = -1099511627777LL;
+			CHECK( 0, fd_msg_avp_setvalue ( avpi, &value ) );
+			
+			/* Ok now bufferize */
+			CHECK( 0, fd_msg_bufferize( msg, &buf, NULL ) );
+			
+			/* Test the first bytes */
+			CHECK( 0x01, buf[0] ); /* Version */
+			CHECK( 0x00, buf[1] ); /* Length: 148 = 0x000094 */
+			CHECK( 0x00, buf[2] );
+			CHECK( 0x94, buf[3] );
+			CHECK( 0x80, buf[4] ); /* flags: only "R" is set. */
+			CHECK( 0x01, buf[5] ); /* Command code: 73573 = 0x011F65 */
+			CHECK( 0x1F, buf[6] );
+			CHECK( 0x65, buf[7] );
+			CHECK( 0x00, buf[8] ); /* App ID */
+			CHECK( 0x01, buf[9] ); 
+			CHECK( 0x1F, buf[10] );
+			CHECK( 0x5E, buf[11] );
+			CHECK( 0x00, buf[12] ); /* hop-by-hop id */
+			CHECK( 0x00, buf[13] );
+			CHECK( 0x00, buf[14] );
+			CHECK( 0x00, buf[15] );
+			CHECK( 0x00, buf[16] ); /* end-to-end id */
+			CHECK( 0x00, buf[17] );
+			CHECK( 0x00, buf[18] );
+			CHECK( 0x00, buf[19] );
+			
+			CHECK( 0x00, buf[20] ); /* First AVP (AVP Test 2 - os) begin: code 91001 = 0x00016379 */
+			CHECK( 0x01, buf[21] );
+			CHECK( 0x63, buf[22] );
+			CHECK( 0x79, buf[23] );
+			CHECK( 0x00, buf[24] ); /* flags: 0 */
+			CHECK( 0x00, buf[25] ); /* length: 14 = 0x00000e */
+			CHECK( 0x00, buf[26] );
+			CHECK( 0x0e, buf[27] );
+			
+			CHECK( 0x77, buf[28] ); /* "waaad\0" + padding */
+			CHECK( 0x61, buf[29] );
+			CHECK( 0x61, buf[30] );
+			CHECK( 0x61, buf[31] );
+			CHECK( 0x64, buf[32] );
+			CHECK( 0x00, buf[33] );
+			CHECK( 0x00, buf[34] );
+			CHECK( 0x00, buf[35] );
+			
+			/* 36 ~ 43 : 2nd AVP header (size at last octet) */
+			CHECK( 0x0c, buf[43] );
+			CHECK( 0x00, buf[44] ); /* 0x123456 stored in integer32 in network byte order */
+			CHECK( 0x12, buf[45] );
+			CHECK( 0x34, buf[46] );
+			CHECK( 0x56, buf[47] );
+			
+			/* 48 ~ 55 : next AVP header */
+			CHECK( 0xff, buf[56] ); /* -0x123456 stored in integer32 in network byte order. */ 
+			CHECK( 0xed, buf[57] ); /* We assume that two's complement is the correct representation, although it's not clearly specified. */
+			CHECK( 0xcb, buf[58] ); /* 00 12 34 56 inversed => FF ED CB A9 */
+			CHECK( 0xaa, buf[59] ); /* then "+1" => FF ED CB AA */
+			
+			/* 60 ~ 67 : next header */
+			CHECK( 0x10, buf[67] ); /* (the size) */
+			CHECK( 0x00, buf[68] ); /* 0x11223344556677 in network byte order */
+			CHECK( 0x11, buf[69] );
+			CHECK( 0x22, buf[70] );
+			CHECK( 0x33, buf[71] );
+			CHECK( 0x44, buf[72] );
+			CHECK( 0x55, buf[73] );
+			CHECK( 0x66, buf[74] );
+			CHECK( 0x77, buf[75] );
+			
+			/* 76 ~ 83 : next header */
+			CHECK( 0xFF, buf[84] ); /*  - 0x11223344556677 (in two's complement) */
+			CHECK( 0xEE, buf[85] ); /* gives FF EE DD CC BB AA 99 89 */
+			CHECK( 0xDD, buf[86] );
+			CHECK( 0xCC, buf[87] );
+			CHECK( 0xBB, buf[88] );
+			CHECK( 0xAA, buf[89] );
+			CHECK( 0x99, buf[90] );
+			CHECK( 0x89, buf[91] );
+			
+			/* 92 ~ 99 : next header */
+			CHECK( 0x0c, buf[99] ); /* (the size) */
+			CHECK( 0xFE, buf[100]); /* 0xFEDCBA98 in network byte order */
+			CHECK( 0xDC, buf[101]);
+			CHECK( 0xBA, buf[102]);
+			CHECK( 0x98, buf[103]);
+			
+			/* 104 ~ 111 : next header */
+			CHECK( 0x10, buf[111] ); /* (the size) */
+			CHECK( 0x12, buf[112]); /* 0x123456789abcdef0LL in network byte order */
+			CHECK( 0x34, buf[113]);
+			CHECK( 0x56, buf[114]);
+			CHECK( 0x78, buf[115]);
+			CHECK( 0x9a, buf[116]);
+			CHECK( 0xbc, buf[117]);
+			CHECK( 0xde, buf[118]);
+			CHECK( 0xf0, buf[119]);
+			
+			/* 120 ~ 127 : next header */
+			CHECK( 0x0c, buf[127] ); /* (the size) */
+			CHECK( 0x4a, buf[128]); /* http://en.wikipedia.org/wiki/IEEE_754-1985 to get descvription of the format */
+			CHECK( 0x00, buf[129]); /* v = 2097153 = 2^21 + 2 ^ 0; sign : "+", 2^21 <= v < 2^22 => exponent = 21; biaised on 8 bits => 21 + 127 => 100 1010 0 */
+			CHECK( 0x00, buf[130]); /* v = (+1) * (1 ^ 21) * ( 1 + 2^-21 ) => significand 000 0000 0000 0000 0000 0100 */
+			CHECK( 0x04, buf[131]); /* result: 4a 00 00 04 */
+			
+			/* 132 ~ 139 : next header */
+			CHECK( 0x10, buf[139] ); /* (the size) */
+			CHECK( 0xc2, buf[140]); /* -1099511627777L ( 2^40 + 1 ) in network byte order */
+			CHECK( 0x70, buf[141]); /* sign: - => most significant bit = 1 */
+			CHECK( 0x00, buf[142]); /* 2^40 <= v < 2^41 => biaised exponent on 11 bits: 1023 + 40: 100 0010  0111 */
+			CHECK( 0x00, buf[143]); /* significand: 1 + 2^-40 => 0000  0000 0000  0000 0000  0000 0000  0000 0000  0001 0000  0000 0000 */
+			CHECK( 0x00, buf[144]); /* result: c2 70 00 00 00 00 10 00 */
+			CHECK( 0x00, buf[145]);
+			CHECK( 0x10, buf[146]);
+			CHECK( 0x00, buf[147]);
+			
+			
+			
+			/* Okay, now delete the message and parse the buffer, then check we obtain the same values back */
+			#if 0
+			fd_log_debug("%s", fd_msg_dump_treeview(FD_DUMP_TEST_PARAMS, msg, fd_g_config->cnf_dict, 0, 1));
+			#endif
+			CHECK( 0, fd_msg_free( msg ) );
+			
+			CHECK( 0, fd_msg_parse_buffer( &buf, 148, &msg) );
+			CHECK( 0, fd_msg_parse_dict( msg, fd_g_config->cnf_dict, NULL ) );
+			#if 0
+			fd_log_debug("%s", fd_msg_dump_treeview(FD_DUMP_TEST_PARAMS, msg, fd_g_config->cnf_dict, 0, 1));
+			#endif
+			
+			CHECK( 0, fd_msg_browse ( msg, MSG_BRW_FIRST_CHILD, &avp, NULL) );
+			CHECK( 0, fd_msg_avp_hdr ( avp, &avpdata ) );
+			CHECK( 6, avpdata->avp_value->os.len );
+			CHECK( 'w', (char)(avpdata->avp_value->os.data[0]) );
+			CHECK( 'a', (char)(avpdata->avp_value->os.data[1]) );
+			CHECK( 'd', (char)(avpdata->avp_value->os.data[4]) );
+			CHECK( '\0', (char)(avpdata->avp_value->os.data[5]) );
+			
+			CHECK( 0, fd_msg_browse ( avp, MSG_BRW_NEXT, &avp, NULL) );
+			CHECK( 0, fd_msg_avp_hdr ( avp, &avpdata ) );
+			CHECK( 0x123456, avpdata->avp_value->i32 );
+			
+			CHECK( 0, fd_msg_browse ( avp, MSG_BRW_NEXT, &avp, NULL) );
+			CHECK( 0, fd_msg_avp_hdr ( avp, &avpdata ) );
+			CHECK( -0x123456, avpdata->avp_value->i32 );
+			
+			CHECK( 0, fd_msg_browse ( avp, MSG_BRW_NEXT, &avp, NULL) );
+			CHECK( 0, fd_msg_avp_hdr ( avp, &avpdata ) );
+			CHECK( 0x11223344556677LL, avpdata->avp_value->i64 );
+			
+			CHECK( 0, fd_msg_browse ( avp, MSG_BRW_NEXT, &avp, NULL) );
+			CHECK( 0, fd_msg_avp_hdr ( avp, &avpdata ) );
+			CHECK( -0x11223344556677LL, avpdata->avp_value->i64 );
+			
+			CHECK( 0, fd_msg_browse ( avp, MSG_BRW_NEXT, &avp, NULL) );
+			CHECK( 0, fd_msg_avp_hdr ( avp, &avpdata ) );
+			CHECK( 0xFEDCBA98, avpdata->avp_value->u32 );
+			
+			CHECK( 0, fd_msg_browse ( avp, MSG_BRW_NEXT, &avp, NULL) );
+			CHECK( 0, fd_msg_avp_hdr ( avp, &avpdata ) );
+			CHECK( 0x123456789abcdef0LL, avpdata->avp_value->u64 );
+			
+			CHECK( 0, fd_msg_browse ( avp, MSG_BRW_NEXT, &avp, NULL) );
+			CHECK( 0, fd_msg_avp_hdr ( avp, &avpdata ) );
+			CHECK( 2097153.0F, avpdata->avp_value->f32 );
+			
+			CHECK( 0, fd_msg_browse ( avp, MSG_BRW_NEXT, &avp, NULL) );
+			CHECK( 0, fd_msg_avp_hdr ( avp, &avpdata ) );
+			CHECK( -1099511627777LL, avpdata->avp_value->f64 );
+			
+			CHECK( 0, fd_msg_free( msg ) );
+		}
+	}
+	
+	/* That's all for the tests yet */
+	PASSTEST();
+} 
+	
diff --git a/tests/testmesg_stress.c b/tests/testmesg_stress.c
new file mode 100644
index 0000000..310a9d2
--- /dev/null
+++ b/tests/testmesg_stress.c
@@ -0,0 +1,689 @@
+/*********************************************************************************************************
+* Software License Agreement (BSD License)                                                               *
+* Author: Sebastien Decugis <sdecugis@freediameter.net>							 *
+*													 *
+* Copyright (c) 2013, WIDE Project and NICT								 *
+* All rights reserved.											 *
+* 													 *
+* Redistribution and use of this software in source and binary forms, with or without modification, are  *
+* permitted provided that the following conditions are met:						 *
+* 													 *
+* * Redistributions of source code must retain the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer.										 *
+*    													 *
+* * Redistributions in binary form must reproduce the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer in the documentation and/or other						 *
+*   materials provided with the distribution.								 *
+* 													 *
+* * Neither the name of the WIDE Project or NICT nor the 						 *
+*   names of its contributors may be used to endorse or 						 *
+*   promote products derived from this software without 						 *
+*   specific prior written permission of WIDE Project and 						 *
+*   NICT.												 *
+* 													 *
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED *
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
+* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR *
+* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 	 *
+* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 	 *
+* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR *
+* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF   *
+* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.								 *
+*********************************************************************************************************/
+
+#include "tests.h"
+#include <dirent.h>
+#include <libgen.h>
+#include <dlfcn.h>
+
+#ifndef BUILD_DIR
+#error "Missing BUILD_DIR information"
+#endif /* BUILD_DIR */
+
+
+/* The number of times each operation is repeated to measure the average operation time */
+#define DEFAULT_NUMBER_OF_SAMPLES	100000
+
+static void display_result(int nr, struct timespec * start, struct timespec * end, char * fct, char * type, char *op)
+{
+	long double dur = (long double)end->tv_sec + (long double)end->tv_nsec/1000000000;
+	dur -= (long double)start->tv_sec + (long double)start->tv_nsec/1000000000;
+	long double thrp = (long double)nr / dur;
+	printf("%-19s: %d %-8s %-7s in %.6LFs (%.1LFmsg/s)\n", fct, nr, type, op, dur, thrp);
+}
+
+struct ext_info {
+	struct fd_list	chain;		/* link in the list */
+	void 		*handler;	/* object returned by dlopen() */
+	int 		(*init_cb)(int, int, char *);
+	char		*ext_name;	/* points to the extension name, either inside depends, or basename(filename) */
+	int		free_ext_name;	/* must be freed if it was malloc'd */
+	const char 	**depends;	/* names of the other extensions this one depends on (if provided) */
+};
+	
+static void load_all_extensions(char * prefix)
+{
+	DIR *dir;
+	struct dirent *dp;
+	char fullname[512];
+	int pathlen;
+	struct fd_list all_extensions = FD_LIST_INITIALIZER(all_extensions);
+	struct fd_list ext_with_depends = FD_LIST_INITIALIZER(ext_with_depends);
+
+	/* Find all extensions which have been compiled along the test */
+	LOG_D("Loading %s*.fdx from: '%s'", BUILD_DIR "/extensions", prefix ?: "");
+	CHECK( 0, (dir = opendir (BUILD_DIR "/extensions")) == NULL ? 1 : 0 );
+	pathlen = snprintf(fullname, sizeof(fullname), BUILD_DIR "/extensions/");
+	
+	while ((dp = readdir (dir)) != NULL) {
+		char * dot = strrchr(dp->d_name, '.');
+		if (dot && ((!prefix) || !(strncmp(dp->d_name, prefix, strlen(prefix)))) && (!(strcmp(dot, ".fdx")))) {
+			/* We found a file with name dict_*.fdx, attempt to load it */
+			struct ext_info * new = malloc(sizeof(struct ext_info));
+			CHECK( 1, new ? 1:0);
+			fd_list_init(&new->chain, new);
+			
+			snprintf(fullname + pathlen, sizeof(fullname) - pathlen, "%s", dp->d_name);
+			
+			LOG_D("Extension: '%s'", dp->d_name);
+			
+			/* load */
+			new->handler = dlopen(fullname, RTLD_NOW | RTLD_GLOBAL);
+			if (!new->handler) {
+				TRACE_DEBUG(INFO, "Unable to load '%s': %s.", fullname, dlerror());
+			}
+			CHECK( 0, new->handler == NULL ? 1 : 0 );
+			
+			/* resolve entry */
+			new->init_cb = dlsym( new->handler, "fd_ext_init" );
+			if (!new->init_cb) {
+				TRACE_DEBUG(INFO, "No 'fd_ext_init' entry point in '%s': %s.", fullname, dlerror());
+			}
+			CHECK( 0, new->init_cb == NULL ? 1 : 0 );
+			
+			new->depends = dlsym( new->handler, "fd_ext_depends" );
+			if (new->depends) {
+				new->ext_name = (char *)new->depends[0];
+				new->free_ext_name = 0;
+				if ( new->depends[1] ) {
+					fd_list_insert_before(&ext_with_depends, &new->chain);
+				} else {
+					fd_list_insert_before(&all_extensions, &new->chain);
+				}
+			} else {
+				new->ext_name = strdup(basename(dp->d_name));
+				new->free_ext_name = 1;
+				fd_list_insert_before(&all_extensions, &new->chain);
+			}
+			
+		}
+	}
+	
+	/* Now, reorder the list by dependencies */
+	{
+		int count, prevcount = 0;
+		struct fd_list * li;
+		do {
+			count = 0;
+			for (li=ext_with_depends.next; li != &ext_with_depends; li=li->next) {
+				struct ext_info * e = li->o;
+				int d;
+				int satisfied=0;
+				
+				/* Can we satisfy all dependencies? */
+				for (d=1;  ;d++) {
+					struct fd_list * eli;
+					if (!e->depends[d]) {
+						satisfied = 1;
+						break;
+					}
+					
+					/* can we find this dependency in the list? */
+					for (eli=all_extensions.next; eli != &all_extensions; eli = eli->next) {
+						struct ext_info * de = eli->o;
+						if (!strcasecmp(de->ext_name, e->depends[d]))
+							break; /* this dependency is satisfied */
+					}
+					
+					if (eli == &all_extensions) {
+						satisfied = 0;
+						break;
+					}
+				}
+				
+				if (satisfied) {
+					/* OK, we have all our dependencies in the list */
+					li=li->prev;
+					fd_list_unlink(&e->chain);
+					fd_list_insert_before(&all_extensions, &e->chain);
+				} else {
+					count++;
+				}
+			}
+			
+			if (prevcount && (prevcount == count)) {
+				LOG_E("Some extensions cannot have their dependencies satisfied, e.g.: %s", ((struct ext_info *)ext_with_depends.next->o)->ext_name);
+				CHECK(0, 1);
+			}
+			prevcount = count;
+			
+			if (FD_IS_LIST_EMPTY(&ext_with_depends))
+				break;
+		} while (1);
+	}
+	
+	/* Now, load all the extensions */
+	{
+		struct fd_list * li;
+		for (li=all_extensions.next; li != &all_extensions; li=li->next) {
+			struct ext_info * e = li->o;
+			int ret = (*e->init_cb)( FD_PROJECT_VERSION_MAJOR, FD_PROJECT_VERSION_MINOR, NULL );
+			LOG_N("Initializing extension '%s': %s", e->ext_name, ret ? strerror(ret) : "Success");
+		}
+	}
+	
+	/* We should probably clean the list here ? */
+}
+
+/* Main test routine */
+int main(int argc, char *argv[])
+{
+	struct msg * acr = NULL;
+	unsigned char * buf = NULL;
+	
+	int dictionaries_loaded = 0;
+	
+	test_parameter = DEFAULT_NUMBER_OF_SAMPLES;
+	
+	/* First, initialize the daemon modules */
+	INIT_FD();
+	CHECK( 0, fd_queues_init()  );
+	CHECK( 0, fd_msg_init()  );
+	CHECK( 0, fd_rtdisp_init()  );
+	
+	
+	{
+		struct dict_object * acr_model = NULL;
+
+		/* Now find the ACR dictionary object */
+		CHECK( 0, fd_dict_search ( fd_g_config->cnf_dict, DICT_COMMAND, CMD_BY_NAME, "Accounting-Request", &acr_model, ENOENT ) );
+
+		/* Create the instance, using the templates */
+		CHECK( 0, fd_msg_new ( acr_model, 0, &acr ) );
+	}
+	
+	/* Now let's create some additional Dictionary objects for the test */
+	{
+		/* The constant values used here are totally arbitrary chosen */
+		struct dict_object * vendor;
+		{
+			struct dict_vendor_data vendor_data = { 73565, "Vendor test" };
+			CHECK( 0, fd_dict_new ( fd_g_config->cnf_dict, DICT_VENDOR, &vendor_data , NULL, &vendor ) );
+		}
+		
+		{
+			struct dict_application_data app_data = { 73566, "Application test" };
+			CHECK( 0, fd_dict_new ( fd_g_config->cnf_dict, DICT_APPLICATION, &app_data , vendor, NULL ) );
+		}
+		
+		{
+			struct dict_avp_data avp_data = { 73567, 0, "AVP Test - no vendor - f32", 0, 0, AVP_TYPE_FLOAT32 };
+			CHECK( 0, fd_dict_new ( fd_g_config->cnf_dict, DICT_AVP, &avp_data , NULL, NULL ) );
+		}
+		
+		{
+			struct dict_avp_data avp_data = { 139103, 0, "AVP Test - no vendor - f64", 0, 0, AVP_TYPE_FLOAT64 };
+			CHECK( 0, fd_dict_new ( fd_g_config->cnf_dict, DICT_AVP, &avp_data , NULL, NULL ) );
+		}
+		
+		{ 
+			struct dict_object  * type = NULL;
+			struct dict_type_data type_data = { AVP_TYPE_INTEGER64, "Int64 test" };
+			struct dict_avp_data  avp_data = { 73568, 73565, "AVP Test - i64", AVP_FLAG_VENDOR, AVP_FLAG_VENDOR, AVP_TYPE_INTEGER64 };
+			CHECK( 0, fd_dict_new ( fd_g_config->cnf_dict, DICT_TYPE, &type_data , NULL, &type ) );
+			CHECK( 0, fd_dict_new ( fd_g_config->cnf_dict, DICT_AVP, &avp_data , type, NULL ) );
+		}
+		
+		{
+			struct dict_object     * type = NULL;
+			struct dict_type_data    type_data = { AVP_TYPE_INTEGER32, "Enum32 test" };
+			struct dict_enumval_data val1 = { "i32 const test (val 1)", { .i32 = 1 } };
+			struct dict_enumval_data val2 = { "i32 const test (val 2)", { .i32 = 2 } };
+			struct dict_enumval_data val3 = { "i32 const test (val -5)",{ .i32 = -5 } };
+			struct dict_avp_data     avp_data = { 73569, 73565, "AVP Test - enumi32", AVP_FLAG_VENDOR, AVP_FLAG_VENDOR, AVP_TYPE_INTEGER32 };
+			
+			CHECK( 0, fd_dict_new ( fd_g_config->cnf_dict, DICT_TYPE, &type_data , NULL, &type ) );
+			CHECK( 0, fd_dict_new ( fd_g_config->cnf_dict, DICT_AVP, &avp_data , type, NULL ) );
+			CHECK( 0, fd_dict_new ( fd_g_config->cnf_dict, DICT_ENUMVAL, &val1 , type, NULL ) );
+			CHECK( 0, fd_dict_new ( fd_g_config->cnf_dict, DICT_ENUMVAL, &val2 , type, NULL ) );
+			CHECK( 0, fd_dict_new ( fd_g_config->cnf_dict, DICT_ENUMVAL, &val3 , type, NULL ) );
+		}
+			
+		{ 
+			struct dict_object  * type = NULL;
+			struct dict_type_data type_data = { AVP_TYPE_OCTETSTRING, "OS test" };
+			struct dict_avp_data  avp_data = { 73570, 73565, "AVP Test - os", AVP_FLAG_VENDOR, AVP_FLAG_VENDOR, AVP_TYPE_OCTETSTRING };
+			CHECK( 0, fd_dict_new ( fd_g_config->cnf_dict, DICT_TYPE, &type_data , NULL, &type ) );
+			CHECK( 0, fd_dict_new ( fd_g_config->cnf_dict, DICT_AVP, &avp_data , type, NULL ) );
+		}
+		
+		{
+			struct dict_object     * type = NULL;
+			struct dict_type_data    type_data = { AVP_TYPE_OCTETSTRING, "OS enum test" };
+			struct dict_enumval_data val1 = { "os const test (Test)", { .os = { (unsigned char *)"Test", 4 } } };
+			struct dict_enumval_data val2 = { "os const test (waaad)", { .os = { (unsigned char *)"waaad", 5 } } };
+			struct dict_enumval_data val3 = { "os const test (waa)", { .os = { (unsigned char *)"waaad", 3 } } };
+			struct dict_avp_data     avp_data = { 73571, 73565, "AVP Test - enumos", AVP_FLAG_VENDOR, AVP_FLAG_VENDOR, AVP_TYPE_OCTETSTRING };
+			
+			CHECK( 0, fd_dict_new ( fd_g_config->cnf_dict, DICT_TYPE, &type_data , NULL, &type ) );
+			CHECK( 0, fd_dict_new ( fd_g_config->cnf_dict, DICT_AVP, &avp_data , type, NULL ) );
+			CHECK( 0, fd_dict_new ( fd_g_config->cnf_dict, DICT_ENUMVAL, &val1 , type, NULL ) );
+			CHECK( 0, fd_dict_new ( fd_g_config->cnf_dict, DICT_ENUMVAL, &val2 , type, NULL ) );
+			CHECK( 0, fd_dict_new ( fd_g_config->cnf_dict, DICT_ENUMVAL, &val3 , type, NULL ) );
+		}
+		
+		{
+			struct dict_object * gavp = NULL;
+			struct dict_avp_data avp_data = { 73572, 73565, "AVP Test - grouped", AVP_FLAG_VENDOR, AVP_FLAG_VENDOR, AVP_TYPE_GROUPED };
+			
+			CHECK( 0, fd_dict_new ( fd_g_config->cnf_dict, DICT_AVP, &avp_data , NULL, &gavp ) );
+			
+			/* Macro to search AVP and create a rule */		
+			#define ADD_RULE( _parent, _vendor, _avpname, _pos, _min, _max, _ord ) {		\
+				struct dict_object * _avp = NULL;						\
+				struct dict_avp_request _req = { (_vendor), 0, (_avpname) };			\
+				struct dict_rule_data _data;							\
+				CHECK( 0, fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME_AND_VENDOR, &_req, &_avp, ENOENT));\
+				_data.rule_avp = _avp;								\
+				_data.rule_position = (_pos);							\
+				_data.rule_order = (_ord);							\
+				_data.rule_min = (_min);							\
+				_data.rule_max = (_max);							\
+				CHECK( 0, fd_dict_new ( fd_g_config->cnf_dict, DICT_RULE, &_data , (_parent), NULL ) );	\
+			}
+			
+			ADD_RULE(gavp, 73565, "AVP Test - os", RULE_OPTIONAL,   -1, -1,  0);
+			
+		}
+			
+		{
+			struct dict_object  * application = NULL;
+			struct dict_object  * command = NULL;
+			struct dict_cmd_data  cmd_data = { 73573, "Test-Command-Request", CMD_FLAG_REQUEST, CMD_FLAG_REQUEST };
+			
+			CHECK( 0, fd_dict_search ( fd_g_config->cnf_dict, DICT_APPLICATION, APPLICATION_BY_NAME, "Application test", &application, ENOENT ) );
+			CHECK( 0, fd_dict_new ( fd_g_config->cnf_dict, DICT_COMMAND, &cmd_data , application, &command ) );
+			ADD_RULE(command, 0,     "AVP Test - no vendor - f32", 	RULE_FIXED_HEAD, -1,  1,  1);
+			ADD_RULE(command, 73565, "AVP Test - i64",		RULE_REQUIRED,   -1, -1,  0);
+			ADD_RULE(command, 73565, "AVP Test - enumi32", 		RULE_OPTIONAL,   -1, -1,  0);
+			ADD_RULE(command, 73565, "AVP Test - os", 		RULE_OPTIONAL,   -1, -1,  0);
+			ADD_RULE(command, 73565, "AVP Test - enumos", 		RULE_OPTIONAL,   -1, -1,  0);
+			ADD_RULE(command, 73565, "AVP Test - grouped", 		RULE_OPTIONAL,   -1, -1,  0);
+		}
+		
+		{
+			struct dict_object  * application = NULL;
+			struct dict_object  * command = NULL;
+			struct dict_cmd_data  cmd_data = { 73573, "Test-Command-Answer", CMD_FLAG_REQUEST, 0 };
+			
+			CHECK( 0, fd_dict_search ( fd_g_config->cnf_dict, DICT_APPLICATION, APPLICATION_BY_NAME, "Application test", &application, ENOENT ) );
+			CHECK( 0, fd_dict_new ( fd_g_config->cnf_dict, DICT_COMMAND, &cmd_data , application, &command ) );
+		}
+		
+		{
+			struct dict_object  * gavp = NULL;
+			struct dict_avp_data  avp_data = { 73574, 73565, "AVP Test - rules", AVP_FLAG_VENDOR, AVP_FLAG_VENDOR, AVP_TYPE_GROUPED };
+			
+			CHECK( 0, fd_dict_new ( fd_g_config->cnf_dict, DICT_AVP, &avp_data , NULL, &gavp ) );
+			
+			ADD_RULE(gavp,     0, "AVP Test - no vendor - f32", RULE_FIXED_HEAD,   0, 1, 1);
+			ADD_RULE(gavp, 73565, "AVP Test - i64", 	    RULE_FIXED_HEAD,  -1, 1, 2);
+			ADD_RULE(gavp, 73565, "AVP Test - enumi32", 	    RULE_FIXED_HEAD,  -1, 1, 3);
+			ADD_RULE(gavp, 73565, "AVP Test - os", 	    	    RULE_REQUIRED,     2, 3, 0);
+			ADD_RULE(gavp, 73565, "AVP Test - enumos",     	    RULE_OPTIONAL,     0, 1, 0);
+			ADD_RULE(gavp, 73565, "AVP Test - grouped",         RULE_FIXED_TAIL,  -1, 1, 1);
+			/* ABNF : 
+				< no vendor - f32 >
+				< i64 >
+				< enumi32 >
+			    2*3 { os }
+			     *1 [ enumos ]
+				< grouped >
+						*/
+		}
+	}
+	
+	/* Now create some values and check the length is correctly handled */
+	{
+		struct dict_object * cmd_model = NULL;
+		struct msg         * msg = NULL;
+		struct dict_object * avp_model = NULL;
+		union avp_value      value;
+		
+		CHECK( 0, fd_dict_search ( fd_g_config->cnf_dict, DICT_COMMAND, CMD_BY_NAME, "Test-Command-Request", &cmd_model, ENOENT ) );
+		
+		/* Check the sizes are handled properly */
+		{
+			struct avp * avpi = NULL;
+			struct avp * avpch = NULL;
+			struct msg_hdr * msgdata = NULL;
+			#define ADD_AVP( _parent, _position, _avpi, _avpvendor, _avpname) {			\
+				struct dict_object * _avp = NULL;						\
+				struct dict_avp_request _req = { (_avpvendor), 0, (_avpname) };			\
+				CHECK( 0, fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME_AND_VENDOR, &_req, &_avp, ENOENT));\
+				CHECK( 0, fd_msg_avp_new ( _avp, 0, &_avpi ) );					\
+				CHECK( 0, fd_msg_avp_add ( (_parent), (_position), _avpi ) );			\
+			}
+			/* Create a message with many AVP inside */
+			CHECK( 0, fd_msg_new ( cmd_model, 0, &msg ) );
+			CHECK( 0, fd_msg_hdr ( msg, &msgdata ) );
+			
+			/* Avp no vendor, float32 => size = 12 */
+			ADD_AVP( msg, MSG_BRW_LAST_CHILD, avpi, 0,     "AVP Test - no vendor - f32" );
+			value.f32 = 3.1415;
+			CHECK( 0, fd_msg_avp_setvalue ( avpi, &value ) );
+			
+			/* Add a vendor AVP, integer64 => size = 20 */
+			ADD_AVP( msg, MSG_BRW_LAST_CHILD, avpi, 73565, "AVP Test - i64" );
+			value.i64 = 0x123456789abcdeLL;
+			CHECK( 0, fd_msg_avp_setvalue ( avpi, &value ) );
+			
+			/* Add an AVP with an enum value */
+			ADD_AVP( msg, MSG_BRW_LAST_CHILD, avpi, 73565, "AVP Test - enumi32" );
+			{
+				struct dict_object * type_model = NULL;
+				struct dict_object * value_model = NULL;
+				struct dict_enumval_request request;
+				
+				CHECK( 0, fd_msg_model ( avpi, &avp_model ) );
+				CHECK( 0, fd_dict_search ( fd_g_config->cnf_dict, DICT_TYPE, TYPE_OF_AVP, avp_model, &type_model, ENOENT ) );
+				memset(&request, 0, sizeof(request));
+				request.type_obj = type_model;
+				request.search.enum_name = "i32 const test (val 2)";
+				CHECK( 0, fd_dict_search ( fd_g_config->cnf_dict, DICT_ENUMVAL, ENUMVAL_BY_STRUCT, &request, &value_model, ENOENT ) );
+				CHECK( 0, fd_dict_getval ( value_model, &request.search ) );
+				CHECK( 0, fd_msg_avp_setvalue ( avpi, &request.search.enum_value ) );
+			}
+			
+			/* Add an AVP with an enum value, negative */
+			ADD_AVP( msg, MSG_BRW_LAST_CHILD, avpi, 73565, "AVP Test - enumi32" );
+			{
+				struct dict_object  * type_model = NULL;
+				struct dict_object  * value_model = NULL;
+				struct dict_enumval_request request;
+				
+				CHECK( 0, fd_msg_model ( avpi, &avp_model ) );
+				CHECK( 0, fd_dict_search ( fd_g_config->cnf_dict, DICT_TYPE, TYPE_OF_AVP, avp_model, &type_model, ENOENT ) );
+				memset(&request, 0, sizeof(request));
+				request.type_obj = type_model;
+				request.search.enum_name = "i32 const test (val -5)";
+				CHECK( 0, fd_dict_search ( fd_g_config->cnf_dict, DICT_ENUMVAL, ENUMVAL_BY_STRUCT, &request, &value_model, ENOENT ) );
+				CHECK( 0, fd_dict_getval ( value_model, &request.search ) );
+				CHECK( 0, fd_msg_avp_setvalue ( avpi, &request.search.enum_value ) );
+			}
+			
+			/* Now add a value which is not a constant into an enumerated AVP */
+			ADD_AVP( msg, MSG_BRW_LAST_CHILD, avpi, 73565, "AVP Test - enumi32" );
+			value.i32 = -10;
+			CHECK( 0, fd_msg_avp_setvalue ( avpi, &value ) );
+			
+			/* Add an octetstring AVP */
+			ADD_AVP( msg, MSG_BRW_LAST_CHILD, avpi, 73565, "AVP Test - os" );
+			{
+				unsigned char buf[90];
+				memcpy(&buf, "This\0 is a buffer of dat\a. It is not a string so we can have any c\0ntr\0l character here...\0\0", 89);
+				value.os.data = buf;
+				value.os.len = 89;
+				CHECK( 0, fd_msg_avp_setvalue ( avpi, &value ) );
+				memset(&buf, 0, sizeof(buf)); /* Test that the OS value is really copied */
+			}
+
+			/* Add an octetstring from an enumerated constant */
+			ADD_AVP( msg, MSG_BRW_LAST_CHILD, avpi, 73565, "AVP Test - enumos" );
+			{
+				struct dict_object  * type_model = NULL;
+				struct dict_object  * value_model = NULL;
+				struct dict_enumval_request request;
+				
+				CHECK( 0, fd_msg_model ( avpi, &avp_model ) );
+				CHECK( 0, fd_dict_search ( fd_g_config->cnf_dict, DICT_TYPE, TYPE_OF_AVP, avp_model, &type_model, ENOENT ) );
+				memset(&request, 0, sizeof(request));
+				request.type_obj = type_model;
+				request.search.enum_name = "os const test (waaad)";
+				CHECK( 0, fd_dict_search ( fd_g_config->cnf_dict, DICT_ENUMVAL, ENUMVAL_BY_STRUCT, &request, &value_model, ENOENT ) );
+				CHECK( 0, fd_dict_getval ( value_model, &request.search ) );
+				CHECK( 0, fd_msg_avp_setvalue ( avpi, &request.search.enum_value ) );
+			}
+				
+			/* Add an octetstring from an enumerated constant */
+			ADD_AVP( msg, MSG_BRW_LAST_CHILD, avpi, 73565, "AVP Test - enumos" );
+			{
+				struct dict_object  * type_model = NULL;
+				struct dict_object  * value_model = NULL;
+				struct dict_enumval_request request;
+				
+				CHECK( 0, fd_msg_model ( avpi, &avp_model ) );
+				CHECK( 0, fd_dict_search ( fd_g_config->cnf_dict, DICT_TYPE, TYPE_OF_AVP, avp_model, &type_model, ENOENT ) );
+				memset(&request, 0, sizeof(request));
+				request.type_obj = type_model;
+				request.search.enum_name = "os const test (waa)";
+				CHECK( 0, fd_dict_search ( fd_g_config->cnf_dict, DICT_ENUMVAL, ENUMVAL_BY_STRUCT, &request, &value_model, ENOENT ) );
+				CHECK( 0, fd_dict_getval ( value_model, &request.search ) );
+				CHECK( 0, fd_msg_avp_setvalue ( avpi, &request.search.enum_value ) );
+			}
+				
+			/* Now test the grouped AVPs */	
+			ADD_AVP( msg, MSG_BRW_LAST_CHILD, avpi, 73565, "AVP Test - grouped" );
+			  ADD_AVP( avpi, MSG_BRW_LAST_CHILD, avpch, 73565, "AVP Test - os" );
+			  {
+				value.os.data = (unsigned char *)"12345678";
+				value.os.len = 8;
+				CHECK( 0, fd_msg_avp_setvalue ( avpch, &value ) );
+			  }
+			  ADD_AVP( avpi, MSG_BRW_LAST_CHILD, avpch, 73565, "AVP Test - os" );
+			  {
+				value.os.data = (unsigned char *)"123456789";
+				value.os.len = 9;
+				CHECK( 0, fd_msg_avp_setvalue ( avpch, &value ) );
+			  }
+			
+			/* Add another similar grouped AVP, to have lot of padding */
+			ADD_AVP( msg, MSG_BRW_LAST_CHILD, avpi, 73565, "AVP Test - grouped" );
+			  ADD_AVP( avpi, MSG_BRW_LAST_CHILD, avpch, 73565, "AVP Test - os" );
+			  {
+				value.os.data = (unsigned char *)"1";
+				value.os.len = 1;
+				CHECK( 0, fd_msg_avp_setvalue ( avpch, &value ) );
+			  }
+			  ADD_AVP( avpi, MSG_BRW_LAST_CHILD, avpch, 73565, "AVP Test - os" );
+			  {
+				value.os.data = (unsigned char *)"1234567";
+				value.os.len = 7;
+				CHECK( 0, fd_msg_avp_setvalue ( avpch, &value ) );
+			  }
+			
+			/* Set the application to the test application: 73566 */
+			msgdata->msg_appl = 73566;
+			
+			/* Set the hop-by-hop ID to a random value: 0x4b44b41d */
+			msgdata->msg_hbhid = 0x4b44b41d;
+			/* Set the end-to-end ID to a random value: 0xe2ee2e1d */
+			msgdata->msg_eteid = 0xe2ee2e1d;
+		}
+		
+		CHECK( 0, fd_msg_bufferize( msg, &buf, NULL ) );
+		
+		LOG_D( "Test message: %s", fd_msg_dump_treeview(FD_DUMP_TEST_PARAMS, msg, NULL, 0, 1));
+		
+		/* Now free the message, we keep only the buffer. */
+		CHECK( 0, fd_msg_free( msg ) );
+		
+	}
+	
+	/* We have our "buf" now, length is 344 -- cf. testmesg.c. */
+redo:	
+	/* Test the throughput of the different functions function */
+	{
+		struct stress_struct {
+			struct msg * m;
+			uint8_t * b;
+		} * stress_array;
+		int i;
+		struct timespec start, end;
+		
+		/* Create the copies of the message buffer */
+		stress_array = calloc(test_parameter, sizeof(struct stress_struct));
+		CHECK( stress_array ? 1 : 0, 1);
+		
+		for (i=0; i < test_parameter; i++) {
+			stress_array[i].b = malloc(344);
+			if (!stress_array[i].b)
+				break;
+			memcpy(stress_array[i].b, buf, 344);
+		}
+		CHECK( test_parameter, i ); /* if false, a malloc failed */
+		
+	/* fd_msg_parse_buffer */
+		
+		CHECK( 0, clock_gettime(CLOCK_REALTIME, &start) );
+		
+		/* Test the msg_parse_buffer function */
+		for (i=0; i < test_parameter; i++) {
+			if (0 != fd_msg_parse_buffer( &stress_array[i].b, 344, &stress_array[i].m) )
+				break;
+		}
+		CHECK( test_parameter, i ); /* if false, a call failed */
+		
+		CHECK( 0, clock_gettime(CLOCK_REALTIME, &end) );
+		display_result(test_parameter, &start, &end, "fd_msg_parse_buffer", "buffers", "parsed");
+		
+	/* fd_msg_parse_dict */
+		
+		CHECK( 0, clock_gettime(CLOCK_REALTIME, &start) );
+		
+		/* Test the fd_msg_parse_dict function */
+		for (i=0; i < test_parameter; i++) {
+			if (0 != fd_msg_parse_dict( stress_array[i].m, fd_g_config->cnf_dict, NULL ) )
+				break;
+		}
+		CHECK( test_parameter, i ); /* if false, a call failed */
+		
+		CHECK( 0, clock_gettime(CLOCK_REALTIME, &end) );
+		display_result(test_parameter, &start, &end, "fd_msg_parse_dict", "messages", "parsed");
+		
+		
+	/* fd_msg_parse_rules */
+		
+		CHECK( 0, clock_gettime(CLOCK_REALTIME, &start) );
+		
+		/* Test the fd_msg_parse_rules function */
+		for (i=0; i < test_parameter; i++) {
+			if (0 != fd_msg_parse_rules( stress_array[i].m, fd_g_config->cnf_dict, NULL ) )
+				break;
+		}
+		CHECK( test_parameter, i ); /* if false, a call failed */
+		
+		CHECK( 0, clock_gettime(CLOCK_REALTIME, &end) );
+		display_result(test_parameter, &start, &end, "fd_msg_parse_rules", "messages", "parsed");
+		
+		
+	/* fd_msg_new_answer_from_req (0) */
+		
+		CHECK( 0, clock_gettime(CLOCK_REALTIME, &start) );
+		
+		/* Test the fd_msg_new_answer_from_req function */
+		for (i=0; i < test_parameter; i++) {
+			if (0 != fd_msg_new_answer_from_req( fd_g_config->cnf_dict, &stress_array[i].m, 0 ) )
+				break;
+		}
+		CHECK( test_parameter, i ); /* if false, a call failed */
+		
+		CHECK( 0, clock_gettime(CLOCK_REALTIME, &end) );
+		display_result(test_parameter, &start, &end, "new_answer(normal)", "messages", "created");
+		
+		/* unlink answers and go back to request messages */
+		for (i=0; i < test_parameter; i++) {
+			struct msg * ans = stress_array[i].m;
+			if (0 != fd_msg_answ_getq( ans, &stress_array[i].m ) )
+				break;
+			if (0 != fd_msg_answ_detach( ans ) )
+				break;
+			fd_msg_free( ans );
+		}
+		CHECK( test_parameter, i ); /* if false, a call failed */
+		
+		
+	/* fd_msg_new_answer_from_req (MSGFL_ANSW_ERROR) */
+		
+		CHECK( 0, clock_gettime(CLOCK_REALTIME, &start) );
+		
+		/* Test the fd_msg_new_answer_from_req function */
+		for (i=0; i < test_parameter; i++) {
+			if ( 0 != fd_msg_new_answer_from_req( fd_g_config->cnf_dict, &stress_array[i].m, MSGFL_ANSW_ERROR ) )
+				break;
+		}
+		CHECK( test_parameter, i ); /* if false, a call failed */
+		
+		CHECK( 0, clock_gettime(CLOCK_REALTIME, &end) );
+		display_result(test_parameter, &start, &end, "new_answer(error)", "messages", "created");
+		
+		/* unlink answers and go back to request messages */
+		for (i=0; i < test_parameter; i++) {
+			struct msg * ans = stress_array[i].m;
+			if (0 != fd_msg_answ_getq( ans, &stress_array[i].m ) )
+				break;
+			if (0 != fd_msg_answ_detach( ans ) )
+				break;
+			fd_msg_free( ans );
+		}
+		
+		
+	/* fd_msg_bufferize */
+		
+
+		CHECK( 0, clock_gettime(CLOCK_REALTIME, &start) );
+		
+		/* Test the fd_msg_bufferize function */
+		for (i=0; i < test_parameter; i++) {
+			size_t len = 0;
+			if (0 != fd_msg_bufferize( stress_array[i].m, &stress_array[i].b, &len ) )
+				break;
+		}
+		CHECK( test_parameter, i ); /* if false, a call failed */
+		
+		CHECK( 0, clock_gettime(CLOCK_REALTIME, &end) );
+		display_result(test_parameter, &start, &end, "fd_msg_bufferize", "buffers", "created");
+		
+		
+	/* fd_msg_free */
+		
+		CHECK( 0, clock_gettime(CLOCK_REALTIME, &start) );
+		
+		/* Free those messages */
+		for (i=0; i < test_parameter; i++) {
+			fd_msg_free( stress_array[i].m );
+		}
+		
+		CHECK( 0, clock_gettime(CLOCK_REALTIME, &end) );
+		display_result(test_parameter, &start, &end, "fd_msg_free", "messages", "freed");
+		
+		
+		for (i=0; i < test_parameter; i++) {
+			free(stress_array[i].b);
+		}
+		free(stress_array);
+	}
+	
+	if (!dictionaries_loaded) {
+		load_all_extensions("dict_");
+		dictionaries_loaded = 1;
+		printf("Loaded all dictionary extensions, restarting...\n");
+		goto redo;
+	}
+	
+	/* That's all for the tests yet */
+	PASSTEST();
+} 
+	
diff --git a/tests/testostr.c b/tests/testostr.c
new file mode 100644
index 0000000..14a64c5
--- /dev/null
+++ b/tests/testostr.c
@@ -0,0 +1,202 @@
+/*********************************************************************************************************
+* Software License Agreement (BSD License)                                                               *
+* Author: Sebastien Decugis <sdecugis@freediameter.net>							 *
+*													 *
+* Copyright (c) 2011, WIDE Project and NICT								 *
+* All rights reserved.											 *
+* 													 *
+* Redistribution and use of this software in source and binary forms, with or without modification, are  *
+* permitted provided that the following conditions are met:						 *
+* 													 *
+* * Redistributions of source code must retain the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer.										 *
+*    													 *
+* * Redistributions in binary form must reproduce the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer in the documentation and/or other						 *
+*   materials provided with the distribution.								 *
+* 													 *
+* * Neither the name of the WIDE Project or NICT nor the 						 *
+*   names of its contributors may be used to endorse or 						 *
+*   promote products derived from this software without 						 *
+*   specific prior written permission of WIDE Project and 						 *
+*   NICT.												 *
+* 													 *
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED *
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
+* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR *
+* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 	 *
+* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 	 *
+* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR *
+* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF   *
+* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.								 *
+*********************************************************************************************************/
+
+#include "tests.h"
+
+#define TEST_STR (os0_t)"This is my test string (with extra unused data)"
+
+/* The following string contains UTF-8 encoded characters (Chinese characters) */
+#define TEST_IDN_UTF8  "freeDiameter.中国"
+#define TEST_IDN_CONV  "freeDiameter.xn--fiqs8s"
+
+/* Main test routine */
+int main(int argc, char *argv[])
+{
+	/* First, initialize the daemon modules */
+	INIT_FD();
+	
+	/* Check the hash function */
+	{
+		uint8_t buf[30];
+		
+		uint32_t hash = fd_os_hash(TEST_STR, CONSTSTRLEN(TEST_STR)); /* reference value */
+		
+		/* Check that a hash of a substring / surstring is different */
+		CHECK( 1, hash != fd_os_hash(TEST_STR, CONSTSTRLEN(TEST_STR) - 1) ? 1 : 0 );
+		CHECK( 1, hash != fd_os_hash(TEST_STR, CONSTSTRLEN(TEST_STR) + 1) ? 1 : 0 );
+		
+		/* Check alignment of the string is not important */
+		memcpy(buf + 4, TEST_STR, CONSTSTRLEN(TEST_STR));
+		CHECK( hash, fd_os_hash(buf + 4, CONSTSTRLEN(TEST_STR)) );
+		
+		memcpy(buf + 3, TEST_STR, CONSTSTRLEN(TEST_STR));
+		CHECK( hash, fd_os_hash(buf + 3, CONSTSTRLEN(TEST_STR)) );
+		
+		memcpy(buf + 2, TEST_STR, CONSTSTRLEN(TEST_STR));
+		CHECK( hash, fd_os_hash(buf + 2, CONSTSTRLEN(TEST_STR)) );
+		
+		memcpy(buf + 1, TEST_STR, CONSTSTRLEN(TEST_STR));
+		CHECK( hash, fd_os_hash(buf + 1, CONSTSTRLEN(TEST_STR)) );
+	}
+	
+	/* Check the Diameter Identity functions */
+	{
+		char * res;
+		size_t len=0;
+		
+		/* A valid ASCII domain name */
+		res = TEST_IDN_CONV;
+		CHECK( 0, fd_os_validate_DiameterIdentity(&res, &len, 1) );
+		CHECK( 0, strcasecmp(res, TEST_IDN_CONV) ); /* the function does not change a valid DN */
+		CHECK( 0, fd_os_validate_DiameterIdentity(&res, &len, 0) );
+		CHECK( 0, strcasecmp(res, TEST_IDN_CONV) );
+		CHECK( CONSTSTRLEN(TEST_IDN_CONV), len );
+		free(res);
+		
+		/* Now, an invalid string */
+		res = TEST_IDN_UTF8;
+		len = 0;
+		
+		#ifdef DIAMID_IDNA_IGNORE
+		
+		/* The UTF-8 chars are considered valid */
+		CHECK( 1, fd_os_is_valid_DiameterIdentity((os0_t)TEST_IDN_UTF8, CONSTSTRLEN(TEST_IDN_UTF8) ) );
+		
+		/* The string should be passed unmodified */
+		CHECK( 0, fd_os_validate_DiameterIdentity(&res, &len, 1) );
+		CHECK( 0, strcasecmp(res, TEST_IDN_UTF8) );
+		CHECK( 0, fd_os_cmp(res, len, TEST_IDN_UTF8, CONSTSTRLEN(TEST_IDN_UTF8)) );
+		CHECK( 0, fd_os_almostcasesrch(res, len, TEST_IDN_UTF8, CONSTSTRLEN(TEST_IDN_UTF8), NULL) );
+		CHECK( 0, fd_os_validate_DiameterIdentity(&res, &len, 0) );
+		CHECK( 0, strcasecmp(res, TEST_IDN_UTF8) );
+		CHECK( CONSTSTRLEN(TEST_IDN_UTF8), len );
+		free(res);
+		
+		#else /* DIAMID_IDNA_IGNORE */
+		
+		/* The UTF-8 chars are recognized as invalid DiameterIdentity */
+		CHECK( 0, fd_os_is_valid_DiameterIdentity((os0_t)TEST_IDN_UTF8, CONSTSTRLEN(TEST_IDN_UTF8) ));
+		
+		# ifdef DIAMID_IDNA_REJECT
+		
+		/* The string must be rejected */
+		CHECK( EINVAL, fd_os_validate_DiameterIdentity(&res, &len, 1) );
+		
+		# else /* DIAMID_IDNA_REJECT */
+		
+		/* The string should be transformed into TEST_IDN_CONV */
+		CHECK( 0, fd_os_validate_DiameterIdentity(&res, &len, 1) );
+		CHECK( 0, strcasecmp(res, TEST_IDN_CONV) );
+		CHECK( CONSTSTRLEN(TEST_IDN_CONV), len );
+		free(res);
+		
+		# endif /* DIAMID_IDNA_REJECT */
+		#endif /* DIAMID_IDNA_IGNORE */
+
+	}
+	
+	{
+		/* test fd_os_cmp and fd_os_almostcasesrch and that they are compatible */
+		char *t1 = "a";
+		char *t2 = "b";
+		char *t3 = "C";
+		char *t4 = "d";
+		char *t5 = "aa";
+		char *t6 = "aB";
+		char *t7 = "Ac";
+		char *t8 = "aD";
+		char *t9 = "AAA";
+		
+		char *t5b = "Aa";
+		char *t6b = "ab";
+		
+		/* First, create a list with all the elements in order given by fd_os_cmp */
+		char *t[] = { t1, t2, t3, t4, t5, t6,t7, t8, t9 };
+		int i;
+		struct fd_list *li, l = FD_LIST_INITIALIZER(l);
+		for (i = 0; i < sizeof(t) / sizeof(t[0]); i++) {
+			/* insert t[i] */
+			struct fd_list *n = malloc(sizeof(struct fd_list));
+			CHECK( 1, n ? 1 : 0 );
+			fd_list_init(n, t[i]);
+			for (li = l.next; li != &l; li = li->next) {
+				if ( fd_os_cmp(t[i], strlen(t[i]), li->o, strlen(li->o)) < 0 )
+					break;
+			} 
+			fd_list_insert_before(li, n);
+		}
+		/* in principle the result is: [ "C", "a", "b", "d", "Ac", "aB", "aD", "aa", "AAA" ] */
+		
+		/* Since there is no equal value in the list (even case-insensitive), check that the order is valid also for the caseinsensitive variant */
+		for (li = l.next; li != l.prev; li = li->next) {
+			CHECK( 1, fd_os_almostcasesrch(li->o, strlen(li->o), li->next->o, strlen(li->next->o), NULL) < 0 ? 1 : 0 );
+		}
+		
+		/* Now check that we can case-insentively find t5b and t6b to be equal to t5 and t6 resp. (this is how we use it in the daemon) */
+		for (li = l.next; li != &l; li = li->next) {
+			int cont, cmp;
+			cmp = fd_os_almostcasesrch(t5b, strlen(t5b), li->o, strlen(li->o), &cont);
+			TRACE_DEBUG(FULL, "Comp '%s' : %d, %d", (char *)li->o, cmp, cont);
+			if (cmp == 0)
+				break;
+			if (!cont)
+				break;
+		}
+		CHECK( li->o, t5 );
+		
+		for (li = l.next; li != &l; li = li->next) {
+			int cont, cmp;
+			cmp = fd_os_almostcasesrch(t6b, strlen(t6b), li->o, strlen(li->o), &cont);
+			TRACE_DEBUG(FULL, "Comp '%s' : %d, %d", (char *)li->o, cmp, cont);
+			if (cmp == 0)
+				break;
+			if (!cont)
+				break;
+		}
+		CHECK( li->o, t6 );
+		
+		
+		/* done */
+		while (!FD_IS_LIST_EMPTY(&l)) {
+			li = l.next;
+			fd_list_unlink(li);
+			free(li);
+		}
+	}
+	
+	/* That's all for the tests yet */
+	PASSTEST();
+} 
+	
diff --git a/tests/testpeers.c b/tests/testpeers.c
new file mode 100644
index 0000000..50d252a
--- /dev/null
+++ b/tests/testpeers.c
@@ -0,0 +1,78 @@
+/*********************************************************************************************************
+* Software License Agreement (BSD License)                                                               *
+* Author: Sebastien Decugis <sdecugis@freediameter.net>							 *
+*													 *
+* Copyright (c) 2013, WIDE Project and NICT								 *
+* All rights reserved.											 *
+* 													 *
+* Redistribution and use of this software in source and binary forms, with or without modification, are  *
+* permitted provided that the following conditions are met:						 *
+* 													 *
+* * Redistributions of source code must retain the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer.										 *
+*    													 *
+* * Redistributions in binary form must reproduce the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer in the documentation and/or other						 *
+*   materials provided with the distribution.								 *
+* 													 *
+* * Neither the name of the WIDE Project or NICT nor the 						 *
+*   names of its contributors may be used to endorse or 						 *
+*   promote products derived from this software without 						 *
+*   specific prior written permission of WIDE Project and 						 *
+*   NICT.												 *
+* 													 *
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED *
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
+* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR *
+* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 	 *
+* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 	 *
+* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR *
+* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF   *
+* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.								 *
+*********************************************************************************************************/
+
+#include "tests.h"
+
+const char * ids[] = { "b11", "b14", "b1", "b4" };
+#define DomainName "localdomain"
+
+/* Main test routine */
+int main(int argc, char *argv[])
+{
+	/* First, initialize the daemon modules */
+	INIT_FD();
+	
+	/* Create 4 peers with these ids */
+	{
+		int i;
+		struct peer_info inf;
+		char locid[255];
+		memset(&inf, 0, sizeof(inf));
+		inf.pi_diamid = (char *)locid;
+		for (i=0; i < sizeof(ids) / sizeof(ids[0]); i++) {
+			snprintf(locid, sizeof(locid), "%s." DomainName, ids[i]);
+			CHECK( 0, fd_peer_add(&inf, __FILE__, NULL, NULL));
+		}
+	}
+	fd_log_debug("%s", fd_peer_dump_list(FD_DUMP_TEST_PARAMS, 0));
+	/* Check we are able to find again any of these */
+	{
+		int i;
+		char locid[255];
+		struct peer_hdr *p;
+		for (i=0; i < sizeof(ids) / sizeof(ids[0]); i++) {
+			snprintf(locid, sizeof(locid), "%s." DomainName, ids[i]);
+			CHECK( 0, fd_peer_getbyid((DiamId_t)locid, strlen((char *)locid), 0, &p));
+			CHECK( 0, strcmp((char *)locid, p->info.pi_diamid));
+			CHECK( 0, fd_peer_getbyid((DiamId_t)locid, strlen((char *)locid), 1, &p));
+			CHECK( 0, strcmp((char *)locid, p->info.pi_diamid));
+		}
+	}
+	
+	
+	/* That's all for the tests yet */
+	PASSTEST();
+} 
+	
diff --git a/tests/tests.h b/tests/tests.h
new file mode 100644
index 0000000..85e6d9b
--- /dev/null
+++ b/tests/tests.h
@@ -0,0 +1,239 @@
+/*********************************************************************************************************
+* Software License Agreement (BSD License)                                                               *
+* Author: Sebastien Decugis <sdecugis@freediameter.net>							 *
+*													 *
+* Copyright (c) 2013, WIDE Project and NICT								 *
+* All rights reserved.											 *
+* 													 *
+* Redistribution and use of this software in source and binary forms, with or without modification, are  *
+* permitted provided that the following conditions are met:						 *
+* 													 *
+* * Redistributions of source code must retain the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer.										 *
+*    													 *
+* * Redistributions in binary form must reproduce the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer in the documentation and/or other						 *
+*   materials provided with the distribution.								 *
+* 													 *
+* * Neither the name of the WIDE Project or NICT nor the 						 *
+*   names of its contributors may be used to endorse or 						 *
+*   promote products derived from this software without 						 *
+*   specific prior written permission of WIDE Project and 						 *
+*   NICT.												 *
+* 													 *
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED *
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
+* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR *
+* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 	 *
+* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 	 *
+* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR *
+* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF   *
+* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.								 *
+*********************************************************************************************************/
+
+/* This file contains the definition of our test harness.
+ * The harness is very simple yet.
+ * It may be interessant to go to dejagnu later...
+ *
+ */
+#ifndef _TESTS_H
+#define _TESTS_H
+
+#include "fdproto-internal.h"
+#include "fdcore-internal.h"
+
+#include <pthread.h>
+#include <errno.h>
+GCC_DIAG_OFF("-Wdeprecated-declarations")
+#include <gcrypt.h>
+GCC_DIAG_ON("-Wdeprecated-declarations")
+
+/* Test timeout duration, unless -n is passed on the command line */
+#ifndef TEST_TIMEOUT
+#define TEST_TIMEOUT	120	/* in seconds */
+#endif /* TEST_TIMEOUT */
+
+/* Standard includes */
+#include <getopt.h>
+#include <time.h>
+#include <libgen.h>
+#include <signal.h>
+
+/* Define the return code values */
+#define PASS	0
+#define FAIL	1
+
+/* Define the macro to fail a test with a message */
+#define FAILTEST( message... ){				\
+	LOG_F(message);					\
+	LOG_F("FAILED: %s ", __STRIPPED_FILE__);	\
+	free(tbuf);					\
+	exit(FAIL);					\
+}
+
+/* Define the macro to pass a test */
+#define PASSTEST( ){					\
+	LOG_N("PASS: %s", __STRIPPED_FILE__);		\
+	(void)fd_core_shutdown();			\
+	(void)fd_core_wait_shutdown_complete();		\
+	(void)fd_thr_term(&signal_thr);			\
+	free(tbuf);					\
+	exit(PASS);					\
+}
+
+static struct fd_config conf;
+extern struct fd_config * fd_g_config;
+
+/* for dumps */
+static char * tbuf = NULL; size_t tbuflen = 0;
+#define FD_DUMP_TEST_PARAMS &tbuf, &tbuflen, NULL
+
+
+/* Define the standard check routines */
+#define CHECK( _val, _assert ){				\
+	LOG_D("CHECK( %s == %s )",			\
+				#_assert,		\
+				#_val);			\
+	{						\
+	__typeof__ (_val) __ret = (_assert);		\
+	if (__ret != (_val)) {				\
+		FAILTEST( "%s:%d: CHECK FAILED : %s == %lx != %lx",	\
+			__STRIPPED_FILE__,		\
+			__LINE__,			\
+			#_assert,			\
+			(unsigned long)__ret,		\
+			(unsigned long)(_val));		\
+	}}						\
+}
+
+static pthread_t signal_thr;
+static void * signal_catch(void * arg)
+{
+	int sig;
+	sigset_t ss;
+	fd_log_threadname ( "Signal catcher" );
+	
+	sigemptyset(&ss);
+	
+	/* We use SIGALRM */
+	sigaddset(&ss, SIGALRM);
+	
+	/* Unblock any other signal for this thread, so that default handler is enabled */
+	CHECK_SYS_DO( pthread_sigmask( SIG_SETMASK, &ss, NULL ), );
+	
+	/* Now wait for sigwait or cancelation */
+	CHECK_POSIX_DO( sigwait(&ss, &sig),  );
+	FAILTEST("The timeout (" _stringize(TEST_TIMEOUT) " sec) was reached. Use -n or change TEST_TIMEOUT if the test needs more time to execute.");
+	
+	return NULL;
+}
+	
+
+GCRY_THREAD_OPTION_PTHREAD_IMPL;
+
+/* gnutls debug. */
+static void fd_gnutls_debug(int level, const char * str) {
+	const char * __thn = ((char *)pthread_getspecific(fd_log_thname) ?: "unnamed");	
+	fd_log_debug("tid:%-20s[gnutls:%d] %s", __thn, level, str);
+}
+static int gnutls_debug = 0;
+
+static int test_parameter = 0;
+
+static inline void parse_cmdline(int argc, char * argv[]) {
+	int c;
+	int no_timeout = 0;
+	while ((c = getopt (argc, argv, "dqnf:F:g:p:")) != -1) {
+		switch (c) {
+			case 'd':	/* Increase verbosity of debug messages.  */
+				fd_g_debug_lvl--;
+				break;
+				
+			case 'q':	/* Decrease verbosity.  */
+				fd_g_debug_lvl++;
+				break;
+			
+			case 'n':	/* Disable the timeout of the test.  */
+				no_timeout = 1;
+				break;
+			
+			case 'f':	/* Full debug for the function with this name.  */
+				#ifdef DEBUG
+				fd_debug_one_function = optarg;
+				#else /* DEBUG */
+				TRACE_DEBUG(INFO, "Error: must compile with DEBUG support to use this feature");
+				#endif /* DEBUG */
+				break;
+				
+			case 'F':	/* Full debug for the functions in file with this name.  */
+				#ifdef DEBUG
+				fd_debug_one_file = optarg;
+				#else /* DEBUG */
+				TRACE_DEBUG(INFO, "Error: must compile with DEBUG support to use this feature");
+				#endif /* DEBUG */
+				break;
+				
+			case 'g':	/* Set a debug level and function for GNU TLS calls.  */
+				gnutls_debug = (int)atoi(optarg);
+				break;
+				
+			case 'p':	/* Set a debug level and function for GNU TLS calls.  */
+				test_parameter = (int)atoi(optarg);
+				break;
+				
+			default:	/* bug: option not considered.  */
+				return;
+		}
+	}
+	if (!no_timeout) {
+		alarm(TEST_TIMEOUT);
+	}
+	CHECK( 0, pthread_create(&signal_thr, NULL, signal_catch, NULL) );
+}
+ 
+static inline void test_init(int argc, char * argv[], char *fname)
+{
+	sigset_t sig_all;
+	sigfillset(&sig_all);
+	
+	CHECK( 0, pthread_sigmask(SIG_BLOCK, &sig_all, NULL));
+	
+	fd_g_config = &conf;
+	memset(fd_g_config, 0, sizeof(struct fd_config));
+	
+	CHECK( 0, fd_libproto_init() );
+	
+	CHECK( 0, fd_hooks_init() );	
+	
+	fd_log_threadname(fname);
+	
+	/* Parse the command line */
+	parse_cmdline(argc, argv);
+	
+	/* Initialize gcrypt and gnutls */
+	(void) gcry_control (GCRYCTL_SET_THREAD_CBS, &gcry_threads_pthread);
+	(void) gcry_control (GCRYCTL_ENABLE_QUICK_RANDOM, 0);
+	CHECK( 0, gnutls_global_init());
+	/* Set gnutls debug level ? */
+	if (gnutls_debug) {
+		gnutls_global_set_log_function((gnutls_log_func)fd_gnutls_debug);
+		gnutls_global_set_log_level (gnutls_debug);
+		TRACE_DEBUG(INFO, "Enabled GNUTLS debug at level %d", gnutls_debug);
+	}
+	
+	/* Initialize the config */
+	CHECK( 0, fd_conf_init() );
+
+	/* Add definitions of the base protocol */
+	CHECK( 0, fd_dict_base_protocol(fd_g_config->cnf_dict) );
+	
+	/* Initialize only the sessions */
+	CHECK( 0, fd_sess_start()  );
+	
+	return;
+}
+#define INIT_FD()  test_init(argc, argv, __STRIPPED_FILE__)
+
+#endif /* _TESTS_H */
diff --git a/tests/testsctp.c b/tests/testsctp.c
new file mode 100644
index 0000000..46453c8
--- /dev/null
+++ b/tests/testsctp.c
@@ -0,0 +1,144 @@
+/*********************************************************************************************************
+* Software License Agreement (BSD License)                                                               *
+* Author: Sebastien Decugis <sdecugis@freediameter.net>							 *
+*													 *
+* Copyright (c) 2013, WIDE Project and NICT								 *
+* All rights reserved.											 *
+* 													 *
+* Redistribution and use of this software in source and binary forms, with or without modification, are  *
+* permitted provided that the following conditions are met:						 *
+* 													 *
+* * Redistributions of source code must retain the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer.										 *
+*    													 *
+* * Redistributions in binary form must reproduce the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer in the documentation and/or other						 *
+*   materials provided with the distribution.								 *
+* 													 *
+* * Neither the name of the WIDE Project or NICT nor the 						 *
+*   names of its contributors may be used to endorse or 						 *
+*   promote products derived from this software without 						 *
+*   specific prior written permission of WIDE Project and 						 *
+*   NICT.												 *
+* 													 *
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED *
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
+* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR *
+* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 	 *
+* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 	 *
+* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR *
+* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF   *
+* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.								 *
+*********************************************************************************************************/
+
+#include "tests.h"
+
+#include <cnxctx.h>
+
+#ifndef TEST_PORT
+#define TEST_PORT	3868
+#endif /* TEST_PORT */
+
+#ifndef NB_STREAMS
+#define NB_STREAMS	10
+#endif /* NB_STREAMS */
+
+
+
+/* Main test routine */
+int main(int argc, char *argv[])
+{
+#ifdef DISABLE_SCTP
+	INIT_FD();
+	/* In this case, we don't perform this simple test */
+	PASSTEST();
+#else /* DISABLE_SCTP */
+	struct cnxctx cli, srv; /* we use only their cc_socket & cc_state */
+	int sock;
+	char buf1[]="abcdef";
+	char *buf2;
+	size_t sz;
+	struct iovec iov;
+	struct fd_list eps = FD_LIST_INITIALIZER(eps);
+	uint16_t str;
+	int ev;
+	
+	/* Initialize the server addresses */
+	{
+		struct addrinfo hints, *ai, *aip;
+		memset(&hints, 0, sizeof(hints));
+		hints.ai_flags  = AI_NUMERICSERV;
+		hints.ai_family = AF_INET;
+		CHECK( 0, getaddrinfo("localhost", _stringize(TEST_PORT), &hints, &ai) );
+		aip = ai;
+		while (aip) {
+			CHECK( 0, fd_ep_add_merge( &eps, aip->ai_addr, aip->ai_addrlen, EP_FL_DISC | EP_ACCEPTALL ));
+			aip = aip->ai_next;
+		};
+		freeaddrinfo(ai);
+		
+		CHECK( 0, FD_IS_LIST_EMPTY(&eps) ? 1 : 0 );
+	}
+	
+	memset(&cli, 0, sizeof(cli));
+	memset(&srv, 0, sizeof(srv));
+	
+	/* First, initialize the daemon modules */
+	INIT_FD();
+	
+	/* Restrain the # of streams */
+	fd_g_config->cnf_sctp_str = NB_STREAMS;
+	
+	/* Create the server socket */
+	CHECK( 0, fd_sctp_create_bind_server( &sock, AF_INET6, &eps, TEST_PORT ));
+	
+	/* Accept incoming clients */
+	CHECK( 0, fd_sctp_listen( sock ));
+	
+	/* Now, create the client socket */
+	CHECK( 0, fd_sctp_client( &cli.cc_socket, 0, TEST_PORT, &eps ));
+	
+	/* Accept this connection */
+	srv.cc_socket = accept(sock, NULL, NULL);
+	
+	/* Send a first message */
+	iov.iov_base = buf1;
+	iov.iov_len = sizeof(buf1);
+	CHECK( sizeof(buf1), fd_sctp_sendstrv(&srv, 1, &iov, 1 ) );
+	CHECK( 0, srv.cc_state);
+	
+	/* Receive this message */
+redo1:
+	CHECK( 0, fd_sctp_recvmeta(&cli, &str, (uint8_t **)&buf2, &sz, &ev) );
+	if (ev == FDEVP_CNX_EP_CHANGE)
+		goto redo1;
+	CHECK( FDEVP_CNX_MSG_RECV, ev);
+	CHECK( 0, cli.cc_state);
+	CHECK( 1, str);
+	CHECK( sizeof(buf1), sz );
+	CHECK( 0, memcmp(buf1, buf2, sz) );
+	free(buf2); buf2 = NULL;
+	
+	/* Send in the other direction */
+	CHECK( sizeof(buf1), fd_sctp_sendstrv(&cli, 2, &iov, 1) );
+	CHECK( 0, cli.cc_state);
+	
+	/* Receive this message */
+redo2:
+	CHECK( 0, fd_sctp_recvmeta(&srv, &str, (uint8_t **)&buf2, &sz, &ev) );
+	if (ev == FDEVP_CNX_EP_CHANGE)
+		goto redo2;
+	CHECK( FDEVP_CNX_MSG_RECV, ev);
+	CHECK( 0, srv.cc_state);
+	CHECK( 2, str);
+	CHECK( sizeof(buf1), sz );
+	CHECK( 0, memcmp(buf1, buf2, sz) );
+	free(buf2); buf2 = NULL;
+	
+	/* That's all for the tests yet */
+	PASSTEST();
+#endif /* DISABLE_SCTP */
+} 
+	
diff --git a/tests/testsess.c b/tests/testsess.c
new file mode 100644
index 0000000..5acc336
--- /dev/null
+++ b/tests/testsess.c
@@ -0,0 +1,400 @@
+/*********************************************************************************************************
+* Software License Agreement (BSD License)                                                               *
+* Author: Sebastien Decugis <sdecugis@freediameter.net>							 *
+*													 *
+* Copyright (c) 2013, WIDE Project and NICT								 *
+* All rights reserved.											 *
+* 													 *
+* Redistribution and use of this software in source and binary forms, with or without modification, are  *
+* permitted provided that the following conditions are met:						 *
+* 													 *
+* * Redistributions of source code must retain the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer.										 *
+*    													 *
+* * Redistributions in binary form must reproduce the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer in the documentation and/or other						 *
+*   materials provided with the distribution.								 *
+* 													 *
+* * Neither the name of the WIDE Project or NICT nor the 						 *
+*   names of its contributors may be used to endorse or 						 *
+*   promote products derived from this software without 						 *
+*   specific prior written permission of WIDE Project and 						 *
+*   NICT.												 *
+* 													 *
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED *
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
+* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR *
+* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 	 *
+* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 	 *
+* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR *
+* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF   *
+* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.								 *
+*********************************************************************************************************/
+
+#include "tests.h"
+
+#define TEST_DIAM_ID 	"testsess.myid"
+#define TEST_OPT_IN	"suffix"
+#define TEST_OPT	(os0_t)TEST_OPT_IN
+#define TEST_SID_IN	TEST_DIAM_ID ";1234;5678;" TEST_OPT_IN
+#define TEST_SID	(os0_t)TEST_SID_IN
+
+#define TEST_EYEC	0x7e57e1ec
+struct sess_state {
+	int	eyec;	/* TEST_EYEC */
+	os0_t   sid; 	/* the session with which the data was registered */
+	int  *  freed;	/* location where to write the freed status */
+	void *  opaque; /* if opaque was provided, this is the value we expect */
+};
+
+static void mycleanup( struct sess_state * data, os0_t sid, void * opaque )
+{
+	/* sanity */
+	CHECK( 1, sid ? 1 : 0 );
+	CHECK( 1, data? 1 : 0 );
+	CHECK( TEST_EYEC, data->eyec );
+	CHECK( 0, strcmp((char *)sid, (char *)data->sid) );
+	if (data->freed)
+		*(data->freed) += 1;
+	if (data->opaque) {
+		CHECK( 1, opaque == data->opaque ? 1 : 0 );  
+	}
+	/* Now, free the data */
+	free(data->sid);
+	free(data);
+}
+
+static __inline__ struct sess_state * new_state(os0_t sid, int *freed) 
+{
+	struct sess_state *new;
+	new = malloc(sizeof(struct sess_state));
+	CHECK( 1, new ? 1 : 0 );
+	memset(new, 0, sizeof(struct sess_state));
+	new->eyec = TEST_EYEC;
+	new->sid = os0dup(sid, strlen((char *)sid));
+	CHECK( 1, new->sid ? 1 : 0 );
+	new->freed = freed;
+	return new;
+}
+
+void * g_opaque = (void *)"test";
+
+/* Avoid a lot of casts */
+#undef strlen
+#define strlen(s) strlen((char *)s)
+#undef strncmp
+#define strncmp(s1,s2,l) strncmp((char *)s1, (char *)s2, l)
+#undef strcmp
+#define strcmp(s1,s2) strcmp((char *)s1, (char *)s2)
+	
+
+/* Main test routine */
+int main(int argc, char *argv[])
+{
+	struct session_handler * hdl1, *hdl2;
+	struct session *sess1, *sess2, *sess3;
+	os0_t str1, str2;
+	size_t str1len, str2len;
+	int new;
+	
+	/* First, initialize the daemon modules */
+	INIT_FD();
+	
+	/* Test functions related to handlers (simple situation) */
+	{
+		void * testptr = NULL;
+		CHECK( 0, fd_sess_handler_create ( &hdl1, mycleanup, NULL, NULL ) );
+		CHECK( 0, fd_sess_handler_create ( &hdl2, mycleanup, NULL, NULL ) );
+		CHECK( 0, fd_sess_handler_destroy( &hdl2, &testptr ) );
+		CHECK( 1, testptr == NULL ? 1 : 0 );
+		CHECK( 0, fd_sess_handler_create ( &hdl2, mycleanup, NULL, g_opaque ) );
+		#if 0
+		fd_log_debug("%s", fd_sess_dump_hdl(FD_DUMP_TEST_PARAMS, hdl1));
+		fd_log_debug("%s", fd_sess_dump_hdl(FD_DUMP_TEST_PARAMS, hdl2));
+		#endif
+	}
+	
+	/* Test Session Id generation (fd_sess_new) */
+	{
+		/* DiamId is provided, not opt */
+		CHECK( 0, fd_sess_new( &sess1, TEST_DIAM_ID, CONSTSTRLEN(TEST_DIAM_ID), NULL, 0 ) );
+		CHECK( 0, fd_sess_new( &sess2, TEST_DIAM_ID, CONSTSTRLEN(TEST_DIAM_ID), NULL, 0 ) );
+		#if 0
+		fd_log_debug("%s", fd_sess_dump(FD_DUMP_TEST_PARAMS, sess1, 1));
+		fd_log_debug("%s", fd_sess_dump(FD_DUMP_TEST_PARAMS, sess2, 1));
+		#endif
+		
+		/* Check both string start with the diameter Id, but are different */
+		CHECK( 0, fd_sess_getsid(sess1, &str1, &str1len) );
+		CHECK( 1, (strlen(str1) == str1len) ? 1 : 0 );
+		CHECK( 0, strncmp(str1, TEST_DIAM_ID ";", CONSTSTRLEN(TEST_DIAM_ID) + 1) );
+		CHECK( 0, fd_sess_getsid(sess2, &str2, &str2len) );
+		CHECK( 0, strncmp(str2, TEST_DIAM_ID ";", CONSTSTRLEN(TEST_DIAM_ID) + 1) );
+		CHECK( 1, strcmp(str1, str2) ? 1 : 0 );
+		CHECK( 0, fd_sess_destroy( &sess1 ) );
+		CHECK( 0, fd_sess_destroy( &sess2 ) );
+		
+		/* diamId and opt */
+		CHECK( 0, fd_sess_new( &sess1, TEST_DIAM_ID, 0, TEST_OPT, 0 ) );
+		CHECK( 0, fd_sess_new( &sess2, TEST_DIAM_ID, CONSTSTRLEN(TEST_DIAM_ID), TEST_OPT, CONSTSTRLEN(TEST_OPT_IN) - 1 ) );
+		#if 0
+		fd_log_debug("%s", fd_sess_dump(FD_DUMP_TEST_PARAMS, sess1, 1));
+		fd_log_debug("%s", fd_sess_dump(FD_DUMP_TEST_PARAMS, sess2, 1));
+		#endif
+		
+		CHECK( 0, fd_sess_getsid(sess1, &str1, &str1len) );
+		CHECK( 0, strncmp(str1, TEST_DIAM_ID ";", CONSTSTRLEN(TEST_DIAM_ID) + 1) );
+		CHECK( 0, strcmp(str1 + str1len - CONSTSTRLEN(TEST_OPT_IN) - 1, ";" TEST_OPT_IN) );
+		
+		CHECK( 0, fd_sess_getsid(sess2, &str2, &str2len) );
+		CHECK( 0, strncmp(str2, TEST_DIAM_ID ";", CONSTSTRLEN(TEST_DIAM_ID) + 1) );
+		CHECK( 0, strncmp(str2 + str2len - CONSTSTRLEN(TEST_OPT_IN), ";" TEST_OPT_IN, CONSTSTRLEN(TEST_OPT_IN)) );
+		
+		CHECK( 1, strcmp(str1, str2) ? 1 : 0 );
+		CHECK( 0, fd_sess_destroy( &sess1 ) );
+		CHECK( 0, fd_sess_destroy( &sess2 ) );
+		
+		/* Now, only opt is provided */
+		CHECK( 0, fd_sess_new( &sess1, NULL, 0, TEST_SID, 0 ) );
+		CHECK( EALREADY, fd_sess_new( &sess2, NULL, 0, TEST_SID, 0 ) );
+		CHECK( sess2, sess1 );
+		CHECK( EALREADY, fd_sess_new( &sess3, NULL, 0, TEST_SID, CONSTSTRLEN(TEST_SID_IN) ) );
+		CHECK( sess3, sess1 );
+		CHECK( 0, fd_sess_new( &sess2, NULL, 0, TEST_SID, CONSTSTRLEN(TEST_SID_IN) - 1 ) );
+		#if 0
+		fd_log_debug("%s", fd_sess_dump(FD_DUMP_TEST_PARAMS, sess1, 1));
+		fd_log_debug("%s", fd_sess_dump(FD_DUMP_TEST_PARAMS, sess2, 1));
+		#endif
+		CHECK( 0, fd_sess_getsid(sess1, &str1, &str1len) );
+		CHECK( 0, fd_sess_getsid(sess2, &str2, &str2len) );
+		CHECK( 0, strncmp( str1, str2, CONSTSTRLEN(TEST_SID_IN) - 1 ) );
+		CHECK( 0, strcmp( str1, TEST_SID ) );
+		CHECK( 1, strcmp( str1, str2 ) ? 1 : 0 );
+		
+		CHECK( 0, fd_sess_destroy( &sess2 ) );
+		CHECK( 0, fd_sess_destroy( &sess1 ) );
+	}
+	
+	/* Test fd_sess_getcount */
+	{
+		uint32_t cnt;
+		CHECK( 0, fd_sess_new( &sess1, TEST_DIAM_ID, CONSTSTRLEN(TEST_DIAM_ID), NULL, 0 ) );
+		CHECK( 0, fd_sess_new( &sess2, TEST_DIAM_ID, CONSTSTRLEN(TEST_DIAM_ID), NULL, 0 ) );
+		CHECK( 0, fd_sess_getcount(&cnt));
+		CHECK( 2, cnt);
+		CHECK( 0, fd_sess_destroy( &sess2 ) );
+		CHECK( 0, fd_sess_getcount(&cnt));
+		CHECK( 1, cnt);
+		CHECK( 0, fd_sess_destroy( &sess1 ) );
+		CHECK( 0, fd_sess_getcount(&cnt));
+		CHECK( 0, cnt);
+		
+	}
+		
+	/* Test fd_sess_fromsid */
+	{
+		CHECK( 0, fd_sess_fromsid( TEST_SID, CONSTSTRLEN(TEST_SID_IN), &sess1, &new ) );
+		CHECK( 1, new ? 1 : 0 );
+		
+		CHECK( 0, fd_sess_fromsid( TEST_SID, CONSTSTRLEN(TEST_SID_IN), &sess2, &new ) );
+		CHECK( 0, new );
+		CHECK( sess1, sess2 );
+		
+		CHECK( 0, fd_sess_fromsid( TEST_SID, CONSTSTRLEN(TEST_SID_IN), &sess3, NULL ) );
+		CHECK( sess1, sess3 );
+		
+		CHECK( 0, fd_sess_destroy( &sess1 ) );
+	}
+	
+	/* Test fd_sess_reclaim */
+	{
+		struct sess_state *tms;
+		
+		CHECK( 0, fd_sess_fromsid( TEST_SID, CONSTSTRLEN(TEST_SID_IN), &sess1, &new ) );
+		CHECK( 1, new ? 1 : 0 );
+		
+		CHECK( 0, fd_sess_reclaim( &sess1 ) );
+		CHECK( NULL, sess1 );
+		
+		CHECK( 0, fd_sess_fromsid( TEST_SID, CONSTSTRLEN(TEST_SID_IN), &sess1, &new ) );
+		CHECK( 1, new ? 1 : 0 );
+		
+		tms = new_state(TEST_SID, NULL);
+		CHECK( 0, fd_sess_state_store ( hdl1, sess1, &tms ) );
+		
+		CHECK( 0, fd_sess_reclaim( &sess1 ) );
+		CHECK( NULL, sess1 );
+		
+		CHECK( 0, fd_sess_fromsid( TEST_SID, CONSTSTRLEN(TEST_SID_IN), &sess1, &new ) );
+		CHECK( 0, new );
+		
+		CHECK( 0, fd_sess_destroy( &sess1 ) );
+		
+		CHECK( 0, fd_sess_fromsid( TEST_SID, CONSTSTRLEN(TEST_SID_IN), &sess1, &new ) );
+		CHECK( 1, new ? 1 : 0 );
+		
+		CHECK( 0, fd_sess_destroy( &sess1 ) );
+	}
+	
+	/* Test timeout function */
+	{
+		struct timespec timeout;
+		
+		CHECK( 0, fd_sess_fromsid( TEST_SID, CONSTSTRLEN(TEST_SID_IN), &sess1, &new ) );
+		CHECK( 1, new ? 1 : 0 );
+		
+		CHECK( 0, clock_gettime(CLOCK_REALTIME, &timeout) );
+		CHECK( 0, fd_sess_settimeout( sess1, &timeout) ); /* expire now */
+		timeout.tv_sec = 0;
+		timeout.tv_nsec= 50000000; /* 50 ms */
+		CHECK( 0, nanosleep(&timeout, NULL) );
+		
+		CHECK( 0, fd_sess_fromsid( TEST_SID, CONSTSTRLEN(TEST_SID_IN), &sess1, &new ) );
+		CHECK( 1, new ? 1 : 0 );
+		
+		CHECK( 0, clock_gettime(CLOCK_REALTIME, &timeout) );
+		timeout.tv_sec += 2678500; /* longer that SESS_DEFAULT_LIFETIME */
+		CHECK( 0, fd_sess_settimeout( sess1, &timeout) );
+		
+		/* Create a second session */
+		CHECK( 0, fd_sess_new( &sess2, TEST_DIAM_ID, 0, NULL, 0 ) );
+		
+		/* We don't really have a way to verify the expiry list is in proper order automatically here... */
+		
+		CHECK( 0, fd_sess_destroy( &sess2 ) );
+		CHECK( 0, fd_sess_destroy( &sess1 ) );
+	}
+	
+	
+	/* Test states operations */
+	{
+		struct sess_state * ms[6], *tms;
+		int freed[6];
+		struct timespec timeout;
+		void * testptr = NULL;
+		
+		/* Create three sessions */
+		CHECK( 0, fd_sess_new( &sess1, TEST_DIAM_ID, 0, NULL, 0 ) );
+		CHECK( 0, fd_sess_new( &sess2, TEST_DIAM_ID, 0, NULL, 0 ) );
+		CHECK( 0, fd_sess_new( &sess3, TEST_DIAM_ID, 0, NULL, 0 ) );
+		
+		/* Create 2 states */
+		CHECK( 0, fd_sess_getsid(sess1, &str1, &str1len) );
+		freed[0] = 0;
+		ms[0] = new_state(str1, &freed[0]);
+		ms[1] = new_state(str1, NULL);
+
+		tms = ms[0]; /* save a copy */
+		CHECK( 0, fd_sess_state_store ( hdl1, sess1, &ms[0] ) );
+		CHECK( NULL, ms[0] );
+		CHECK( EINVAL, fd_sess_state_store ( hdl1, sess1, NULL ) );
+		CHECK( EALREADY, fd_sess_state_store ( hdl1, sess1, &ms[1] ) );
+		CHECK( 1, ms[1] ? 1 : 0 );
+		
+		#if 0
+		fd_log_debug("%s", fd_sess_dump(FD_DUMP_TEST_PARAMS, sess1, 1));
+		#endif
+		
+		CHECK( 0, fd_sess_state_retrieve( hdl1, sess1, &ms[0] ) );
+		CHECK( tms, ms[0] );
+		CHECK( 0, freed[0] );
+		
+		CHECK( 0, fd_sess_state_retrieve( hdl1, sess2, &tms ) );
+		CHECK( NULL, tms );
+		
+		mycleanup(ms[0], str1, NULL);
+		mycleanup(ms[1], str1, NULL);
+		
+		/* Now create 6 states */
+		memset(&freed[0], 0, sizeof(freed));
+		CHECK( 0, fd_sess_getsid(sess1, &str1, &str1len) );
+		ms[0] = new_state(str1, &freed[0]);
+		ms[1] = new_state(str1, &freed[1]);
+		CHECK( 0, fd_sess_getsid(sess2, &str1, &str1len) );
+		ms[2] = new_state(str1, &freed[2]);
+		ms[3] = new_state(str1, &freed[3]);
+		CHECK( 0, fd_sess_getsid(sess3, &str1, &str1len) );
+		ms[4] = new_state(str1, &freed[4]);
+		ms[5] = new_state(str1, &freed[5]);
+		ms[5]->opaque = g_opaque;
+		str2 = os0dup(str1, str1len);
+		CHECK( 1, str2 ? 1 : 0 );
+		
+		/* Store the six states */
+		CHECK( 0, fd_sess_state_store ( hdl1, sess1, &ms[0] ) );
+		CHECK( 0, fd_sess_state_store ( hdl2, sess1, &ms[1] ) );
+		CHECK( 0, fd_sess_state_store ( hdl1, sess2, &ms[2] ) );
+		CHECK( 0, fd_sess_state_store ( hdl2, sess2, &ms[3] ) );
+		CHECK( 0, fd_sess_state_store ( hdl1, sess3, &ms[4] ) );
+		CHECK( 0, fd_sess_state_store ( hdl2, sess3, &ms[5] ) );
+		
+		#if 0
+		fd_log_debug("%s", fd_sess_dump(FD_DUMP_TEST_PARAMS, sess1, 1));
+		fd_log_debug("%s", fd_sess_dump(FD_DUMP_TEST_PARAMS, sess2, 1));
+		fd_log_debug("%s", fd_sess_dump(FD_DUMP_TEST_PARAMS, sess3, 1));
+		#endif
+		
+		/* Destroy session 3 */
+		CHECK( 0, fd_sess_destroy( &sess3 ) );
+		CHECK( 0, freed[0] );
+		CHECK( 0, freed[1] );
+		CHECK( 0, freed[2] );
+		CHECK( 0, freed[3] );
+		CHECK( 1, freed[4] );
+		CHECK( 1, freed[5] );
+		
+		/* Destroy handler 2 */
+		CHECK( 0, fd_sess_handler_destroy( &hdl2, &testptr ) );
+		CHECK( 0, freed[0] );
+		CHECK( 1, freed[1] );
+		CHECK( 0, freed[2] );
+		CHECK( 1, freed[3] );
+		CHECK( 1, freed[4] );
+		CHECK( 1, freed[5] );
+		CHECK( 1, testptr == g_opaque ? 1 : 0 );
+		
+		#if 1
+		fd_log_debug("%s", fd_sess_dump(FD_DUMP_TEST_PARAMS, sess1, 1));
+		fd_log_debug("%s", fd_sess_dump(FD_DUMP_TEST_PARAMS, sess2, 1));
+		#endif
+		
+		/* Create again session 3, check that no data is associated to it */
+		CHECK( 0, fd_sess_fromsid( str2, str1len, &sess3, &new ) );
+		CHECK( 1, new ? 1 : 0 );
+		CHECK( 0, fd_sess_state_retrieve( hdl1, sess3, &tms ) );
+		CHECK( NULL, tms );
+		CHECK( 0, fd_sess_destroy( &sess3 ) );
+		free(str2);
+		
+		/* Timeout does call cleanups */
+		CHECK( 0, clock_gettime(CLOCK_REALTIME, &timeout) );
+		CHECK( 0, fd_sess_settimeout( sess2, &timeout) );
+		#if 1
+		fd_log_debug("%s", fd_sess_dump(FD_DUMP_TEST_PARAMS, sess1, 1));
+		fd_log_debug("%s", fd_sess_dump(FD_DUMP_TEST_PARAMS, sess2, 1));
+		#endif
+		timeout.tv_sec = 0;
+		timeout.tv_nsec= 50000000; /* 50 ms */
+		CHECK( 0, nanosleep(&timeout, NULL) );
+		CHECK( 0, freed[0] );
+		CHECK( 1, freed[1] );
+		CHECK( 1, freed[2] );
+		CHECK( 1, freed[3] );
+		CHECK( 1, freed[4] );
+		CHECK( 1, freed[5] );
+		
+		/* Check the last data can still be retrieved */
+		CHECK( 0, fd_sess_state_retrieve( hdl1, sess1, &tms ) );
+		CHECK( 1, tms ? 1 : 0);
+		CHECK( 0, fd_sess_getsid(sess1, &str1, &str1len) );
+		mycleanup(tms, str1, NULL);
+	}
+	
+	/* TODO: add tests on messages referencing sessions */
+	
+	/* That's all for the tests yet */
+	PASSTEST();
+} 
+