Initial commit
Change-Id: I6a4444e3c193dae437cd7929f4c39aba7b749efa
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"