Initial commit
Change-Id: I6a4444e3c193dae437cd7929f4c39aba7b749efa
diff --git a/contrib/CxDx/README b/contrib/CxDx/README
new file mode 100644
index 0000000..9554e44
--- /dev/null
+++ b/contrib/CxDx/README
@@ -0,0 +1,17 @@
+Date: Thu, 13 Oct 2011 14:01:40 -0300
+From: "Norberto R. de Goes Jr." <norberto@cpqd.com.br>
+To: help@freediameter.net
+Subject: [Help] Cx dictionary (samples "c" and "xml")
+
+Hi.
+
+Just a contribution, they were not tested.
+Best regards,
+
+--
+Norberto R. de Goes Jr.
+CPqD - DRC
+Tel.: +55 19 3705-4241 / Fax: +55 19 3705-6125
+norberto@cpqd.com.br
+www.cpqd.com.br
+
diff --git a/contrib/CxDx/dict_cxdx.c b/contrib/CxDx/dict_cxdx.c
new file mode 100644
index 0000000..dd58c8d
--- /dev/null
+++ b/contrib/CxDx/dict_cxdx.c
@@ -0,0 +1,1724 @@
+/*********************************************************************************************************
+ * Software License Agreement (BSD License) *
+ * Author: Norberto R. de Goes Jr. *
+ * *
+ * Copyright (c) 2011, Norberto R. de Goes Jr.. *
+ * *
+ * All rights reserved. *
+ * *
+ * Redistribution and use of this software in source and binary forms, with or without modification, are *
+ * permitted provided that the following conditions are met: *
+ * *
+ * * Redistributions of source code must retain the above *
+ * copyright notice, this list of conditions and the *
+ * following disclaimer. *
+ * *
+ * * Redistributions in binary form must reproduce the above *
+ * copyright notice, this list of conditions and the *
+ * following disclaimer in the documentation and/or other *
+ * materials provided with the distribution. *
+ * *
+ * * Neither the name of the Teraoka Laboratory nor the *
+ * names of its contributors may be used to endorse or *
+ * promote products derived from this software without *
+ * specific prior written permission of Teraoka Laboratory *
+ * *
+ * *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED *
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR *
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT *
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS *
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR *
+ * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF *
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
+ *********************************************************************************************************/
+
+
+/*********************************************************************************************************
+
+ === CpqD/DRC - Projeto ADRIMS - Mar/2011 ===
+ === Dicionario Dx/Cx ===
+ Baseado no "dict_sip" do FreeDiameter (www.freediameter.net)
+ Norberto R Goes Jr
+*********************************************************************************************************/
+
+
+#include <freeDiameter/extension.h>
+
+
+
+/* The content of this file follows the same structure as dict_base_proto.c */
+
+#define CHECK_dict_new( _type, _data, _parent, _ref ) \
+ CHECK_FCT( fd_dict_new( fd_g_config->cnf_dict, (_type), (_data), (_parent), (_ref)) );
+
+#define CHECK_dict_search( _type, _criteria, _what, _result ) \
+ CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, (_type), (_criteria), (_what), (_result), ENOENT) );
+
+
+struct local_rules_definition
+{
+ char *avp_name;
+ enum rule_position position;
+ int min;
+ int max;
+};
+
+/*==================================================================*/
+
+#define RULE_ORDER( _position ) ((((_position) == RULE_FIXED_HEAD) || ((_position) == RULE_FIXED_TAIL)) ? 1 : 0 )
+
+/*==================================================================*/
+
+#define PARSE_loc_rules( _rulearray, _parent, _avp_search_flag) { \
+ int __ar; \
+ for (__ar=0; __ar < sizeof(_rulearray) / sizeof((_rulearray)[0]); __ar++) { \
+ struct dict_rule_data __data = { NULL, \
+ (_rulearray)[__ar].position, \
+ 0, \
+ (_rulearray)[__ar].min, \
+ (_rulearray)[__ar].max}; \
+ __data.rule_order = RULE_ORDER(__data.rule_position); \
+ \
+ CHECK_FCT( fd_dict_search( \
+ fd_g_config->cnf_dict, \
+ DICT_AVP, \
+ _avp_search_flag, \
+ (_rulearray)[__ar].avp_name, \
+ &__data.rule_avp, 0 ) ); \
+ if ( !__data.rule_avp ) { \
+ TRACE_DEBUG(INFO, "AVP Not found: '%s'", (_rulearray)[__ar].avp_name ); \
+ return ENOENT; \
+ } \
+ \
+ CHECK_FCT_DO( fd_dict_new( fd_g_config->cnf_dict, DICT_RULE, &__data, _parent, NULL), \
+ { \
+ TRACE_DEBUG(INFO, "Error on rule with AVP '%s'", \
+ (_rulearray)[__ar].avp_name ); \
+ return EINVAL; \
+ } ); \
+ } \
+ }
+
+#define enumval_def_u32( _val_, _str_ ) \
+ { _str_, { .u32 = _val_ }}
+
+#define enumval_def_os( _len_, _val_, _str_ ) \
+ { _str_, { .os = { .data = (unsigned char *)_val_, .len = _len_ }}}
+
+
+/*==================================================================*/
+/*==================================================================*/
+/*==================================================================*/
+/*==================================================================*/
+
+int cxdx_dict_init(char * conffile)
+{
+
+#define VENDOR_3GPP_Id 10415
+
+
+ struct dict_object * vendor_dict;
+ {
+ struct dict_vendor_data vendor_data = { VENDOR_3GPP_Id, "3GPP" };
+ CHECK_dict_new (DICT_VENDOR, &vendor_data, NULL, &vendor_dict);
+ }
+
+
+ struct dict_object * cxdx_dict;
+ {
+ struct dict_application_data data = { 16777216 /* NRGJ */, "Diameter CxDx Application" };
+ CHECK_dict_new (DICT_APPLICATION, &data, vendor_dict, &cxdx_dict);
+ }
+
+
+ /* ##### AVP section #################################### */
+ {
+ struct dict_object * UTF8String_type;
+ struct dict_object * DiameterURI_type;
+
+ CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "UTF8String", &UTF8String_type);
+ CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "DiameterURI", &DiameterURI_type);
+
+ /* Digest AVPs: */
+
+ /* Visited-Network-Identifier */
+ {
+ struct dict_avp_data data =
+ {
+ 600, /* Code */
+ VENDOR_3GPP_Id, /* Vendor */
+ "Visited-Network-Identifier", /* Name */
+ AVP_FLAG_MANDATORY | AVP_FLAG_VENDOR, /* Fixed flags */
+ AVP_FLAG_MANDATORY | AVP_FLAG_VENDOR, /* Fixed flag values */
+ AVP_TYPE_OCTETSTRING /* base type of data */
+ };
+ CHECK_dict_new( DICT_AVP, &data , UTF8String_type, NULL);
+ }
+
+ /* Public-Identity */
+ {
+ struct dict_avp_data data =
+ {
+ 601, /* Code */
+ VENDOR_3GPP_Id, /* Vendor */
+ "Public-Identity", /* Name */
+ AVP_FLAG_MANDATORY | AVP_FLAG_VENDOR, /* Fixed flags */
+ AVP_FLAG_MANDATORY | AVP_FLAG_VENDOR, /* Fixed flag values */
+ AVP_TYPE_OCTETSTRING /* base type of data */
+ };
+ CHECK_dict_new( DICT_AVP, &data , UTF8String_type, NULL);
+ }
+
+
+ /* Server-Name */
+ {
+ struct dict_avp_data data =
+ {
+ 602, /* Code */
+ VENDOR_3GPP_Id, /* Vendor */
+ "Server-Name", /* Name */
+ AVP_FLAG_MANDATORY | AVP_FLAG_VENDOR, /* Fixed flags */
+ AVP_FLAG_MANDATORY | AVP_FLAG_VENDOR, /* Fixed flag values */
+ AVP_TYPE_OCTETSTRING /* base type of data */
+ };
+ CHECK_dict_new( DICT_AVP, &data , DiameterURI_type/*UTF8String_type*/, NULL);
+ }
+
+
+ /* Optional-Capability */
+ {
+ struct dict_avp_data data =
+ {
+ 605, /* Code */
+ VENDOR_3GPP_Id, /* Vendor */
+ "Optional-Capability", /* Name */
+ AVP_FLAG_MANDATORY | AVP_FLAG_VENDOR, /* Fixed flags */
+ AVP_FLAG_MANDATORY | AVP_FLAG_VENDOR, /* Fixed flag values */
+ AVP_TYPE_UNSIGNED32 /* base type of data */
+ };
+ CHECK_dict_new( DICT_AVP, &data , NULL, NULL);
+ }
+
+
+ /* Feature-List-ID */
+ {
+ struct dict_avp_data data =
+ {
+ 629, /* Code */
+ VENDOR_3GPP_Id, /* Vendor */
+ "Feature-List-ID", /* Name */
+ AVP_FLAG_VENDOR, /* Fixed flags */
+ AVP_FLAG_VENDOR, /* Fixed flag values */
+ AVP_TYPE_UNSIGNED32 /* base type of data */
+ };
+ CHECK_dict_new( DICT_AVP, &data , NULL, NULL);
+ }
+
+
+ /* Feature-List */
+ {
+ struct dict_avp_data data =
+ {
+ 630, /* Code */
+ VENDOR_3GPP_Id, /* Vendor */
+ "Feature-List", /* Name */
+ AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, /* Fixed flags */
+ AVP_FLAG_MANDATORY, /* Fixed flag values */
+ AVP_TYPE_UNSIGNED32 /* base type of data */
+ };
+ CHECK_dict_new( DICT_AVP, &data , NULL, NULL);
+ }
+
+ /* Server-Capabilities */
+ {
+ struct dict_object * avp;
+ struct dict_avp_data data =
+ {
+ 603, /* Code */
+ VENDOR_3GPP_Id, /* Vendor */
+ "Server-Capabilities", /* Name */
+ AVP_FLAG_MANDATORY | AVP_FLAG_VENDOR, /* Fixed flags */
+ AVP_FLAG_MANDATORY | AVP_FLAG_VENDOR, /* Fixed flag values */
+ AVP_TYPE_GROUPED /* base type of data */
+ };
+
+ struct local_rules_definition rules[] =
+ {
+ { "Vendor-Id", RULE_REQUIRED, -1, 1 },
+ { "Feature-List-ID", RULE_REQUIRED, -1, 1 },
+ { "Feature-List", RULE_REQUIRED, -1, 1 }
+ };
+
+ CHECK_dict_new (DICT_AVP, &data , NULL, &avp);
+ PARSE_loc_rules(rules, avp, AVP_BY_NAME_ALL_VENDORS );
+ }
+
+
+
+ /* User-Authorization-Type */
+ {
+ struct dict_avp_data data =
+ {
+ 623, /* Code */
+ VENDOR_3GPP_Id, /* Vendor */
+ "User-Authorization-Type", /* Name */
+ AVP_FLAG_MANDATORY | AVP_FLAG_VENDOR, /* Fixed flags */
+ AVP_FLAG_MANDATORY | AVP_FLAG_VENDOR, /* Fixed flag values */
+ AVP_TYPE_OCTETSTRING /* base type of data */
+ };
+ CHECK_dict_new( DICT_AVP, &data , UTF8String_type, NULL);
+ }
+
+
+ /* Supported-Features */
+ {
+ struct dict_object * avp;
+ struct dict_avp_data data =
+ {
+ 628, /* Code */
+ VENDOR_3GPP_Id, /* Vendor */
+ "Supported-Features", /* Name */
+ AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, /* Fixed flags */
+ AVP_FLAG_MANDATORY, /* Fixed flag values */
+ AVP_TYPE_GROUPED /* base type of data */
+ };
+
+ struct local_rules_definition rules[] =
+ {
+ { "Vendor-Id", RULE_REQUIRED, -1, 1 },
+ { "Feature-List-ID", RULE_REQUIRED, -1, 1 },
+ { "Feature-List", RULE_REQUIRED, -1, 1 }
+ };
+
+ CHECK_dict_new (DICT_AVP, &data , NULL, &avp);
+ PARSE_loc_rules(rules, avp, AVP_BY_NAME_ALL_VENDORS );
+ }
+
+
+
+
+ } /* end AVP section */
+
+
+
+ /* ### Command section ############################# */
+ {
+ /* User-Authorization-Request (UAR) Command */
+ {
+ /*
+ The User-Authorization-Request (UAR) is indicated by the Command-Code
+ set to 283 and the Command Flags' 'R' bit set. The Diameter client
+ in a SIP server sends this command to the Diameter server to request
+ authorization for the SIP User Agent to route a SIP REGISTER request.
+ Because the SIP REGISTER request implicitly carries a permission to
+ bind an AOR to a contact address, the Diameter client uses the
+ Diameter UAR as a first authorization request towards the Diameter
+ server to authorize the registration. For instance, the Diameter
+ server can verify that the AOR is a legitimate user of the realm.
+
+ The Diameter client in the SIP server requests authorization for one
+ of the possible values defined in the SIP-User-Authorization-Type AVP
+ (Section 9.10).
+
+ The user name used for authentication of the user is conveyed in a
+ User-Name AVP (defined in the Diameter base protocol, RFC 3588
+ [RFC3588]). The location of the authentication user name in the SIP
+ REGISTER request varies depending on the authentication mechanism.
+ When the authentication mechanism is HTTP Digest as defined in RFC
+ 2617 [RFC2617], the authentication user name is found in the
+ "username" directive of the SIP Authorization header field value.
+ This Diameter SIP application only provides support for HTTP Digest
+ authentication in SIP; other authentication mechanisms are not
+ currently supported.
+
+ The SIP or SIPS URI to be registered is conveyed in the SIP-AOR AVP
+ (Section 9.8). Typically this SIP or SIPS URI is found in the To
+ header field value of the SIP REGISTER request that triggered the
+ Diameter UAR message.
+
+ The SIP-Visited-Network-Id AVP indicates the network that is
+ providing SIP services (e.g., SIP proxy functionality or any other
+ kind of services) to the SIP User Agent.
+
+ The Message Format of the UAR command is as follows:
+
+
+ < UAR> ::=< Diameter Header: 300, REQ, PXY, 16777216 >
+ < Session-Id >
+ { Vendor-Specific-Application-Id }
+ { Auth-Session-State }
+ { Origin-Host }
+ { Origin-Realm }
+ [ Destination-Host ]
+ { Destination-Realm }
+ { User-Name }
+ *[ Supported-Features ]
+ { Public-Identity }
+ { Visited-Network-Identifier }
+ [ User-Authorization-Type ]
+ [ UAR-Flags ]
+ *[ AVP ]
+ *[ Proxy-Info ]
+ *[ Route-Record ]
+ */
+
+ struct dict_object * cmd;
+ struct dict_cmd_data data =
+ {
+ 300, /* Code */
+ "User-Authorization-Request", /* Name */
+ CMD_FLAG_REQUEST | CMD_FLAG_PROXIABLE | CMD_FLAG_ERROR, /* Fixed flags */
+ CMD_FLAG_REQUEST | CMD_FLAG_PROXIABLE /* Fixed flag values */
+ };
+
+ struct local_rules_definition rules[] =
+ {
+ { "Session-Id", RULE_FIXED_HEAD, -1, 1 },
+ { "Vendor-Specific-Application-Id", RULE_REQUIRED, -1, 1 },
+ { "Auth-Session-State", RULE_REQUIRED, -1, 1 },
+ { "Origin-Host", RULE_REQUIRED, -1, 1 },
+ { "Origin-Realm", RULE_REQUIRED, -1, 1 },
+ // { "Destination-Host", RULE_OPTIONAL, -1, 1 },
+ { "Destination-Realm", RULE_REQUIRED, -1, 1 },
+ { "User-Name", RULE_REQUIRED, -1, 1 },
+ // { "Supported-Features", RULE_OPTIONAL, -1, -1 },
+ { "Public-Identity", RULE_REQUIRED, -1, 1 },
+ { "Visited-Network-Identifier", RULE_REQUIRED, -1, 1 },
+ // { "UAR-Flags", RULE_OPTIONAL, -1, 1 },
+ // { "User-Authorization-Type", RULE_OPTIONAL, -1, 1 },
+ // { "Proxy-Info", RULE_OPTIONAL, -1, -1 },
+ // { "Route-Record", RULE_OPTIONAL, -1, -1 }
+ };
+
+ CHECK_dict_new( DICT_COMMAND, &data , cxdx_dict, &cmd);
+ PARSE_loc_rules( rules, cmd, AVP_BY_NAME_ALL_VENDORS);
+ }
+
+ /* User-Authorization-Answer (UAA) Command */
+ {
+ /*
+ The User-Authorization-Answer (UAA) is indicated by the Command-Code
+ set to 283 and the Command Flags' 'R' bit cleared. The Diameter
+ server sends this command in response to a previously received
+ Diameter User-Authorization-Request (UAR) command. The Diameter
+ server indicates the result of the requested registration
+ authorization. Additionally, the Diameter server may indicate a
+ collection of SIP capabilities that assists the Diameter client to
+ select a SIP proxy to the AOR under registration.
+
+
+ In addition to the values already defined in RFC 3588 [RFC3588], the
+ Result-Code AVP may contain one of the values defined in
+ Section 10.1.
+
+ Whenever the Diameter server fails to process the Diameter UAR
+ message, it MUST stop processing and return the relevant error in the
+ Diameter UAA message. When there is success in the process, the
+ Diameter server MUST set the code to DIAMETER_SUCCESS in the Diameter
+ UAA message.
+
+ If the Diameter server requires a User-Name AVP value to process the
+ Diameter UAR request, but the Diameter UAR message did not contain a
+ User-Name AVP value, the Diameter server MUST set the Result-Code AVP
+ value to DIAMETER_USER_NAME_REQUIRED (see Section 10.1.2) and return
+ it in a Diameter UAA message. Upon reception of this Diameter UAA
+ message with the Result-Code AVP value set to
+ DIAMETER_USER_NAME_REQUIRED, the SIP server typically requests
+ authentication by sending a SIP 401 (Unauthorized) or SIP 407 (Proxy
+ Authentication Required) response back to the originator.
+
+ When the authorization procedure succeeds, the Diameter server
+ constructs a User-Authorization-Answer (UAA) message that MUST
+ include (1) the address of the SIP server already assigned to the
+ user name, (2) the capabilities needed by the SIP server (Diameter
+ client) to select another SIP server for the user, or (3) a
+ combination of the previous two options.
+
+ If the Diameter server is already aware of a SIP server allocated to
+ the user, the Diameter UAA message contains the address of that SIP
+ server.
+
+ The Diameter UAA message contains the capabilities required by a SIP
+ server to trigger and execute services. It is required that these
+ capabilities are present in the Diameter UAA message due to the
+ possibility that the Diameter client (in the SIP server) allocates a
+ different SIP server to trigger and execute services for that
+ particular user.
+
+ If a User-Name AVP is present in the Diameter UAR message, then the
+ Diameter server MUST verify the existence of the user in the realm,
+ i.e., the User-Name AVP value is a valid user within that realm. If
+ the Diameter server does not recognize the user name received in the
+ User-Name AVP, the Diameter server MUST build a Diameter User-
+ Authorization-Answer (UAA) message and MUST set the Result-Code AVP
+ to DIAMETER_ERROR_USER_UNKNOWN.
+
+
+ If a User-Name AVP is present in the Diameter UAR message, then the
+ Diameter server MUST authorize that User-Name AVP value is able to
+ register the SIP or SIPS URI included in the SIP-AOR AVP. If this
+ authorization fails, the Diameter server must set the Result-Code AVP
+ to DIAMETER_ERROR_IDENTITIES_DONT_MATCH and send it in a Diameter
+ User-Authorization-Answer (UAA) message.
+
+ Note: Correlation between User-Name and SIP-AOR AVP values is
+ required in order to avoid registration of a SIP-AOR allocated to
+ another user.
+
+ If there is a SIP-Visited-Network-Id AVP in the Diameter UAR message,
+ and the SIP-User-Authorization-Type AVP value received in the
+ Diameter UAR message is set to REGISTRATION or REGISTRATION&
+ CAPABILITIES, then the Diameter server SHOULD verify whether the user
+ is allowed to roam into the network specified in the
+ SIP-Visited-Network-Id AVP in the Diameter UAR message. If the user
+ is not allowed to roam into that network, the Diameter AAA server
+ MUST set the Result-Code AVP value in the Diameter UAA message to
+ DIAMETER_ERROR_ROAMING_NOT_ALLOWED.
+
+ If the SIP-User-Authorization-Type AVP value received in the Diameter
+ UAR message is set to REGISTRATION or REGISTRATION&CAPABILITIES, then
+ the Diameter server SHOULD verify whether the SIP-AOR AVP value is
+ authorized to register in the Home Realm. Where the SIP AOR is not
+ authorized to register in the Home Realm, the Diameter server MUST
+ set the Result-Code AVP to DIAMETER_AUTHORIZATION_REJECTED and send
+ it in a Diameter UAA message.
+
+ When the SIP-User-Authorization-Type AVP is not present in the
+ Diameter UAR message, or when it is present and its value is set to
+ REGISTRATION, then:
+
+ o If the Diameter server is not aware of any previous registration
+ of the user name (including registrations of other SIP AORs
+ allocated to the same user name), then the Diameter server does
+ not know of any SIP server allocated to the user. In this case,
+ the Diameter server MUST set the Result-Code AVP value to
+ DIAMETER_FIRST_REGISTRATION in the Diameter UAA message, and the
+ Diameter server SHOULD include the required SIP server
+ capabilities in the SIP-Server-Capabilities AVP value in the
+ Diameter UAA message. The SIP-Server-Capabilities AVP assists the
+ Diameter client (SIP server) to select an appropriate SIP server
+ for the user, according to the required capabilities.
+
+ o In some cases, the Diameter server is aware of a previously
+ assigned SIP server for the same or different SIP AORs allocated
+ to the same user name. In these cases, re-assignment of a new SIP
+ server may or may not be needed, depending on the capabilities of
+ the SIP server. The Diameter server MUST always include the
+ allocated SIP server URI in the SIP-Server-URI AVP of the UAA
+ message. If the Diameter server does not return the SIP
+ capabilities, the Diameter server MUST set the Result-Code AVP in
+ the Diameter UAA message to DIAMETER_SUBSEQUENT_REGISTRATION.
+ Otherwise (i.e., if the Diameter server includes a
+ SIP-Server-Capabilities AVP), then the Diameter server MUST set
+ the Result-Code AVP in the Diameter UAA message to
+ DIAMETER_SERVER_SELECTION. Then the Diameter client determines,
+ based on the received information, whether it needs to select a
+ new SIP server.
+
+ When the SIP-User-Authorization-Type AVP value received in the
+ Diameter UAR message is set to REGISTRATION&CAPABILITIES, then
+ Diameter Server MUST return the list of capabilities in the
+ SIP-Server-Capabilities AVP value of the Diameter UAA message, it
+ MUST set the Result-Code to DIAMETER_SUCCESS, and it MUST NOT return
+ a SIP-Server-URI AVP. The SIP-Server-Capabilities AVP enables the
+ SIP server (Diameter client) to select another appropriate SIP server
+ for invoking and executing services for the user, depending on the
+ required capabilities. The Diameter server MAY leave the list of
+ capabilities empty to indicate that any SIP server can be selected.
+
+ When the SIP-User-Authorization-Type AVP value received in the
+ Diameter UAR message is set to DEREGISTRATION, then:
+
+ o If the Diameter server is aware of a SIP server assigned to the
+ SIP AOR under deregistration, the Diameter server MUST set the
+ Result-Code AVP to DIAMETER_SUCCESS and MUST set the
+ SIP-Server-URI AVP value to the known SIP server, and return them
+ in the Diameter UAA message.
+
+ o If the Diameter server is not aware of a SIP server assigned to
+ the SIP AOR under deregistration, then the Diameter server MUST
+ set the Result-Code AVP in the Diameter UAA message to
+ DIAMETER_ERROR_IDENTITY_NOT_REGISTERED.
+
+ The Message Format of the UAA command is as follows:
+
+ <UAA> ::= < Diameter Header: 283, PXY >
+ < Session-Id >
+ { Auth-Application-Id }
+ { Auth-Session-State }
+ { Result-Code }
+ { Origin-Host }
+ { Origin-Realm }
+ [ SIP-Server-URI ]
+ [ SIP-Server-Capabilities ]
+ [ Authorization-Lifetime ]
+ [ Auth-Grace-Period ]
+ [ Redirect-Host ]
+ [ Redirect-Host-Usage ]
+ [ Redirect-Max-Cache-Time ]
+ * [ Proxy-Info ]
+ * [ Route-Record ]
+ * [ AVP ]
+
+
+ */
+ struct dict_object * cmd;
+ struct dict_cmd_data data =
+ {
+ 300, /* Code */
+ "User-Authorization-Answer", /* Name */
+ CMD_FLAG_REQUEST | CMD_FLAG_PROXIABLE | CMD_FLAG_ERROR, /* Fixed flags */
+ CMD_FLAG_PROXIABLE /* Fixed flag values */
+ };
+
+ struct local_rules_definition rules[] =
+ {
+ { "Session-Id", RULE_FIXED_HEAD, -1, 1 },
+ { "Auth-Application-Id", RULE_REQUIRED, -1, 1 },
+ { "Auth-Session-State", RULE_REQUIRED, -1, 1 },
+ { "Result-Code", RULE_REQUIRED, -1, 1 },
+ { "Origin-Host", RULE_REQUIRED, -1, 1 },
+ { "Origin-Realm", RULE_REQUIRED, -1, 1 },
+ { "Proxy-Info", RULE_OPTIONAL, -1, -1 },
+ { "Route-Record", RULE_OPTIONAL, -1, -1 }
+ };
+
+ CHECK_dict_new( DICT_COMMAND, &data , cxdx_dict, &cmd);
+ PARSE_loc_rules( rules, cmd, AVP_BY_NAME );
+ }
+
+
+
+
+
+#if 0 /* TODO - NRGJ : alterar conforme RFC-3GPP : */
+
+ /* Multimedia-Auth-Request (MAR) Command */
+ {
+ /*
+ The Multimedia-Auth-Request (MAR) command is indicated by the
+ Command-Code set to 286 and the Command Flags' 'R' bit set. The
+ Diameter client in a SIP server sends this command to the Diameter
+ server to request that the Diameter server authenticate and authorize
+ a user attempt to use some SIP service (in this context, SIP service
+ can be something as simple as a SIP subscription or using the proxy
+ services for a SIP request).
+
+ The MAR command may also register the SIP server's own URI to the
+ Diameter server, so that future LIR/LIA messages can return this URI.
+ If the SIP server is acting as a SIP registrar (see examples in
+ Sections 6.2 and 6.3), its Diameter client MUST include a SIP-
+ Server-URI AVP in the MAR command. In any other cases (see example
+ in Section 6.4), its Diameter client MUST NOT include a SIP-Server-
+ URI AVP in the MAR command.
+
+ The SIP-Method AVP MUST include the SIP method name of the SIP
+ request that triggered this Diameter MAR message. The Diameter
+ server can use this AVP to authorize some SIP requests depending on
+ the method.
+
+ The Diameter MAR message MUST include a SIP-AOR AVP. The SIP-AOR AVP
+ indicates the target of the SIP request. The value of the AVP is
+ extracted from different places in SIP request, depending on the
+ semantics of the SIP request. For SIP REGISTER messages the SIP-AOR
+ AVP value indicates the intended public user identity under
+ registration, and it is the SIP or SIPS URI populated in the To
+ header field value (addr-spec as per RFC 3261 [RFC3261]) of the SIP
+ REGISTER request. For other types of SIP requests, such as INVITE,
+ SUBSCRIBE, MESSAGE, etc., the SIP-AOR AVP value indicates the
+ intended destination of the request. This is typically populated in
+ the Request-URI of the SIP request. Extracting the SIP-AOR AVP value
+ from the proper SIP header field is the Diameter client's
+ responsibility. Extensions to SIP (new SIP methods or new semantics)
+ may require the SIP-AOR to be extracted from other parts of the
+ request.
+
+ If the SIP request includes some sort of authentication information,
+ the Diameter client MUST include the user name, extracted from the
+ authentication information of the SIP request, in the User-Name AVP
+ value.
+
+ The Message Format of the MAR command is as follows:
+
+ <MAR> ::= < Diameter Header: 286, REQ, PXY >
+ < Session-Id >
+ { Auth-Application-Id }
+ { Auth-Session-State }
+ { Origin-Host }
+ { Origin-Realm }
+ { Destination-Realm }
+ { SIP-AOR }
+ { SIP-Method }
+ [ Destination-Host ]
+ [ User-Name ]
+ [ SIP-Server-URI ]
+ [ SIP-Number-Auth-Items ]
+ [ SIP-Auth-Data-Item ]
+ * [ Proxy-Info ]
+ * [ Route-Record ]
+ * [ AVP ]
+
+ */
+
+ struct dict_object * cmd;
+ struct dict_cmd_data data =
+ {
+ 303, /* Code */
+ "Multimedia-Auth-Request", /* Name */
+ CMD_FLAG_REQUEST | CMD_FLAG_PROXIABLE | CMD_FLAG_ERROR, /* Fixed flags */
+ CMD_FLAG_REQUEST | CMD_FLAG_PROXIABLE /* Fixed flag values */
+ };
+
+ struct local_rules_definition rules[] =
+ { { "Session-Id", RULE_FIXED_HEAD, -1, 1 }
+ ,{ "Auth-Application-Id", RULE_REQUIRED, -1, 1 }
+ ,{ "Auth-Session-State", RULE_REQUIRED, -1, 1 }
+ ,{ "Origin-Host", RULE_REQUIRED, -1, 1 }
+ ,{ "Origin-Realm", RULE_REQUIRED, -1, 1 }
+ ,{ "Destination-Realm", RULE_REQUIRED, -1, 1 }
+ ,{ "SIP-AOR", RULE_REQUIRED, -1, 1 }
+ ,{ "SIP-Method", RULE_REQUIRED, -1, 1 }
+ ,{ "Destination-Host", RULE_OPTIONAL, -1, 1 }
+ ,{ "User-Name", RULE_OPTIONAL, -1, 1 }
+ ,{ "SIP-Server-URI", RULE_OPTIONAL, -1, 1 }
+ ,{ "SIP-Number-Auth-Items", RULE_OPTIONAL, -1, 1 }
+ ,{ "SIP-Auth-Data-Item", RULE_OPTIONAL, -1, 1 }
+ ,{ "Proxy-Info", RULE_OPTIONAL, -1, -1 }
+ ,{ "Route-Record", RULE_OPTIONAL, -1, -1 }
+
+ };
+
+ CHECK_dict_new( DICT_COMMAND, &data , cxdx_dict, &cmd);
+ PARSE_loc_rules( rules, cmd, AVP_BY_NAME );
+ }
+ /* Multimedia-Auth-Answer (MAA) Command */
+ {
+ /*
+
+ The Multimedia-Auth-Answer (MAA) is indicated by the Command-Code set
+ to 286 and the Command Flags' 'R' bit cleared. The Diameter server
+ sends this command in response to a previously received Diameter
+ Multimedia-Auth-Request (MAR) command.
+
+ In addition to the values already defined in RFC 3588 [RFC3588], the
+ Result-Code AVP may contain one of the values defined in
+ Section 10.1.
+
+ If the Diameter server requires a User-Name AVP value to process the
+ Diameter MAR request, but the Diameter MAR message did not contain a
+ User-Name AVP value, the Diameter server MUST set the Result-Code AVP
+ value to DIAMETER_USER_NAME_REQUIRED (see Section 10.1.2) and return
+ it in a Diameter MAA message. The Diameter server MAY include a
+ SIP-Number-Auth-Items AVP and one or more SIP-Auth-Data-Item AVPs
+ with authentication information (e.g., a challenge). Upon reception
+ of this Diameter MAA message with the Result-Code AVP value set to
+ DIAMETER_USER_NAME_REQUIRED, the SIP server typically requests
+ authentication by generating a SIP 401 (Unauthorized) or SIP 407
+ (Proxy Authentication Required) response back to the originator.
+
+ If the User-Name AVP is present in the Diameter MAR message, the
+ Diameter server MUST verify the existence of the user in the realm,
+ i.e., the User-Name AVP value is a valid user within that realm. If
+ the Diameter server does not recognize the user name received in the
+ User-Name AVP, the Diameter server MUST build a Diameter
+ Multimedia-Auth-Answer (MAA) message and MUST set the Result-Code AVP
+ to DIAMETER_ERROR_USER_UNKNOWN.
+
+ If the SIP-Methods AVP value of the Diameter MAR message is set to
+ REGISTER and a User-Name AVP is present, then the Diameter server
+ MUST authorize that User-Name AVP value is able to use the URI
+ included in the SIP-AOR AVP. If this authorization fails, the
+ Diameter server must set the Result-Code AVP to
+ DIAMETER_ERROR_IDENTITIES_DONT_MATCH and send it in a Diameter
+ Multimedia-Auth-Answer (MAA) message.
+
+ Note: Correlation between User-Name and SIP-AOR AVP values is only
+ required for SIP REGISTER request, to prevent a user from
+ registering a SIP-AOR allocated to another user. In other types
+ of SIP requests (e.g., INVITE), the SIP-AOR indicates the intended
+ destination of the request, rather than the originator of it.
+
+ The Diameter server MUST verify whether the authentication scheme
+ (SIP-Authentication-Scheme AVP value) indicated in the grouped
+ SIP-Auth-Data-Item AVP is supported or not. If that authentication
+ scheme is not supported, then the Diameter server MUST set the
+ Result-Code AVP to DIAMETER_ERROR_AUTH_SCHEME_NOT_SUPPORTED and send
+ it in a Diameter Multimedia-Auth-Answer (MAA) message.
+
+ If the SIP-Number-Auth-Items AVP is present in the Diameter MAR
+ message, it indicates the number of authentication data items that
+ the Diameter client is requesting. It is RECOMMENDED that the
+ Diameter server, when building the Diameter MAA message, includes a
+ number of SIP-Auth-Data-Item AVPs that are a subset of the
+ authentication data items requested by the Diameter client in the
+ SIP-Number-Auth-Items AVP value of the Diameter MAR message.
+
+ If the SIP-Server-URI AVP is present in the Diameter MAR message,
+ then the Diameter server MUST compare the stored SIP server (assigned
+ to the user) with the SIP-Server-URI AVP value (received in the
+ Diameter MAR message). If they don't match, the Diameter server MUST
+ temporarily save the newly received SIP server assigned to the user,
+ and MUST set an "authentication pending" flag for the user. If they
+ match, the Diameter server shall clear the "authentication pending"
+ flag for the user.
+
+ In any other situation, if there is a success in processing the
+ Diameter MAR command and the Diameter server stored the
+ SIP-Server-URI, the Diameter server MUST set the Result-Code AVP
+ value to DIAMETER_SUCCESS and return it in a Diameter MAA message.
+
+ If there is a success in processing the Diameter MAR command, but the
+ Diameter server does not store the SIP-Server-URI because the AVP was
+ not present in the Diameter MAR command, then the Diameter server
+ MUST set the Result-Code AVP value to either:
+
+ 1. DIAMETER_SUCCESS_AUTH_SENT_SERVER_NOT_STORED, if the Diameter
+ server is sending authentication credentials to create a
+ challenge.
+
+ 2. DIAMETER_SUCCESS_SERVER_NAME_NOT_STORED, if the Diameter server
+ successfully authenticated the user and authorized the SIP server
+ to proceed with the SIP request.
+
+ Otherwise, the Diameter server MUST set the Result-Code AVP value to
+ DIAMETER_UNABLE_TO_COMPLY, and it MUST NOT include any
+ SIP-Auth-Data-Item AVP.
+
+ The Message Format of the MAA command is as follows:
+
+ <MAA> ::= < Diameter Header: 286, PXY >
+ < Session-Id >
+ { Auth-Application-Id }
+ { Result-Code }
+ { Auth-Session-State }
+ { Origin-Host }
+ { Origin-Realm }
+ [ User-Name ]
+ [ SIP-AOR ]
+ [ SIP-Number-Auth-Items ]
+ * [ SIP-Auth-Data-Item ]
+ [ Authorization-Lifetime ]
+ [ Auth-Grace-Period ]
+ [ Redirect-Host ]
+ [ Redirect-Host-Usage ]
+ [ Redirect-Max-Cache-Time ]
+ * [ Proxy-Info ]
+ * [ Route-Record ]
+ * [ AVP ]
+
+ */
+ struct dict_object * cmd;
+ struct dict_cmd_data data = {
+ 286, /* Code */
+ "Multimedia-Auth-Answer", /* Name */
+ CMD_FLAG_REQUEST | CMD_FLAG_PROXIABLE | CMD_FLAG_ERROR, /* Fixed flags */
+ CMD_FLAG_PROXIABLE /* Fixed flag values */
+ };
+ struct local_rules_definition rules[] =
+ { { "Session-Id", RULE_FIXED_HEAD, -1, 1 }
+ ,{ "Auth-Application-Id", RULE_REQUIRED, -1, 1 }
+ ,{ "Result-Code", RULE_REQUIRED, -1, 1 }
+ ,{ "Auth-Session-State", RULE_REQUIRED, -1, 1 }
+ ,{ "Origin-Host", RULE_REQUIRED, -1, 1 }
+ ,{ "Origin-Realm", RULE_REQUIRED, -1, 1 }
+ ,{ "User-Name", RULE_OPTIONAL, -1, 1 }
+ ,{ "SIP-AOR", RULE_OPTIONAL, -1, 1 }
+ ,{ "SIP-Number-Auth-Items", RULE_OPTIONAL, -1, 1 }
+ ,{ "SIP-Auth-Data-Item", RULE_OPTIONAL, -1, -1 }
+ ,{ "Authorization-Lifetime", RULE_OPTIONAL, -1, 1 }
+ ,{ "Auth-Grace-Period", RULE_OPTIONAL, -1, 1 }
+ ,{ "Redirect-Host", RULE_OPTIONAL, -1, 1 }
+ ,{ "Redirect-Host-Usage", RULE_OPTIONAL, -1, 1 }
+ ,{ "Redirect-Max-Cache-Time", RULE_OPTIONAL, -1, 1 }
+ ,{ "Proxy-Info", RULE_OPTIONAL, -1, -1 }
+ ,{ "Route-Record", RULE_OPTIONAL, -1, -1 }
+
+ };
+
+ CHECK_dict_new( DICT_COMMAND, &data , cxdx_dict, &cmd);
+ PARSE_loc_rules( rules, cmd, AVP_BY_NAME );
+ }
+ /* Server-Assignment-Request (SAR) Command */
+ {
+ /*
+
+ The Server-Assignment-Request (SAR) command is indicated by the
+ Command-Code set to 284 and the Command Flags' 'R' bit set. The
+ Diameter client in a SIP server sends this command to the Diameter
+ server to indicate the completion of the authentication process and
+ to request that the Diameter server store the URI of the SIP server
+ that is currently serving the user. The main functions of the
+ Diameter SAR command are to inform the Diameter server of the URI of
+ the SIP server allocated to the user, and to store or clear it from
+ the Diameter server. Additionally, the Diameter client can request
+ to download the user profile or part of it.
+
+ During the registration procedure, a SIP server becomes assigned to
+ the user. The Diameter client in the assigned SIP server MUST
+ include its own URI in the SIP-Server-URI AVP of the
+ Server-Assignment-Request (SAR) Diameter message and send it to the
+ Diameter server. The Diameter server then becomes aware of the
+ allocation of the SIP server to the user name and the server's URI.
+
+ The Diameter client in the SIP server MAY send a Diameter SAR message
+ because of other reasons. These reasons are identified in the
+ SIP-Server-Assignment-Type AVP (Section 9.4) value. For instance, a
+ Diameter client in a SIP server may contact the Diameter server to
+ request deregistration of a user, to inform the Diameter server of an
+ authentication failure, or just to download the user profile. For a
+ complete description of all the SIP-Server-Assignment-Type AVP
+ values, see Section 9.4.
+
+ Typically the reception of a SIP REGISTER request in a SIP server
+ will trigger the Diameter client in the SIP server to send the
+ Diameter SAR message. However, if a SIP server is receiving other
+ SIP request, such as INVITE, and the SIP server does not have the
+ user profile, the Diameter client in the SIP server may send the
+ Diameter SAR message to the Diameter server in order to download the
+ user profile and make the Diameter server aware of the SIP server
+ assigned to the user.
+ The user profile is an important piece of information that dictates
+ the behavior of the SIP server when triggering or providing services
+ for the user. Typically the user profile is divided into:
+
+ o Services to be rendered to the user when the user is registered
+ and initiates a SIP request.
+
+ o Services to be rendered to the user when the user is registered
+ and a SIP request destined to that user arrives to the SIP proxy.
+
+ o Services to be rendered to the user when the user is not
+ registered and a SIP request destined to that user arrives to the
+ SIP proxy.
+
+ The SIP-Server-Assignment-Type AVP indicates the reason why the
+ Diameter client (SIP server) contacted the Diameter server. If the
+ Diameter client sets the SIP-Server-Assignment-Type AVP value to
+ REGISTRATION, RE_REGISTRATION, UNREGISTERED_USER, NO_ASSIGNMENT,
+ AUTHENTICATION_FAILURE or AUTHENTICATION_TIMEOUT, the Diameter client
+ MUST include exactly one SIP-AOR AVP in the Diameter SAR message.
+
+ The SAR message MAY contain zero or more SIP-Supported-User-Data-Type
+ AVPs. Each of them contains a type of user data understood by the
+ SIP server. This allows the Diameter client to provide an indication
+ to the Diameter server of the different format of user data
+ understood by the SIP server. The Diameter server uses this
+ information to select one or more SIP-User-Data AVPs that will be
+ included in the SAA message.
+
+ The Message Format of the SAR command is as follows:
+
+ <SAR> ::= < Diameter Header: 284, REQ, PXY >
+ < Session-Id >
+ { Auth-Application-Id }
+ { Auth-Session-State }
+ { Origin-Host }
+ { Origin-Realm }
+ { Destination-Realm }
+ { SIP-Server-Assignment-Type }
+ { SIP-User-Data-Already-Available }
+ [ Destination-Host ]
+ [ User-Name ]
+ [ SIP-Server-URI ]
+ * [ SIP-Supported-User-Data-Type ]
+ * [ SIP-AOR ]
+ * [ Proxy-Info ]
+ * [ Route-Record ]
+ * [ AVP ]
+ */
+ struct dict_object * cmd;
+ struct dict_cmd_data data = {
+ 284, /* Code */
+ "Server-Assignment-Request", /* Name */
+ CMD_FLAG_REQUEST | CMD_FLAG_PROXIABLE | CMD_FLAG_ERROR, /* Fixed flags */
+ CMD_FLAG_REQUEST | CMD_FLAG_PROXIABLE /* Fixed flag values */
+ };
+ struct local_rules_definition rules[] =
+ { { "Session-Id", RULE_FIXED_HEAD, -1, 1 }
+ ,{ "Auth-Application-Id", RULE_REQUIRED, -1, 1 }
+ ,{ "Auth-Session-State", RULE_REQUIRED, -1, 1 }
+ ,{ "Origin-Host", RULE_REQUIRED, -1, 1 }
+ ,{ "Origin-Realm", RULE_REQUIRED, -1, 1 }
+ ,{ "Destination-Realm", RULE_REQUIRED, -1, 1 }
+ ,{ "SIP-Server-Assignment-Type", RULE_REQUIRED, -1, 1 }
+ ,{ "SIP-User-Data-Already-Available", RULE_REQUIRED, -1, 1 }
+ ,{ "Destination-Host", RULE_OPTIONAL, -1, 1 }
+ ,{ "User-Name", RULE_OPTIONAL, -1, 1 }
+ ,{ "SIP-Server-URI", RULE_OPTIONAL, -1, 1 }
+ ,{ "SIP-Supported-User-Data-Type", RULE_OPTIONAL, -1, -1 }
+ ,{ "SIP-AOR", RULE_OPTIONAL, -1, -1 }
+ ,{ "Proxy-Info", RULE_OPTIONAL, -1, -1 }
+ ,{ "Route-Record", RULE_OPTIONAL, -1, -1 }
+
+ };
+
+ CHECK_dict_new( DICT_COMMAND, &data , cxdx_dict, &cmd);
+ PARSE_loc_rules( rules, cmd, AVP_BY_NAME );
+ }
+ /* Server-Assignment-Answer (SAA) Command */
+ {
+ /*
+
+ The Server-Assignment-Answer (SAA) is indicated by the Command-Code
+ set to 284 and the Command Flags' 'R' bit cleared. The Diameter
+ server sends this command in response to a previously received
+ Diameter Server-Assignment-Request (SAR) command. The response may
+ include the user profile or part of it, if requested.
+
+ In addition to the values already defined in RFC 3588 [RFC3588], the
+ Result-Code AVP may contain one of the values defined in
+ Section 10.1.
+
+ The Result-Code AVP value in the Diameter SAA message may indicate a
+ success or an error in the execution of the Diameter SAR command. If
+ Result-Code AVP value in the Diameter SAA message does not contain an
+ error code, the SAA message MAY include one or more SIP-User-Data
+ AVPs that typically contain the profile of the user, indicating
+ services that the SIP server can provide to that user.
+
+ The Diameter server MAY include one or more
+ SIP-Supported-User-Data-Type AVPs, each one identifying a type of
+ user data format supported in the Diameter server. If there is not a
+ common supported user data type between the Diameter client and the
+ Diameter server, the Diameter server SHOULD declare its list of
+ supported user data types by including one or more
+ SIP-Supported-User-Data-Type AVPs in a Diameter SAA message. This
+ indication is merely for debugging reasons, since there is not a
+ fallback mechanism that allows the Diameter client to retrieve the
+ profile in a supported format.
+
+ If the Diameter server requires a User-Name AVP value to process the
+ Diameter SAR request, but the Diameter SAR message did not contain a
+ User-Name AVP value, the Diameter server MUST set the Result-Code AVP
+ value to DIAMETER_USER_NAME_REQUIRED (see Section 10.1.2) and return
+ it in a Diameter SAA message. Upon reception of this Diameter SAA
+ message with the Result-Code AVP value set to
+ DIAMETER_USER_NAME_REQUIRED, the SIP server typically requests
+ authentication by generating a SIP 401 (Unauthorized) or SIP 407
+ (Proxy Authentication Required) response back to the originator.
+
+ If the User-Name AVP is included in the Diameter SAR message, upon
+ reception of the Diameter SAR message, the Diameter server MUST
+ verify the existence of the user in the realm, i.e., the User-Name
+ AVP value is a valid user within that realm. If the Diameter server
+ does not recognize the user name received in the User-Name AVP, the
+ Diameter server MUST build a Diameter Server-Assignment-Answer (SAA)
+ message and MUST set the Result-Code AVP to
+ DIAMETER_ERROR_USER_UNKNOWN.
+ Then the Diameter server MUST authorize that User-Name AVP value is a
+ valid authentication name for the SIP or SIPS URI included in the
+ SIP-AOR AVP of the Diameter SAR message. If this authorization
+ fails, the Diameter server must set the Result-Code AVP to
+ DIAMETER_ERROR_IDENTITIES_DONT_MATCH and send it in a Diameter
+ Server-Assignment-Answer (SAA) message.
+
+ After successful execution of the Diameter SAR command, the Diameter
+ server MUST clear the "authentication pending" flag and SHOULD move
+ the temporarily stored SIP server URI to permanent storage.
+
+ The actions of the Diameter server upon reception of the Diameter SAR
+ message depend on the value of the SIP-Server-Assignment-Type:
+
+ o If the SIP-Server-Assignment-Type AVP value in the Diameter SAR
+ message is set to REGISTRATION or RE_REGISTRATION, the Diameter
+ server SHOULD verify that there is only one SIP-AOR AVP.
+ Otherwise, the Diameter server MUST answer with a Diameter SAA
+ message with the Result-Code AVP value set to
+ DIAMETER_AVP_OCCURS_TOO_MANY_TIMES and MUST NOT include any
+ SIP-User-Data AVP. If there is only one SIP-AOR AVP and if the
+ SIP-User-Data-Already-Available AVP value is set to
+ USER_DATA_NOT_AVAILABLE, then the Diameter server SHOULD include
+ one or more user profile data with the SIP or SIPS URI (SIP-AOR
+ AVP) and all other SIP identities associated with that AVP in the
+ SIP-User-Data AVP value of the Diameter SAA message. On selecting
+ the type of user data, the Diameter server SHOULD take into
+ account the supported formats at the SIP server
+ (SIP-Supported-User-Data-Type AVP in the SAR message) and the
+ local policy. Additionally, the Diameter server MUST set the
+ Result-Code AVP value to DIAMETER_SUCCESS in the Diameter SAA
+ message. The Diameter server considers the SIP AOR authenticated
+ and registered.
+
+ o If the SIP-Server-Assignment-Type AVP value in the Diameter SAR
+ message is set to UNREGISTERED_USER, then the Diameter server MUST
+ store the SIP server address included in the SIP-Server-URI AVP
+ value. The Diameter server will return the SIP server address in
+ Diameter Location-Info-Answer (LIA) messages. If the
+ SIP-User-Data-Already-Available AVP value is set to
+ USER_DATA_NOT_AVAILABLE, then the Diameter server SHOULD include
+ one or more user profile data associated with the SIP or SIPS URI
+ (SIP-AOR AVP) and associated identities in the SIP-User-Data AVP
+ value of the Diameter SAA message. On selecting the type of user
+ data, the Diameter server SHOULD take into account the supported
+ formats at the SIP server (SIP-Supported-User-Data-Type AVP in the
+ SAR message) and the local policy. The Diameter server MUST set
+ the Result-Code AVP value to DIAMETER_SUCCESS. The Diameter
+ server considers the SIP AOR UNREGISTERED, but with a SIP server
+ allocated to trigger and provide services for unregistered users.
+ Note that in case of UNREGISTERED_USER (SIP-Server-Assignment-Type
+ AVP), the Diameter server MUST verify that there is only one
+ SIP-AOR AVP. Otherwise, the Diameter server MUST answer the
+ Diameter SAR message with a Diameter SAA message, and it MUST set
+ the Result-Code AVP value to DIAMETER_AVP_OCCURS_TOO_MANY_TIMES
+ and MUST NOT include any SIP-User-Data AVP.
+ If the User-Name AVP was not present in the Diameter SAR message
+ and the SIP-AOR is not known for the Diameter server, the Diameter
+ server MUST NOT include a User-Name AVP in the Diameter SAA
+ message and MUST set the Result-Code AVP value to
+ DIAMETER_ERROR_USER_UNKNOWN.
+
+ o If the SIP-Server-Assignment-Type AVP value in the Diameter SAR
+ message is set to TIMEOUT_DEREGISTRATION, USER_DEREGISTRATION,
+ DEREGISTRATION_TOO_MUCH_DATA, or ADMINISTRATIVE_DEREGISTRATION,
+ the Diameter server MUST clear the SIP server address associated
+ with all SIP AORs indicated in each of the SIP-AOR AVP values
+ included in the Diameter SAR message. The Diameter server
+ considers all of these SIP AORs as not registered. The Diameter
+ server MUST set the Result-Code AVP value to DIAMETER_SUCCESS in
+ the Diameter SAA message.
+
+ o If the SIP-Server-Assignment-Type AVP value in the Diameter SAR
+ message is set to TIMEOUT_DEREGISTRATION_STORE_SERVER_NAME or
+ USER_DEREGISTRATION_STORE_SERVER_NAME, the Diameter server MAY
+ keep the SIP server address associated with the SIP AORs included
+ in the SIP-AOR AVP values of the Diameter SAR message, even though
+ the SIP AORs become unregistered. This feature allows a SIP
+ server to request that the Diameter server remain an assigned SIP
+ server for those SIP AORs (SIP-AOR AVP values) allocated to the
+ same user name, and avoid SIP server assignment. The Diameter
+ server MUST consider all these SIP AORs as not registered. If the
+ Diameter server honors the request of the Diameter client (SIP
+ server) to remain as an allocated SIP server, then the Diameter
+ server MUST keep the SIP server assigned to those SIP AORs
+ allocated to the username and MUST set the Result-Code AVP value
+ to DIAMETER_SUCCESS in the Diameter SAA message. Otherwise, when
+ the Diameter server does not honor the request of the Diameter
+ client (SIP server) to remain as an allocated SIP server, the
+ Diameter server MUST clear the SIP server name assigned to those
+ SIP AORs and it MUST set the Result-Code AVP value to
+ DIAMETER_SUCCESS_SERVER_NAME_NOT_STORED in the Diameter SAA
+ message.
+ o If the SIP-Server-Assignment-Type AVP value in the Diameter SAR
+ message is set to NO_ASSIGNMENT, the Diameter server SHOULD first
+ verify that the SIP-Server-URI AVP value in the Diameter SAR
+ message is the same URI as the one assigned to the SIP-AOR AVP
+ value. If they differ, then the Diameter server MUST set the
+ Result-Code AVP value to DIAMETER_UNABLE_TO_COMPLY in the Diameter
+ SAA message. Otherwise, if the SIP-User-Data-Already-Available
+ AVP value is set to USER_DATA_NOT_AVAILABLE, then the Diameter
+ server SHOULD include the user profile data with the SIP or SIPS
+ URI (SIP-AOR AVP) and all other SIP identities associated with
+ that AVP in the SIP-User-Data AVP value of the Diameter SAA
+ message. On selecting the type of user data, the Diameter server
+ SHOULD take into account the supported formats at the SIP server
+ (SIP-Supported-User-Data-Type AVP in the SAR message) and the
+ local policy.
+
+ o If the SIP-Server-Assignment-Type AVP value in the Diameter SAR
+ message is set to AUTHENTICATION_FAILURE or
+ AUTHENTICATION_TIMEOUT, the Diameter server MUST verify that there
+ is exactly one SIP-AOR AVP in the Diameter SAR message. If the
+ number of occurrences of the SIP-AOR AVP is not exactly one, the
+ Diameter server MUST set the Result-Code AVP value to
+ DIAMETER_AVP_OCCURS_TOO_MANY_TIMES in the Diameter SAA message,
+ and SHOULD not take further actions. If there is exactly one
+ SIP-AOR AVP in the Diameter SAR message, the Diameter server MUST
+ clear the address of the SIP server assigned to the SIP AOR
+ allocated to the user name, and the Diameter server MUST set the
+ Result-Code AVP value to DIAMETER_SUCCESS in the Diameter SAA
+ message. The Diameter server MUST consider the SIP AOR as not
+ registered.
+
+ The Message Format of the SAA command is as follows:
+
+ <SAA> ::= < Diameter Header: 284, PXY >
+ < Session-Id >
+ { Auth-Application-Id }
+ { Result-Code }
+ { Auth-Session-State }
+ { Origin-Host }
+ { Origin-Realm }
+ * [ SIP-User-Data ]
+ [ SIP-Accounting-Information ]
+ * [ SIP-Supported-User-Data-Type ]
+ [ User-Name ]
+ [ Auth-Grace-Period ]
+ [ Authorization-Lifetime ]
+ [ Redirect-Host ]
+ [ Redirect-Host-Usage ]
+ [ Redirect-Max-Cache-Time ]
+ * [ Proxy-Info ]
+ * [ Route-Record ]
+ * [ AVP ]
+
+
+
+
+ */
+ struct dict_object * cmd;
+ struct dict_cmd_data data = {
+ 284, /* Code */
+ "Server-Assignment-Answer", /* Name */
+ CMD_FLAG_REQUEST | CMD_FLAG_PROXIABLE | CMD_FLAG_ERROR, /* Fixed flags */
+ CMD_FLAG_PROXIABLE /* Fixed flag values */
+ };
+ struct local_rules_definition rules[] =
+ { { "Session-Id", RULE_FIXED_HEAD, -1, 1 }
+ ,{ "Auth-Application-Id", RULE_REQUIRED, -1, 1 }
+ ,{ "Result-Code", RULE_REQUIRED, -1, 1 }
+ ,{ "Auth-Session-State", RULE_REQUIRED, -1, 1 }
+ ,{ "Origin-Host", RULE_REQUIRED, -1, 1 }
+ ,{ "Origin-Realm", RULE_REQUIRED, -1, 1 }
+ ,{ "SIP-User-Data", RULE_OPTIONAL, -1, -1 }
+ ,{ "SIP-Accounting-Information", RULE_OPTIONAL, -1, 1 }
+ ,{ "SIP-Supported-User-Data-Type", RULE_OPTIONAL, -1, -1 }
+ ,{ "User-Name", RULE_OPTIONAL, -1, 1 }
+ ,{ "Auth-Grace-Period", RULE_OPTIONAL, -1, 1 }
+ ,{ "Authorization-Lifetime", RULE_OPTIONAL, -1, 1 }
+ ,{ "Redirect-Host", RULE_OPTIONAL, -1, 1 }
+ ,{ "Redirect-Host-Usage", RULE_OPTIONAL, -1, 1 }
+ ,{ "Redirect-Max-Cache-Time", RULE_OPTIONAL, -1, 1 }
+ ,{ "Proxy-Info", RULE_OPTIONAL, -1, -1 }
+ ,{ "Route-Record", RULE_OPTIONAL, -1, -1 }
+
+ };
+
+ CHECK_dict_new( DICT_COMMAND, &data , cxdx_dict, &cmd);
+ PARSE_loc_rules( rules, cmd, AVP_BY_NAME );
+ }
+ /* Location-Info-Request (LIR) Command */
+ {
+ /*
+
+ The Location-Info-Request (LIR) is indicated by the Command-Code set
+ to 285 and the Command Flags' 'R' bit set. The Diameter client in a
+ SIP server sends this command to the Diameter server to request
+ routing information, e.g., the URI of the SIP server assigned to the
+ SIP-AOR AVP value allocated to the users.
+
+ The Message Format of the LIR command is as follows:
+
+ <LIR> ::= < Diameter Header: 285, REQ, PXY >
+ < Session-Id >
+ { Auth-Application-Id }
+ { Auth-Session-State }
+ { Origin-Host }
+ { Origin-Realm }
+ { Destination-Realm }
+ { SIP-AOR }
+ [ Destination-Host ]
+ * [ Proxy-Info ]
+ * [ Route-Record ]
+ * [ AVP ]
+ */
+ struct dict_object * cmd;
+ struct dict_cmd_data data = {
+ 285, /* Code */
+ "Location-Info-Request", /* Name */
+ CMD_FLAG_REQUEST | CMD_FLAG_PROXIABLE | CMD_FLAG_ERROR, /* Fixed flags */
+ CMD_FLAG_REQUEST | CMD_FLAG_PROXIABLE /* Fixed flag values */
+ };
+ struct local_rules_definition rules[] =
+ { { "Session-Id", RULE_FIXED_HEAD, -1, 1 }
+ ,{ "Auth-Application-Id", RULE_REQUIRED, -1, 1 }
+ ,{ "Auth-Session-State", RULE_REQUIRED, -1, 1 }
+ ,{ "Origin-Host", RULE_REQUIRED, -1, 1 }
+ ,{ "Origin-Realm", RULE_REQUIRED, -1, 1 }
+ ,{ "Destination-Realm", RULE_REQUIRED, -1, 1 }
+ ,{ "SIP-AOR", RULE_REQUIRED, -1, 1 }
+ ,{ "Destination-Host", RULE_OPTIONAL, -1, 1 }
+ ,{ "Proxy-Info", RULE_OPTIONAL, -1, -1 }
+ ,{ "Route-Record", RULE_OPTIONAL, -1, -1 }
+
+ };
+
+ CHECK_dict_new( DICT_COMMAND, &data , cxdx_dict, &cmd);
+ PARSE_loc_rules( rules, cmd, AVP_BY_NAME );
+ }
+ /* Location-Info-Answer (LIA) Command */
+ {
+ /*
+ The Location-Info-Answer (LIA) is indicated by the Command-Code set
+ to 285 and the Command Flags' 'R' bit cleared. The Diameter server
+ sends this command in response to a previously received Diameter
+ Location-Info-Request (LIR) command.
+
+ In addition to the values already defined in RFC 3588 [RFC3588], the
+ Result-Code AVP may contain one of the values defined in
+ Section 10.1. When the Diameter server finds an error in processing
+ the Diameter LIR message, the Diameter server MUST stop the process
+ of the message and answer with a Diameter LIA message that includes
+ the appropriate error code in the Result-Code AVP value. When there
+ is no error, the Diameter server MUST set the Result-Code AVP value
+ to DIAMETER_SUCCESS in the Diameter LIA message.
+
+ One of the errors that the Diameter server may find is that the
+ SIP-AOR AVP value is not a valid user in the realm. In such cases,
+ the Diameter server MUST set the Result-Code AVP value to
+ DIAMETER_ERROR_USER_UNKNOWN and return it in a Diameter LIA message.
+
+ If the Diameter server cannot process the Diameter LIR command, e.g.,
+ due to a database error, the Diameter server MUST set the Result-Code
+ AVP value to DIAMETER_UNABLE_TO_COMPLY and return it in a Diameter
+ LIA message. The Diameter server MUST NOT include any SIP-Server-URI
+ or SIP-Server-Capabilities AVP in the Diameter LIA message.
+
+ The Diameter server may or may not be aware of a SIP server assigned
+ to the SIP-AOR AVP value included in the Diameter LIR message. If
+ the Diameter server is aware of a SIP server allocated to that
+ particular user, the Diameter server MUST include the URI of such SIP
+ server in the SIP-Server-URI AVP and return it in a Diameter LIA
+ message. This is typically the situation when the user is either
+ registered, or unregistered but a SIP server is still assigned to the
+ user.
+
+ When the Diameter server is not aware of a SIP server allocated to
+ the user (typically the case when the user unregistered), the
+ Result-Code AVP value in the Diameter LIA message depends on whether
+ the Diameter server is aware that the user has services defined for
+ unregistered users:
+
+ o Those users who have services defined for unregistered users may
+ require the allocation of a SIP server to trigger and perhaps
+ execute those services. Therefore, when the Diameter server is
+ not aware of an assigned SIP server, but the user has services
+ defined for unregistered users, the Diameter server MUST set the
+ Result-Code AVP value to DIAMETER_UNREGISTERED_SERVICE and return
+ it in a Diameter LIA message. The Diameter server MAY also
+ include a SIP-Server-Capabilities AVP to facilitate the SIP server
+ (Diameter client) with the selection of an appropriate SIP server
+ with the required capabilities. Absence of the SIP-Server-
+ Capabilities AVP indicates to the SIP server (Diameter client)
+ that any SIP server is suitable to be allocated for the user.
+
+ o Those users who do not have service defined for unregistered users
+ do not require further processing. The Diameter server MUST set
+ the Result-Code AVP value to
+ DIAMETER_ERROR_IDENTITY_NOT_REGISTERED and return it to the
+ Diameter client in a Diameter LIA message. The SIP server
+ (Diameter client) may return the appropriate SIP response (e.g.,
+ 480 (Temporarily unavailable)) to the original SIP request.
+
+ The Message Format of the LIA command is as follows:
+
+ <LIA> ::= < Diameter Header: 285, PXY >
+ < Session-Id >
+ { Auth-Application-Id }
+ { Result-Code }
+ { Auth-Session-State }
+ { Origin-Host }
+ { Origin-Realm }
+ [ SIP-Server-URI ]
+ [ SIP-Server-Capabilities ]
+ [ Auth-Grace-Period ]
+ [ Authorization-Lifetime ]
+ [ Redirect-Host ]
+ [ Redirect-Host-Usage ]
+ [ Redirect-Max-Cache-Time ]
+ * [ Proxy-Info ]
+ * [ Route-Record ]
+ * [ AVP ]
+ */
+ struct dict_object * cmd;
+ struct dict_cmd_data data = {
+ 285, /* Code */
+ "Location-Info-Answer", /* Name */
+ CMD_FLAG_REQUEST | CMD_FLAG_PROXIABLE | CMD_FLAG_ERROR, /* Fixed flags */
+ CMD_FLAG_PROXIABLE /* Fixed flag values */
+ };
+ struct local_rules_definition rules[] =
+ { { "Session-Id", RULE_FIXED_HEAD, -1, 1 }
+ ,{ "Auth-Application-Id", RULE_REQUIRED, -1, 1 }
+ ,{ "Result-Code", RULE_REQUIRED, -1, 1 }
+ ,{ "Auth-Session-State", RULE_REQUIRED, -1, 1 }
+ ,{ "Origin-Host", RULE_REQUIRED, -1, 1 }
+ ,{ "Origin-Realm", RULE_REQUIRED, -1, 1 }
+ ,{ "SIP-Server-URI", RULE_OPTIONAL, -1, 1 }
+ ,{ "SIP-Server-Capabilities", RULE_OPTIONAL, -1, 1 }
+ ,{ "Auth-Grace-Period", RULE_OPTIONAL, -1, 1 }
+ ,{ "Authorization-Lifetime", RULE_OPTIONAL, -1, 1 }
+ ,{ "Redirect-Host", RULE_OPTIONAL, -1, 1 }
+ ,{ "Redirect-Host-Usage", RULE_OPTIONAL, -1, 1 }
+ ,{ "Redirect-Max-Cache-Time", RULE_OPTIONAL, -1, 1 }
+ ,{ "Proxy-Info", RULE_OPTIONAL, -1, -1 }
+ ,{ "Route-Record", RULE_OPTIONAL, -1, -1 }
+
+ };
+
+ CHECK_dict_new( DICT_COMMAND, &data , cxdx_dict, &cmd);
+ PARSE_loc_rules( rules, cmd, AVP_BY_NAME );
+ }
+ /* Registration-Termination-Request (RTR) Command */
+ {
+ /*
+ The Registration-Termination-Request (RTR) command is indicated by
+ the Command-Code set to 287 and the Command Flags' 'R' bit set. The
+ Diameter server sends this command to the Diameter client in a SIP
+ server to indicate to the SIP server that one or more SIP AORs have
+ to be deregistered. The command allows an operator to
+ administratively cancel the registration of a user from a centralized
+ Diameter server.
+
+ The Diameter server has the capability to initiate the deregistration
+ of a user and inform the SIP server by means of the Diameter RTR
+ command. The Diameter server can decide whether only one SIP AOR is
+ going to be deregistered, a list of SIP AORs, or all the SIP AORs
+ allocated to the user.
+
+ The absence of a SIP-AOR AVP in the Diameter RTR message indicates
+ that all the SIP AORs allocated to the user identified by the
+ User-Name AVP are being deregistered.
+
+ The Diameter server MUST include a SIP-Deregistration-Reason AVP
+ value to indicate the reason for the deregistration.
+
+ The Message Format of the RTR command is as follows:
+
+ <RTR> ::= < Diameter Header: 287, REQ, PXY >
+ < Session-Id >
+ { Auth-Application-Id }
+ { Auth-Session-State }
+ { Origin-Host }
+ { Origin-Realm }
+ { Destination-Host }
+ { SIP-Deregistration-Reason }
+ [ Destination-Realm ]
+ [ User-Name ]
+ * [ SIP-AOR ]
+ * [ Proxy-Info ]
+ * [ Route-Record ]
+ * [ AVP ]
+
+ */
+
+ struct dict_object * cmd;
+ struct dict_cmd_data data =
+ {
+ 287, /* Code */
+ "Registration-Termination-Request", /* Name */
+ CMD_FLAG_REQUEST | CMD_FLAG_PROXIABLE | CMD_FLAG_ERROR, /* Fixed flags */
+ CMD_FLAG_REQUEST | CMD_FLAG_PROXIABLE /* Fixed flag values */
+ };
+
+ struct local_rules_definition rules[] =
+ {
+ { "Session-Id", RULE_FIXED_HEAD, -1, 1 },
+ { "Auth-Application-Id", RULE_REQUIRED, -1, 1 },
+ { "Auth-Session-State", RULE_REQUIRED, -1, 1 },
+ { "Origin-Host", RULE_REQUIRED, -1, 1 },
+ { "Origin-Realm", RULE_REQUIRED, -1, 1 },
+ { "Destination-Host", RULE_REQUIRED, -1, 1 },
+ { "SIP-Deregistration-Reason",RULE_REQUIRED, -1, 1 },
+ { "Destination-Realm", RULE_OPTIONAL, -1, 1 },
+ { "User-Name", RULE_OPTIONAL, -1, 1 },
+ { "SIP-AOR", RULE_REQUIRED, -1, -1 },
+ { "Proxy-Info", RULE_OPTIONAL, -1, -1 },
+ { "Route-Record", RULE_OPTIONAL, -1, -1 }
+ };
+
+ CHECK_dict_new( DICT_COMMAND, &data , cxdx_dict, &cmd);
+ PARSE_loc_rules( rules, cmd, AVP_BY_NAME );
+ }
+ /* Registration-Termination-Answer (RTA) Command */
+ {
+ /*
+ The Registration-Termination-Answer (RTA) is indicated by the
+ Command-Code set to 287 and the Command Flags' 'R' bit cleared. The
+ Diameter client sends this command in response to a previously
+ received Diameter Registration-Termination-Request (RTR) command.
+
+ In addition to the values already defined in RFC 3588 [RFC3588], the
+ Result-Code AVP may contain one of the values defined in
+ Section 10.1.
+
+ If the SIP server (Diameter client) requires a User-Name AVP value to
+ process the Diameter RTR request, but the Diameter RTR message did
+ not contain a User-Name AVP value, the Diameter client MUST set the
+ Result-Code AVP value to DIAMETER_USER_NAME_REQUIRED (see Section
+ 10.1.2) and return it in a Diameter RTA message.
+
+ The SIP server (Diameter client) applies the administrative
+ deregistration to each of the URIs included in each of the SIP-AOR
+ AVP values, or, if there is no SIP-AOR AVP present in the Diameter
+ RTR request, to all the URIs allocated to the User-Name AVP value.
+
+ The value of the SIP-Deregistration-Reason AVP in the Diameter RTR
+ command has an effect on the actions performed at the SIP server
+ (Diameter client):
+
+ o If the value is set to PERMANENT_TERMINATION, then the user has
+ terminated his/her registration to the realm. If informing the
+ interested parties (e.g., subscribers to the "reg" event
+ [RFC3680]) about the administrative deregistration is supported
+ through SIP procedures, the SIP server (Diameter client) will do
+ so. The Diameter Client in the SIP Server SHOULD NOT request a
+ new user registration. The SIP server clears the registration
+ state of the deregistered AORs.
+
+ o If the value is set to NEW_SIP_SERVER_ASSIGNED, the Diameter
+ server informs the SIP server (Diameter client) that a new SIP
+ server has been allocated to the user, due to some reason. The
+ SIP server, if supported through SIP procedures, will inform the
+ interested parties (e.g., subscribers to the "reg" event
+ [RFC3680]) about the administrative deregistration at this SIP
+ server. The Diameter client in the SIP server SHOULD NOT request
+ a new user registration. The SIP server clears the registration
+ state of the deregistered SIP AORs.
+
+ o If the value is set to SIP_SERVER_CHANGE, the Diameter server
+ informs the SIP server (Diameter client) that a new SIP server has
+ to be allocated to the user, e.g., due to user's capabilities
+ requiring a new SIP server, or not enough resources in the current
+ SIP server. If informing the interested parties about the
+ administrative deregistration is supported through SIP procedures
+ (e.g., subscriptions to the "reg" event [RFC3680]), the SIP server
+ will do so. The Diameter client in the SIP Server SHOULD NOT
+ request a new user registration. The SIP server clears the
+ registration state of the deregistered SIP AORs.
+
+ o If the value is set to REMOVE_SIP_SERVER, the Diameter server
+ informs the SIP server (Diameter client) that the SIP server will
+ no longer be bound in the Diameter server with that user. The SIP
+ server can delete all data related to the user.
+
+ The Message Format of the RTA command is as follows:
+
+ <RTA> ::= < Diameter Header: 287, PXY >
+ < Session-Id >
+ { Auth-Application-Id }
+ { Result-Code }
+ { Auth-Session-State }
+ { Origin-Host }
+ { Origin-Realm }
+ [ Authorization-Lifetime ]
+ [ Auth-Grace-Period ]
+ [ Redirect-Host ]
+ [ Redirect-Host-Usage ]
+ [ Redirect-Max-Cache-Time ]
+ * [ Proxy-Info ]
+ * [ Route-Record ]
+ * [ AVP ]
+
+ */
+ struct dict_object * cmd;
+ struct dict_cmd_data data = {
+ 287, /* Code */
+ "Registration-Termination-Answer", /* Name */
+ CMD_FLAG_REQUEST | CMD_FLAG_PROXIABLE | CMD_FLAG_ERROR, /* Fixed flags */
+ CMD_FLAG_PROXIABLE /* Fixed flag values */
+ };
+ struct local_rules_definition rules[] =
+ { { "Session-Id", RULE_FIXED_HEAD, -1, 1 }
+ ,{ "Auth-Application-Id", RULE_REQUIRED, -1, 1 }
+ ,{ "Result-Code", RULE_REQUIRED, -1, 1 }
+ ,{ "Auth-Session-State", RULE_REQUIRED, -1, 1 }
+ ,{ "Origin-Host", RULE_REQUIRED, -1, 1 }
+ ,{ "Origin-Realm", RULE_REQUIRED, -1, 1 }
+ ,{ "Authorization-Lifetime", RULE_OPTIONAL, -1, 1 }
+ ,{ "Auth-Grace-Period", RULE_OPTIONAL, -1, 1 }
+ ,{ "Redirect-Host", RULE_OPTIONAL, -1, 1 }
+ ,{ "Redirect-Host-Usage", RULE_OPTIONAL, -1, 1 }
+ ,{ "Redirect-Max-Cache-Time", RULE_OPTIONAL, -1, 1 }
+ ,{ "Proxy-Info", RULE_OPTIONAL, -1, -1 }
+ ,{ "Route-Record", RULE_OPTIONAL, -1, -1 }
+
+ };
+
+ CHECK_dict_new( DICT_COMMAND, &data , cxdx_dict, &cmd);
+ PARSE_loc_rules( rules, cmd, AVP_BY_NAME );
+ }
+
+ /* Push-Profile-Request (PPR) Command */
+ {
+ /*
+ The Push-Profile-Request (PPR) command is indicated by the
+ Command-Code set to 288 and the Command Flags' 'R' bit set. The
+ Diameter server sends this command to the Diameter client in a SIP
+ server to update either the user profile of an already registered
+ user in that SIP server or the SIP accounting information. This
+ allows an operator to modify the data of a user profile or the
+ accounting information and push it to the SIP server where the user
+ is registered.
+
+ Each user has a user profile associated with him/her and other
+ accounting information. The profile or the accounting information
+ may change with time, e.g., due to addition of new services to the
+ user. When the user profile or the accounting information changes,
+ the Diameter server sends a Diameter Push-Profile-Request (PPR)
+ command to the Diameter client in a SIP server, in order to start
+ applying those new services.
+
+ A PPR command MAY contain a SIP-Accounting-Information AVP that
+ updates the addresses of the accounting servers. Changes in the
+ addresses of the accounting servers take effect immediately. The
+ Diameter client SHOULD close any existing accounting session with the
+ existing server and start providing accounting information to the
+ newly acquired accounting server.
+
+ A PPR command MAY contain zero or more SIP-User-Data AVP values
+ containing the new user profile. On selecting the type of user data,
+ the Diameter server SHOULD take into account the supported formats at
+ the SIP server (SIP-Supported-User-Data-Type AVP sent in a previous
+ SAR message) and the local policy.
+
+ The User-Name AVP indicates the user to whom the profile is
+ applicable.
+
+ The Message Format of the PPR command is as follows:
+
+ <PPR> ::= < Diameter Header: 288, REQ, PXY >
+ < Session-Id >
+ { Auth-Application-Id }
+ { Auth-Session-State }
+ { Origin-Host }
+ { Origin-Realm }
+ { Destination-Realm }
+ { User-Name }
+ * [ SIP-User-Data ]
+ [ SIP-Accounting-Information ]
+ [ Destination-Host ]
+ [ Authorization-Lifetime ]
+ [ Auth-Grace-Period ]
+ * [ Proxy-Info ]
+ * [ Route-Record ]
+ * [ AVP ]
+
+ */
+ struct dict_object * cmd;
+ struct dict_cmd_data data = {
+ 288, /* Code */
+ "Push-Profile-Request", /* Name */
+ CMD_FLAG_REQUEST | CMD_FLAG_PROXIABLE | CMD_FLAG_ERROR, /* Fixed flags */
+ CMD_FLAG_REQUEST | CMD_FLAG_PROXIABLE /* Fixed flag values */
+ };
+ struct local_rules_definition rules[] =
+ { { "Session-Id", RULE_FIXED_HEAD, -1, 1 }
+ ,{ "Auth-Application-Id", RULE_REQUIRED, -1, 1 }
+ ,{ "Auth-Session-State", RULE_REQUIRED, -1, 1 }
+ ,{ "Origin-Host", RULE_REQUIRED, -1, 1 }
+ ,{ "Origin-Realm", RULE_REQUIRED, -1, 1 }
+ ,{ "Destination-Realm", RULE_REQUIRED, -1, 1 }
+ ,{ "User-Name", RULE_REQUIRED, -1, 1 }
+ ,{ "SIP-User-Data", RULE_OPTIONAL, -1, -1 }
+ ,{ "SIP-Accounting-Information", RULE_OPTIONAL, -1, 1 }
+ ,{ "Destination-Host", RULE_OPTIONAL, -1, 1 }
+ ,{ "Authorization-Lifetime", RULE_OPTIONAL, -1, 1 }
+ ,{ "Auth-Grace-Period", RULE_OPTIONAL, -1, 1 }
+ ,{ "Proxy-Info", RULE_OPTIONAL, -1, -1 }
+ ,{ "Route-Record", RULE_OPTIONAL, -1, -1 }
+
+ };
+
+ CHECK_dict_new( DICT_COMMAND, &data , cxdx_dict, &cmd);
+ PARSE_loc_rules( rules, cmd, AVP_BY_NAME );
+ }
+ /* Push-Profile-Answer (PPA) Command */
+ {
+ /*
+
+
+ The Push-Profile-Answer (PPA) is indicated by the Command-Code set to
+ 288 and the Command Flags' 'R' bit cleared. The Diameter client
+ sends this command in response to a previously received Diameter
+ Push-Profile-Request (PPR) command.
+
+ In addition to the values already defined in RFC 3588 [RFC3588], the
+ Result-Code AVP may contain one of the values defined in
+ Section 10.1.
+
+ If there is no error when processing the received Diameter PPR
+ message, the SIP server (Diameter client) MUST download the received
+ user profile from the SIP-User-Data AVP values in the Diameter PPR
+ message and store it associated with the user specified in the
+ User-Name AVP value.
+
+ If the SIP server does not recognize or does not support some of the
+ data transferred in the SIP-User-Data AVP values, the Diameter client
+ in the SIP server MUST return a Diameter PPA message that includes a
+ Result-Code AVP set to the value DIAMETER_ERROR_NOT_SUPPORTED_USER_DATA.
+
+ If the SIP server (Diameter client) receives a Diameter PPR message
+ with a User-Name AVP that is unknown, the Diameter client MUST set
+ the Result-Code AVP value to DIAMETER_ERROR_USER_UNKNOWN and MUST
+ return it to the Diameter server in a Diameter PPA message.
+
+ If the SIP server (Diameter client) receives in the
+ SIP-User-Data-Content AVP value (of the grouped SIP-User-Data AVP)
+ more data than it can accept, it MUST set the Result-Code AVP value
+ to DIAMETER_ERROR_TOO_MUCH_DATA and MUST return it to the Diameter
+ server in a Diameter PPA message. The SIP server MUST NOT override
+ the existing user profile with the one received in the PPR message.
+
+ If the Diameter server receives the Result-Code AVP value set to
+ DIAMETER_ERROR_TOO_MUCH_DATA in a Diameter PPA message, it SHOULD
+ force a new re-registration of the user by sending to the Diameter
+ client a Diameter Registration-Termination-Request (RTR) with the
+ SIP-Deregistration-Reason AVP value set to SIP_SERVER_CHANGE. This
+ will force a re-registration of the user and will trigger a selection
+ of a new SIP server.
+
+ If the Diameter client is not able to honor the command, for any
+ other reason, it MUST set the Result-Code AVP value to
+ DIAMETER_UNABLE_TO_COMPLY and it MUST return it in a Diameter PPA
+ message.
+
+ The Message Format of the PPA command is as follows:
+
+ <PPA> ::= < Diameter Header: 288, PXY >
+ < Session-Id >
+ { Auth-Application-Id }
+ { Result-Code }
+ { Auth-Session-State }
+ { Origin-Host }
+ { Origin-Realm }
+ [ Redirect-Host ]
+ [ Redirect-Host-Usage ]
+ [ Redirect-Max-Cache-Time ]
+ * [ Proxy-Info ]
+ * [ Route-Record ]
+ * [ AVP ]
+
+
+
+ */
+ struct dict_object * cmd;
+ struct dict_cmd_data data = {
+ 288, /* Code */
+ "Push-Profile-Answer", /* Name */
+ CMD_FLAG_REQUEST | CMD_FLAG_PROXIABLE | CMD_FLAG_ERROR, /* Fixed flags */
+ CMD_FLAG_PROXIABLE /* Fixed flag values */
+ };
+ struct local_rules_definition rules[] =
+ { { "Session-Id", RULE_FIXED_HEAD, -1, 1 }
+ ,{ "Auth-Application-Id", RULE_REQUIRED, -1, 1 }
+ ,{ "Result-Code", RULE_REQUIRED, -1, 1 }
+ ,{ "Auth-Session-State", RULE_REQUIRED, -1, 1 }
+ ,{ "Origin-Host", RULE_REQUIRED, -1, 1 }
+ ,{ "Origin-Realm", RULE_REQUIRED, -1, 1 }
+ ,{ "Redirect-Host", RULE_OPTIONAL, -1, 1 }
+ ,{ "Redirect-Host-Usage", RULE_OPTIONAL, -1, 1 }
+ ,{ "Redirect-Max-Cache-Time", RULE_OPTIONAL, -1, 1 }
+ ,{ "Proxy-Info", RULE_OPTIONAL, -1, -1 }
+ ,{ "Route-Record", RULE_OPTIONAL, -1, -1 }
+
+ };
+
+ CHECK_dict_new( DICT_COMMAND, &data , cxdx_dict, &cmd);
+ PARSE_loc_rules( rules, cmd, AVP_BY_NAME );
+ }
+
+#endif /* TODO - NRGJ */
+
+ } /* end Command section */
+
+
+
+ TRACE_DEBUG(INFO, "Extension 'Dictionary CxDx' initialized");
+ return 0;
+}
+
+
+EXTENSION_ENTRY("dict_cxdx", cxdx_dict_init);
+
diff --git a/contrib/CxDx/dict_cxdx.xml b/contrib/CxDx/dict_cxdx.xml
new file mode 100644
index 0000000..9956c21
--- /dev/null
+++ b/contrib/CxDx/dict_cxdx.xml
@@ -0,0 +1,407 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE dictionary SYSTEM "dictionary.dtd">
+
+
+<!--**************************************************************************************
+
+ === CpqD/DRC - Projeto ADRIMS - Mar/2011 ===
+ === Dicionario Dx/Cx ===
+ Baseado no "dict_sip" do FreeDiameter (www.freediameter.net)
+ Norberto R Goes Jr
+**************************************************************************************-->
+
+
+<dictionary>
+
+ <!-- ******************************************************** -->
+ <!-- ********************* Vendors ************************** -->
+ <!-- ******************************************************** -->
+
+ <vendor id="13019" name="ETSI" />
+
+ <vendor id="10415" name="3GPP" />
+
+ <!-- ******************************************************** -->
+ <!-- ***************** CxDx Application *********************-->
+ <!-- ******************************************************** -->
+
+ <application id="16777216" name="Diameter CxDx Application"
+ uri="http://www.cpqd.com.br">
+
+ <!-- ******************************************************** -->
+ <!-- ******************** Commands ************************** -->
+ <!-- ******************************************************** -->
+
+ <command name="User-Authorization" code="300" >
+
+ <requestrules>
+ <fixed>
+ <avprule name="Session-Id" minimum="1" maximum="1"/>
+ </fixed>
+
+ <required>
+ <avprule name="Vendor-Specific-Application-Id" maximum="1" />
+ <avprule name="Auth-Session-State" maximum="1" />
+ <avprule name="Origin-Host" maximum="1" />
+ <avprule name="Origin-Realm" maximum="1" />
+ <avprule name="Destination-Realm" maximum="1" />
+ <avprule name="User-Name" maximum="1" />
+ <avprule name="Public-Identity" maximum="1" />
+ <avprule name="Visited-Network-Identifier" maximum="1" />
+ </required>
+
+ <optional>
+ <avprule name="Destination-Host" maximum="1"/>
+ <avprule name="Supported-Features" />
+ <avprule name="User-Authorization-Type" maximum="1"/>
+ <avprule name="UAR-Flags" maximum="1" />
+ <avprule name="AVP" />
+ <avprule name="Proxy-Info" />
+ <avprule name="Route-Record" />
+ </optional>
+ </requestrules>
+
+
+ <answerrules>
+ <fixed>
+ <avprule name="Session-Id" minimum="1" maximum="1"/>
+ </fixed>
+
+ <required>
+ <avprule name="Vendor-Specific-Application-Id" maximum="1" />
+ <avprule name="Auth-Session-State" maximum="1" />
+ <avprule name="Origin-Host" maximum="1" />
+ <avprule name="Origin-Realm" maximum="1"/>
+
+ </required>
+
+ <optional>
+ <avprule name="Result-Code" maximum="1"/>
+ <avprule name="Experimental-Result" maximum="1"/>
+ <avprule name="Supported-Features" />
+ <avprule name="Server-Name" maximum="1"/>
+ <avprule name="Server-Capabilities" maximum="1"/>
+ <avprule name="Wildcarded-IMPU" maximum="1"/>
+ <avprule name="AVP" />
+ <avprule name="Failed-AVP" />
+ <avprule name="Proxy-Info" />
+ <avprule name="Route-Record" />
+ </optional>
+
+ </answerrules>
+
+ </command>
+
+
+
+ <command name="Server-Assignment" code="301" >
+
+ <requestrules>
+ <fixed>
+ <avprule name="Session-Id" minimum="1" maximum="1"/>
+ </fixed>
+
+ <required>
+ <avprule name="Vendor-Specific-Application-Id" maximum="1" />
+ <avprule name="Auth-Session-State" maximum="1" />
+ <avprule name="Origin-Host" maximum="1" />
+ <avprule name="Origin-Realm" maximum="1" />
+ <avprule name="Destination-Realm" maximum="1" />
+ <avprule name="Server-Name" maximum="1"/>
+ <avprule name="Server-Assignment-Type" maximum="1" />
+ <avprule name="User-Data-Already-Available" maximum="1" />
+ </required>
+
+ <optional>
+ <avprule name="Destination-Host" maximum="1"/>
+ <avprule name="User-Name" maximum="1" />
+ <avprule name="Supported-Features" />
+ <avprule name="Public-Identity" />
+ <avprule name="Wildcarded-PSI" maximum="1"/>
+ <avprule name="Wildcarded-IMPU" maximum="1"/>
+ <!-- avprule name="SCSCF-Restoration-Info" maximum="1"/> -->
+ <!-- avprule name="Multiple-Registration-Indication" maximum="1"/> -->
+ <!--avprule name="Session-Priority" maximum="1"/> -->
+ <avprule name="AVP" />
+ <avprule name="Proxy-Info" />
+ <avprule name="Route-Record" />
+ </optional>
+ </requestrules>
+
+
+ <answerrules>
+ <fixed>
+ <avprule name="Session-Id" minimum="1" maximum="1"/>
+ </fixed>
+
+ <required>
+ <avprule name="Vendor-Specific-Application-Id" maximum="1" />
+ <avprule name="Auth-Session-State" maximum="1" />
+ <avprule name="Origin-Host" maximum="1" />
+ <avprule name="Origin-Realm" maximum="1"/>
+ </required>
+
+ <optional>
+ <avprule name="Result-Code" maximum="1"/>
+ <avprule name="Experimental-Result" maximum="1"/>
+ <avprule name="User-Name" maximum="1" />
+ <avprule name="Supported-Features" />
+ <!--avprule name="User-Data" maximum="1"/> -->
+ <!--avprule name="Charging-Information" maximum="1"/> -->
+ <!--avprule name="Associated-Identities" maximum="1"/> -->
+ <!--avprule name="Loose-Route-Indication" maximum="1"/> -->
+ <!--avprule name="SCSCF-Restoration-Info" /> -->
+ <!--avprule name="Associated-Registered-Identities " maximum="1"/> -->
+ <avprule name="AVP" />
+ <avprule name="Server-Name" maximum="1"/>
+ <avprule name="Failed-AVP" />
+ <avprule name="Proxy-Info" />
+ <avprule name="Route-Record" />
+
+ </optional>
+
+ </answerrules>
+
+ </command>
+
+
+
+
+
+ <!-- ******************************************************** -->
+ <!-- *********************** AVPs *************************** -->
+ <!-- ******************************************************** -->
+
+ <avp name="Visited-Network-Identifier" code="600" vendor-id="10415" mandatory="must"
+ may-encrypt="no">
+ <type type-name="OctetString" />
+ </avp>
+
+ <avp name="Public-Identity" code="601" vendor-id="10415" mandatory="must"
+ may-encrypt="no">
+ <type type-name="UTF8String" />
+ </avp>
+
+ <avp name="Server-Name" code="602" vendor-id="10415" mandatory="must"
+ may-encrypt="no">
+ <type type-name="UTF8String" />
+ </avp>
+
+ <!-- "Server-Capabilites" (603) usa as duas AVPs a seguir : -->
+ <avp name="Feature-List-ID" code="629" vendor-id="10415" mandatory="must"
+ may-encrypt="no"> <!-- verificar flags / NRGJ -->
+ <type type-name="Unsigned32" />
+ </avp>
+
+ <avp name="Feature-List" code="630" vendor-id="10415" mandatory="must"
+ may-encrypt="no"> <!-- verificar flags / NRGJ -->
+ <type type-name="Unsigned32" />
+ </avp>
+
+ <avp name="Server-Capabilities" code="603" vendor-id="10415" mandatory="must"
+ may-encrypt="no">
+ <grouped>
+ <optional>
+ <avprule name="Vendor-Id" maximum="1" />
+ <avprule name="Feature-List-ID" maximum="1" />
+ <avprule name="Feature-List" maximum="1" />
+ </optional>
+ </grouped>
+ </avp>
+
+ <avp name="Mandatory-Capability" code="604" vendor-id="10415" mandatory="must"
+ may-encrypt="no">
+ <type type-name="Unsigned32" />
+ </avp>
+
+ <avp name="Optional-Capability" code="605" vendor-id="10415" mandatory="must"
+ may-encrypt="no">
+ <type type-name="Unsigned32" />
+ </avp>
+
+ <avp name="User-Data" code="606" vendor-id="10415" mandatory="must"
+ may-encrypt="no">
+ <type type-name="OctetString" />
+ </avp>
+
+ <avp name="SIP-Number-Auth-Items" code="607" vendor-id="10415" mandatory="must"
+ may-encrypt="no">
+ <type type-name="Unsigned32" />
+ </avp>
+
+ <avp name="SIP-Authentication-Scheme" code="608" vendor-id="10415" mandatory="must"
+ may-encrypt="no">
+ <type type-name="UTF8String" />
+ </avp>
+
+ <avp name="SIP-Authenticate" code="609" vendor-id="10415" mandatory="must"
+ may-encrypt="no">
+ <type type-name="OctetString" />
+ </avp>
+
+ <avp name="SIP-Authorization" code="610" vendor-id="10415" mandatory="must"
+ may-encrypt="no">
+ <type type-name="OctetString" />
+ </avp>
+
+ <avp name="SIP-Authentication-Context" code="611" vendor-id="10415" mandatory="must"
+ may-encrypt="no">
+ <type type-name="OctetString" />
+ </avp>
+
+
+
+ <!-- "SIP-Auth-Data-Item" (612) usa as AVPs a seguir : -->
+
+ <avp name="SIP-Item-Number" code="613" vendor-id="10415" mandatory="must"
+ may-encrypt="no">
+ <type type-name="Unsigned32" />
+ </avp>
+
+ <avp name="Confidentiality-Key" code="625" vendor-id="10415" mandatory="must"
+ may-encrypt="no">
+ <type type-name="OctetString" />
+ </avp>
+
+ <avp name="Integrity-Key" code="626" vendor-id="10415" mandatory="must"
+ may-encrypt="no">
+ <type type-name="OctetString" />
+ </avp>
+
+ <avp name="Digest-Realm" code="104" vendor-id="10415" mandatory="must"
+ may-encrypt="no"> <!-- verificar flags / NRGJ -->
+ <type type-name="UTF8String" />
+ </avp>
+
+ <avp name="Digest-Algorithm" code="111" vendor-id="10415" mandatory="must"
+ may-encrypt="no"> <!-- verificar flags / NRGJ -->
+ <type type-name="UTF8String" />
+ </avp>
+
+ <avp name="Digest-QoP" code="110" vendor-id="10415" mandatory="must"
+ may-encrypt="no"> <!-- verificar flags / NRGJ -->
+ <type type-name="UTF8String" />
+ </avp>
+
+ <avp name="Digest-HA1" code="121" vendor-id="10415" mandatory="must"
+ may-encrypt="no"> <!-- verificar flags / NRGJ -->
+ <type type-name="UTF8String" />
+ </avp>
+
+
+ <avp name="SIP-Digest-Authenticate" code="635" vendor-id="10415"
+ may-encrypt="no"> <!-- verificar flags / NRGJ -->
+ <grouped>
+ <required>
+ <avprule name="Digest-Realm" minimum="1" maximum="1" />
+ </required>
+ <optional>
+ <avprule name="Digest-Algorithm" maximum="1" />
+ <avprule name="Digest-QoP" maximum="1" />
+ <avprule name="Digest-HA1" maximum="1" />
+ <avprule name="AVP" />
+ </optional>
+ </grouped>
+
+ </avp>
+
+ <avp name="Line-Identifier" code="500" vendor-id="13019" mandatory="must"
+ may-encrypt="no"> <!-- verificar flags / NRGJ -->
+ <type type-name="OctetString" />
+ </avp>
+
+ <avp name="SIP-Auth-Data-Item" code="612" vendor-id="10415" mandatory="must"
+ may-encrypt="no">
+ <grouped>
+ <optional>
+ <avprule name="SIP-Item-Number" maximum="1" />
+ <avprule name="SIP-Authentication-Scheme" maximum="1" />
+ <avprule name="SIP-Authenticate" maximum="1" />
+ <avprule name="SIP-Authorization" maximum="1" />
+ <avprule name="SIP-Authentication-Context" maximum="1" />
+ <avprule name="Confidentiality-Key" maximum="1" />
+ <avprule name="Integrity-Key" maximum="1" />
+ <avprule name="SIP-Digest-Authenticate" maximum="1" />
+ <avprule name="Framed-IP-Address" maximum="1" />
+ <avprule name="Framed-IPv6-Prefix" maximum="1" />
+ <avprule name="Framed-Interface-Id" maximum="1" />
+ <avprule name="Line-Identifier" />
+ <avprule name="AVP" />
+ </optional>
+ </grouped>
+ </avp>
+
+
+
+
+ <avp name="Server-Assignment-Type" code="614" mandatory="must"
+ may-encrypt="no">
+ <type type-name="Enumerated"/>
+ <enum name="NO_ASSIGNMENT" code="0"/>
+ <enum name="REGISTRATION" code="1"/>
+ <enum name="RE_REGISTRATION" code="2"/>
+ <enum name="UNREGISTERED_USER" code="3"/>
+ <enum name="TIMEOUT_DEREGISTRATION" code="4"/>
+ <enum name="USER_DEREGISTRATION" code="5"/>
+ <enum name="TIMEOUT_DEREGISTRATION_STORE_SERVER_NAME" code="6"/>
+ <enum name="USER_DEREGISTRATION_STORE_SERVER_NAME" code="7"/>
+ <enum name="ADMINISTRATIVE_DEREGISTRATION " code="8"/>
+ <enum name="AUTHENTICATION_FAILURE" code="9"/>
+ <enum name="AUTHENTICATION_TIMEOUT" code="10"/>
+ <enum name="DEREGISTRATION_TOO_MUCH_DATA" code="11"/>
+ <enum name="AAA_USER_DATA_REQUEST" code="12"/>
+ <enum name="PGW_UPDATE " code="13"/>
+ </avp>
+
+
+ <avp name="User-Data-Already-Available" code="624" mandatory="must"
+ may-encrypt="no">
+ <type type-name="Enumerated"/>
+ <enum name="USER_DATA_NOT_AVAILABLE" code="0"/>
+ <enum name="USER_DATA_ALREADY_AVAILABLE" code="1"/>
+ </avp>
+
+
+ <avp name="Wildcarded-PSI" code="634" vendor-id="10415"
+ may-encrypt="no">
+ <type type-name="UTF8String" />
+ </avp>
+
+
+ <avp name="User-Authorization-Type" code="623" vendor-id="10415" mandatory="must"
+ may-encrypt="no">
+ <type type-name="UTF8String" />
+ </avp>
+
+
+
+ <avp name="Wildcarded-IMPU" code="636" vendor-id="10415" mandatory="must"
+ may-encrypt="no">
+ <type type-name="UTF8String" />
+ </avp>
+
+ <avp name="UAR-Flags" code="637" vendor-id="10415" mandatory="must"
+ may-encrypt="no">
+ <type type-name="Unsigned32" />
+ </avp>
+
+
+ <avp name="Supported-Features" code="628" vendor-id="10415"
+ may-encrypt="no">
+ <grouped>
+ <optional>
+ <avprule name="Vendor-Id" maximum="1" />
+ <avprule name="Feature-List-ID" maximum="1" />
+ <avprule name="Feature-List" maximum="1" />
+ </optional>
+ </grouped>
+ </avp>
+
+
+
+ </application>
+
+
+</dictionary>
+
+
diff --git a/contrib/OpenWRT/HOWTO b/contrib/OpenWRT/HOWTO
new file mode 100644
index 0000000..af07b43
--- /dev/null
+++ b/contrib/OpenWRT/HOWTO
@@ -0,0 +1,305 @@
+#####################
+# !! IMPORTANT !! #
+#####################
+
+The uClibc library that is shipped with OpenWRT lacks support for several POSIX thread
+features, such as pthread_cleanup_{push,pop}, that are required by the freeDiameter
+framework.
+
+Until these features are included in the base OpenWRT system, the framework will not
+behave correctly on this platform.
+
+Therefore, the OpenWRT port is NOT usable properly at this moment with uClibc.
+
+A test software is included in test_required for checking if new uClibc distributions
+support the required features. You'll have to adapt the Makefile according to your environment.
+
+An alternative choice if your hardware allows it is to use (e)glibc in your openwrt image.
+
+#####################
+
+
+
+This HOWTO describes how to generate a set of ipkg modules for
+providing support of freeDiameter in an OpenWRT system.
+
+This HOWTO is written for OpenWRT 10.03 (BackFire) and no guarantee is provided
+that it will work for you. Be prepared to eventually brick your routeur...
+
+Table of contents:
+0) Quick HOWTO: optimistic step-by-step instructions.
+1) Prerequisites: get the OpenWRT development environment ready.
+2) Supplied packages: use the existing packages when possible (gnutls, ...)
+3) Other dependencies: provide for additional missing dependencies (sctp ...)
+4) freediameter package: now create the freeDiameter package
+5) Configuration: how to set the configuration on the router.
+
+This HOWTO will NOT cover how to install OpenWRT on your access device, nor
+its basic configuration. Please refer to OpenWRT website for this type of HOWTOs.
+
+
+==============================================
+0) Quick HOWTO
+==============================================
+The following instructions should allow you to put freeDiameter on your OpenWRT-compatible router.
+In case something goes wrong, you should follow the detailed instructions in the remaining of
+this file.
+
+Be warned: playing with the software in your router may brick it, i.e. make it unusable forever.
+Do it at your own risk.
+
+1) Get the OpenWRT environment:
+$ git clone git://nbd.name/openwrt.git
+$ cd openwrt
+
+2) Get the feeds
+$ cp feeds.conf.default feeds.conf
+$ echo "src-hg freediameter http://www.freediameter.net/hg/fD-OWRT-packages" >> feeds.conf
+$ scripts/feeds update
+$ scripts/feeds install freeDiameter
+
+3) Configure your image
+$ make menuconfig
+(set Target System and Target Profile as needed for your equipment)
+
+- Network --->
+ freeDiameter (M)
+ freeDiameter-test (M)
+ wpad (*)
+ wpad-mini ( )
+
+
+4) Set the C library to glibc instead of uClibc (broken support, see #26)
+
+- Advanced configuration options (for developers) --->
+ - Toolchain Options ---->
+ C Library implementation (Use eglibc)
+
+
+5) Build the image and packages, this takes a while
+$ make world
+
+6) Export the bin/* directory through a webserver.
+ We assume it is available at http://192.168.1.25/owrt
+
+7) Flash the router with your new image -- THIS DESTROYS ALL CONFIG ON THE ROUTER!
+$ ssh root@192.168.1.1
+# cd /tmp
+# wget http://192.168.1.25/owrt/openwrt-brcm47xx-squashfs.trx
+ ;; change the file name with yours
+# mtd -r write openwrt-brcm47xx-squashfs.trx linux
+ ;; wait for reboot
+$ telnet 192.168.1.1
+# passwd
+# sync
+# exit
+
+8) Update the opkg router's config to get your new packages
+ssh root@192.168.1.1
+# echo "src/gz localrepo http://192.168.1.25/owrt/packages" >> /etc/opkg.conf
+# opkg update
+
+9) Install freeDiameter, you're done. Optionnaly, install also certtool on the router before, to
+ generate the TLS certificate automatically.
+# opkg install freeDiameter
+
+==============================================
+1) Prerequisites:
+==============================================
+
+We will first need a working OpenWRT toolchain environment. You can retrieve
+pre-compiled binaries of such toolchains ("Image builder") on the OpenWRT website. Anyway,
+in case the architecture you are interested in is not listed, you can build
+the full toolchain from source. This is the path we are following in this HOWTO.
+
+a) Retrieve the latest OpenWRT source, using subversion or git.
+Since I have to go through a proxy, I use the later here, svn being quite annoying with proxies.
+Note, the following commands must not be run as root.
+$ git clone git://nbd.name/openwrt.git
+ (Note: you might instead use "backfire.git" if you want to stick with an OpenWRT release.)
+$ cd openwrt
+$ cp feeds.conf.default feeds.conf
+
+b) If you are using git, you have to edit the feeds.conf file to use git as well for packages.
+Do the following modifications in this case:
+$ vi feeds.conf
+ Comment out this line:
+src-svn packages https://svn.openwrt.org/openwrt/packages
+ Add this line instead:
+src-git packages git://nbd.name/packages.git
+
+ You can leave uncommented the luci (for GNUTLS) and Xwrt (webif) repositories. Since these repositories
+use svn over http, you can use subversion even if you are behind a proxy.
+
+c) Then issue the following command to update the package list:
+$ scripts/feeds update
+
+d) Now, let's already create the toolchain and basic image.
+$ make menuconfig
+
+This will open a menu for you. You must select the target you are building for.
+See http://wiki.openwrt.org/toh/start for the table of hardware and associated information.
+In my case, I am using a Buffalo WZR-HP-G300NH router. I therefore select these options:
+- Target System --->
+ Atheros AR71xx/AR7240/AR913x
+- Target Profile --->
+ Buffalo WZR-HP-G300NH
+
+For many routeurs, the recommended kernel is a 2.4x version. I have NOT tried with such kernel,
+and the SCTP support is likely to be different in this generation of kernels. I strongly recommend
+to go with a 2.6x kernel, whenever possible.
+
+e) As per freeDiameter ticket #26, you also need to change the library to glibc instead of uClibc.
+Change the option as follow:
+
+- Advanced configuration options (for developers) --->
+ - Toolchain Options ---->
+ C Library implementation (Use eglibc)
+
+f) Once configured, create the toolchain and default image (this takes a while):
+$ make world
+
+After this command completes successfully, your build environment is ready.
+The resulting image and packages are stored in the "bin/" subdirectory.
+It is very convenient if you make this repository available in http to your routeur.
+
+You should probably try at this early stage to flash your device with the image you have generated.
+If the default basic image does not work, it is probably not worth adding new problems on top of it.
+
+For troubleshooting, please consult OpenWRT documentation directly.
+"make prereq" may help you building the initial image also.
+See http://downloads.openwrt.org/docs/buildroot-documentation.html for additional information
+concerning this step.
+
+You should now be able to login on your routeur with telnet (first time) or ssh (after setting a password).
+
+==============================================
+2) Supplied packages:
+==============================================
+
+There are some dependencies of freeDiameter already available in the OpenWRT packages repository.
+You can check for the available packages with the script:
+$ ./scripts/feeds search <package>
+
+We will now describe how to install these dependencies. At the time this HOWTO is written,
+the OpenWRT repositories contains packages for sctp, ipv6, gnutls, pthreads and hostapd.
+Follow these instructions to build them.
+
+Alternatively, you can find these packages pre-compiled in the OpenWRT packages repository.
+
+a) Add the packages
+$ scripts/feeds install libgnutls
+$ scripts/feeds install sctp
+
+b) Select the following components in the menu:
+$ make menuconfig
+- Base system --->
+ libpthread (M)
+
+- Network --->
+ sctp (M)
+ hostapd (M)
+ wpad-mini ( )
+
+- Libraries --->
+ SSL --->
+ libgnutls (M)
+
+- Kernel modules --->
+ Network Support --->
+ kmod-ipv6 (M)
+
+Quit and save the new config, then:
+$ make world
+
+This will add a bunch of modules in your bin directory that will be required for freeDiameter.
+Since we are removing the wpad-mini daemon from the base image, this image (trx or bin file) is also recompiled.
+
+Note that if you are setting your device as WPA supplicant also (wireless client), you must select wpad instead of hostapd.
+(in any case, the -mini version is not suitable since we will use the RADIUS authentication).
+
+
+You should now reflash your routeur with the new firmware image. The simplest way to achieve if your routeur has enough
+flash memory is to:
+- copy the new trx image to your routeur's /tmp (using wget or scp)
+- run this command (on the device) -- replace <newfile.trx> with your actual filename:
+ root@OpenWrt:~# mtd -r write <newfile.trx> linux
+
+WARNING: this will erase your existing configuration on the routeur.
+In case you need to save it, you may try the sysupgrade command instead.
+
+This will reboot the device after writing the new image file.
+Afterwards, if you have set up the http server on your development machine properly
+(let's assume it has IP address 192.168.1.25)
+you can run the following command on your router:
+ root@OpenWrt:~# echo "src/gz mydev http://192.168.1.25/packages" >> /etc/opkg.conf
+ root@OpenWrt:~# opkg update
+
+Install the newly compiled packages with:
+ root@OpenWrt:~# opkg install kmod-ipv6 hostapd libpthread sctp
+
+==============================================
+3) Missing packages:
+==============================================
+
+UPDATE: Starting from revision r22917, sctp and kmod-sctp are included in the OpenWRT distribution, and have been removed
+from freeDiameter package. One may consider using a freeDiameter package prior to 2010/09/05 in order to get the sctp
+package, or a more recent OpenWRT environment.
+
+PREVIOUS SITUATION: If you are using components prior to 2010/09/05, the following applies:
+P:
+P: There are other dependencies for freeDiameter that are not provided by OpenWRT packages.
+P: For convenience, we include these meta-packages in the freeDiameter distribution -- but they
+P: might not be up-to-date.
+P:
+P: a) Adding the contributed directory to the feeds
+P: Add the following line in your feeds.conf file:
+P: src-link freediameter /path/to/freediameter/contrib/OpenWRT/packages/
+P:
+P: Then run:
+P: $ scripts/feeds update
+P:
+P: This should allow you to install the missing dependencies as follow:
+P:
+P:
+P: b) SCTP library (note: you might alternatively compile freeDiameter without SCTP support).
+P: $ scripts/feeds install sctp
+P:
+P:
+P: c) Select these components in the menu:
+P: $ make menuconfig
+P: - Libraries --->
+P: sctp (M)
+P:
+P: Quit and save the new config, then:
+P: $ make world
+P:
+P:
+P: d) Install this on the router as well:
+P: root@OpenWrt:~# opkg update
+P: root@OpenWrt:~# opkg install sctp
+
+
+==============================================
+4) freediameter package:
+==============================================
+
+Now, your environment should be ready to compile the freeDiameter ipkg package.
+$ scripts/feeds install freeDiameter
+
+Note that in order to build this package, you need to have cmake & flex on your compilation machine.
+
+$ make menuconfig
+- Network --->
+ freeDiameter (M)
+ freeDiameter-test (M)
+
+Quit and save the new config, then:
+$ make world
+
+On your router, run:
+# opkg update
+# opkg install freeDiameter
+
+
+
diff --git a/contrib/OpenWRT/others/D-Link_DIR-330_netconfig.patch b/contrib/OpenWRT/others/D-Link_DIR-330_netconfig.patch
new file mode 100644
index 0000000..a35556a
--- /dev/null
+++ b/contrib/OpenWRT/others/D-Link_DIR-330_netconfig.patch
@@ -0,0 +1,35 @@
+diff --git a/target/linux/brcm47xx/base-files/etc/init.d/netconfig b/target/linux/brcm47xx/base-files/etc/init.d/netconfig
+index d7839b6..6446483 100755
+--- a/target/linux/brcm47xx/base-files/etc/init.d/netconfig
++++ b/target/linux/brcm47xx/base-files/etc/init.d/netconfig
+@@ -150,6 +150,30 @@ start() {
+ }
+ }
+ }
++ if (model == "D-Link DIR-330") { # boardtype is 0x0472, so we need to reset the parameters
++ # The switch is on eth1, this script defaults to switch on eth0, so we write the values directly instead.
++ print "#### DIR-330: eth1 must be up for configuring the switch "
++ print "config interface switchport"
++ print " option ifname \"eth1\""
++ print " option proto none"
++ print ""
++ print "config switch eth1"
++ print " option enable 1"
++ print ""
++ print "config switch_vlan eth1_0"
++ print " option device \"eth1\""
++ print " option vlan 0"
++ print " option ports \"0 1 2 3 5t\""
++ print ""
++ print "config switch_vlan eth1_1"
++ print " option device \"eth1\""
++ print " option vlan 1"
++ print " option ports \"4 5t\""
++ print ""
++ c["lan_ifname"] = "eth0.0"
++ c["wan_ifname"] = "eth0.1"
++ }
++
+ # Buffalo WBR-B11 and Buffalo WBR-G54
+ if (nvram["boardtype"] == "bcm94710ap") {
+ c["vlan0ports"] = "0 1 2 3 4 5u"
diff --git a/contrib/OpenWRT/packages/freeDiameter/Makefile b/contrib/OpenWRT/packages/freeDiameter/Makefile
new file mode 100644
index 0000000..d06502c
--- /dev/null
+++ b/contrib/OpenWRT/packages/freeDiameter/Makefile
@@ -0,0 +1,241 @@
+#
+# Software License Agreement (BSD License)
+#
+# Copyright (c) 2013, WIDE Project and NICT
+# All rights reserved.
+#
+# See LICENSE file from freeDiameter source package for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=freeDiameter
+PKG_REV:=696
+PKG_VERSION:=r$(PKG_REV)
+PKG_RELEASE:=1
+
+PKG_SOURCE_PROTO:=hg
+PKG_SOURCE_VERSION:=$(PKG_REV)
+PKG_SOURCE_SUBDIR:=$(PKG_NAME)-$(PKG_VERSION)
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
+PKG_SOURCE_URL:=http://www.freediameter.net/hg/freeDiameter
+# PKG_MD5SUM:=
+
+PKG_FIXUP:=libtool
+PKG_INSTALL:=1
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/freeDiameter
+ SECTION:=freeDiameter
+ CATEGORY:=Network
+ TITLE:=freeDiameter
+ URL:=http://www.freediameter.net
+ DEPENDS:=+sctp +libgnutls +libpthread +kmod-ipv6
+endef
+
+define Package/freeDiameter-test
+ SECTION:=freeDiameter
+ CATEGORY:=Network
+ TITLE:=freeDiameter-test
+ URL:=http://www.freediameter.net
+ DEPENDS:=+freeDiameter
+endef
+
+define Package/freeDiameter/description
+ freeDiameter + RADIUS/Diameter gateway extension package.
+endef
+
+define Package/freeDiameter-test/description
+ The app_test.fdx extension for freeDiameter, useful only to perform some
+tests between freeDiameter peers (ping-like for Diameter).
+endef
+
+define Package/freeDiameter/conffiles
+/etc/freeDiameter/freeDiameter.conf
+/etc/freeDiameter/rgw.conf
+endef
+
+define Build/Configure
+ IN_OPENWRT=1 \
+ AR="$(TARGET_CROSS)ar" \
+ AS="$(TARGET_CC) -c $(TARGET_CFLAGS)" \
+ LD="$(TARGET_CROSS)ld" \
+ NM="$(TARGET_CROSS)nm" \
+ CC="$(TARGET_CC)" \
+ GCC="$(TARGET_CC)" \
+ CXX="$(TARGET_CROSS)g++" \
+ RANLIB="$(TARGET_CROSS)ranlib" \
+ STRIP="$(TARGET_CROSS)strip" \
+ OBJCOPY="$(TARGET_CROSS)objcopy" \
+ OBJDUMP="$(TARGET_CROSS)objdump" \
+ TARGET_CPPFLAGS="$(TARGET_CPPFLAGS)" \
+ TARGET_CFLAGS="$(TARGET_CFLAGS)" \
+ TARGET_LDFLAGS="$(TARGET_LDFLAGS)" \
+ cmake \
+ -DCMAKE_PREFIX_PATH:PATH=$(STAGING_DIR)/usr \
+ -DCMAKE_INSTALL_PREFIX:PATH=/usr \
+ -DDIAMID_IDNA_REJECT:BOOL=ON \
+ -DBUILD_TESTING:BOOL=OFF \
+ -DCMAKE_BUILD_TYPE:STRING=DebianPackage \
+ -DDEFAULT_CONF_PATH:PATH=/etc/freeDiameter \
+ -DBUILD_APP_RADGW:BOOL=ON \
+ -DBUILD_DBG_MONITOR:BOOL=ON \
+ -DBUILD_TEST_APP:BOOL=ON \
+ VERBOSE=1 \
+ $(PKG_BUILD_DIR)/CMakeLists.txt
+endef
+
+TARGET_LDFLAGS := -L$(STAGING_DIR)/usr/lib $(TARGET_LDFLAGS)
+define Package/freeDiameter/install
+ # binaries
+ $(INSTALL_DIR) $(1)/usr/bin
+ $(CP) \
+ $(PKG_INSTALL_DIR)/usr/bin/freeDiameterd* \
+ $(1)/usr/bin/
+ # libraries & extensions
+ $(INSTALL_DIR) $(1)/usr/lib/
+ $(CP) \
+ $(PKG_INSTALL_DIR)/usr/lib/* \
+ $(1)/usr/lib/
+ # Remove the test_app from the main package (see freeDiameter-test)
+ $(RM) $(1)/usr/lib/freeDiameter/test_app*
+
+ # configuration files
+ $(INSTALL_DIR) $(1)/etc/freeDiameter
+ $(INSTALL_CONF) \
+ $(PKG_BUILD_DIR)/doc/freediameter.conf.sample \
+ $(1)/etc/freeDiameter/freeDiameter.conf
+ $(SED) 's,TLS_Cred,#TLS_Cred,g' $(1)/etc/freeDiameter/freeDiameter.conf
+ echo "" >> $(1)/etc/freeDiameter/freeDiameter.conf
+ echo "### OPENWRT specific" >> $(1)/etc/freeDiameter/freeDiameter.conf
+ echo "TLS_Cred = \"/etc/freeDiameter/freeDiameter.pem\", \"/etc/freeDiameter/freeDiameter.key\";" \
+ >> $(1)/etc/freeDiameter/freeDiameter.conf
+ echo "TLS_CA = \"/etc/freeDiameter/freeDiameter.ca.pem\";" \
+ >> $(1)/etc/freeDiameter/freeDiameter.conf
+ echo "TLS_DH_File = \"/etc/freeDiameter/dh.pem\";" \
+ >> $(1)/etc/freeDiameter/freeDiameter.conf
+ echo "SCTP_streams = 3;" >> $(1)/etc/freeDiameter/freeDiameter.conf
+ echo "LoadExtension = \"dict_nasreq.fdx\";" >> $(1)/etc/freeDiameter/freeDiameter.conf
+ echo "LoadExtension = \"dict_eap.fdx\";" >> $(1)/etc/freeDiameter/freeDiameter.conf
+ echo "LoadExtension = \"app_radgw.fdx\":\"rgw.conf\";" \
+ >> $(1)/etc/freeDiameter/freeDiameter.conf
+ echo "# test_app.fdx provided in freeDiameter-test package:" \
+ >> $(1)/etc/freeDiameter/freeDiameter.conf
+ echo "# LoadExtension = \"test_app.fdx\";" >> $(1)/etc/freeDiameter/freeDiameter.conf
+ echo "## Add overrides below this point" >> $(1)/etc/freeDiameter/freeDiameter.conf
+
+
+ $(INSTALL_CONF) \
+ $(PKG_BUILD_DIR)/doc/app_radgw.conf.sample \
+ $(1)/etc/freeDiameter/rgw.conf
+ $(SED) 's,RGWX,#RGWX,g' $(1)/etc/freeDiameter/rgw.conf
+ echo "" >> $(1)/etc/freeDiameter/rgw.conf
+ echo "### OPENWRT specific" >> $(1)/etc/freeDiameter/rgw.conf
+ echo " RGWX = \"auth.rgwx\" : auth;" >> $(1)/etc/freeDiameter/rgw.conf
+ echo " RGWX = \"acct.rgwx\" : acct;" >> $(1)/etc/freeDiameter/rgw.conf
+ echo "" >> $(1)/etc/freeDiameter/rgw.conf
+ echo " cli = 127.0.0.1 / \"secret key\" ;" >> $(1)/etc/freeDiameter/rgw.conf
+ echo " auth_server_ip4 = 127.0.0.1;" >> $(1)/etc/freeDiameter/rgw.conf
+ echo " auth_server_ip6 = ::1 ;" >> $(1)/etc/freeDiameter/rgw.conf
+ echo " acct_server_ip4 = 127.0.0.1;" >> $(1)/etc/freeDiameter/rgw.conf
+ echo " acct_server_ip6 = ::1 ;" >> $(1)/etc/freeDiameter/rgw.conf
+endef
+
+define Package/freeDiameter-test/install
+ # Only the test_app extension
+ $(INSTALL_DIR) $(1)/usr/lib/freeDiameter/
+ $(CP) $(PKG_INSTALL_DIR)/usr/lib/freeDiameter/test_app* \
+ $(1)/usr/lib/freeDiameter/
+endef
+
+define Package/freeDiameter/postinst
+#!/bin/sh
+
+# Test if the configuration file contains the local identity already
+localid=`sed -n -r -e "s/^[[:space:]]*Identity[[:space:]]*=[[:space:]]*\"([^\"]*)\"[[:space:]]*;/\1/p" /etc/freeDiameter/freeDiameter.conf`
+if [ -z "$$localid" ]; then
+ # Ask for the local name
+ echo -n "Full name of your access point? (openwrt.localdomain) : "
+ read localid
+ if [ -z "$$localid" ]; then
+ localid="openwrt.localdomain"
+ fi
+ echo "Identity = \"$$localid\";" >> /etc/freeDiameter/freeDiameter.conf
+fi
+
+# Is there already a ConnectPeer directive?
+grep -q -E -e "^[[:space:]]*ConnectPeer[[:space:]]*=" /etc/freeDiameter/freeDiameter.conf
+if [ "$$?" -eq "1" ]; then
+ echo -n "Diameter Identity of your Diameter server: "
+ read serverid
+ if [ -z "$$serverid" ]; then
+ echo "Skipped. Please add ConnectPeer directive to your /etc/freeDiameter/freeDiameter.conf file later."
+ else
+ echo -n "IP or IPv6 address of your Diameter server? (leave blank for dynamic resolution) "
+ read serverip
+ connstr=""
+ if [ -n "$$serverip" ]; then
+ connstr=" { ConnectTo = \"$$serverip\"; }"
+ fi
+ echo "ConnectPeer = \"$$serverid\"$$connstr;" >> /etc/freeDiameter/freeDiameter.conf
+ fi
+fi
+
+# Certificate configuration
+if [ ! -f "/usr/bin/certtool" ]; then
+ echo "certtool is not installed, skipping creation of default certificate and DH parameters."
+ echo "The following files are expected by freeDiameter:"
+ echo " /etc/freeDiameter/freeDiameter.key"
+ echo " /etc/freeDiameter/freeDiameter.pem"
+ echo " /etc/freeDiameter/freeDiameter.ca.pem"
+ echo " /etc/freeDiameter/dh.pem"
+ exit 0
+fi
+if [ ! -f "/etc/freeDiameter/freeDiameter.key" ]; then
+ echo "Creating a new private key for freeDiameter, please wait"
+ certtool -p --outfile /etc/freeDiameter/freeDiameter.key
+fi
+if [ ! -f "/etc/freeDiameter/freeDiameter.pem" ]; then
+ echo "organization = freeDiameter" > /tmp/template.cnf
+ echo "unit = OpenWRT" >>/tmp/template.cnf
+ echo "state = internet" >>/tmp/template.cnf
+ echo "country = net" >>/tmp/template.cnf
+ echo "cn = $$localid" >>/tmp/template.cnf
+ echo "expiration_days = 3650" >>/tmp/template.cnf
+ echo "signing_key" >>/tmp/template.cnf
+ echo "encryption_key" >>/tmp/template.cnf
+ if [ ! -f "/etc/freeDiameter/freeDiameter.csr" ]; then
+ echo "Creating a new CSR (use if you have a separate CA)"
+ certtool -q --load-privkey /etc/freeDiameter/freeDiameter.key \
+ --outfile /etc/freeDiameter/freeDiameter.csr \
+ --template /tmp/template.cnf
+ fi
+ echo "Creating a new certificate for freeDiameter"
+ certtool -s --load-privkey /etc/freeDiameter/freeDiameter.key \
+ --outfile /etc/freeDiameter/freeDiameter.pem \
+ --template /tmp/template.cnf
+ rm -f /tmp/template.cnf
+ cat /etc/freeDiameter/freeDiameter.pem >> /etc/freeDiameter/freeDiameter.ca.pem
+ echo "Done."
+ echo "========================================================================"
+ echo "To enable TLS communication, you should either:"
+ echo " - use a real certificate signed by your server's CA:"
+ echo " Use the CSR provided in /etc/freeDiameter/freeDiameter.csr"
+ echo " Save the new certificate as /etc/freeDiameter/freeDiameter.pem"
+ echo " Replace the contents of /etc/freeDiameter/freeDiameter.ca.pem with your CA's certificate"
+ echo " - or, declare the certificates as trusted as follow: "
+ echo " Add your server's CA certificate into /etc/freeDiameter/freeDiameter.ca.pem"
+ echo " Add the content of /etc/freeDiameter/freeDiameter.pem into your server's trusted CA file"
+ echo "========================================================================"
+fi
+if [ ! -f "/etc/freeDiameter/dh.pem" ]; then
+ echo "Creating new Diffie-Hellman parameters file. This operation takes a while..."
+ certtool --generate-dh-params --outfile /etc/freeDiameter/dh.pem
+ echo "Done."
+fi
+echo "freeDiameter configuration completed and stored in /etc/freeDiameter/."
+endef
+
+$(eval $(call BuildPackage,freeDiameter))
+$(eval $(call BuildPackage,freeDiameter-test))
diff --git a/contrib/OpenWRT/packages/freeDiameter/patches/01-freeDiameter-OpenWRT.patch b/contrib/OpenWRT/packages/freeDiameter/patches/01-freeDiameter-OpenWRT.patch
new file mode 100644
index 0000000..6f43c8d
--- /dev/null
+++ b/contrib/OpenWRT/packages/freeDiameter/patches/01-freeDiameter-OpenWRT.patch
@@ -0,0 +1,19 @@
+diff -Nur freeDiameter/CMakeLists.txt freeDiameter-OpenWRT/CMakeLists.txt
+--- freeDiameter/CMakeLists.txt 2010-08-13 16:19:35.000000000 +0900
++++ freeDiameter-OpenWRT/CMakeLists.txt 2010-08-13 16:21:32.000000000 +0900
+@@ -51,6 +51,14 @@
+ SET(DEBUG 1)
+ ENDIF (CMAKE_BUILD_TYPE MATCHES "Debug|Profiling|DebugValgrind")
+
++# OpenWRT
++SET(IN_OPENWRT $ENV{IN_OPENWRT})
++IF (IN_OPENWRT)
++ ADD_DEFINITIONS("$ENV{TARGET_LDFLAGS}" "$ENV{TARGET_CPPFLAGS}" "$ENV{TARGET_CFLAGS}")
++ INCLUDE_DIRECTORIES("$ENV{TARGET_LDFLAGS}" "$ENV{TARGET_CPPFLAGS}" "$ENV{TARGET_CFLAGS}")
++ENDIF(IN_OPENWRT)
++
++
+ # some subfolders use yacc and lex parsers
+ SET(BISON_GENERATE_DEFINES TRUE)
+ SET(BISON_PREFIX_OUTPUTS TRUE)
+Binary files freeDiameter/.hg/dirstate and freeDiameter-OpenWRT/.hg/dirstate differ
diff --git a/contrib/OpenWRT/test_required/Makefile b/contrib/OpenWRT/test_required/Makefile
new file mode 100644
index 0000000..d13cc91
--- /dev/null
+++ b/contrib/OpenWRT/test_required/Makefile
@@ -0,0 +1,15 @@
+OWRT_ENV_ROOT=/root/openwrt-env/openwrt
+STAGING_UCLIBC_ROOT=$(OWRT_ENV_ROOT)/staging_dir/target-mipsel_uClibc-0.9.31
+STAGING_GCC_ROOT=$(OWRT_ENV_ROOT)/staging_dir/toolchain-mipsel_gcc-4.3.3+cs_uClibc-0.9.31
+
+CFLAGS=-Os -pipe -mips32 -mtune=mips32 -funit-at-a-time -fhonour-copts -msoft-float -I$(STAGING_UCLIBC_ROOT)/usr/include -I$(STAGING_UCLIBC_ROOT)/include -I$(STAGING_GCC_ROOT)/usr/include -I$(STAGING_GCC_ROOT)/include
+LDFLAGS=-L$(STAGING_UCLIBC_ROOT)/usr/lib -L$(STAGING_UCLIBC_ROOT)/lib -L$(STAGING_GCC_ROOT)/usr/lib -L$(STAGING_GCC_ROOT)/lib
+
+GCC=mipsel-openwrt-linux-uclibc-gcc
+PATH:=$(STAGING_GCC_ROOT)/bin/:$(PATH)
+
+testcase: testcase.o
+ $(GCC) $(LDFLAGS) -lpthread testcase.o -o testcase
+
+testcase.o: testcase.c
+ $(GCC) $(CFLAGS) -o testcase.o -c testcase.c
diff --git a/contrib/OpenWRT/test_required/testcase.c b/contrib/OpenWRT/test_required/testcase.c
new file mode 100644
index 0000000..11d7882
--- /dev/null
+++ b/contrib/OpenWRT/test_required/testcase.c
@@ -0,0 +1,90 @@
+#include <pthread.h>
+#include <stdio.h>
+#include <strings.h>
+#include <assert.h>
+
+static pthread_barrier_t bar;
+static pthread_mutex_t mtx = PTHREAD_MUTEX_INITIALIZER;
+static pthread_cond_t cnd = PTHREAD_COND_INITIALIZER;
+static int called = 0;
+
+#ifndef ASSERT
+#define ASSERT(x) assert(x)
+#endif /* ASSERT */
+
+static void cleanupmutex(void * arg)
+{
+ printf("cancelation cleanup handler called\n");
+ if (arg) {
+ ASSERT( pthread_mutex_unlock((pthread_mutex_t *)arg) == 0 );
+ called++;
+ }
+
+}
+
+static void * mythread(void * a)
+{
+ int ret;
+
+ /* lock mutex */
+ ASSERT( pthread_mutex_lock(&mtx) == 0 );
+
+ /* Push cleanup */
+ pthread_cleanup_push(cleanupmutex, &mtx);
+
+ printf("thread synchronization (mutex acquired)\n");
+
+ /* Wake the other thread */
+ ret = pthread_barrier_wait(&bar);
+ ASSERT( (ret == 0) || (ret == PTHREAD_BARRIER_SERIAL_THREAD) );
+
+ /* Now wait for the condition, this unlocks the mutex */
+ do {
+ printf("thread waiting cond\n");
+ ASSERT( pthread_cond_wait(&cnd, &mtx) == 0);
+ printf("thread woken\n");
+ } while (1);
+
+ /* Cleanup, never reached */
+ pthread_cleanup_pop(1);
+ return NULL;
+}
+
+int main(int argc, char * argv[])
+{
+ int ret;
+ pthread_t thr;
+ void * dummy;
+
+ /* initialize the barrier */
+ ASSERT( pthread_barrier_init(&bar, NULL, 2) == 0 );
+
+ printf("Creating thread\n");
+
+ /* Create the thread */
+ ASSERT( pthread_create(&thr, NULL, mythread, NULL) == 0 );
+
+ printf("main synchronization\n");
+ ret = pthread_barrier_wait(&bar);
+ ASSERT( (ret == 0) || (ret == PTHREAD_BARRIER_SERIAL_THREAD) );
+
+ ASSERT( pthread_mutex_lock(&mtx) == 0 );
+ printf("main: thread is now waiting for condvar\n");
+
+ /* Cancel the thread */
+ ASSERT( pthread_cancel(thr) == 0 );
+
+ /* Now, unlock, so that the thread can actually really exit */
+ ASSERT( pthread_mutex_unlock(&mtx) == 0 );
+
+ /* Release thread resources */
+ ASSERT( pthread_join(thr, &dummy) == 0 );
+
+ if (called == 1)
+ printf("Test successful!\n");
+ else
+ printf("Test failed! Cleanup was not called (& lock not released)\n");
+
+ return 0;
+
+}
diff --git a/contrib/PKI/ca_script/Makefile b/contrib/PKI/ca_script/Makefile
new file mode 100644
index 0000000..70476d4
--- /dev/null
+++ b/contrib/PKI/ca_script/Makefile
@@ -0,0 +1,149 @@
+#!/usr/bin/make -s
+#
+# This file is designed to automatize the CA tasks such as:
+# -> init : create the initial CA tree and the CA root certificate.
+# -> newcsr: create a new private key and csr. $name and $email must be set. C, ST, L, O, OU may be overwitten (example: make newcsr C=FR)
+# -> cert : sign a pending CSR and generate the certificate. $name must be provided.
+# -> revoke: revoke a certificate. $name must be provided.
+# -> gencrl: update/create the CRL.
+#
+# The file should be located in the directory STATIC_DIR as defined below.
+# The DIR directory will contain the data of the CA. It might be placed in /var.
+# The DIR should also be configured in openssl.cnf file under [ CA_default ]->dir.
+#
+# Here are the steps to install the CA scripts in default environment:
+## mkdir /etc/openssl-ca.static
+## cp Makefile openssl.cnf /etc/openssl-ca.static
+# ( configure the default parameters of your CA in /etc/openssl-ca/openssl.cnf ) ##
+## mkdir /etc/openssl-ca
+## make -f /etc/openssl-ca.static/Makefile destroy force=y
+## cd /etc/openssl-ca
+## make init
+## make help
+
+DIR = /home/thedoc/testbed.aaa/ca
+STATIC_DIR = /home/thedoc/testbed.aaa/ca
+CONFIG = -config $(DIR)/openssl.cnf
+
+#Defaults for new CSR
+C = JP
+ST = Tokyo
+L = Koganei
+O = WIDE
+OU = "AAA WG"
+
+#Default lifetime
+DAYS = 365
+
+#Values for the CA
+CA_CN = mgr.testbed.aaa
+CA_mail = sdecugis@freediameter.net
+
+#Disable "make destroy"
+force =
+
+
+# Default: print the help
+all: help
+
+# Help message
+help:
+ @echo "\n\
+Default values (can be overwritten on command-line):\n\
+ [C=$(C)] [ST=$(ST)] [L=$(L)] [O=$(O)] [OU=$(OU)]\n\
+ [CA_CN=$(CA_CN)] [CA_mail=$(CA_mail)]\n\n\
+Available commands:\n\
+ make init\n\
+ Creates the initial CA structure in $(DIR)\n\
+ make gencrl\n\
+ Regenerates the CRL. Should be run at least once a month.\n\
+ make newcsr name=foo email=b@r [type=ca]\n\
+ Create private key and csr in clients subdir (named foo.*)\n\
+ make cert name=foo\n\
+ Signs the CSR foo.csr and creates the certificate foo.cert.\n\
+ make revoke name=foo\n\
+ Revokes the certificate foo.cert and regenerates the CRL.\n\
+\n\
+Notes:\n\
+ Content from public-www should be available from Internet. \n\
+ The URL to CRL should be set in openssl.cnf.\n\
+ A cron job should execute make gencrl once a month.\n\
+";
+
+# Destroy the CA completely. Use with care.
+destroy:
+ @if [ -z "$(force)" ]; then echo "Restart disabled, use: make destroy force=y"; exit 1; fi
+ @if [ ! -d $(STATIC_DIR) ]; then echo "Error in setup"; exit 1; fi
+ @echo "Removing everything (for debug purpose)..."
+ @rm -rf $(DIR)/*
+ @ln -sf $(STATIC_DIR)/Makefile $(DIR)
+ @ln -sf $(STATIC_DIR)/openssl.cnf $(DIR)
+
+# Initialize the CA structure and keys.
+init:
+ @if [ -d $(DIR)/private ]; then echo "CA already initialized."; exit 1; fi
+ @echo "Creating CA structure..."
+ @mkdir $(DIR)/crl
+ @mkdir $(DIR)/certs
+ @mkdir $(DIR)/newcerts
+ @mkdir $(DIR)/public-www
+ @mkdir $(DIR)/private
+ @chmod 700 $(DIR)/private
+ @mkdir $(DIR)/clients
+ @mkdir $(DIR)/clients/privkeys
+ @mkdir $(DIR)/clients/csr
+ @mkdir $(DIR)/clients/certs
+ @echo "01" > $(DIR)/serial
+ @touch $(DIR)/index.txt
+ @openssl req $(CONFIG) -new -batch -x509 -days 3650 -nodes -newkey rsa:2048 -out $(DIR)/public-www/cacert.pem \
+ -keyout $(DIR)/private/cakey.pem -subj /C=$(C)/ST=$(ST)/L=$(L)/O=$(O)/OU=$(OU)/CN=$(CA_CN)/emailAddress=$(CA_mail)
+ @ln -s $(DIR)/public-www/cacert.pem $(DIR)/certs/`openssl x509 -noout -hash < $(DIR)/public-www/cacert.pem`.0
+ @$(MAKE) -f $(DIR)/Makefile gencrl
+
+# Regenerate the Certificate Revocation List.
+# This list should be available publicly
+gencrl:
+ @openssl ca $(CONFIG) -gencrl -out $(DIR)/public-www/crl.pem
+ @ln -sf $(DIR)/public-www/crl.pem $(DIR)/crl/`openssl crl -noout -hash < $(DIR)/public-www/crl.pem`.r0
+
+# Create a new private key and a CSR, in case the client does not provide the CSR by another mean.
+# Usage is: make newcsr name=peer.client.fqdn email=admin@client.fqdn
+newcsr:
+ @if [ -z "$(name)" -o -z "$(email)" ]; then echo "Please provide certificate name and email address: make newcsr name=mn.nautilus.org email=you@mail.com"; exit 1; fi
+ @if [ -e $(DIR)/clients/csr/$(name).csr ]; then echo "There is already a pending csr for this name."; exit 1; fi
+ @if [ ! -e $(DIR)/clients/privkeys/$(name).key.pem ]; \
+ then echo "Generating a private key for $(name) ..."; \
+ openssl genrsa -out $(DIR)/clients/privkeys/$(name).key.pem 1024; \
+ fi;
+ @echo "Creating the CSR in $(DIR)/clients/csr/$(name).csr";
+ @openssl req $(CONFIG) -new -batch -out $(DIR)/clients/csr/$(name).csr \
+ -key $(DIR)/clients/privkeys/$(name).key.pem \
+ -subj /C=$(C)/ST=$(ST)/L=$(L)/O=$(O)/OU=$(OU)/CN=$(name)/emailAddress=$(email)
+
+# Process a CSR to create a x509 certificate. The certificate is valid for 1 year.
+# It should be sent to the client by any mean.
+cert:
+ @if [ -z "$(name)" ]; then echo "name must be provided: make cert name=mn.n6.org"; exit 1; fi
+ @if [ ! -e $(DIR)/clients/csr/$(name).csr ]; then echo "Could not find CSR in $(DIR)/clients/csr/$(name).csr."; exit 1; fi
+ @if [ -e $(DIR)/clients/certs/$(name).cert ]; \
+ then echo "Revoking old certificate..."; \
+ $(MAKE) revoke name=$(name); \
+ fi;
+ @openssl ca $(CONFIG) -in $(DIR)/clients/csr/$(name).csr \
+ -out $(DIR)/clients/certs/$(name).cert \
+ -days $(DAYS) \
+ -batch
+ @ln -s $(DIR)/clients/certs/$(name).cert $(DIR)/certs/`openssl x509 -noout -hash < $(DIR)/clients/certs/$(name).cert`.0
+
+# Revoke a certificate.
+revoke:
+ @if [ -z "$(name)" ]; then echo "name must be provided: make revoke name=mn.n6.org"; exit 1; fi
+ @if [ ! -e $(DIR)/clients/certs/$(name).cert ]; \
+ then echo "$(DIR)/clients/certs/$(name).cert not found"; \
+ exit 1; \
+ fi;
+ @openssl ca $(CONFIG) -revoke $(DIR)/clients/certs/$(name).cert;
+ @rm -f $(DIR)/certs/`openssl x509 -noout -hash < $(DIR)/clients/certs/$(name).cert`.0
+ @$(MAKE) gencrl
+
+# End of file...
diff --git a/contrib/PKI/ca_script/openssl.cnf b/contrib/PKI/ca_script/openssl.cnf
new file mode 100644
index 0000000..e4671d8
--- /dev/null
+++ b/contrib/PKI/ca_script/openssl.cnf
@@ -0,0 +1,315 @@
+#
+# OpenSSL example configuration file.
+# This is mostly being used for generation of certificate requests.
+#
+
+# This definition stops the following lines choking if HOME isn't
+# defined.
+HOME = .
+RANDFILE = $ENV::HOME/.rnd
+
+# Extra OBJECT IDENTIFIER info:
+#oid_file = $ENV::HOME/.oid
+oid_section = new_oids
+
+# To use this configuration file with the "-extfile" option of the
+# "openssl x509" utility, name here the section containing the
+# X.509v3 extensions to use:
+# extensions =
+# (Alternatively, use a configuration file that has only
+# X.509v3 extensions in its main [= default] section.)
+
+[ new_oids ]
+
+# We can add new OIDs in here for use by 'ca' and 'req'.
+# Add a simple OID like this:
+# testoid1=1.2.3.4
+# Or use config file substitution like this:
+# testoid2=${testoid1}.5.6
+
+####################################################################
+[ ca ]
+default_ca = CA_default # The default ca section
+
+####################################################################
+[ CA_default ]
+
+dir = /etc/openssl-ca # Where everything is kept
+certs = $dir/certs # Where the issued certs are kept
+crl_dir = $dir/crl # Where the issued crl are kept
+database = $dir/index.txt # database index file.
+#unique_subject = no # Set to 'no' to allow creation of
+ # several ctificates with same subject.
+new_certs_dir = $dir/newcerts # default place for new certs.
+
+certificate = $dir/public-www/cacert.pem # The CA certificate
+serial = $dir/serial # The current serial number
+# crlnumber = $dir/crlnumber # the current crl number
+ # must be commented out to leave a V1 CRL
+crl = $dir/public-www/crl.pem # The current CRL
+private_key = $dir/private/cakey.pem# The private key
+RANDFILE = $dir/private/.rand # private random number file
+
+x509_extensions = usr_cert # The extentions to add to the cert
+
+# Comment out the following two lines for the "traditional"
+# (and highly broken) format.
+name_opt = ca_default # Subject Name options
+cert_opt = ca_default # Certificate field options
+
+# Extension copying option: use with caution.
+# copy_extensions = copy
+
+# Extensions to add to a CRL. Note: Netscape communicator chokes on V2 CRLs
+# so this is commented out by default to leave a V1 CRL.
+# crlnumber must also be commented out to leave a V1 CRL.
+# crl_extensions = crl_ext
+
+default_days = 365 # how long to certify for
+default_crl_days= 30 # how long before next CRL
+default_md = sha1 # which md to use.
+preserve = no # keep passed DN ordering
+
+# A few difference way of specifying how similar the request should look
+# For type CA, the listed attributes must be the same, and the optional
+# and supplied fields are just that :-)
+# policy = policy_match
+policy = policy_anything
+
+# For the CA policy
+[ policy_match ]
+countryName = match
+stateOrProvinceName = match
+organizationName = match
+organizationalUnitName = optional
+commonName = supplied
+emailAddress = optional
+
+# For the 'anything' policy
+# At this point in time, you must list all acceptable 'object'
+# types.
+[ policy_anything ]
+countryName = optional
+stateOrProvinceName = optional
+localityName = optional
+organizationName = optional
+organizationalUnitName = optional
+commonName = supplied
+emailAddress = optional
+
+####################################################################
+[ req ]
+default_bits = 1024
+default_keyfile = privkey.pem
+distinguished_name = req_distinguished_name
+attributes = req_attributes
+x509_extensions = v3_ca # The extentions to add to the self signed cert
+
+# Passwords for private keys if not present they will be prompted for
+# input_password = fdsecret
+# output_password = fdsecret
+
+# This sets a mask for permitted string types. There are several options.
+# default: PrintableString, T61String, BMPString.
+# pkix : PrintableString, BMPString.
+# utf8only: only UTF8Strings.
+# nombstr : PrintableString, T61String (no BMPStrings or UTF8Strings).
+# MASK:XXXX a literal mask value.
+# WARNING: current versions of Netscape crash on BMPStrings or UTF8Strings
+# so use this option with caution!
+string_mask = utf8only
+
+# req_extensions = v3_req # The extensions to add to a certificate request
+
+[ req_distinguished_name ]
+countryName = Country Name (2 letter code)
+countryName_default = JP
+countryName_min = 2
+countryName_max = 2
+
+stateOrProvinceName = State or Province Name (full name)
+stateOrProvinceName_default = Tokyo
+
+localityName = Locality Name (eg, city)
+localityName_default = Koganei
+
+0.organizationName = Organization Name (eg, company)
+0.organizationName_default = WIDE
+
+# we can do this but it is not needed normally :-)
+1.organizationName = Second Organization Name (eg, company)
+1.organizationName_default = NICT
+
+organizationalUnitName = Organizational Unit Name (eg, section)
+organizationalUnitName_default = AAA WG
+
+commonName = Common Name (i.e. Diameter Agent hostname)
+commonName_max = 64
+
+emailAddress = Email Address (i.e. Diameter agent administrator)
+emailAddress_max = 64
+
+# SET-ex3 = SET extension number 3
+
+[ req_attributes ]
+challengePassword = A challenge password
+challengePassword_min = 0
+challengePassword_max = 20
+
+unstructuredName = An optional company name
+
+[ usr_cert ]
+
+# These extensions are added when 'ca' signs a request.
+
+# This goes against PKIX guidelines but some CAs do it and some software
+# requires this to avoid interpreting an end user certificate as a CA.
+
+basicConstraints=CA:FALSE
+
+# Here are some examples of the usage of nsCertType. If it is omitted
+# the certificate can be used for anything *except* object signing.
+
+# This is OK for an SSL server.
+# nsCertType = server
+
+# For an object signing certificate this would be used.
+# nsCertType = objsign
+
+# For normal client use this is typical
+# nsCertType = client, email
+
+# and for everything including object signing:
+# nsCertType = client, email, objsign
+
+# This is typical in keyUsage for a client certificate.
+# keyUsage = nonRepudiation, digitalSignature, keyEncipherment
+
+# This will be displayed in Netscape's comment listbox.
+nsComment = "OpenSSL Generated Certificate"
+
+# PKIX recommendations harmless if included in all certificates.
+subjectKeyIdentifier=hash
+authorityKeyIdentifier=keyid,issuer
+
+# This stuff is for subjectAltName and issuerAltname.
+# Import the email address.
+# subjectAltName=email:copy
+# An alternative to produce certificates that aren't
+# deprecated according to PKIX.
+# subjectAltName=email:move
+
+# Copy subject details
+# issuerAltName=issuer:copy
+
+#nsCaRevocationUrl = http://www.domain.dom/ca-crl.pem
+#nsBaseUrl
+#nsRevocationUrl
+#nsRenewalUrl
+#nsCaPolicyUrl
+#nsSslServerName
+
+[ v3_req ]
+
+# Extensions to add to a certificate request
+
+basicConstraints = CA:FALSE
+keyUsage = nonRepudiation, digitalSignature, keyEncipherment
+
+[ v3_ca ]
+
+
+# Extensions for a typical CA
+
+
+# PKIX recommendation.
+
+subjectKeyIdentifier=hash
+
+authorityKeyIdentifier=keyid:always,issuer:always
+
+# This is what PKIX recommends but some broken software chokes on critical
+# extensions.
+#basicConstraints = critical,CA:true
+# So we do this instead.
+basicConstraints = CA:true
+
+# Key usage: this is typical for a CA certificate. However since it will
+# prevent it being used as an test self-signed certificate it is best
+# left out by default.
+# keyUsage = cRLSign, keyCertSign
+
+# Some might want this also
+# nsCertType = sslCA, emailCA
+
+# Include email address in subject alt name: another PKIX recommendation
+# subjectAltName=email:copy
+# Copy issuer details
+# issuerAltName=issuer:copy
+
+# DER hex encoding of an extension: beware experts only!
+# obj=DER:02:03
+# Where 'obj' is a standard or added object
+# You can even override a supported extension:
+# basicConstraints= critical, DER:30:03:01:01:FF
+
+[ crl_ext ]
+
+# CRL extensions.
+# Only issuerAltName and authorityKeyIdentifier make any sense in a CRL.
+
+# issuerAltName=issuer:copy
+authorityKeyIdentifier=keyid:always,issuer:always
+
+[ proxy_cert_ext ]
+# These extensions should be added when creating a proxy certificate
+
+# This goes against PKIX guidelines but some CAs do it and some software
+# requires this to avoid interpreting an end user certificate as a CA.
+
+basicConstraints=CA:FALSE
+
+# Here are some examples of the usage of nsCertType. If it is omitted
+# the certificate can be used for anything *except* object signing.
+
+# This is OK for an SSL server.
+# nsCertType = server
+
+# For an object signing certificate this would be used.
+# nsCertType = objsign
+
+# For normal client use this is typical
+# nsCertType = client, email
+
+# and for everything including object signing:
+# nsCertType = client, email, objsign
+
+# This is typical in keyUsage for a client certificate.
+# keyUsage = nonRepudiation, digitalSignature, keyEncipherment
+
+# This will be displayed in Netscape's comment listbox.
+nsComment = "OpenSSL Generated Certificate"
+
+# PKIX recommendations harmless if included in all certificates.
+subjectKeyIdentifier=hash
+authorityKeyIdentifier=keyid,issuer:always
+
+# This stuff is for subjectAltName and issuerAltname.
+# Import the email address.
+# subjectAltName=email:copy
+# An alternative to produce certificates that aren't
+# deprecated according to PKIX.
+# subjectAltName=email:move
+
+# Copy subject details
+# issuerAltName=issuer:copy
+
+#nsCaRevocationUrl = http://www.domain.dom/ca-crl.pem
+#nsBaseUrl
+#nsRevocationUrl
+#nsRenewalUrl
+#nsCaPolicyUrl
+#nsSslServerName
+
+# This really needs to be in place for it to be a proxy certificate.
+proxyCertInfo=critical,language:id-ppl-anyLanguage,pathlen:3,policy:foo
diff --git a/contrib/PKI/ca_script2/Makefile b/contrib/PKI/ca_script2/Makefile
new file mode 100644
index 0000000..845176e
--- /dev/null
+++ b/contrib/PKI/ca_script2/Makefile
@@ -0,0 +1,178 @@
+#!/usr/bin/make -s
+#
+# This file is inspired from freeDiameter's contrib/ca_script and
+# improved to handle multiple CA in a hierarchical fashion.
+# Warning: the directory structure is flat, does not reflect the CA hierarchy
+
+SCRIPT_DIR = .
+DATA_DIR = ./ca_data
+
+CONFIG = -config $(SCRIPT_DIR)/openssl.cnf
+REMAKE = $(MAKE) -f $(SCRIPT_DIR)/Makefile
+
+#Disable "make destroy" -- overwrite on command line
+force =
+
+#RSA key sizes, can be overwritten on command line
+cakeysize = 2048
+keysize = 1024
+
+# Save current date
+DATE=`date +%Y%m%d-%H%M%S`
+
+# Default: print the help
+all: help
+
+# Help message
+help:
+ @echo "\n\
+Available commands:\n\
+ make init topca=name\n\
+ Creates the initial top-level CA structure\n\
+ make newca name=newcaname ca=parentca\n\
+ Creates a new sub-CA that can be used for certificates later.\n\
+ make newcert name=foo ca=parentca\n\
+ Create private key and csr, then issue the certificate (named foo.*)\n\
+ make p12 name=foo ca=parentca\n\
+ Same as newcert, but additionnaly creates a pkcs12 file to ship client certificate to Windows or Mac\n\
+ make ship name=foo ca=parentca\n\
+ Create an archive with the data for the client (useful for freeDiameter peers)\n\
+ make revoke name=foo ca=parentca\n\
+ Revokes the certificate foo.cert issued by parentca and regenerates the CRL.\n\
+ make gencrl ca=caname\n\
+ Regenerates the CRL of CA caname. Should be run periodically.\n\
+\n\
+";
+
+# Destroy the CA hierarchy completely. Use with care.
+destroy:
+ @if [ -z "$(force)" ]; then echo "Destroy disabled, use: make destroy force=y"; exit 1; fi
+ @if [ ! -d $(SCRIPT_DIR) ]; then echo "Error in setup"; exit 1; fi
+ @echo "Removing everything (for debug purpose)..."
+ @rm -rf $(DATA_DIR)/*
+
+# Initialize the CA structure
+structure:
+ @if [ -z "$(caname)" ]; then echo "Internal error: caname is missing"; exit 1; fi
+ @if [ -d $(DATA_DIR)/$(caname) ]; then echo "CA $(caname) already exists."; exit 1; fi
+ # Creating CA structure
+ @mkdir -p $(DATA_DIR)/$(caname)
+ @mkdir $(DATA_DIR)/$(caname)/public
+ @mkdir $(DATA_DIR)/$(caname)/public/crl
+ @mkdir $(DATA_DIR)/$(caname)/private
+ @chmod 700 $(DATA_DIR)/$(caname)/private
+ @mkdir $(DATA_DIR)/$(caname)/clients
+ @echo "01" > $(DATA_DIR)/$(caname)/serial
+ @echo "01" > $(DATA_DIR)/$(caname)/crlnumber
+ @touch $(DATA_DIR)/$(caname)/index.txt
+
+# Initialize the top-level CA structure and keys.
+init:
+ @if [ -z "$(topca)" ]; then echo "Please specify the name of the root CA. Ex: make init topca=rootca.testbed.aaa"; exit 1; fi
+ # Create the folder hierarchy
+ @$(REMAKE) structure caname=$(topca)
+ # Generate the self-signed certificate
+ @CA_ROOT_DIR=$(DATA_DIR)/$(topca) openssl req $(CONFIG) -new -batch -x509 -days 3650 -nodes -newkey rsa:$(cakeysize) -out $(DATA_DIR)/$(topca)/public/cacert.pem \
+ -keyout $(DATA_DIR)/$(topca)/private/cakey.pem -extensions ca_cert -subj /CN=$(topca)
+ @ln -s cacert.pem $(DATA_DIR)/$(topca)/public/`openssl x509 -noout -hash < $(DATA_DIR)/$(topca)/public/cacert.pem`.0
+ @touch $(DATA_DIR)/$(topca)/public/cachain.pem
+ @ln -s ../../$(topca)/public/cacert.pem $(DATA_DIR)/$(topca)/public/caroot.pem
+ @$(REMAKE) gencrl ca=$(topca)
+
+# Create a secondary CA
+newca:
+ @if [ -z "$(name)" -o -z "$(ca)" ]; then echo "Missing parameter. Ex: make newca name=subca.testbed.aaa ca=rootca.testbed.aaa"; exit 1; fi
+ @if [ ! -e $(DATA_DIR)/$(ca)/private/cakey.pem ]; then echo "The parent CA $(ca) does not exist."; exit 1; fi
+ @if [ ! -d $(DATA_DIR)/$(name) ]; then $(REMAKE) structure caname=$(name); fi
+ # Generate the private key and CSR for the new CA if needed
+ @if [ ! -e $(DATA_DIR)/$(name)/private/cakey.pem ]; then \
+ openssl genrsa -out $(DATA_DIR)/$(name)/private/cakey.pem $(cakeysize) ; fi
+ @if [ ! -e $(DATA_DIR)/$(name)/private/cacsr.pem ]; then \
+ CA_ROOT_DIR=$(DATA_DIR)/$(name) openssl req $(CONFIG) -new -batch -out $(DATA_DIR)/$(name)/private/cacsr.pem \
+ -key $(DATA_DIR)/$(name)/private/cakey.pem \
+ -subj /CN=$(name) -reqexts v3_req_ca; fi
+ # Revoke a previous certificate for this CA if any
+ @if [ -e $(DATA_DIR)/$(name)/public/cacert.pem ]; then \
+ echo "Revoking previous certificate ..."; \
+ $(REMAKE) revoke name=$(name) ca=$(ca); \
+ mv $(DATA_DIR)/$(name)/public/cacert.pem $(DATA_DIR)/$(name)/public/cacert-$(DATE).pem; fi
+ # Issue the new CA certificate
+ @CA_ROOT_DIR=$(DATA_DIR)/$(ca) openssl ca $(CONFIG) -in $(DATA_DIR)/$(name)/private/cacsr.pem \
+ -out $(DATA_DIR)/$(name)/public/cacert.pem \
+ -batch -extensions ca_cert
+ # Hash and link to parent
+ @ln -s cacert.pem $(DATA_DIR)/$(ca)/public/`openssl x509 -noout -hash < $(DATA_DIR)/$(name)/public/cacert.pem`.0
+ @rm -f $(DATA_DIR)/$(name)/parent
+ @ln -s ../$(ca) $(DATA_DIR)/$(name)/parent
+ @cat $(DATA_DIR)/$(name)/public/cacert.pem $(DATA_DIR)/$(ca)/public/cachain.pem > $(DATA_DIR)/$(name)/public/cachain.pem
+ @ln -s ../../$(ca)/public/caroot.pem $(DATA_DIR)/$(name)/public/caroot.pem
+ @for CRLFILE in `cd $(DATA_DIR)/$(ca)/public/crl && ls -1`; do ln -sf ../../../$(ca)/public/crl/$$CRLFILE $(DATA_DIR)/$(name)/public/crl/$$CRLFILE; done
+ @$(REMAKE) gencrl ca=$(name)
+
+# Create a new certificate for use in TLS communications and other terminal usages
+newcert:
+ @if [ -z "$(name)" -o -z "$(ca)" ]; then echo "Missing parameter. Ex: make newcert name=service.testbed.aaa ca=ca.testbed.aaa"; exit 1; fi
+ @if [ ! -e $(DATA_DIR)/$(ca)/private/cakey.pem ]; then echo "The parent CA $(ca) does not exist."; exit 1; fi
+ @if [ ! -d $(DATA_DIR)/$(ca)/clients/$(name) ]; then mkdir $(DATA_DIR)/$(ca)/clients/$(name); fi
+ # Create a private key if needed
+ @if [ ! -e $(DATA_DIR)/$(ca)/clients/$(name)/privkey.pem ]; then \
+ openssl genrsa -out $(DATA_DIR)/$(ca)/clients/$(name)/privkey.pem $(keysize); fi
+ # Create a CSR if needed
+ @if [ ! -e $(DATA_DIR)/$(ca)/clients/$(name)/csr.pem ]; then \
+ CA_ROOT_DIR=$(DATA_DIR)/$(ca) openssl req $(CONFIG) -new -batch -out $(DATA_DIR)/$(ca)/clients/$(name)/csr.pem \
+ -key $(DATA_DIR)/$(ca)/clients/$(name)/privkey.pem \
+ -subj /CN=$(name); fi
+ # Revoke a previous certificate if any
+ @if [ -e $(DATA_DIR)/$(ca)/clients/$(name)/cert.pem ]; then \
+ $(REMAKE) revoke name=$(name) ca=$(ca); \
+ mv $(DATA_DIR)/$(ca)/clients/$(name)/cert.pem $(DATA_DIR)/$(ca)/clients/$(name)/cert-$(DATE).pem; fi
+ # Now sign the new certificate with the CA key
+ @CA_ROOT_DIR=$(DATA_DIR)/$(ca) openssl ca $(CONFIG) -in $(DATA_DIR)/$(ca)/clients/$(name)/csr.pem \
+ -out $(DATA_DIR)/$(ca)/clients/$(name)/cert.pem \
+ -batch
+ # Hash
+ @ln -sf `cat $(DATA_DIR)/$(ca)/serial.old`.pem $(DATA_DIR)/$(ca)/public/`openssl x509 -noout -hash < $(DATA_DIR)/$(ca)/clients/$(name)/cert.pem`.0
+ # Compiled informations for the client
+ @cat $(DATA_DIR)/$(ca)/clients/$(name)/cert.pem $(DATA_DIR)/$(ca)/public/cachain.pem > $(DATA_DIR)/$(ca)/clients/$(name)/certchain.pem
+ @ln -sf ../../public/crl $(DATA_DIR)/$(ca)/clients/$(name)/crl
+ @ln -sf ../../public/caroot.pem $(DATA_DIR)/$(ca)/clients/$(name)/ca.pem
+
+# Create a PKCS#12 file containing the client's information
+p12: newcert
+ # Create the PKCS#12 file
+ @cat $(DATA_DIR)/$(ca)/clients/$(name)/privkey.pem \
+ $(DATA_DIR)/$(ca)/clients/$(name)/certchain.pem \
+ $(DATA_DIR)/$(ca)/clients/$(name)/ca.pem \
+ | openssl pkcs12 -export -out $(DATA_DIR)/$(ca)/clients/$(name)/$(name).p12
+ @echo "Client certificate is created in $(DATA_DIR)/$(ca)/clients/$(name)/$(name).p12"
+
+# Create an archive to send the data to the client node
+ship:
+ @if [ -z "$(name)" -o -z "$(ca)" ]; then echo "Missing parameter. Ex: make ship name=service.testbed.aaa ca=ca.testbed.aaa"; exit 1; fi
+ @if [ ! -e $(DATA_DIR)/$(ca)/private/cakey.pem ]; then echo "The parent CA $(ca) does not exist."; exit 1; fi
+ @if [ ! -e $(DATA_DIR)/$(ca)/clients/$(name)/privkey.pem ]; then echo "The client $(name) does not exist, use 'make newcert' first."; exit 1; fi
+ # Ship the data
+ @tar -c -C $(DATA_DIR)/$(ca)/clients/$(name) -z -f $(ca)_$(name).tar.gz -h .
+ @echo "The files have been packaged into archive: $(ca)_$(name).tar.gz"
+
+# Revoke a certificate
+revoke:
+ @if [ -z "$(name)" -o -z "$(ca)" ]; then echo "Missing parameter. Ex: make revoke name=service.testbed.aaa ca=ca.testbed.aaa"; exit 1; fi
+ @if [ ! -e $(DATA_DIR)/$(ca)/private/cakey.pem ]; then echo "The parent CA $(ca) does not exist."; exit 1; fi
+ @if [ ! -e $(DATA_DIR)/$(ca)/clients/$(name)/cert.pem ]; \
+ then echo "$(DATA_DIR)/$(ca)/clients/$(name)/cert.pem not found"; \
+ exit 1; \
+ fi;
+ # Revoke the certificate
+ @CA_ROOT_DIR=$(DATA_DIR)/$(ca) openssl ca $(CONFIG) -revoke $(DATA_DIR)/$(ca)/clients/$(name)/cert.pem;
+ @$(REMAKE) gencrl ca=$(ca)
+
+# Regenerate the Certificate Revocation List.
+gencrl:
+ @if [ -z "$(ca)" ]; then echo "Missing parameter. Ex: make gencrl ca=ca.testbed.aaa"; exit 1; fi
+ # Create the CRL
+ @CA_ROOT_DIR=$(DATA_DIR)/$(ca) openssl ca $(CONFIG) -gencrl -out $(DATA_DIR)/$(ca)/public/crl/$(ca).pem
+ @ln -s crl/$(ca).pem $(DATA_DIR)/$(ca)/public/local.pem
+ @ln -s local.pem $(DATA_DIR)/$(ca)/public/`openssl crl -noout -hash < $(DATA_DIR)/$(ca)/public/crl/$(ca).pem`.r0
+
+# End of file...
diff --git a/contrib/PKI/ca_script2/openssl.cnf b/contrib/PKI/ca_script2/openssl.cnf
new file mode 100644
index 0000000..2202209
--- /dev/null
+++ b/contrib/PKI/ca_script2/openssl.cnf
@@ -0,0 +1,120 @@
+# Note: for this file to be working, an environment var CA_ROOT_DIR = directory
+# must be defined and pointing to the CA top-level directory.
+
+HOME = .
+RANDFILE = $ENV::HOME/.rnd
+
+oid_section = new_oids
+
+[ new_oids ]
+
+
+####################################################################
+[ req ]
+default_bits = 1024
+# default_keyfile = privkey.pem
+string_mask = utf8only
+
+distinguished_name = req_distinguished_name
+attributes = req_attributes
+req_extensions = v3_req # overwrite with -reqexts
+x509_extensions = ca_cert # overwrite with -extensions; used for self-signed keys only
+
+[ req_distinguished_name ]
+countryName = Country Name (2 letter code)
+countryName_default = JP
+countryName_min = 2
+countryName_max = 2
+stateOrProvinceName = State or Province Name (full name)
+stateOrProvinceName_default = Tokyo
+localityName = Locality Name (eg, city)
+localityName_default = Koganei
+0.organizationName = Organization Name (eg, company)
+0.organizationName_default = WIDE
+1.organizationName = Second Organization Name (eg, company)
+1.organizationName_default = NICT
+organizationalUnitName = Organizational Unit Name (eg, section)
+organizationalUnitName_default = AAA WG testbed
+
+[ req_attributes ]
+challengePassword = A challenge password
+challengePassword_min = 0
+challengePassword_max = 20
+unstructuredName = An optional company name
+
+[ v3_req ]
+# Extensions to add to a certificate request
+basicConstraints = CA:FALSE
+keyUsage = nonRepudiation, digitalSignature, keyEncipherment
+
+[ v3_req_ca ]
+# Extensions to add to a certificate request for CA
+basicConstraints = CA:TRUE
+
+
+####################################################################
+[ ca ]
+default_ca = CA_default # The default ca section
+
+[ CA_default ]
+
+dir = $ENV::CA_ROOT_DIR # Where everything is kept
+certs = $dir/public # Where the issued certs are kept
+crl_dir = $dir/public # Where the issued crl are kept
+database = $dir/index.txt # database index file.
+#unique_subject = no # Set to 'no' to allow creation of
+ # several ctificates with same subject.
+new_certs_dir = $dir/public # default place for new certs.
+
+certificate = $dir/public/cacert.pem # The CA certificate
+serial = $dir/serial # The current serial number
+crlnumber = $dir/crlnumber # the current crl number
+crl = $dir/public/local.pem # The current CRL
+private_key = $dir/private/cakey.pem # The private key
+x509_extensions = usr_cert # The extentions to add to the cert
+ # overwrite with -extensions
+name_opt = ca_default # Subject Name options
+cert_opt = ca_default # Certificate field options
+crl_extensions = crl_ext
+
+default_days = 3650 # how long to certify for
+default_crl_days= 365 # how long before next CRL
+default_md = sha1 # which md to use.
+preserve = no # keep passed DN ordering
+
+# We accept to sign anything, but a real deployment would limit to proper domain etc...
+policy = policy_anything
+
+[ policy_anything ]
+countryName = optional
+stateOrProvinceName = optional
+localityName = optional
+organizationName = optional
+organizationalUnitName = optional
+commonName = supplied
+emailAddress = optional
+
+[ usr_cert ]
+basicConstraints=CA:FALSE
+# This is typical in keyUsage for a client certificate.
+keyUsage = nonRepudiation, digitalSignature, keyEncipherment
+subjectKeyIdentifier=hash
+authorityKeyIdentifier=keyid,issuer
+
+[ ca_cert ]
+# Extensions for a typical CA
+subjectKeyIdentifier=hash
+authorityKeyIdentifier=keyid:always,issuer:always
+basicConstraints = critical,CA:true # Remove "critical," in case of problems
+keyUsage = cRLSign, keyCertSign
+# subjectAltName=email:copy
+# Copy issuer details
+# issuerAltName=issuer:copy
+
+[ crl_ext ]
+# CRL extensions.
+# Only issuerAltName and authorityKeyIdentifier make any sense in a CRL.
+# issuerAltName=issuer:copy
+authorityKeyIdentifier=keyid:always,issuer:always
+
+
diff --git a/contrib/PKI/phpki-0.82.patch b/contrib/PKI/phpki-0.82.patch
new file mode 100644
index 0000000..e954d88
--- /dev/null
+++ b/contrib/PKI/phpki-0.82.patch
@@ -0,0 +1,284 @@
+diff -Nur phpki-0.82/ca/main.php phpki-0.82-fD/ca/main.php
+--- phpki-0.82/ca/main.php 2005-11-17 10:17:20.000000000 +0900
++++ phpki-0.82-fD/ca/main.php 2010-05-27 17:04:44.000000000 +0900
+@@ -36,7 +36,7 @@
+ else {
+ ?>
+ <font color=#ff0000>
+- <h2>There was an error updating the Certificate Revocation List.</h2></font><br>
++ <h2>There was an error updating the Certificate Revocation List.</h2></font><br />
+ <blockquote>
+ <h3>Debug Info:</h3>
+ <pre><?=$errtxt?></pre>
+@@ -53,8 +53,11 @@
+ default:
+ printHeader('ca');
+ ?>
+- <br>
+- <br>
++ <br />
++ <br />
++
++ <center><h3>For <span style="color: #FF0000;">freeDiameter</span> specific instructions, scroll down this page...</h3></center><br />
++
+ <center>
+ <table class=menu width=600><th class=menu colspan=2><big>CERTIFICATE MANAGEMENT MENU</big></th>
+
+@@ -89,7 +92,57 @@
+
+ </table>
+ </center>
+- <br><br>
++ <br /><br />
++ <center>
++ <table class=menu width=900><th class=menu colspan=2><big>FREEDIAMETER INSTRUCTIONS</big></th>
++ <tr><td style="text-align: center; vertical-align: middle; font-weight: bold;">
++ Create a new certificate</td>
++
++ <td>Use the <strong><cite>Create a New Certificate</cite></strong> link in previous table to request a new certificate. Fill the form as follow:
++ <ul>
++ <li><strong>Common Name</strong>: use your new freeDiameter identity (usually the FQDN).</li>
++ <li><strong>E-mail Address</strong>: Provide your address so that you can be contacted in case of inquiry.</li>
++ <li><strong>Organization</strong>: use "freeDiameter testbed" for example.</li>
++ <li><strong>Certificate Password</strong>: Do not loose the password you provide, you'll need it in the next step. <br />
++ The password must be >= 8 chars.</li>
++ <li>The other fields can be filled at your taste.</li>
++ </ul>
++ Once you have validated, you can check the values, and then proceed to download the new certificate and private key.
++ You will receive a file in PEM format. Let's call this file <em>mycertprotected.pem</em>.
++ It contains:
++ <ul>
++ <li>Your password-protected RSA private key.</li>
++ <li>Your certificate in PEM format.</li>
++ <li>The CA certificate.</li>
++ </ul></td></tr>
++
++ <tr><td style="text-align: center; vertical-align: middle; font-weight: bold;">
++ Split the file</td>
++
++ <td>In order to use the information with freeDiameter daemon, you must transform the data as follow:
++ <ul>
++ <li><strong>Decode the private key</strong>: <br />
++ <code>openssl rsa -in <em>mycertprotected.pem</em> -out /etc/ssl/private/freeDiameter.key</code><br />
++ OpenSSL will ask for the password you entered when creating the certificate.</li>
++ <li><strong>Extract your certificate</strong>: <br />
++ <code>openssl x509 -in <em>mycertprotected.pem</em> > /etc/ssl/certs/freeDiameter.pem</code></li>
++ <li><strong>Get the CA certificate</strong>: <br />
++ <code>wget --no-check-certificate "$config[base_url]index.php?stage=dl_root" -O /etc/ssl/certs/freeDiameter_testbed_CA.pem</code></li>
++ </ul>
++ Note: for the last step, you could also extract it directly from the PEM file you received.<br />
++ Note: the CRL is also available from the website, but this feature is not tested yet.</td></tr>
++
++ <tr><td style="text-align: center; vertical-align: middle; font-weight: bold;">
++ Configure freeDiameter</td>
++
++ <td>Here is the configuration related to TLS that you should set in your <em>/etc/freeDiameter/freeDiameter.conf</em> file:
++ <blockquote>TLS_Cred = "/etc/ssl/certs/freeDiameter.pem", "/etc/ssl/private/freeDiameter.key";<br />
++TLS_CA = "/etc/ssl/certs/freeDiameter_testbed_CA.pem";</blockquote></td></tr>
++
++
++ </table>
++ </center>
++ <br /><br />
+ <?
+ printFooter();
+ }
+diff -Nur phpki-0.82/ca/request_cert.php phpki-0.82-fD/ca/request_cert.php
+--- phpki-0.82/ca/request_cert.php 2007-01-04 14:45:09.000000000 +0900
++++ phpki-0.82-fD/ca/request_cert.php 2010-05-27 16:59:16.000000000 +0900
+@@ -197,6 +197,7 @@
+
+ switch($cert_type) {
+ case 'server':
++ case 'freediameter':
+ upload(array("$config[private_dir]/$serial-key.pem","$config[new_certs_dir]/$serial.pem",$config['cacert_pem']), "$common_name ($email).pem",'application/pkix-cert');
+ break;
+ case 'email':
+@@ -225,7 +226,7 @@
+ if (! $email) $email = "";
+ if (! $expiry) $expiry = 1;
+ if (! $keysize) $keysize = 1024;
+- if (! $cert_type) $cert_type = 'email';
++ if (! $cert_type) $cert_type = 'freediameter';
+
+ printHeader();
+ ?>
+@@ -302,13 +303,14 @@
+ <td>Certificate Use: </td>
+ <td><select name=cert_type>
+ <?
+- print '<option value="email" '.($cert_type=='email'?'selected':'').'>E-mail, SSL Client</option>';
+- print '<option value="email_signing" '.($cert_type=='email_signing'?'selected':'').'>E-mail, SSL Client, Code Signing</option>';
+- print '<option value="server" '.($cert_type=='server'?'selected':'').'>SSL Server</option>';
+- print '<option value="vpn_client" '.($cert_type=='vpn_client'?'selected':'').'>VPN Client Only</option>';
+- print '<option value="vpn_server" '.($cert_type=='vpn_server'?'selected':'').'>VPN Server Only</option>';
+- print '<option value="vpn_client_server" '.($cert_type=='vpn_client_server'?'selected':'').'>VPN Client, VPN Server</option>';
+- print '<option value="time_stamping" '.($cert_type=='time_stamping'?'selected':'').'>Time Stamping</option>';
++ print '<option value="email" disabled '.($cert_type=='email'?'selected':'').'>E-mail, SSL Client</option>';
++ print '<option value="email_signing" disabled '.($cert_type=='email_signing'?'selected':'').'>E-mail, SSL Client, Code Signing</option>';
++ print '<option value="server" disabled '.($cert_type=='server'?'selected':'').'>SSL Server</option>';
++ print '<option value="freediameter" '.($cert_type=='freediameter'?'selected':'').'>freeDiameter node</option>';
++ print '<option value="vpn_client" disabled '.($cert_type=='vpn_client'?'selected':'').'>VPN Client Only</option>';
++ print '<option value="vpn_server" disabled '.($cert_type=='vpn_server'?'selected':'').'>VPN Server Only</option>';
++ print '<option value="vpn_client_server" disabled '.($cert_type=='vpn_client_server'?'selected':'').'>VPN Client, VPN Server</option>';
++ print '<option value="time_stamping" disabled '.($cert_type=='time_stamping'?'selected':'').'>Time Stamping</option>';
+ ?>
+ </select></td>
+ </tr>
+diff -Nur phpki-0.82/include/openssl_functions.php phpki-0.82-fD/include/openssl_functions.php
+--- phpki-0.82/include/openssl_functions.php 2007-01-04 15:47:57.000000000 +0900
++++ phpki-0.82-fD/include/openssl_functions.php 2010-05-27 16:59:57.000000000 +0900
+@@ -69,6 +69,13 @@
+ default_days = 365
+ policy = policy_supplied
+
++[ freediameter_cert ]
++x509_extensions = freediameter_ext
++default_days = 730
++policy = policy_supplied
++
++
++
+ [ vpn_cert ]
+ x509_extensions = vpn_client_server_ext
+ default_days = 365
+@@ -152,6 +159,24 @@
+ nsRevocationUrl = ns_revoke_query.php?
+ nsCaPolicyUrl = $config[base_url]policy.html
+
++[ freediameter_ext ]
++basicConstraints = CA:false
++keyUsage = critical, digitalSignature, keyEncipherment
++extendedKeyUsage = critical, serverAuth, clientAuth
++nsCertType = critical, server, client
++subjectKeyIdentifier = hash
++authorityKeyIdentifier = keyid:always, issuer:always
++subjectAltName = DNS:$common_name,email:copy
++issuerAltName = issuer:copy
++crlDistributionPoints = URI:$config[base_url]index.php?stage=dl_crl
++nsComment = \"PHPki/OpenSSL Generated Secure Certificate for freeDiameter\"
++nsBaseUrl = $config[base_url]
++nsRevocationUrl = ns_revoke_query.php?
++nsCaPolicyUrl = $config[base_url]policy.html
++
++
++
++
+ [ time_stamping_ext ]
+ basicConstraints = CA:false
+ keyUsage = critical, nonRepudiation, digitalSignature
+diff -Nur phpki-0.82/openssl.cnf phpki-0.82-fD/openssl.cnf
+--- phpki-0.82/openssl.cnf 2006-07-23 00:33:34.000000000 +0900
++++ phpki-0.82-fD/openssl.cnf 2010-05-27 17:00:33.000000000 +0900
+@@ -39,6 +39,11 @@
+ default_days = 365
+ policy = policy_supplied
+
++[ freediameter_cert ]
++x509_extensions = freediameter_ext
++default_days = 730
++policy = policy_supplied
++
+ [ vpn_cert ]
+ x509_extensions = vpn_client_server_ext
+ default_days = 365
+@@ -115,6 +120,23 @@
+ nsRevocationUrl = ns_revoke_query.php?
+ nsCaPolicyUrl = http://www.somewhere.com/phpki/policy.html
+
++[ freediameter_ext ]
++basicConstraints = CA:false
++keyUsage = critical, digitalSignature, keyEncipherment
++extendedKeyUsage = critical, serverAuth, clientAuth
++nsCertType = critical, server, client
++subjectKeyIdentifier = hash
++authorityKeyIdentifier = keyid:always, issuer:always
++subjectAltName = DNS:$common_name,email:copy
++issuerAltName = issuer:copy
++crlDistributionPoints = URI:$config[base_url]index.php?stage=dl_crl
++nsComment = "PHPki/OpenSSL Generated Secure Certificate for freeDiameter"
++nsBaseUrl = $config[base_url]
++nsRevocationUrl = ns_revoke_query.php?
++nsCaPolicyUrl = $config[base_url]policy.html
++
++
++
+ [ vpn_client_ext ]
+ basicConstraints = critical, CA:false
+ keyUsage = critical, digitalSignature
+diff -Nur phpki-0.82/setup.php phpki-0.82-fD/setup.php
+--- phpki-0.82/setup.php 2007-07-22 23:34:08.000000000 +0900
++++ phpki-0.82-fD/setup.php 2010-05-27 17:01:41.000000000 +0900
+@@ -339,6 +339,11 @@
+ default_days = 365
+ policy = policy_supplied
+
++[ freediameter_cert ]
++x509_extensions = freediameter_ext
++default_days = 730
++policy = policy_supplied
++
+ [ vpn_cert ]
+ x509_extensions = vpn_client_server_ext
+ default_days = 365
+@@ -418,6 +423,22 @@
+ nsRevocationUrl = ns_revoke_query.php?
+ nsCaPolicyUrl = $config[base_url]policy.html
+
++[ freediameter_ext ]
++basicConstraints = CA:false
++keyUsage = critical, digitalSignature, keyEncipherment
++extendedKeyUsage = critical, serverAuth, clientAuth
++nsCertType = critical, server, client
++subjectKeyIdentifier = hash
++authorityKeyIdentifier = keyid:always, issuer:always
++subjectAltName = DNS:$common_name,email:copy
++issuerAltName = issuer:copy
++crlDistributionPoints = URI:$config[base_url]index.php?stage=dl_crl
++nsComment = "PHPki/OpenSSL Generated Secure Certificate for freeDiameter"
++nsBaseUrl = $config[base_url]
++nsRevocationUrl = ns_revoke_query.php?
++nsCaPolicyUrl = $config[base_url]policy.html
++
++
+ [ time_stamping_ext ]
+ basicConstraints = CA:false
+ keyUsage = critical, nonRepudiation, digitalSignature
+diff -Nur phpki-0.82/setup.php-presetup phpki-0.82-fD/setup.php-presetup
+--- phpki-0.82/setup.php-presetup 2007-07-22 23:34:08.000000000 +0900
++++ phpki-0.82-fD/setup.php-presetup 2010-05-27 17:01:41.000000000 +0900
+@@ -339,6 +339,11 @@
+ default_days = 365
+ policy = policy_supplied
+
++[ freediameter_cert ]
++x509_extensions = freediameter_ext
++default_days = 730
++policy = policy_supplied
++
+ [ vpn_cert ]
+ x509_extensions = vpn_client_server_ext
+ default_days = 365
+@@ -418,6 +423,22 @@
+ nsRevocationUrl = ns_revoke_query.php?
+ nsCaPolicyUrl = $config[base_url]policy.html
+
++[ freediameter_ext ]
++basicConstraints = CA:false
++keyUsage = critical, digitalSignature, keyEncipherment
++extendedKeyUsage = critical, serverAuth, clientAuth
++nsCertType = critical, server, client
++subjectKeyIdentifier = hash
++authorityKeyIdentifier = keyid:always, issuer:always
++subjectAltName = DNS:$common_name,email:copy
++issuerAltName = issuer:copy
++crlDistributionPoints = URI:$config[base_url]index.php?stage=dl_crl
++nsComment = "PHPki/OpenSSL Generated Secure Certificate for freeDiameter"
++nsBaseUrl = $config[base_url]
++nsRevocationUrl = ns_revoke_query.php?
++nsCaPolicyUrl = $config[base_url]policy.html
++
++
+ [ time_stamping_ext ]
+ basicConstraints = CA:false
+ keyUsage = critical, nonRepudiation, digitalSignature
diff --git a/contrib/README b/contrib/README
new file mode 100644
index 0000000..678d30b
--- /dev/null
+++ b/contrib/README
@@ -0,0 +1,61 @@
+This file describes the content of the "contrib" directory.
+For information about the freeDiameter project, please refer
+to top-level README file.
+
+- update_copyright.sh : This script will simply update the copyright information
+ in all source files in the freeDiameter mercurial repository, based
+ on the last modification time. Thought I might share it if other people find
+ it useful for their own project...
+
+
+- debian : This directory contains the packaging information to create native Debian / Ubuntu
+ packages. It requires debhelper >= 7.3.9 (support for cmake). To use, simply link the
+ debian folder from the main freeDiameter folder, then use your building script as
+ usual ('dh binary' or 'pdebuild' or ...).
+ If you simply intend to use freeDiameter package, the relevant information is located
+ at: http://www.freediameter.net/trac/wiki/DebRepository
+
+
+- PKI : This directory contains useful material related to establishing a
+ Public Key Infrastructure (PKI) for deploying x509 certificates
+ and use these for TLS authentication of the freeDiameter nodes.
+
+ IMPORTANT: Please note that these solutions are NOT suitable
+ for use in a production environment! It allows easy deployment of
+ certificates for tests, and that is their sole purpose.
+
+ The directory contains:
+
+ - ca_script: a simple Makefile allowing you to generate a self-signed certificate (root)
+ and then issue new certificates and private keys for your users.
+ Run "make" without argument to get the help.
+
+ - ca_script2: An evolution of the previous Makefile. This one allows you
+ to create a hierarchy of CA and certificates.
+
+ - phpki-0.82.patch : This patch is to be applied to PHPki to customize the use for freeDiameter.
+ PHPki (http://sourceforge.net/projects/phpki/) is a PHP-based web interface
+ that provides more or less the same services as ca_script.
+
+
+- OpenWRT : This directory contains the scripts and documentation related to
+ the integration of freeDiameter RADIUS/Diameter gateway component in the openWRT
+ distribution (http://openwrt.org) -- the goal is to give the access point the
+ ability to "talk" Diameter instead of RADIUS.
+
+
+- nightly_tests : This directory contains the scripts and documentation for the nightly
+ tests run on freeDiameter. The results are published at the following URL:
+ http://www.freediameter.net/CDash/index.php?project=freeDiameter
+
+
+- dict_legacy: XML and DTD files for the dict_legacy_xml.fdx extension.
+
+- dict_dcca: partial implementations of the DCCA dictionary
+
+- dict_gx: untested implementation of the Gx interface.
+
+- test_Gx: a responder on the Gx interface that always send SUCCESS status.
+
+- wireshark: This contains some information on how to use Wireshark to monitor Diameter
+ exchange protected with TLS. It involves patching the wireshark software.
diff --git a/contrib/RPM/build_rpm.txt b/contrib/RPM/build_rpm.txt
new file mode 100755
index 0000000..53eb77f
--- /dev/null
+++ b/contrib/RPM/build_rpm.txt
@@ -0,0 +1,6 @@
+[krum@ThinkPad DelMe]$ cp freeDiameter.spec /home/krum/rpmbuild/SPECS/
+[krum@ThinkPad DelMe]$ cd /home/krum/rpmbuild/SOURCES/
+[krum@ThinkPad ~]$ cd /home/krum/rpmbuild/SOURCES/
+[krum@ThinkPad SOURCES]$ wget http://www.freediameter.net/hg/freeDiameter/archive/1.1.6.tar.gz
+[krum@ThinkPad SOURCES]$ cd ../SPECS/
+[krum@ThinkPad SPECS]$ rpmbuild -ba freeDiameter.spec
diff --git a/contrib/RPM/freeDiameter.spec b/contrib/RPM/freeDiameter.spec
new file mode 100755
index 0000000..7f492db
--- /dev/null
+++ b/contrib/RPM/freeDiameter.spec
@@ -0,0 +1,78 @@
+
+Name: freeDiameter
+Version: 1.1.6
+Release: 1%{?dist}
+Packager: krum.boy4ev@gmail.com
+Summary: freeDiameter is an implementation of the Diameter protocol.
+Group: Development/Libraries
+License: BSD License
+URL: http://www.freediameter.net
+Source0: http://www.freediameter.net/hg/freeDiameter/archive/1.1.6.tar.gz
+
+BuildRequires: cmake make gcc gcc-c++ flex bison lksctp-tools-devel
+BuildRequires: gnutls-devel libgcrypt-devel libidn-devel
+BuildRequires: mercurial
+Requires: lksctp-tools
+
+%description
+freeDiameter is an implementation of the Diameter protocol.
+
+Diameter is a protocol designed to carry Authentication, Authorization and
+Accounting (AAA) payload. It is an evolution of the RADIUS protocol (as the
+name suggests).
+
+See http://www.freediameter.net/ for more information on the project.
+
+freeDiameter was previously known as the "waaad" project (WIDE AAA Daemon)
+This project is not related to the "freediameter" project from Sun on sourceforge.
+
+Author: Sebastien Decugis.
+
+%package daemon
+Summary: Simple daemon parses the command line and initializes the freeDiameter framework.
+Group: Development/Libraries
+Requires: freeDiameter
+
+%description daemon
+freeDiameterd : this simple daemon parses the command line and initializes the
+freeDiameter framework. Use it for your Diameter server & agent components.
+In case of Diameter clients, you probably will prefer linking the libfdcore
+directly with your client application that must be made Diameter-aware.
+
+
+%prep
+%setup -qn %{name}-%{version}
+
+
+%build
+mkdir -p build
+cd build
+cmake ../
+
+make %{?_smp_mflags}
+
+
+%install
+rm -rf $RPM_BUILD_ROOT
+cd build
+make install DESTDIR=$RPM_BUILD_ROOT
+make test
+
+%post daemon
+echo "/usr/local/lib/" > /etc/ld.so.conf.d/%{name}.conf
+/sbin/ldconfig
+
+%files
+%defattr(-,root,root,-)
+/usr/local/include/
+/usr/local/lib/
+
+%files daemon
+%defattr(-,root,root,-)
+/usr/local/bin/
+
+
+
+%changelog
+ * Sat Jul 5 2013 Krum Boychev <krum.boy4ev@gmail.com> - 1.1.6-1
+ - initial version
diff --git a/contrib/app_acct_tools/README b/contrib/app_acct_tools/README
new file mode 100644
index 0000000..4728f15
--- /dev/null
+++ b/contrib/app_acct_tools/README
@@ -0,0 +1,47 @@
+This folder contains several tools to use and parse the data from the app_acct.fdx extension.
+
+- database.sql :
+ An example database format for use with the scripts in this folder.
+
+- app_acct.conf :
+ The part of app_acct.conf that is relevant to this database schema.
+
+- purge_to_file.php :
+ This PHP script is used to take the records from the incoming table (stored by app_acct.fdx
+ extension) and save these records in a file in SQL format. This is similar to pg_dump
+ command, except that all the records that have been saved in the file are removed from
+ the table. This can be used in cron jobs for example to maintain a reasonable size of
+ the incoming table and move the data to another host for off-line processing. It can
+ also be useful to aggregate the data from different hosts, if you are load-balancing your
+ accounting servers for example (granted that all app_acct.fdx use identical table format
+ on all the servers). See the top of the file for configuration parameters.
+
+- process_records.php :
+ This PHP script processes the records pertaining to users sessions, as follow:
+ * when a session is complete (STOP record received), it stores a session summary
+ into the processed records table (see process_database.sql file for format).
+ * It optionally archives the processed records into a different table, before deleting them.
+ * It can also move records of unterminated sessions that are older than a configurable time
+ to an orphan_records table, so that they are not re-processed every time.
+ This orphans table must have the same structure as the "incoming" table.
+
+- display_results.php, display_self.php, display_stats.php :
+ These scripts give a few examples of how to display the processed data.
+
+USAGE:
+ *) Initial: create your database using database.sql file
+ *) Configure the app_acct.fdx extension using tips from app_acct.conf
+
+ The following processing can be run for example as cron jobs.
+ 1) On each accounting server for the realm, configure the app_acct.fdx extension to
+ dump the records in a local database (all servers must use the same database format).
+ The table would typically be "incoming".
+ 2) Run the purge_to_file.php script on each server regularly, then move the generated
+ files onto a single server for processing. This server only needs the other tables.
+ 3) Add the data from the files into the database in this server by running:
+ psql < file.sql
+ Each file that has been added should then be archived and removed so that it is not
+ re-added later.
+ 4) Run the process_records.php script on this processing server. Now, the database
+ contains the aggregated data that can be visualized with display_*.php scripts.
+
diff --git a/contrib/app_acct_tools/app_acct.conf b/contrib/app_acct_tools/app_acct.conf
new file mode 100644
index 0000000..0c9cdb8
--- /dev/null
+++ b/contrib/app_acct_tools/app_acct.conf
@@ -0,0 +1,68 @@
+
+# This is the configuration for use with the database created by 'database.sql' file.
+# One should take care of configuring the ConnInfo properly.
+ConnInfo = "";
+
+# The table and special fields names:
+Table = "incoming";
+Timestamp_field = "recorded_on";
+Server_name_field = "recorded_serv";
+
+# The AVPs that are saved in the table:
+"Origin-Host";
+"Origin-Realm";
+"Destination-Realm";
+"Destination-Host";
+"Session-Id";
+"Origin-State-Id";
+"Accounting-Record-Type";
+"Accounting-Record-Number";
+"User-Name";
+"Event-Timestamp";
+"Acct-Application-Id";
+"Accounting-Sub-Session-Id";
+"Acct-Session-Id";
+"Acct-Multi-Session-Id";
+"Origin-AAA-Protocol";
+"Acct-Delay-Time";
+"NAS-Identifier";
+"NAS-IP-Address";
+"NAS-IPv6-Address";
+"NAS-Port";
+"NAS-Port-Id";
+"NAS-Port-Type";
+"Service-Type";
+"Termination-Cause";
+"Accounting-Input-Octets";
+"Accounting-Input-Packets";
+"Accounting-Output-Octets";
+"Accounting-Output-Packets";
+"Acct-Authentic";
+"Acct-Link-Count";
+"Acct-Session-Time";
+"Acct-Tunnel-Connection";
+"Acct-Tunnel-Packets-Lost";
+"Callback-Id";
+"Callback-Number";
+"Called-Station-Id";
+"Calling-Station-Id";
+"Connect-Info";
+"Originating-Line-Info";
+"Authorization-Lifetime";
+"Session-Timeout";
+"Idle-Timeout";
+"Port-Limit";
+"Accounting-Realtime-Required";
+"Acct-Interim-Interval";
+"Filter-Id";
+"NAS-Filter-Rule";
+"QoS-Filter-Rule";
+"Login-IP-Host";
+"Login-IPv6-Host";
+"Login-LAT-Group";
+"Login-LAT-Node";
+"Login-LAT-Port";
+"Login-LAT-Service";
+"Login-Service";
+"Login-TCP-Port";
+"Route-Record" = { multi=5; };
diff --git a/contrib/app_acct_tools/database.sql b/contrib/app_acct_tools/database.sql
new file mode 100644
index 0000000..c3a3072
--- /dev/null
+++ b/contrib/app_acct_tools/database.sql
@@ -0,0 +1,227 @@
+-- database.sql
+-- Script to create the tables for process_records.php script to perform.
+-- IMPORTANT NOTE: No constraint and almost no index are created by this script.
+-- One should consider adding the appropriate indexes according to their utilization of the data.
+
+-- Incoming table table.
+-- This table is used by app_acct.fdx to store the Accounting records.
+CREATE TABLE incoming (
+ "Origin-Host" bytea NOT NULL,
+ "Origin-Realm" bytea NOT NULL,
+ "Destination-Realm" bytea,
+ "Destination-Host" bytea,
+ "Session-Id" bytea NOT NULL,
+ "Origin-State-Id" integer,
+ "Accounting-Record-Type" integer NOT NULL,
+ "Accounting-Record-Number" integer NOT NULL,
+ "User-Name" bytea,
+ "Event-Timestamp" bytea,
+ "Acct-Application-Id" integer,
+ "Accounting-Sub-Session-Id" bigint,
+ "Acct-Session-Id" bytea,
+ "Acct-Multi-Session-Id" bytea,
+ "Origin-AAA-Protocol" integer,
+ "Acct-Delay-Time" integer,
+ "NAS-Identifier" bytea,
+ "NAS-IP-Address" bytea,
+ "NAS-IPv6-Address" bytea,
+ "NAS-Port" integer,
+ "NAS-Port-Id" bytea,
+ "NAS-Port-Type" integer,
+ "Service-Type" integer,
+ "Termination-Cause" integer,
+ "Accounting-Input-Octets" bigint,
+ "Accounting-Input-Packets" bigint,
+ "Accounting-Output-Octets" bigint,
+ "Accounting-Output-Packets" bigint,
+ "Acct-Authentic" integer,
+ "Acct-Link-Count" integer,
+ "Acct-Session-Time" integer,
+ "Acct-Tunnel-Connection" bytea,
+ "Acct-Tunnel-Packets-Lost" integer,
+ "Callback-Id" bytea,
+ "Callback-Number" bytea,
+ "Called-Station-Id" bytea,
+ "Calling-Station-Id" bytea,
+ "Connect-Info" bytea,
+ "Originating-Line-Info" bytea,
+ "Authorization-Lifetime" integer,
+ "Session-Timeout" integer,
+ "Idle-Timeout" integer,
+ "Port-Limit" integer,
+ "Accounting-Realtime-Required" integer,
+ "Acct-Interim-Interval" integer,
+ "Filter-Id" bytea,
+ "NAS-Filter-Rule" bytea,
+ "QoS-Filter-Rule" bytea,
+ "Login-IP-Host" bytea,
+ "Login-IPv6-Host" bytea,
+ "Login-LAT-Group" bytea,
+ "Login-LAT-Node" bytea,
+ "Login-LAT-Port" bytea,
+ "Login-LAT-Service" bytea,
+ "Login-Service" integer,
+ "Login-TCP-Port" integer,
+ "Route-Record1" bytea,
+ "Route-Record2" bytea,
+ "Route-Record3" bytea,
+ "Route-Record4" bytea,
+ "Route-Record5" bytea,
+ "recorded_on" timestamp with time zone NOT NULL,
+ "recorded_serv" bytea
+ );
+
+
+-- Accounting Data.
+-- This is is the processed data that is used also by display_results.php
+CREATE TABLE processed (
+ user_name bytea,
+ user_device bytea,
+ nas_info bytea,
+ sess_start timestamp with time zone,
+ sess_duration interval,
+ downl_bytes bigint,
+ upl_bytes bigint,
+ downl_packets bigint,
+ upl_packets bigint
+ );
+CREATE INDEX un_index ON processed (user_name);
+
+
+
+-- Orphans table.
+-- This is optional, and it must match the structure of your incoming table.
+CREATE TABLE orphans (
+ "Origin-Host" bytea NOT NULL,
+ "Origin-Realm" bytea NOT NULL,
+ "Destination-Realm" bytea,
+ "Destination-Host" bytea,
+ "Session-Id" bytea NOT NULL,
+ "Origin-State-Id" integer,
+ "Accounting-Record-Type" integer NOT NULL,
+ "Accounting-Record-Number" integer NOT NULL,
+ "User-Name" bytea,
+ "Event-Timestamp" bytea,
+ "Acct-Application-Id" integer,
+ "Accounting-Sub-Session-Id" bigint,
+ "Acct-Session-Id" bytea,
+ "Acct-Multi-Session-Id" bytea,
+ "Origin-AAA-Protocol" integer,
+ "Acct-Delay-Time" integer,
+ "NAS-Identifier" bytea,
+ "NAS-IP-Address" bytea,
+ "NAS-IPv6-Address" bytea,
+ "NAS-Port" integer,
+ "NAS-Port-Id" bytea,
+ "NAS-Port-Type" integer,
+ "Service-Type" integer,
+ "Termination-Cause" integer,
+ "Accounting-Input-Octets" bigint,
+ "Accounting-Input-Packets" bigint,
+ "Accounting-Output-Octets" bigint,
+ "Accounting-Output-Packets" bigint,
+ "Acct-Authentic" integer,
+ "Acct-Link-Count" integer,
+ "Acct-Session-Time" integer,
+ "Acct-Tunnel-Connection" bytea,
+ "Acct-Tunnel-Packets-Lost" integer,
+ "Callback-Id" bytea,
+ "Callback-Number" bytea,
+ "Called-Station-Id" bytea,
+ "Calling-Station-Id" bytea,
+ "Connect-Info" bytea,
+ "Originating-Line-Info" bytea,
+ "Authorization-Lifetime" integer,
+ "Session-Timeout" integer,
+ "Idle-Timeout" integer,
+ "Port-Limit" integer,
+ "Accounting-Realtime-Required" integer,
+ "Acct-Interim-Interval" integer,
+ "Filter-Id" bytea,
+ "NAS-Filter-Rule" bytea,
+ "QoS-Filter-Rule" bytea,
+ "Login-IP-Host" bytea,
+ "Login-IPv6-Host" bytea,
+ "Login-LAT-Group" bytea,
+ "Login-LAT-Node" bytea,
+ "Login-LAT-Port" bytea,
+ "Login-LAT-Service" bytea,
+ "Login-Service" integer,
+ "Login-TCP-Port" integer,
+ "Route-Record1" bytea,
+ "Route-Record2" bytea,
+ "Route-Record3" bytea,
+ "Route-Record4" bytea,
+ "Route-Record5" bytea,
+ "recorded_on" timestamp with time zone NOT NULL,
+ "recorded_serv" bytea
+ );
+
+-- Archives table.
+-- This is also optional, and it must match the structure of your incoming table.
+CREATE TABLE archived (
+ "Origin-Host" bytea NOT NULL,
+ "Origin-Realm" bytea NOT NULL,
+ "Destination-Realm" bytea,
+ "Destination-Host" bytea,
+ "Session-Id" bytea NOT NULL,
+ "Origin-State-Id" integer,
+ "Accounting-Record-Type" integer NOT NULL,
+ "Accounting-Record-Number" integer NOT NULL,
+ "User-Name" bytea,
+ "Event-Timestamp" bytea,
+ "Acct-Application-Id" integer,
+ "Accounting-Sub-Session-Id" bigint,
+ "Acct-Session-Id" bytea,
+ "Acct-Multi-Session-Id" bytea,
+ "Origin-AAA-Protocol" integer,
+ "Acct-Delay-Time" integer,
+ "NAS-Identifier" bytea,
+ "NAS-IP-Address" bytea,
+ "NAS-IPv6-Address" bytea,
+ "NAS-Port" integer,
+ "NAS-Port-Id" bytea,
+ "NAS-Port-Type" integer,
+ "Service-Type" integer,
+ "Termination-Cause" integer,
+ "Accounting-Input-Octets" bigint,
+ "Accounting-Input-Packets" bigint,
+ "Accounting-Output-Octets" bigint,
+ "Accounting-Output-Packets" bigint,
+ "Acct-Authentic" integer,
+ "Acct-Link-Count" integer,
+ "Acct-Session-Time" integer,
+ "Acct-Tunnel-Connection" bytea,
+ "Acct-Tunnel-Packets-Lost" integer,
+ "Callback-Id" bytea,
+ "Callback-Number" bytea,
+ "Called-Station-Id" bytea,
+ "Calling-Station-Id" bytea,
+ "Connect-Info" bytea,
+ "Originating-Line-Info" bytea,
+ "Authorization-Lifetime" integer,
+ "Session-Timeout" integer,
+ "Idle-Timeout" integer,
+ "Port-Limit" integer,
+ "Accounting-Realtime-Required" integer,
+ "Acct-Interim-Interval" integer,
+ "Filter-Id" bytea,
+ "NAS-Filter-Rule" bytea,
+ "QoS-Filter-Rule" bytea,
+ "Login-IP-Host" bytea,
+ "Login-IPv6-Host" bytea,
+ "Login-LAT-Group" bytea,
+ "Login-LAT-Node" bytea,
+ "Login-LAT-Port" bytea,
+ "Login-LAT-Service" bytea,
+ "Login-Service" integer,
+ "Login-TCP-Port" integer,
+ "Route-Record1" bytea,
+ "Route-Record2" bytea,
+ "Route-Record3" bytea,
+ "Route-Record4" bytea,
+ "Route-Record5" bytea,
+ "recorded_on" timestamp with time zone NOT NULL,
+ "recorded_serv" bytea
+ );
+
diff --git a/contrib/app_acct_tools/display_results.php b/contrib/app_acct_tools/display_results.php
new file mode 100644
index 0000000..f84d3d2
--- /dev/null
+++ b/contrib/app_acct_tools/display_results.php
@@ -0,0 +1,141 @@
+<?php
+
+# The copyright of this file is the same as the freeDiameter project. Licence is BSD.
+
+# This file should no be called directly;
+# instead it should be included from another script that sets its parameters as described below.
+
+## $USERS
+# An array of the user names to display; the empty array will display all users.
+# This parameter MUST be set.
+if (!isset($USERS))
+ die('Do not call this file directly');
+
+## $START_TIME:
+# If set, this restricts the displayed data to sessions starting after $START
+
+## $END_TIME:
+# If set, this restricts the displayed data to sessions starting before $END
+
+## $LIMIT:
+## $LIMIT_OFFSET:
+# If set, these limit the number of accounting records displayed (for pagination purpose)
+
+#------------------------------------------------------------------------------------------
+# DATABASE:
+
+/* The Connection String used to access that database:
+ Example: "host=localhost dbname=app_acct user=freediameter password=foo" */
+$CONNSTR="";
+
+/* The name of the table containing the processed data (from process_records.php script) */
+$PROCESSED="processed";
+
+#------------------------------------------------------------------------------------------
+
+
+/* Connect to the database */
+$dbconn = pg_connect($CONNSTR)
+ or die('Could not connect: ' . pg_last_error() . "\n");
+
+/* Function to format download size (from php.net) */
+function human_readable( $size )
+{
+ $count = 0;
+ $format = array("B","KB","MB","GB","TB","PB","EB","ZB","YB");
+ while(($size/1024)>1 && $count<8)
+ {
+ $size=$size/1024;
+ $count++;
+ }
+ if( $size >= 100 ) $decimals = 0;
+ elseif ($size >= 10 ) $decimals = 1;
+ else $decimals = 2;
+ $return = number_format($size,$decimals,'.',' ')." ".$format[$count];
+ return $return;
+}
+
+/* Build the SQL query */
+$sql = 'SELECT *, to_char(sess_start, \'YYYY-MM-DD HH24:MI:SS (TZ)\') as fmt_sess_start FROM "'.$PROCESSED.'"';
+$where=0;
+if ($USERS) {
+ $USERS = array_map(pg_escape_bytea, $USERS);
+ $sql .= " WHERE user_name IN ('". join("', '", array_values($USERS))."') ";
+ $where = 1;
+}
+
+if ($START_TIME) {
+ $START_TIME = pg_escape_string($START_TIME);
+ if ($where++)
+ $sql .= " AND ";
+ else
+ $sql .= " WHERE ";
+ $sql .= "sess_start >= '".$START_TIME."'";
+}
+if ($END_TIME) {
+ $END_TIME = pg_escape_string($END_TIME);
+ if ($where++)
+ $sql .= " AND ";
+ else
+ $sql .= " WHERE ";
+ $sql .= "sess_start <= '".$END_TIME."'";
+}
+
+$sql .= " ORDER BY sess_start, sess_duration";
+
+if ($LIMIT)
+ $sql .= " LIMIT $LIMIT";
+if ($LIMIT_OFFSET)
+ $sql .= " OFFSET $LIMIT_OFFSET";
+
+/* Execute the query */
+$result = pg_query($dbconn, $sql) or die('Query failed: ' . pg_last_error() . "\n");
+$recs = pg_num_rows($result);
+if ($recs == 0) {
+ echo "<p><em>Sorry, no data is available in this selection.</em></p>\n";
+} else {
+ echo "<p><strong>$recs</strong> records found.</p>\n";
+?>
+ <table>
+ <tr>
+ <th>Device identifier</th>
+ <th>Access Device information</th>
+ <th>Session started on</th>
+ <th>Duration</th>
+ <th>Downloaded</th>
+ <th>Uploaded</th>
+ </tr>
+<?php
+ while ($record = pg_fetch_array($result, null, PGSQL_ASSOC)) {
+ echo " <tr title='".htmlentities(pg_unescape_bytea($record["user_name"]))."'>\n";
+ echo " <td>";
+ echo htmlentities(pg_unescape_bytea($record["user_device"]));
+ echo "</td>\n";
+ echo " <td>";
+ echo htmlentities(pg_unescape_bytea($record["nas_info"]));
+ echo "</td>\n";
+ echo " <td>";
+ echo $record["fmt_sess_start"];
+ echo "</td>\n";
+ echo " <td>";
+ echo htmlentities($record["sess_duration"]);
+ echo "</td>\n";
+ echo " <td>";
+ echo human_readable( $record["downl_bytes"] )." (".$record["downl_packets"]."pckts)";
+ echo "</td>\n";
+ echo " <td>";
+ echo human_readable( $record["upl_bytes"] )." (".$record["upl_packets"]."pckts)";
+ echo "</td>\n";
+ echo " </tr>\n";
+
+ }
+}
+pg_free_result($result);
+
+
+/* Closing connection */
+pg_close($dbconn);
+
+
+
+?>
diff --git a/contrib/app_acct_tools/display_self.php b/contrib/app_acct_tools/display_self.php
new file mode 100644
index 0000000..906cb0a
--- /dev/null
+++ b/contrib/app_acct_tools/display_self.php
@@ -0,0 +1,139 @@
+<?php
+
+# This file is an example wrapper around display_results.php.
+
+# It relies on clients authentication based on certificate usage
+# (it must be the same certificate as used during AAA access, so that the User-Name matches).
+# See your web server documentation for details.
+# Example for apache2:
+# (+ detail in http://httpd.apache.org/docs/2.0/ssl/ssl_howto.html#allclients )
+# - in vhost definition file, refence the CA chain of your users certificates:
+# SSLCACertificateFile /var/www/conf/ssl.crt/ca.crt
+# - in vhost file or .htaccess file (adjust Depth to your setup):
+# <IfModule mod_ssl.c>
+# SSLVerifyClient require
+# SSLVerifyDepth 2
+# </IfModule>
+
+/* Check the client is correctly SSL authenticated with his server */
+if (!isset($_SERVER["SSL_CLIENT_VERIFY"]) || $_SERVER["SSL_CLIENT_VERIFY"] != "SUCCESS")
+ die("SSL authentication failed, the webserver is probably not configured correctly.\n");
+
+/* Force some parameters to integer values */
+if ($_GET["t_limit"])
+ $_GET["t_limit"] = (int) $_GET["t_limit"];
+if ($_GET["t_offset"])
+ $_GET["t_offset"] = (int) $_GET["t_offset"];
+
+/* Default form values */
+if (!isset($_GET["Submit"])) {
+ $_GET["t_limit"] = 50;
+ $_GET["c_limit"] = 1;
+ $_GET["t_offset"] = 0;
+}
+
+/* Output the form */
+?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<html lang="en-US">
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+
+ <title>Accounting Data</title>
+ <meta name="description" content="This page gives you access to your personal accounting data.">
+ <meta name="keywords" content="accounting">
+
+ <style type="text/css">
+ body { text-align:center; }
+ table { border-collapse:collapse; margin-left:auto; margin-right:auto; }
+ table, td, th { border:1px solid green; padding-left:.5em; padding-right:.5em;}
+ th { background-color:green; color:white; }
+ </style>
+</head>
+
+<body >
+ <h1>Accounting data</h1>
+ <p>Note well: this page displays only data about <em>terminated</em> sessions.</p>
+ <form method="GET">
+ <table>
+ <tr>
+ <th colspan="3">
+ Filtering parameters
+ </th>
+ </tr>
+ <tr>
+ <td><input type="checkbox" name="c_starttime"<?php if (isset($_GET["c_starttime"])) echo " checked"; ?>></td>
+ <td>Show only sessions starting from (<a href="http://www.postgresql.org/docs/8.4/static/datatype-datetime.html">YYYY-MM-DD HH:MM:SS</a>):</td>
+ <td><input type="text" name="t_starttime"<?php if (isset($_GET["t_starttime"])) echo 'value="'.$_GET["t_starttime"].'"'; ?>></td>
+ </tr>
+ <tr>
+ <td><input type="checkbox" name="c_endtime"<?php if (isset($_GET["c_endtime"])) echo " checked"; ?>></td>
+ <td>Show only sessions starting until (<a href="http://www.postgresql.org/docs/8.4/static/datatype-datetime.html">YYYY-MM-DD HH:MM:SS</a>):</td>
+ <td><input type="text" name="t_endtime"<?php if (isset($_GET["t_endtime"])) echo 'value="'.$_GET["t_endtime"].'"'; ?>></td>
+ </tr>
+ <tr>
+ <td><input type="checkbox" name="c_limit"<?php if (isset($_GET["c_limit"])) echo " checked"; ?>></td>
+ <td>Show only this number of records:</td>
+ <td><input type="text" name="t_limit"<?php if (isset($_GET["t_limit"])) echo 'value="'.$_GET["t_limit"].'"'; ?>></td>
+ </tr>
+ <tr>
+ <td><input type="checkbox" name="c_offset"<?php if (isset($_GET["c_offset"])) echo " checked"; ?>></td>
+ <td>Starting from record:</td>
+ <td><input type="text" name="t_offset"<?php if (isset($_GET["t_offset"])) echo 'value="'.$_GET["t_offset"].'"'; ?>></td>
+ </tr>
+ <tr>
+ <th colspan="3">
+ Apply this filter: <input type="submit" name="Submit">
+ </th>
+ </tr>
+ </table>
+ </form>
+
+<p>
+ Currently displaying user <em><?php echo htmlentities($_SERVER["SSL_CLIENT_S_DN_CN"]); ?></em><?php
+
+/* Search user by CN or Email since some OS use the later during EAP-TLS authentication */
+$USERS = array($_SERVER["SSL_CLIENT_S_DN_CN"], $_SERVER["SSL_CLIENT_S_DN_Email"]);
+
+/* If the start time boundary was specified... */
+if ($_GET["c_starttime"] && $_GET["t_starttime"]) {
+ $START_TIME=$_GET["t_starttime"];
+}
+if ($_GET["c_endtime"] && $_GET["t_endtime"]) {
+ $END_TIME=$_GET["t_endtime"];
+}
+
+/* idem with end time */
+if ($START_TIME && $END_TIME) {
+ echo ", sessions starting between $START_TIME and $END_TIME";
+} elseif ($START_TIME) {
+ echo ", sessions starting after $START_TIME";
+} elseif ($END_TIME) {
+ echo ", sessions starting before $END_TIME";
+}
+
+/* Pagination */
+if ($_GET["c_limit"] && $_GET["t_limit"]) {
+ $LIMIT=$_GET["t_limit"];
+}
+if ($_GET["c_offset"] && $_GET["t_offset"]) {
+ $LIMIT_OFFSET=$_GET["t_offset"];
+}
+if ($LIMIT) {
+ echo ", limited to ".$LIMIT." records";
+ if ($LIMIT_OFFSET)
+ echo " starting at ".$LIMIT_OFFSET;
+} else if ($LIMIT_OFFSET) {
+ echo " starting at record ".$LIMIT_OFFSET;
+}
+echo ".\n";
+?>
+</p>
+
+<?php
+/* This file will generate the array of data matching the selection */
+require("display_results.php");
+
+?>
+</body>
+</html>
diff --git a/contrib/app_acct_tools/display_stats.php b/contrib/app_acct_tools/display_stats.php
new file mode 100644
index 0000000..31beb12
--- /dev/null
+++ b/contrib/app_acct_tools/display_stats.php
@@ -0,0 +1,269 @@
+<?php
+
+# The copyright of this file is the same as the freeDiameter project. Licence is BSD.
+
+#------------------------------------------------------------------------------------------
+# DATABASE:
+
+/* The Connection String used to access that database:
+ Example: "host=localhost dbname=app_acct user=freediameter password=foo" */
+$CONNSTR="";
+
+/* The name of the table containing the processed data (from process_records.php script) */
+$PROCESSED="processed";
+
+#------------------------------------------------------------------------------------------
+
+?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<html lang="en-US">
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+
+ <title>Accounting Data</title>
+ <meta name="description" content="This page gives you access to your personal accounting data.">
+ <meta name="keywords" content="accounting">
+
+ <style type="text/css">
+ body { text-align:center; }
+ table.colored { border-collapse:collapse; margin-left:auto; margin-right:auto; }
+ table.colored td, table.colored th { border:1px solid green; padding-left:.5em; padding-right:.5em;}
+ .colored th { background-color:green; color:white; }
+ hr { width:15px; margin-top:2em;margin-bottom:2em; }
+ </style>
+</head>
+
+<body >
+ <h1>Statistical accounting data</h1>
+ <form method="GET">
+ <table class="colored">
+ <tr>
+ <th colspan="3">
+ Filtering options
+ </th>
+ </tr>
+ <tr>
+ <td><input type="checkbox" name="c_starttime"<?php if (isset($_GET["c_starttime"])) echo " checked"; ?>></td>
+ <td>Limit to sessions starting from (<a href="http://www.postgresql.org/docs/8.4/static/datatype-datetime.html">hint</a>):</td>
+ <td><input type="text" title="YYYY-MM-DD HH:MM:SS" name="t_starttime"<?php if (isset($_GET["t_starttime"])) echo 'value="'.$_GET["t_starttime"].'"'; ?>></td>
+ </tr>
+ <tr>
+ <td><input type="checkbox" name="c_endtime"<?php if (isset($_GET["c_endtime"])) echo " checked"; ?>></td>
+ <td>Limit to sessions starting until (<a href="http://www.postgresql.org/docs/8.4/static/datatype-datetime.html">hint</a>):</td>
+ <td><input type="text" title="YYYY-MM-DD HH:MM:SS" name="t_endtime"<?php if (isset($_GET["t_endtime"])) echo 'value="'.$_GET["t_endtime"].'"'; ?>></td>
+ </tr>
+ <tr>
+ <th colspan="3">
+ Apply this filter: <input type="submit" name="Submit">
+ </th>
+ </tr>
+ </table>
+ </form>
+ <p>Note well: this page displays only data about <em>terminated</em> sessions.</p>
+<?php
+
+/* Connect to the database */
+$dbconn = pg_connect($CONNSTR)
+ or die('Could not connect: ' . pg_last_error() . "\n");
+
+if ($_GET["c_starttime"] && $_GET["t_starttime"]) {
+ $START_TIME=$_GET["t_starttime"];
+}
+if ($_GET["c_endtime"] && $_GET["t_endtime"]) {
+ $END_TIME=$_GET["t_endtime"];
+}
+$sql_cond="";
+if ($START_TIME) {
+ $sql_cond = "sess_start >= '".pg_escape_string($START_TIME)."'";
+}
+if ($END_TIME) {
+ if ($sql_cond)
+ $sql_cond .= " AND ";
+ $sql_cond .= "sess_start =< '".pg_escape_string($END_TIME)."'";
+}
+
+
+/* Function to format download size (from php.net) */
+function human_readable( $size )
+{
+ $count = 0;
+ $format = array("B","KB","MB","GB","TB","PB","EB","ZB","YB");
+ while(($size/1024)>1 && $count<8)
+ {
+ $size=$size/1024;
+ $count++;
+ }
+ if( $size >= 100 ) $decimals = 0;
+ elseif ($size >= 10 ) $decimals = 1;
+ else $decimals = 2;
+ $return = number_format($size,$decimals,'.',' ')." ".$format[$count];
+ return $return;
+}
+
+?>
+
+ <hr />
+
+<?php
+
+/* First query: global data */
+$sql = 'SELECT SUM(downl_bytes) as total_down, SUM(upl_bytes) as total_up,';
+$sql .= ' to_char(min(sess_start), \'YYYY-MM-DD HH24:MI:SS TZ\') as first_sess,';
+$sql .= ' to_char(max(sess_start), \'YYYY-MM-DD HH24:MI:SS TZ\') as last_sess,';
+$sql .= ' count(distinct user_name) as nb_users,';
+$sql .= ' count(distinct nas_info) as nb_ap';
+$sql .= ' FROM "'.$PROCESSED.'"';
+if ($sql_cond)
+ $sql .= ' WHERE '.$sql_cond;
+
+/* Execute the query */
+$result = pg_query($dbconn, $sql) or die('Query failed: ' . pg_last_error() . "\n");
+if (pg_num_rows($result) == 0) {
+ echo "<p><em>No data is available in the selected period.</em></p>\n";
+ die("</body></html>\n");
+}
+
+$data = pg_fetch_array($result, null, PGSQL_ASSOC);
+?>
+ <table class="colored">
+ <tr>
+ <th colspan="2">Total accounted data</th>
+ </tr>
+<?php
+echo " <tr><td>First session started:</td><td>".$data["first_sess"]."</td></tr>\n";
+echo " <tr><td>Last session started:</td><td>".$data["last_sess"]."</td></tr>\n";
+echo " <tr><td>Total data downloaded:</td><td><strong>".human_readable($data["total_down"])."</strong></td></tr>\n";
+echo " <tr><td>Total data uploaded:</td><td><strong>".human_readable($data["total_up"])."</strong></td></tr>\n";
+echo " <tr><td>Number of users who connected at least once:</td><td>".$data["nb_users"]."</td></tr>\n";
+echo " <tr><td>Number of access points involved:</td><td>".$data["nb_ap"]."</td></tr>\n";
+echo " </tr>\n";
+echo " </table>\n";
+
+pg_free_result($result);
+
+?>
+
+ <hr />
+
+ <table class="colored">
+ <tr>
+ <th colspan="2">Top-5 <strong>downloading</strong> users</th>
+ </tr>
+<?php
+
+/* Now, get the top 5 downloaders */
+$sql = 'SELECT SUM(downl_bytes) as total_down, user_name';
+$sql .= ' FROM "'.$PROCESSED.'"';
+if ($sql_cond)
+ $sql .= ' WHERE '.$sql_cond;
+$sql .= ' GROUP BY user_name';
+$sql .= ' ORDER BY total_down desc, user_name';
+$sql .= ' LIMIT 5';
+
+/* Execute the query */
+$result = pg_query($dbconn, $sql) or die('Query failed: ' . pg_last_error() . "\n");
+while ($data = pg_fetch_array($result, null, PGSQL_ASSOC)) {
+ echo " <tr>\n";
+ echo " <td>".htmlentities(pg_unescape_bytea($data["user_name"]))."</td>\n";
+ echo " <td>".human_readable($data["total_down"])."</td>\n";
+ echo " </tr>\n";
+}
+pg_free_result($result);
+?>
+ </table>
+
+ <hr />
+
+ <table class="colored">
+ <tr>
+ <th colspan="2">Top-5 <strong>uploading</strong> users</th>
+ </tr>
+<?php
+
+/* Now, get the top 5 downloaders */
+$sql = 'SELECT SUM(upl_bytes) as total_up, user_name';
+$sql .= ' FROM "'.$PROCESSED.'"';
+if ($sql_cond)
+ $sql .= ' WHERE '.$sql_cond;
+$sql .= ' GROUP BY user_name';
+$sql .= ' ORDER BY total_up desc, user_name';
+$sql .= ' LIMIT 5';
+
+/* Execute the query */
+$result = pg_query($dbconn, $sql) or die('Query failed: ' . pg_last_error() . "\n");
+while ($data = pg_fetch_array($result, null, PGSQL_ASSOC)) {
+ echo " <tr>\n";
+ echo " <td>".htmlentities(pg_unescape_bytea($data["user_name"]))."</td>\n";
+ echo " <td>".human_readable($data["total_up"])."</td>\n";
+ echo " </tr>\n";
+}
+pg_free_result($result);
+?>
+ </table>
+
+ <hr />
+
+ <table class="colored">
+ <tr>
+ <th colspan="2">Top-8 access devices (by number of users)</th>
+ </tr>
+<?php
+
+/* Now, get the top 5 downloaders */
+$sql = 'SELECT count(distinct user_name) as unc, nas_info';
+$sql .= ' FROM "'.$PROCESSED.'"';
+if ($sql_cond)
+ $sql .= ' WHERE '.$sql_cond;
+$sql .= ' GROUP BY nas_info';
+$sql .= ' ORDER BY unc desc, nas_info';
+$sql .= ' LIMIT 8';
+
+/* Execute the query */
+$result = pg_query($dbconn, $sql) or die('Query failed: ' . pg_last_error() . "\n");
+while ($data = pg_fetch_array($result, null, PGSQL_ASSOC)) {
+ echo " <tr>\n";
+ echo " <td>".htmlentities(pg_unescape_bytea($data["nas_info"]))."</td>\n";
+ echo " <td>".$data["unc"]."</td>\n";
+ echo " </tr>\n";
+}
+pg_free_result($result);
+?>
+ </table>
+
+ <hr />
+
+ <table class="colored">
+ <tr>
+ <th colspan="2">Top-8 access devices (by traffic: up+down)</th>
+ </tr>
+<?php
+
+/* Now, get the top 5 downloaders */
+$sql = 'SELECT SUM(upl_bytes) + SUM(downl_bytes) as traffic, nas_info';
+$sql .= ' FROM "'.$PROCESSED.'"';
+if ($sql_cond)
+ $sql .= ' WHERE '.$sql_cond;
+$sql .= ' GROUP BY nas_info';
+$sql .= ' ORDER BY traffic desc, nas_info';
+$sql .= ' LIMIT 8';
+
+/* Execute the query */
+$result = pg_query($dbconn, $sql) or die('Query failed: ' . pg_last_error() . "\n");
+while ($data = pg_fetch_array($result, null, PGSQL_ASSOC)) {
+ echo " <tr>\n";
+ echo " <td>".htmlentities(pg_unescape_bytea($data["nas_info"]))."</td>\n";
+ echo " <td>".human_readable($data["traffic"])."</td>\n";
+ echo " </tr>\n";
+}
+pg_free_result($result);
+?>
+ </table>
+
+ <hr />
+<?php
+/* Closing connection */
+pg_close($dbconn);
+?>
+<p><small>Data generated by scripts from the <a href="http://www.freediameter.net">freeDiameter</a> project.</small></p>
+</body>
+</html>
diff --git a/contrib/app_acct_tools/process_records.php b/contrib/app_acct_tools/process_records.php
new file mode 100644
index 0000000..c64e1d6
--- /dev/null
+++ b/contrib/app_acct_tools/process_records.php
@@ -0,0 +1,205 @@
+<?php
+# This file may be called either from CLI or web PHP installation.
+# The copyright is the same as the freeDiameter project. Licence is BSD.
+
+# IMPORTANT: This script is highly experimental, PLEASE KEEP A COPY OF YOUR ACCOUNTING DATA
+# if this data has any importance.
+
+/*-------------------------------------------------------*/
+
+/* This script supports only one database where all tables are kept.
+ The Connection String used to access that database:
+ Example: "host=localhost dbname=app_acct user=freediameter password=foo" */
+$CONNSTR="";
+
+
+/**** 1 : Incoming records (output of app_acct.fdx) ****/
+/* The name of the table were the raw records are saved (from app_acct.conf) */
+$INCOMING="incoming";
+
+/* Note: For this script, this table MUST contain the following fields (with these names):
+ Session-Id, User-Name, Accounting-Record-Type, Accounting-Record-Number, Acct-Session-Id,
+ Accounting-{In,Out}put-{Octets,Packets},
+ NAS-Identifier, Called-Station-Id, Calling-Station-Id, recorded_on.
+ */
+
+
+/**** 2 : Processed records (output of this script, input for display_results.php) ****/
+/* The name of the table */
+$PROCESSED="processed";
+
+/* See process_database.sql for command to create this database */
+
+/**** 3 : Orphan records (optional) ****/
+/* The script can move records belonging to an unterminated session that has not received any new
+ record for more than $ORPHAN_DELAY (based on recorded_on field) into an $ORPHANED_TABLE table, so that
+ these records are not re-processed everytime the script runs.
+ If $ORPHANED_TABLE is empty, this feature is disabled. */
+$ORPHANED_TABLE="orphans";
+$ORPHAN_DELAY = "2 days";
+
+
+/**** 4 : Archived records (optional) ****/
+/* When data has been processed successfully, the records can be saved into an archive table before being deleted. */
+/* This table also must have the same structure as $INCOMING */
+$ARCHIVES_TABLE="archived";
+
+/*-------------------------------------------------------*/
+
+/* Connect to the database */
+$dbconn = pg_connect($CONNSTR)
+ or die('Could not connect: ' . pg_last_error() . "\n");
+
+/* Handle orphans first */
+if ($ORPHANED_TABLE) {
+ $orphans_sql = 'SELECT * FROM "'.$INCOMING.'" ';
+ $orphans_sql.= 'WHERE "Acct-Session-Id" IN (';
+ $orphans_sql.= ' SELECT data.asid ';
+ $orphans_sql.= ' FROM (';
+ $orphans_sql.= ' SELECT "Acct-Session-Id" as asid, MAX("recorded_on") as latest, bool_or("Accounting-Record-Type" = 2) as got_start, bool_or("Accounting-Record-Type" = 4) as got_stop ';
+ $orphans_sql.= ' FROM "'.$INCOMING.'"';
+ $orphans_sql.= ' GROUP BY "Acct-Session-Id") ';
+ $orphans_sql.= ' as data';
+ $orphans_sql.= ' WHERE data.latest < current_timestamp - interval \''. $ORPHAN_DELAY .'\' AND NOT ( got_start AND got_stop )';
+ $orphans_sql.= ');';
+
+ /* Execute, move the orphaned records to the appropriate table. */
+ $result = pg_query($dbconn, $orphans_sql) or die('Query failed: ' . pg_last_error() . "\n");
+ if (pg_num_rows($result) > 0) {
+ $i = 0;
+ while ($orphan = pg_fetch_array($result, null, PGSQL_ASSOC)) {
+ $i++;
+
+ // this doesn't work: pg_insert( $dbconn, $ORPHANED_TABLE, $orphan ) or die('Insert failed: ' . pg_last_error() . "\n");
+ $sql = "INSERT INTO \"$ORPHANED_TABLE\" ";
+ $sql .= '("';
+ $sql .= join('", "', array_keys($orphan));
+ $sql .= '") VALUES (';
+ for($c = 0; $c < count($orphan); $c++)
+ $sql .= ($c ? ', ' : '').'$'.($c+1);
+ $sql .= ')';
+ pg_query_params($dbconn, $sql, array_values($orphan)) or die('Insert failed: ' . pg_last_error() . "\n");
+
+ // This also doesn't work: pg_delete( $dbconn, $INCOMING, $orphan ) or die('Removing orphan failed: ' . pg_last_error() . "\n");
+ $sql = "DELETE FROM \"$INCOMING\" WHERE ";
+ $sql .= '"Acct-Session-Id" = $1 AND "recorded_on" = $2';
+ pg_query_params($dbconn, $sql, array($orphan["Acct-Session-Id"], $orphan["recorded_on"])) or die('Removing orphan failed: ' . pg_last_error() . "\n");
+ }
+ echo $i." orphans have been moved to '".$ORPHANED_TABLE."'\n";
+ }
+ pg_free_result($result);
+}
+
+/* Delete duplicate records (which might have been received by different servers on different time, but are identical otherwise */
+$duplicate_sql = ' SELECT * FROM (SELECT count(*) as cnt, min("recorded_on") as first, "Session-Id", "Acct-Session-Id", "Accounting-Record-Type", "Accounting-Record-Number"';
+$duplicate_sql .= ' FROM "'.$INCOMING.'" GROUP BY "Session-Id", "Acct-Session-Id", "Accounting-Record-Type", "Accounting-Record-Number") as qry WHERE qry.cnt > 1';
+$result = pg_query($dbconn, $orphans_sql) or die('Query failed: ' . pg_last_error() . "\n");
+if (pg_num_rows($result) > 0) {
+ /* We have some duplicates to delete */
+ $i=0;
+ while ($dup = pg_fetch_array($result, null, PGSQL_ASSOC)) {
+ $i++;
+ $sql = "DELETE FROM \"$INCOMING\" WHERE ";
+ $sql .= '"Session-Id" = $1 AND "Acct-Session-Id" = $2 AND "Accounting-Record-Type" = $3 AND "Accounting-Record-Number" = $4 AND "recorded_on" <> $5';
+ $params = array($dup["Session-Id"], $dup["Acct-Session-Id"], $dup["Accounting-Record-Type"], $dup["Accounting-Record-Number"], $dup["first"]);
+ pg_query_params($dbconn, $sql, $params) or die('Removing duplicates failed: ' . pg_last_error() . "\n");
+ }
+ echo $i." duplicate records have been deleted from '".$INCOMING."'\n";
+}
+pg_free_result($result);
+
+
+/* Now, find Acct-Session-Id of completed sessions */
+$completed_sql = ' SELECT "Session-Id", "Acct-Session-Id" FROM (';
+$completed_sql .= ' SELECT "Session-Id", "Acct-Session-Id", bool_or("Accounting-Record-Type" = 2) as got_start, bool_or("Accounting-Record-Type" = 4) as got_stop ';
+$completed_sql .= ' FROM "'.$INCOMING.'" GROUP BY "Session-Id", "Acct-Session-Id"';
+$completed_sql .= ' ) as input';
+$completed_sql .= ' WHERE got_start AND got_stop';
+
+$sids = pg_query($dbconn, $completed_sql) or die('Query failed: ' . pg_last_error() . "\n");
+if (pg_num_rows($sids) > 0) {
+ while ($sids_line = pg_fetch_array($sids, null, PGSQL_ASSOC)) {
+ $sid = $sids_line["Session-Id"];
+ $asid = $sids_line["Acct-Session-Id"];
+ echo "Processing Acct-Session-Id '".$asid."', Session-Id '".$sid ."'... ";
+
+ $data=array();
+
+ /* We simply ignore the interim record(s) in this first version, since they contain only cumulative data. It could be used in later version to draw the session details for example. */
+
+ $result = pg_query_params($dbconn, 'SELECT *, "recorded_on" - CAST(textcat(text("Acct-Session-Time"), text(\' seconds\')) as INTERVAL) as start_time FROM "'.$INCOMING.
+ '" WHERE "Session-Id" = $1 AND "Acct-Session-Id" = $2 AND "Accounting-Record-Type" = 4 ORDER BY "recorded_on"',
+ array($sid, $asid)) or die('Query failed: ' . pg_last_error() . "\n");
+ $record = pg_fetch_array($result, null, PGSQL_ASSOC) or die('Internal error, got_stop is true but no record was returned');
+
+ $data[/* "user_name" */] = $record["User-Name"];
+ $data[/* "user_device" */] = $record["Calling-Station-Id"];
+
+ $nas_id= ($record["NAS-Identifier"] ?: $record["Origin-Host"]) ?: "<unidentified NAS>";
+ $ip = $record["NAS-IP-Address"] ?: $record["NAS-IPv6-Address"];
+ $nas_ip= $ip ? inet_ntop(pg_unescape_bytea($ip)) : "<unknown NAS IP>";
+ $nas_csi = $record["Called-Station-Id"];
+ $data[/* "nas_info" */] = $nas_id . " (".$nas_ip.")" . ($nas_csi ? " - Called Station: ".$nas_csi : "");
+
+ /* Is it possible to infer the session start time from this record only? */
+ if ($record["Acct-Session-Time"]) {
+ /* Yes, let's go */
+ $data[/* "sess_start" */] = $record["start_time"];
+ $data[/* "sess_duration" */] = $record["Acct-Session-Time"]." seconds";
+ } else {
+ /* No the information is missing, let's compute the approx value with the START record timestamp */
+ $res = pg_query_params($dbconn, 'SELECT t_start."recorded_on" as begining, t_end."recorded_on" - t_start."recorded_on" as duration'.
+ ' FROM (SELECT "recorded_on" FROM "'.$INCOMING.'" WHERE "Session-Id" = $1 AND "Acct-Session-Id" = $2 AND "Accounting-Record-Type" = 4 ORDER BY "recorded_on" LIMIT 1) as t_end, '.
+ ' (SELECT "recorded_on" FROM "'.$INCOMING.'" WHERE "Session-Id" = $1 AND "Acct-Session-Id" = $2 AND "Accounting-Record-Type" = 2 ORDER BY "Accounting-Record-Number", "recorded_on" LIMIT 1) as t_start',
+ array($sid, $asid)) or die('Query failed: ' . pg_last_error() . "\n");
+ $vals = pg_fetch_array($result, null, PGSQL_ASSOC) or die('Internal error, unable to compute session time');
+ $data[/* "sess_start" */] = $vals["begining"];
+ $data[/* "sess_duration" */] = $vals["duration"];
+ pg_free_result($res);
+ }
+
+ $data[/* "downl_bytes" */] = $record["Accounting-Output-Octets"];
+ $data[/* "downl_packets" */] = $record["Accounting-Output-Packets"];
+ $data[/* "upl_bytes" */] = $record["Accounting-Input-Octets"];
+ $data[/* "upl_packets" */] = $record["Accounting-Input-Packets"];
+ pg_free_result($result);
+
+ $result = pg_query_params($dbconn,
+ 'INSERT INTO "'.$PROCESSED.'" (user_name, user_device, nas_info, sess_start, sess_duration, downl_bytes, downl_packets, upl_bytes, upl_packets) '.
+ 'VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9)', $data) or die('Query failed: ' . pg_last_error() . "\n");
+ pg_free_result($result);
+ echo "Data stored into '$PROCESSED'... ";
+
+ /* Now that we have processed it, move these records to the $ARCHIVES_TABLE table. */
+ if ($ARCHIVES_TABLE) {
+ $result = pg_query_params($dbconn, 'SELECT * FROM "'.$INCOMING.'" WHERE "Session-Id" = $1 AND "Acct-Session-Id" = $2', array($sid, $asid)) or die('Query failed: ' . pg_last_error() . "\n");
+ $i = 0;
+ while ($rec = pg_fetch_array($result, null, PGSQL_ASSOC)) {
+ $i++;
+
+ $sql = "INSERT INTO \"$ARCHIVES_TABLE\" ";
+ $sql .= '("';
+ $sql .= join('", "', array_keys($rec));
+ $sql .= '") VALUES (';
+ for($c = 0; $c < count($rec); $c++)
+ $sql .= ($c ? ', ' : '').'$'.($c+1);
+ $sql .= ')';
+ pg_query_params($dbconn, $sql, array_values($rec)) or die('Insert failed: ' . pg_last_error() . "\n");
+ }
+ echo $i." records archived into '".$ARCHIVES_TABLE."'";
+ pg_free_result($result);
+ }
+ echo "\n";
+ $result = pg_query_params($dbconn, 'DELETE FROM "'.$INCOMING.'" WHERE "Session-Id" = $1 AND "Acct-Session-Id" = $2', array($sid, $asid)) or die('Query failed: ' . pg_last_error() . "\n");
+ pg_free_result($result);
+ }
+}
+pg_free_result($sids);
+
+echo "Operation completed with success!\n";
+
+/* Closing connection */
+pg_close($dbconn);
+
+
+?>
diff --git a/contrib/app_acct_tools/purge_to_file.php b/contrib/app_acct_tools/purge_to_file.php
new file mode 100644
index 0000000..0fc9f29
--- /dev/null
+++ b/contrib/app_acct_tools/purge_to_file.php
@@ -0,0 +1,157 @@
+<?php
+# This file may be called either from CLI or web PHP installation.
+
+# The copyright is the same as the freeDiameter project. Licence is BSD.
+
+/*-------------------------------------------------------*/
+
+/* -- These parameters must match the app_acct.conf file -- */
+
+/* The Connection String used to access the database.
+ Example: "host=localhost dbname=app_acct user=freediameter password=foo" */
+$CONNSTR="";
+
+/* The name of the table were the records are saved by app_acct.fdx */
+$TABLE="incoming";
+
+
+/* -- These parameters are specific to this script -- */
+
+/* Name of the dump file to create. It can be relative or absolute.
+ The script fails if this file already exists.
+ Use for example "data-".date("Ymdhis").".sql" to avoid collisions. */
+$DUMPFILE="incoming_data.sql";
+
+/* Does the script also echoes an HTML TABLE of the data processed? */
+$DISPLAY_HTML=FALSE; // it would be better to detect if we are called through Web or CLI...
+/* In addition, issue a full HTML page (including headers) ? */
+$HTML_HEADERS=TRUE;
+
+/*-------------------------------------------------------*/
+
+/* Connect to the database */
+$dbconn = pg_connect($CONNSTR)
+ or die('Could not connect: ' . pg_last_error() . "\n");
+
+/* Check if the file exists */
+$file = fopen($DUMPFILE, "xb")
+ or die("The file '$DUMPFILE' already exists or cannot be created, aborting.\n");
+
+/* First, query the table format */
+$format_sql = "SELECT ".
+ " a.attname AS field,".
+ " t.typname AS type,".
+/* " a.attlen AS length,". */
+ " a.atttypmod AS lengthvar,".
+ " a.attnotnull AS notnull".
+ " FROM".
+ " pg_class c,".
+ " pg_attribute a,".
+ " pg_type t".
+ " WHERE".
+ " c.relname = '" . $TABLE . "'".
+ " AND a.attnum > 0".
+ " AND a.attrelid = c.oid".
+ " AND a.atttypid = t.oid".
+ " ORDER BY a.attnum";
+$result = pg_query($dbconn, $format_sql) or die('Query failed: ' . pg_last_error() . "\n");
+
+/* app_acct.fdx only uses a few different fields types: */
+$conv_types = array(
+ "timestamptz" => "timestamp with time zone", /* recorded on */
+ "bytea" => "bytea", /* octet string */
+ "int4" => "integer", /* unsigned32, integer32, float32 */
+ "int8" => "bigint" /* unsigned64, integer64, float64 */
+ );
+
+$fields_types=array();
+
+fwrite($file, " -- Data purged on ".date(DATE_RFC822)."\n\n");
+fwrite($file, " -- Format of the table it was extracted from:\n");
+fwrite($file, " -- CREATE TABLE \"".$TABLE."\" (\n");
+$i = 0;
+while ($field = pg_fetch_array($result, null, PGSQL_ASSOC)) {
+ if ($i++)
+ fwrite($file, ",\n");
+ fwrite($file, " -- \"".$field["field"]."\" ");
+ if (array_key_exists($field["type"], $conv_types))
+ $fields_types[$field["field"]] = $conv_types[$field["type"]];
+ else
+ $fields_types[$field["field"]] = $field["type"];
+ fwrite($file, $fields_types[$field["field"]]);
+ if ($field["lengthvar"] != "-1")
+ fwrite($file, "(".$field["lengthvar"].")");
+ if ($field["notnull"] == "t")
+ fwrite($file, " NOT NULL");
+}
+fwrite($file, "\n -- );\n\n");
+pg_free_result($result);
+
+/* Now, the data */
+$result = pg_query($dbconn, "SELECT * FROM \"".$TABLE."\"") or die('Query failed: ' . pg_last_error() . "\n");
+if (pg_num_rows($result) > 0) {
+ fwrite($file, "INSERT INTO \"".$TABLE."\"\n (\n");
+ $i = pg_num_fields($result);
+ if ($DISPLAY_HTML && $HTML_HEADERS) echo "<HTML>\n<HEAD><TITLE>Purge</TITLE></HEAD>\n<BODY>\n";
+ if ($DISPLAY_HTML) echo "<TABLE>\n <TR>\n";
+ for ($j = 0; $j < $i; $j++) {
+ fwrite($file, ($j ? ", " : "") . "\"" . pg_escape_string(pg_field_name($result, $j)). "\"");
+ if ($DISPLAY_HTML) echo " <TD>".htmlentities(pg_field_name($result, $j))."</TD>\n";
+ }
+ fwrite($file, "\n )\n VALUES \n");
+ if ($DISPLAY_HTML) echo " </TR>\n";
+ $i = 0;
+ while ($line = pg_fetch_array($result, null, PGSQL_ASSOC)) {
+ if ($i++)
+ fwrite($file, ",\n");
+ fwrite($file, " ( ");
+
+ if ($DISPLAY_HTML) echo " <TR>\n";
+ $j = 0;
+ $sql = "";
+ foreach ($line as $f => $v) {
+ if (!is_null($v))
+ switch ($fields_types[$f]) {
+ case "bytea":
+ $v = "E'".pg_escape_bytea(pg_unescape_bytea($v))."'";
+ break;
+ case "timestamp with time zone":
+ $v = "E'".pg_escape_string($v)."'";
+ break;
+ }
+ else
+ $v = "NULL";
+
+ if ($DISPLAY_HTML) echo " <TD>".htmlentities(print_r($line[$f], TRUE))."</TD>\n";
+
+ fwrite($file, ($j ? ", " : "") . $v);
+ $sql .= ($j ? " AND " : "") . "\"".pg_escape_string($f)."\" ";
+ if (is_null($line[$f]))
+ $sql .= " IS NULL";
+ else
+ $sql .= " = " . $v;
+ $j++;
+ }
+ fwrite($file, ")");
+ if ($DISPLAY_HTML) echo " </TR>\n";
+ $res = pg_query( "DELETE FROM \"".$TABLE."\" WHERE ".$sql) or die('DELETE query failed: ' . pg_last_error() . "\n");
+ pg_free_result($res);
+ }
+ fwrite($file, "\n;\n");
+ if ($DISPLAY_HTML) echo "</TABLE>\n";
+ if ($DISPLAY_HTML && $HTML_HEADERS) echo "</BODY>\n</HTML>\n";
+ else echo $i." records have been successfully written to '".$DUMPFILE."' and removed from database.\n";
+} else {
+ if ($DISPLAY_HTML) echo "<p><em>No new record in the database</em></p>\n";
+ else echo "No new record in the database, the generated file is empty.\n";
+}
+pg_free_result($result);
+
+/* Closing connection */
+pg_close($dbconn);
+
+/* Closing the file */
+fclose($file);
+
+
+?>
diff --git a/contrib/debian/changelog b/contrib/debian/changelog
new file mode 100644
index 0000000..526d9ef
--- /dev/null
+++ b/contrib/debian/changelog
@@ -0,0 +1,209 @@
+freediameter (1.2.1) UNRELEASED; urgency=low
+
+ * New extension: rt_randomize (load-balancing on possible destinations)
+ * New contrib: Gx extension.
+ * rt_redirect.fdx and rt_load_balance.fdx improvement: use a hash table. Thanks Thomas.
+ * New hook HOOK_MESSAGE_SENDING to give a last chance to edit messages before they are sent.
+ This will be mostly used for enforcing interoperability constraints on non-compliant peers.
+ * Simplified log output. Old output can be recovered with DEBUG_WITH_META build option.
+ * Updated the internal counters for finer control on the load.
+ * Fixes in message expiry mechanism.
+ * Bug fixes in error messages generation and various parts.
+ * Improvements on shutdown sequence handling.
+ * Improvements to the dict_dcca_* extensions.
+ * Improved default CMake configuration.
+ * Improved build for MacOSX
+ * Fixes for a few newer operating systems compatibility.
+ * Fixed default secure Diameter port number 5868 instead of5658 (errata of RFC 6733)
+
+ -- Sebastien Decugis <sdecugis@freediameter.net> Sat, 30 Jan 2016 23:38:03 +0800
+
+freediameter (1.2.0) UNRELEASED; urgency=low
+
+ * Major changes in the logging system to be more syslog and production friendly
+ * New extension: dict_dcca_3gpp
+ * New extension: dict_dcca_starent (Starent DCCA vendor-specific AVPs)
+ * New extension: rt_ignore_dh (hide network topology by proxying Destination-Host).
+ * New extension: rt_load_balance (load balancer based on pending queue size).
+ * New extension: rt_busypeers. See doc/rt_busypeers.conf.sample.
+ * New extension: dbg_msg_timings. Measures timing of message operations.
+ * New extension: dbg_msg_dumps. Use to control hooks display.
+ * New API (fd_hook_*) for extensions to control messages logging & profiling
+ * New API (fd_stats_*) for extensions to monitor framework state (e.g. SNMP implem)
+ * API change: all the fd_*_dump functions now return malloc'd strings instead of logging directly.
+ * API change: callback parameter of fd_rt_out_register had its signature updated.
+ * Updated dbg_monitoring extension to use the new API
+ * New script to generate dictionary extensions from org file (see contrib/tools)
+ * New compilation option: WORKAROUND_ACCEPT_INVALID_VSAI to improve compatibility
+ with invalid Vendor-Specific-Application-Id AVPs received from some equipments (e.g. Cisco).
+ * New compilation option: DISABLE_PEER_EXPIRY for use in test environments.
+ * Extensions are now also searched in LD_LIBRARY_PATH.
+ * Copy Proxy-Info AVP automatically in new answers.
+ * Port value 0 allowed in configuration to disable local server (e.g. disable non-secure port).
+ * API change: fd_msg_send_timeout now takes a separate callback for timeout situation.
+ * Function changes: fd_msg_dump_* now split in three different type of output.
+ * New test testmesg_stress to measure message parser performance
+ * Fix termination of the framework to avoid failures.
+ * Fix invalid timespec value in peer PSM appearing randomly (leading to crash).
+ * Return DIAMETER_LOOP_DETECTED if local peer in the Route-Record list of a message.
+ * Allow running without TLS configuration.
+ * Upgraded SCTP code to comply with RFC 6458
+ * Using default secure Diameter port number 5658 as per RFC 6733
+ * Updated TLS code for performance improvements with new GNU TLS.
+ * Fix interlocking problem when large number of requests were failed over.
+ * New option in test_app.fdx extension for long messages payload.
+ * Performance improvement in message sending code path.
+
+ -- Sebastien Decugis <sdecugis@freediameter.net> Sat, 14 Sep 2013 18:08:07 +0800
+
+freediameter (1.1.6) UNRELEASED; urgency=low
+
+ * Fix major issue in 1.1.5 preventing to send answers to a received message.
+ * New command-line option: --enable_msg_log=( DROPPED | RECEIVED | SENT | NODELIVER | TIMING )
+ * Improved parsing error handling and Failed-AVP generation.
+ * Added support for some timings measurements in freeDiameter (in the logs)
+ * Fix port handling when using non-default port.
+ * Some cleanups in several dictionary files.
+ * New option to fd_dict_search: AVP_BY_STRUCT
+ * Improved compatibility with C++ compilers.
+ * Cleanups in sessions creation/destruction to avoid memory corruption under stress.
+ * Add support for "include" directive in freeDiameter.conf file.
+
+ -- Sebastien Decugis <sdecugis@freediameter.net> Sun, 03 Mar 2013 07:40:43 +0100
+
+freediameter (1.1.5) UNRELEASED; urgency=low
+
+ * Added compatibility with MAC OS X
+ * Fix behavior of timeout whe nsending messages to allow re-send.
+ * Several cleanups and new contributions included.
+ * Added dependency on C++ compiler for CMakeLists.txt
+
+ -- Sebastien Decugis <sdecugis@freediameter.net> Sat, 03 Nov 2012 17:58:11 +0100
+
+freediameter (1.1.4) UNRELEASED; urgency=low
+
+ * Compatibility with GnuTLS 3.x versions / updated packaging files accordingly
+ * Fix crash on Sparc 64 (possibly other 64b machines)
+ * Updated dict_dcca in extensions and contrib (thanks Konstantin)
+ * Changed dumping of messages to avoid interleaved information
+
+ -- Sebastien Decugis <sdecugis@freediameter.net> Fri, 24 Aug 2012 00:17:05 +0200
+
+freediameter (1.1.3) UNRELEASED; urgency=low
+
+ * Fixed a memory leak
+ * Clean-up of some extensions
+
+ -- Sebastien Decugis <sdecugis@freediameter.net> Tue, 03 Jul 2012 08:15:49 +0200
+
+freediameter (1.1.2) UNRELEASED; urgency=low
+
+ * FIFO queues are now capped to avoid memory exhaustion.
+ * Cleanups in MIPv6 dictionaries.
+ * app_acct upgraded: enabled vendor-specific AVP logging, thread-safe version.
+ * New function: fd_dict_getlistof to list dictionary contents.
+ * New function: fd_dict_delete to remove an entry (dangerous function!)
+ * New function: fd_sess_getcount to get count of session objects.
+ * A few additional bug fixes, check hg log for details.
+
+ -- Sebastien Decugis <sdecugis@freediameter.net> Tue, 21 Feb 2012 18:38:10 +0100
+
+freediameter (1.1.1) UNRELEASED; urgency=low
+
+ * Bug fix release
+ * Supports newer GNUTLS versions
+ * Allow empty OctetString AVPs (l=0)
+ * Allow two instances of freeDiameter on a single host.
+
+ -- Sebastien Decugis <sdecugis@nict.go.jp> Fri, 30 Sep 2011 21:56:50 +0200
+
+freediameter (1.1.0) UNRELEASED; urgency=low
+
+ * Source package restructured. Most of the
+ framework now contained in the libfdcore library.
+ libfreeDiameter renamed as libfdproto.
+ This closes #15.
+ * API version bumped to version 4.
+ * Improved fd_dict_new() when the same object already exists.
+ * Improvements to dict_legacy_xml extension.
+ * Cleanups in links to shared libraries
+ * (app_radgw.fdx) Better handling conversion of DEA with error status
+ to RADIUS (closes #25)
+ * Allow default signals such as SIGTSTP (ctrl-z) to be used with
+ freeDiameterd
+ * Improved DiameterIdentity handling (esp. interationalization issues),
+ and improve efficiency of some string operations in peers, sessions,
+ and dictionary modules (closes #7)
+ * Cleanup in the session module to free only unreferenced sessions (#16)
+ * Removed fd_cpu_flush_cache(), replaced by more robust alternatives.
+ * Improved peer state machine algorithm to counter SCTP multistream race
+ condition.
+ * New extension rt_redirect.fdx that handles the Diameter Redirect errors.
+ * New extension app_redirect that allows sending Redirect indications to
+ other peers. See doc/app_redirect.conf.sample for more information.
+ * Added incomplete dictionary extension for rfc4006 (DCCA), courtesy
+ of Konstantin Chekushin <koch@lmt.lv>
+
+ -- Sebastien Decugis <sdecugis@freediameter.net> Tue, 29 Mar 2011 10:41:19 +0900
+
+freediameter (1.0.4) UNRELEASED; urgency=low
+
+ * Added new API to specify timeout on receiving answer (#10)
+ * Bumped API version number accordingly.
+ * New test_netemul extension (simple network emulator proxy)
+ * Improved API compatibility to C++ compilers
+
+ -- Sebastien Decugis <sdecugis@nict.go.jp> Tue, 11 Jan 2011 12:28:22 +0900
+
+freediameter (1.0.3) UNRELEASED; urgency=low
+
+ * Fixed a couple of issues for portability (#21, #22, #23)
+ * Fixed issue with ListenOn bit ordering (#20)
+ * Added dictionary support for MIPv6 application objects.
+ * Added dictionary support for legacy XML files.
+ * Added python interface dbg_interactive (experimental).
+ * Added parameters to fd_disp_register() and fd_sess_handler_create(),
+ Bumped API version number accordingly.
+
+ -- Sebastien Decugis <sdecugis@nict.go.jp> Tue, 14 Dec 2010 11:39:29 +0900
+
+freediameter (1.0.2) UNRELEASED; urgency=low
+
+ * Fix an issue in app_diameap.fdx with user names (#18)
+ * Allow DH parameters loaded from a file (#17)
+ * Fixed a few compilation warnings on 64bits architectures.
+ * New ALL_EXTENSIONS build option.
+
+ -- Sebastien Decugis <sdecugis@nict.go.jp> Wed, 27 Oct 2010 11:17:32 +0900
+
+freediameter (1.0.1) UNRELEASED; urgency=low
+
+ * app_acct.fdx: new set of PHP scripts available in source
+ contrib/app_acct_tools
+ * app_acct.fdx: new directive 'Server_name_field' in the
+ configuration.
+ * app_radgw.fdx: new directive 'nonai' in acct and auth plugins to
+ disable NAI processing.
+ * app_radgw.fdx: New support for RADIUS proxies.
+ * app_radgw.fdx: many bug fixes.
+ * daemon: Check the local certificate is valid during TLS
+ initialization.
+ * daemon: Fixed issue for IP addresses in the form x.x.x.235
+ * daemon: new option --dbg_gnutls to get GNUTLS debug messages.
+ * debian: some cleanups in the packaging (dependencies, meta-data)
+ * rt_ereg.fdx: New routing extension based on regular expression
+ matching in package freediameter-daemon.
+
+ -- Sebastien Decugis <sdecugis@nict.go.jp> Wed, 15 Sep 2010 18:30:28 +0900
+
+freediameter (1.0.0-2) experimental; urgency=low
+
+ * Official release 1.0.0
+
+ -- Sebastien Decugis <sdecugis@nict.go.jp> Thu, 29 Jul 2010 17:27:13 +0900
+
+freediameter (1.0.0-1) experimental; urgency=low
+
+ * Initial Release.
+
+ -- Sebastien Decugis <sdecugis@nict.go.jp> Wed, 19 May 2010 15:36:54 +0900
diff --git a/contrib/debian/compat b/contrib/debian/compat
new file mode 100644
index 0000000..7f8f011
--- /dev/null
+++ b/contrib/debian/compat
@@ -0,0 +1 @@
+7
diff --git a/contrib/debian/control b/contrib/debian/control
new file mode 100644
index 0000000..919e10e
--- /dev/null
+++ b/contrib/debian/control
@@ -0,0 +1,229 @@
+Source: freediameter
+Section: contrib/net
+Priority: extra
+Maintainer: Sebastien Decugis <sdecugis@freediameter.net>
+Build-Depends: debhelper ( >= 7.3.9),
+ cmake, make, gcc, g++, bison, flex,
+ libsctp-dev, libgnutls-dev | gnutls-dev, libidn11-dev,
+ libpq-dev, libmysqlclient-dev, libxml2-dev, swig, python-dev,
+ libgcrypt11-dev | libgcrypt20-dev
+Standards-Version: 3.8.3
+Homepage: http://www.freediameter.net
+
+Package: freediameter-common
+Architecture: any
+Depends: ${shlibs:Depends}, ${misc:Depends}
+Description: The freeDiameter libraries.
+ This package contains the freeDiameter framework core libraries,
+ required by all freeDiameter components.
+ It may also be useful for other projects which need to
+ perform operations on Diameter messages.
+ .
+ The freeDiameter framework provides support for the Diameter
+ Base Protocol. Without any extension, the framework can only
+ be used as a Diameter routing agent. You probably want to
+ install some freeDiameter extension(s) to extend its
+ features, and also the freediameter-daemon package that
+ will initialize the framework for you.
+ .
+ See 'freeDiameter-dev' package to retrieve the API for the library.
+
+Package: freediameter-dev
+Architecture: any
+Section: contrib/devel
+Depends: freediameter-common (= ${binary:Version}), libsctp-dev, libgnutls-dev, libgcrypt-dev
+Description: This package provides the development files for freeDiameter.
+
+Package: freediameter-daemon
+Architecture: any
+Depends: ${shlibs:Depends}, ${misc:Depends}, freediameter-common (= ${binary:Version})
+Suggests: ssl-cert, freediameter-dictionary-rfc4005, freediameter-dictionary-rfc4072, freediameter-dictionary-rfc4740,
+ freediameter-dictionary-mip6, freediameter-dictionary-legacy
+Description: The freeDiameter daemon.
+ This daemon is a simple loader for the freeDiameter framework.
+ It is shipped with a small set of extensions, for
+ example to configure the routing behavior. See the
+ examples in /usr/share/freediameter* for more details.
+
+Package: freediameter-debug-tools
+Architecture: any
+Section: contrib/debug
+Depends: ${misc:Depends}, freediameter-common (= ${binary:Version})
+Suggests: python, libmysqlclient16 | libmysqlclient18
+Description: freeDiameter debug tools.
+ This package provides useful tools to help tracking
+ problems in freeDiameter installation. For example,
+ the dbg_interactive.fdx extension allows access to the
+ framework via a python interpreter console.
+
+Package: freediameter-dictionary-rfc4005
+Architecture: any
+Depends: ${misc:Depends}, freediameter-common (= ${binary:Version})
+Description: RFC4005 (NASREQ) dictionary support.
+ This freeDiameter extension provides the dictionary support
+ for commands and AVP defined in RFC4005 (NASREQ).
+ .
+ In order to use this extension, your main freeDiameter
+ configuration file must contain a LoadExtension directive.
+ See freeDiameter documentation for more details.
+ .
+ This extension does not require a configuration file.
+
+Package: freediameter-dictionary-rfc4006
+Architecture: any
+Depends: ${misc:Depends}, freediameter-common (= ${binary:Version})
+Description: RFC4006 (DCCA) dictionary support (incomplete).
+ This freeDiameter extension provides the dictionary support
+ for commands and AVP defined in RFC4006 (DCCA).
+ .
+ In order to use this extension, your main freeDiameter
+ configuration file must contain a LoadExtension directive.
+ See freeDiameter documentation for more details.
+ .
+ This extension does not require a configuration file.
+ .
+ Currently this extension is not complete: only AVP definitions
+ are included. See the source file for more details.
+
+Package: freediameter-dictionary-rfc4072
+Architecture: any
+Depends: ${misc:Depends}, freediameter-common (= ${binary:Version}), freediameter-dictionary-rfc4005 (= ${binary:Version})
+Description: RFC4072 (Diameter EAP) dictionary support.
+ This freeDiameter extension provides the dictionary support
+ for commands and AVP defined in RFC4072 (Diameter EAP).
+ .
+ In order to use this extension, your main freeDiameter
+ configuration file must contain a LoadExtension directive.
+ See freeDiameter documentation for more details.
+ .
+ This extension does not require a configuration file.
+
+Package: freediameter-dictionary-rfc4740
+Architecture: any
+Depends: ${misc:Depends}, freediameter-common (= ${binary:Version})
+Description: RFC4740 (Diameter SIP) dictionary support.
+ This freeDiameter extension provides the dictionary support
+ for commands and AVP defined in RFC4740 (Diameter SIP).
+ .
+ In order to use this extension, your main freeDiameter
+ configuration file must contain a LoadExtension directive.
+ See freeDiameter documentation for more details.
+ .
+ This extension does not require a configuration file.
+
+Package: freediameter-dictionary-mip6
+Architecture: any
+Depends: ${misc:Depends}, freediameter-common (= ${binary:Version})
+Description: Diameter Mobile IPv6 application dictionary support.
+ This package contains a set of extensions to provide the support
+ for commands and AVP defined in several RFCs related to
+ Diameter MIPv6. It is split is several extensions:
+ mip6a, mip6i, nas-mipv6, rfc5777.
+ .
+ In order to use these extensions, your main freeDiameter
+ configuration file must contain LoadExtension directives.
+ See freeDiameter documentation for more details.
+ .
+ These extensions do not require a configuration file.
+
+Package: freediameter-dictionary-legacy
+Architecture: any
+Depends: ${misc:Depends}, freediameter-common (= ${binary:Version}), libxml2
+Description: Legacy XML dictionary files support.
+ This freeDiameter extension allows the use of XML dictionary
+ files with the freeDiameter framework. Please note that
+ dictionaries provided as XML files come with less features
+ than native binary format, so the later should be preferred
+ when possible.
+ .
+ In order to use this extension, your main freeDiameter
+ configuration file must contain a LoadExtension directive.
+ See freeDiameter documentation for more details.
+ .
+ This extension requires a configuration file. See
+ dict_legacy_xml.conf.sample for documentation.
+
+Package: freediameter-radius-gateway
+Architecture: any
+Depends: ${misc:Depends}, freediameter-daemon (= ${binary:Version})
+Suggests: freediameter-dictionary-rfc4072 (= ${binary:Version}), freediameter-dictionary-rfc4740 (= ${binary:Version})
+Description: RADIUS/Diameter extensible gateway.
+ This freeDiameter extension implements a RADIUS to Diameter
+ gateway. It allows a RADIUS client to connect to a Diameter
+ server.
+ .
+ The support for specific Diameter applications and/or RADIUS
+ extensions is provided in the gateway by the use of plugins.
+ Currently, the following plugins are available:
+ - echodrop.rgwx : drop or echo a RADIUS attribute.
+ The attribute is not converted to Diameter.
+ See echodrop.rgwx.conf.sample for details.
+ - auth.rgwx : Convert Access-Request to Diameter AAR or DER.
+ Requests For Comments: RADIUS: 2865, 3162, 2868,
+ 2869, 3579; Diameter: 4005, 4072.
+ Requires freediameter-dictionary-rfc4072.
+ - sip.rgwx : Convert Access-Request to Diameter SIP messages.
+ Requests For Comments: Diameter: 4740.
+ Requires freediameter-dictionary-rfc4740.
+ - acct.rgwx : Converts Accounting-Request (2866) to Diameter
+ ACR (3588).
+ Requires freediameter-dictionary-rfc4072.
+ .
+ In order to use this extension, your main freeDiameter
+ configuration file must contain a LoadExtension directive.
+ See freeDiameter documentation for more details.
+ .
+ This extension requires a configuration file.
+ See app_radgw.conf.sample for more details.
+
+Package: freediameter-accounting-server
+Architecture: any
+Depends: ${misc:Depends}, freediameter-daemon (= ${binary:Version}), libpq5
+Suggests: freediameter-dictionary-rfc4072
+Description: freeDiameter simple Accounting server.
+ This freeDiameter extension implements the Diameter Base
+ Accounting application. It saves the accounting records
+ in a PostgreSQL database backend in a highly configurable
+ maneer.
+ .
+ In order to use this extension, your main freeDiameter
+ configuration file must contain a LoadExtension directive.
+ See freeDiameter documentation for more details.
+ .
+ This extension requires a configuration file.
+ See app_acct.conf.sample for more details.
+ .
+ You may find some useful resources to parse the saved records
+ in the contrib/app_acct_tools folder in source package.
+
+Package: freediameter-eap-server
+Architecture: any
+Depends: ${misc:Depends}, freediameter-daemon (= ${binary:Version}), libmysqlclient16 | libmysqlclient18, freediameter-dictionary-rfc4072 (= ${binary:Version})
+Description: freeDiameter Diameter EAP server implementation.
+ This freeDiameter extension implements a Diameter EAP server.
+ It supports EAP-MD5 and EAP-TLS methods currently.
+ .
+ In order to use this extension, your main freeDiameter
+ configuration file must contain a LoadExtension directive.
+ See freeDiameter documentation for more details.
+ .
+ This extension requires a configuration file.
+ See app_diameap.conf.sample and
+ http://diameap.yagami.freediameter.net for more details.
+
+Package: freediameter-sip-server
+Architecture: any
+Depends: ${misc:Depends}, freediameter-daemon (= ${binary:Version}), libmysqlclient16 | libmysqlclient18, freediameter-dictionary-rfc4740 (= ${binary:Version})
+Description: freeDiameter Diameter SIP server implementation.
+ This freeDiameter extension implements a prototype
+ Diameter SIP server.
+ See http://www.freediameter.net/trac/wiki/app_sip.fdx for
+ status information.
+ .
+ In order to use this extension, your main freeDiameter
+ configuration file must contain a LoadExtension directive.
+ See freeDiameter documentation for more details.
+ .
+ This extension requires a configuration file.
+ See app_sip.conf.sample for more details.
+
diff --git a/contrib/debian/copyright b/contrib/debian/copyright
new file mode 100644
index 0000000..114bfa6
--- /dev/null
+++ b/contrib/debian/copyright
@@ -0,0 +1,35 @@
+Format-Specification: http://dep.debian.net/deps/dep5/
+Name: freeDiameter
+Maintainer: Sebastien Decugis <sdecugis@freediameter.net>
+Source: http://www.freediameter.net
+
+Files: *
+Copyright: 2008-2011, WIDE Project and NICT.
+License: BSD
+ Redistribution and use of this software in source and binary forms, with or without modification, are
+ permitted provided that the following conditions are met:
+ .
+ * Redistributions of source code must retain the above
+ copyright notice, this list of conditions and the
+ following disclaimer.
+ .
+ * Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the
+ following disclaimer in the documentation and/or other
+ materials provided with the distribution.
+ .
+ * Neither the name of the WIDE Project or NICT nor the
+ names of its contributors may be used to endorse or
+ promote products derived from this software without
+ specific prior written permission of WIDE Project and
+ NICT.
+ .
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
+ WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+ TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
diff --git a/contrib/debian/dirs b/contrib/debian/dirs
new file mode 100644
index 0000000..e9e5399
--- /dev/null
+++ b/contrib/debian/dirs
@@ -0,0 +1 @@
+etc/freeDiameter/
diff --git a/contrib/debian/docs b/contrib/debian/docs
new file mode 100644
index 0000000..5238a99
--- /dev/null
+++ b/contrib/debian/docs
@@ -0,0 +1,3 @@
+INSTALL*
+LICENSE
+README
diff --git a/contrib/debian/freediameter-accounting-server.examples b/contrib/debian/freediameter-accounting-server.examples
new file mode 100644
index 0000000..adce646
--- /dev/null
+++ b/contrib/debian/freediameter-accounting-server.examples
@@ -0,0 +1 @@
+doc/app_acct.conf.sample
diff --git a/contrib/debian/freediameter-accounting-server.install b/contrib/debian/freediameter-accounting-server.install
new file mode 100644
index 0000000..6d3b1d9
--- /dev/null
+++ b/contrib/debian/freediameter-accounting-server.install
@@ -0,0 +1 @@
+usr/lib/freeDiameter/app_acct.fdx
diff --git a/contrib/debian/freediameter-common.examples b/contrib/debian/freediameter-common.examples
new file mode 100644
index 0000000..8abb336
--- /dev/null
+++ b/contrib/debian/freediameter-common.examples
@@ -0,0 +1,5 @@
+doc/freediameter.conf.sample
+doc/acl_wl.conf.sample
+doc/rt_default.conf.sample
+doc/rt_ereg.conf.sample
+doc/single_host
diff --git a/contrib/debian/freediameter-common.install b/contrib/debian/freediameter-common.install
new file mode 100644
index 0000000..b8861ed
--- /dev/null
+++ b/contrib/debian/freediameter-common.install
@@ -0,0 +1,6 @@
+usr/lib/libfdproto.so*
+usr/lib/libfdcore.so*
+usr/lib/freeDiameter/acl_wl.fdx
+usr/lib/freeDiameter/rt_default.fdx
+usr/lib/freeDiameter/rt_ereg.fdx
+usr/lib/freeDiameter/dbg_monitor.fdx
diff --git a/contrib/debian/freediameter-daemon.default b/contrib/debian/freediameter-daemon.default
new file mode 100644
index 0000000..ed8b792
--- /dev/null
+++ b/contrib/debian/freediameter-daemon.default
@@ -0,0 +1,7 @@
+# Defaults for freediameter initscript
+# sourced by /etc/init.d/freediameter
+# installed at /etc/default/freediameter by the maintainer scripts
+
+# Additional options that are passed to the Daemon.
+# See "freeDiameterd --help" for supported flags.
+DAEMON_OPTS=""
diff --git a/contrib/debian/freediameter-daemon.init b/contrib/debian/freediameter-daemon.init
new file mode 100644
index 0000000..7b2a31a
--- /dev/null
+++ b/contrib/debian/freediameter-daemon.init
@@ -0,0 +1,160 @@
+#! /bin/sh
+
+### BEGIN INIT INFO
+# Provides: freediameter
+# Default-Start: 2 3 4 5
+# Default-Stop: 0 1 6
+# Required-Start: $remote_fs $syslog
+# Required-Stop: $remote_fs $syslog
+# Short-Description: Start freeDiameter daemon at boot time
+# Description: Start the freeDiameter daemon at boot time.
+# freeDiameter is an extensible implementation of the Diameter protocol,
+# designed for Authentication, Authorization and Accounting. Diameter is
+# an evolution of the RADIUS protocol.
+### END INIT INFO#
+
+DAEMON=/usr/bin/freeDiameterd
+CONF=/etc/freeDiameter/freeDiameter.conf
+NAME=freediameter
+DESC="freeDiameter daemon"
+
+test -x $DAEMON || exit 0
+
+LOGDIR=/var/log/freediameter
+PIDFILE=/var/run/$NAME.pid
+DODTIME=30 # Time to wait for the server to die, in seconds
+ # The value is high because we wait for STA answers
+ # before disconnecting the peers.
+
+# Include freediameter defaults if available
+if [ -f /etc/default/freediameter ] ; then
+ . /etc/default/freediameter
+fi
+
+test x"" != x$DAEMON_OPTS || test -f $CONF || exit 0
+
+set -e
+
+running_pid()
+{
+ # Check if a given process pid's cmdline matches a given name
+ pid=$1
+ name=$2
+ [ -z "$pid" ] && return 1
+ [ ! -d /proc/$pid ] && return 1
+ cmd=`cat /proc/$pid/cmdline | tr "\000" "\n"|head -n 1 |cut -d : -f 1`
+ # Is this the expected child?
+ [ "$cmd" != "$name" ] && return 1
+ return 0
+}
+
+running()
+{
+# Check if the process is running looking at /proc
+# (works for all users)
+
+ # No pidfile, probably no daemon present
+ [ ! -f "$PIDFILE" ] && return 1
+ # Obtain the pid and check it against the binary name
+ pid=`cat $PIDFILE`
+ running_pid $pid $DAEMON || return 1
+ return 0
+}
+
+force_stop() {
+# Forcefully kill the process
+ [ ! -f "$PIDFILE" ] && return
+ if running ; then
+ kill -15 $pid
+ # Is it really dead?
+ [ -n "$DODTIME" ] && sleep "$DODTIME"s
+ if running ; then
+ kill -9 $pid
+ [ -n "$DODTIME" ] && sleep "$DODTIME"s
+ if running ; then
+ echo "Cannot kill $LABEL (pid=$pid)!"
+ exit 1
+ fi
+ fi
+ fi
+ rm -f $PIDFILE
+ return 0
+}
+
+case "$1" in
+ start)
+ echo -n "Starting $DESC: "
+ start-stop-daemon --start --quiet --pidfile $PIDFILE \
+ --exec $DAEMON -- $DAEMON_OPTS
+ if running ; then
+ echo "$NAME."
+ else
+ echo " ERROR."
+ fi
+ ;;
+ stop)
+ echo -n "Stopping $DESC: "
+ start-stop-daemon --stop --quiet --pidfile $PIDFILE \
+ --exec $DAEMON
+ echo "$NAME."
+ ;;
+ force-stop)
+ echo -n "Forcefully stopping $DESC: "
+ force_stop
+ if ! running ; then
+ echo "$NAME."
+ else
+ echo " ERROR."
+ fi
+ ;;
+ #reload)
+ #
+ # If the daemon can reload its config files on the fly
+ # for example by sending it SIGHUP, do it here.
+ #
+ # If the daemon responds to changes in its config file
+ # directly anyway, make this a do-nothing entry.
+ #
+ # echo "Reloading $DESC configuration files."
+ # start-stop-daemon --stop --signal 1 --quiet --pidfile \
+ # /var/run/$NAME.pid --exec $DAEMON
+ #;;
+ force-reload)
+ #
+ # If the "reload" option is implemented, move the "force-reload"
+ # option to the "reload" entry above. If not, "force-reload" is
+ # just the same as "restart" except that it does nothing if the
+ # daemon isn't already running.
+ # check wether $DAEMON is running. If so, restart
+ start-stop-daemon --stop --test --quiet --pidfile \
+ /var/run/$NAME.pid --exec $DAEMON \
+ && $0 restart \
+ || exit 0
+ ;;
+ restart)
+ echo -n "Restarting $DESC: "
+ start-stop-daemon --stop --quiet --pidfile \
+ /var/run/$NAME.pid --exec $DAEMON
+ [ -n "$DODTIME" ] && sleep $DODTIME
+ start-stop-daemon --start --quiet --pidfile \
+ /var/run/$NAME.pid --exec $DAEMON -- $DAEMON_OPTS
+ echo "$NAME."
+ ;;
+ status)
+ echo -n "$LABEL is "
+ if running ; then
+ echo "running"
+ else
+ echo " not running."
+ exit 1
+ fi
+ ;;
+ *)
+ N=/etc/init.d/$NAME
+ # echo "Usage: $N {start|stop|restart|reload|force-reload}" >&2
+ echo "Usage: $N {start|stop|restart|force-reload|status|force-stop}" >&2
+ exit 1
+ ;;
+esac
+
+exit 0
diff --git a/contrib/debian/freediameter-daemon.install b/contrib/debian/freediameter-daemon.install
new file mode 100644
index 0000000..cf167a3
--- /dev/null
+++ b/contrib/debian/freediameter-daemon.install
@@ -0,0 +1 @@
+usr/bin/freeDiameterd*
diff --git a/contrib/debian/freediameter-debug-tools.examples b/contrib/debian/freediameter-debug-tools.examples
new file mode 100644
index 0000000..9750d1e
--- /dev/null
+++ b/contrib/debian/freediameter-debug-tools.examples
@@ -0,0 +1,3 @@
+doc/test_app.conf.sample
+doc/test_netemul.conf.sample
+doc/dbg_interactive.py.sample
diff --git a/contrib/debian/freediameter-debug-tools.install b/contrib/debian/freediameter-debug-tools.install
new file mode 100644
index 0000000..32c7f56
--- /dev/null
+++ b/contrib/debian/freediameter-debug-tools.install
@@ -0,0 +1,5 @@
+usr/lib/freeDiameter/dbg_rt.fdx
+usr/lib/freeDiameter/test_app.fdx
+usr/lib/freeDiameter/test_sip.fdx
+usr/lib/freeDiameter/test_netemul.fdx
+usr/lib/freeDiameter/dbg_interactive.fdx
diff --git a/contrib/debian/freediameter-dev.install b/contrib/debian/freediameter-dev.install
new file mode 100644
index 0000000..e055d40
--- /dev/null
+++ b/contrib/debian/freediameter-dev.install
@@ -0,0 +1 @@
+usr/include/freeDiameter/*
diff --git a/contrib/debian/freediameter-dictionary-legacy.examples b/contrib/debian/freediameter-dictionary-legacy.examples
new file mode 100644
index 0000000..9aede23
--- /dev/null
+++ b/contrib/debian/freediameter-dictionary-legacy.examples
@@ -0,0 +1,2 @@
+doc/dict_legacy_xml.conf.sample
+contrib/dict_legacy/dictionary.dtd
diff --git a/contrib/debian/freediameter-dictionary-legacy.install b/contrib/debian/freediameter-dictionary-legacy.install
new file mode 100644
index 0000000..acddf9b
--- /dev/null
+++ b/contrib/debian/freediameter-dictionary-legacy.install
@@ -0,0 +1 @@
+usr/lib/freeDiameter/dict_legacy_xml.fdx
diff --git a/contrib/debian/freediameter-dictionary-mip6.install b/contrib/debian/freediameter-dictionary-mip6.install
new file mode 100644
index 0000000..b337c3e
--- /dev/null
+++ b/contrib/debian/freediameter-dictionary-mip6.install
@@ -0,0 +1,4 @@
+usr/lib/freeDiameter/dict_nas_mipv6.fdx
+usr/lib/freeDiameter/dict_mip6i.fdx
+usr/lib/freeDiameter/dict_mip6a.fdx
+usr/lib/freeDiameter/dict_rfc5777.fdx
diff --git a/contrib/debian/freediameter-dictionary-rfc4005.install b/contrib/debian/freediameter-dictionary-rfc4005.install
new file mode 100644
index 0000000..1c82430
--- /dev/null
+++ b/contrib/debian/freediameter-dictionary-rfc4005.install
@@ -0,0 +1 @@
+usr/lib/freeDiameter/dict_nasreq.fdx
diff --git a/contrib/debian/freediameter-dictionary-rfc4006.install b/contrib/debian/freediameter-dictionary-rfc4006.install
new file mode 100644
index 0000000..0284a39
--- /dev/null
+++ b/contrib/debian/freediameter-dictionary-rfc4006.install
@@ -0,0 +1 @@
+usr/lib/freeDiameter/dict_dcca.fdx
diff --git a/contrib/debian/freediameter-dictionary-rfc4072.install b/contrib/debian/freediameter-dictionary-rfc4072.install
new file mode 100644
index 0000000..39c44ad
--- /dev/null
+++ b/contrib/debian/freediameter-dictionary-rfc4072.install
@@ -0,0 +1 @@
+usr/lib/freeDiameter/dict_eap.fdx
diff --git a/contrib/debian/freediameter-dictionary-rfc4740.install b/contrib/debian/freediameter-dictionary-rfc4740.install
new file mode 100644
index 0000000..08dbfe2
--- /dev/null
+++ b/contrib/debian/freediameter-dictionary-rfc4740.install
@@ -0,0 +1 @@
+usr/lib/freeDiameter/dict_sip.fdx
diff --git a/contrib/debian/freediameter-eap-server.examples b/contrib/debian/freediameter-eap-server.examples
new file mode 100644
index 0000000..7a9ed7a
--- /dev/null
+++ b/contrib/debian/freediameter-eap-server.examples
@@ -0,0 +1,2 @@
+doc/app_diameap.conf.sample
+doc/eap_tls_plugin.diameap.conf.sample
diff --git a/contrib/debian/freediameter-eap-server.install b/contrib/debian/freediameter-eap-server.install
new file mode 100644
index 0000000..bafb174
--- /dev/null
+++ b/contrib/debian/freediameter-eap-server.install
@@ -0,0 +1,2 @@
+usr/lib/freeDiameter/app_diameap.fdx
+usr/lib/freeDiameter/*.emp
diff --git a/contrib/debian/freediameter-radius-gateway.examples b/contrib/debian/freediameter-radius-gateway.examples
new file mode 100644
index 0000000..0326df0
--- /dev/null
+++ b/contrib/debian/freediameter-radius-gateway.examples
@@ -0,0 +1,2 @@
+doc/app_radgw.conf.sample
+doc/echodrop.rgwx.conf.sample
diff --git a/contrib/debian/freediameter-radius-gateway.install b/contrib/debian/freediameter-radius-gateway.install
new file mode 100644
index 0000000..23ee8dc
--- /dev/null
+++ b/contrib/debian/freediameter-radius-gateway.install
@@ -0,0 +1,2 @@
+usr/lib/freeDiameter/app_radgw.fdx
+usr/lib/freeDiameter/*.rgwx
diff --git a/contrib/debian/freediameter-sip-server.examples b/contrib/debian/freediameter-sip-server.examples
new file mode 100644
index 0000000..f49290b
--- /dev/null
+++ b/contrib/debian/freediameter-sip-server.examples
@@ -0,0 +1,4 @@
+doc/app_sip.conf.sample
+doc/app_sip.sql
+doc/app_sip_SL.sql
+doc/test_sip.conf.sample
diff --git a/contrib/debian/freediameter-sip-server.install b/contrib/debian/freediameter-sip-server.install
new file mode 100644
index 0000000..4b8c612
--- /dev/null
+++ b/contrib/debian/freediameter-sip-server.install
@@ -0,0 +1,3 @@
+usr/lib/freeDiameter/app_sip.fdx
+usr/share/doc/freeDiameter-sip-server/*
+usr/bin/freediameter-sip-*
diff --git a/contrib/debian/rules b/contrib/debian/rules
new file mode 100755
index 0000000..808f7ea
--- /dev/null
+++ b/contrib/debian/rules
@@ -0,0 +1,31 @@
+#!/usr/bin/make -f
+# -*- makefile -*-
+# Sample debian/rules that uses debhelper.
+#
+# This file was originally written by Joey Hess and Craig Small.
+# As a special exception, when this file is copied by dh-make into a
+# dh-make output file, you may use that output file without restriction.
+# This special exception was added by Craig Small in version 0.37 of dh-make.
+#
+# Modified to make a template file for a multi-binary package with separated
+# build-arch and build-indep targets by Bill Allombert 2001
+
+# Uncomment this to turn on verbose mode.
+#export DH_VERBOSE=1
+
+# This has to be exported to make some magic below work.
+export DH_OPTIONS
+
+# Comment this out if you want to include the tests when the package is built
+skip_the_tests=-DBUILD_TESTING:BOOL=OFF
+
+%:
+ dh $@
+
+override_dh_auto_configure:
+ dh_auto_configure -- $(skip_the_tests) \
+ -DCMAKE_BUILD_TYPE:STRING=DebianPackage \
+ -DDEFAULT_CONF_PATH:PATH=/etc/freeDiameter \
+ -DALL_EXTENSIONS:BOOL=ON
+
+
diff --git a/contrib/debian/update_changelog.txt b/contrib/debian/update_changelog.txt
new file mode 100644
index 0000000..ac6efbd
--- /dev/null
+++ b/contrib/debian/update_changelog.txt
@@ -0,0 +1,3 @@
+new release: dch -v 1.0.3 -D UNRELEASED --release-heuristic log
+Simple addition: dch "changelog entry text"
+
diff --git a/contrib/dict_dcca/README b/contrib/dict_dcca/README
new file mode 100644
index 0000000..7da3cc8
--- /dev/null
+++ b/contrib/dict_dcca/README
@@ -0,0 +1,5 @@
+Files provided courtesy of Konstantin Chekushin under the same license as freeDiameter.
+
+Comment:
+"They are not full, I've filled only that I wanted to use in our app_dcca module. "
+
diff --git a/contrib/dict_dcca/dict_dcca_3gpp.c b/contrib/dict_dcca/dict_dcca_3gpp.c
new file mode 100644
index 0000000..af78426
--- /dev/null
+++ b/contrib/dict_dcca/dict_dcca_3gpp.c
@@ -0,0 +1,841 @@
+/*
+ * Dictionary definitions of objects specified in DCCA (Nokia, 3GPP).
+ */
+#include <freeDiameter/extension.h>
+
+
+/* The content of this file follows the same structure as dict_base_proto.c */
+
+#define CHECK_dict_new( _type, _data, _parent, _ref ) \
+ CHECK_FCT( fd_dict_new( fd_g_config->cnf_dict, (_type), (_data), (_parent), (_ref)) );
+
+#define CHECK_dict_search( _type, _criteria, _what, _result ) \
+ CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, (_type), (_criteria), (_what), (_result), ENOENT) );
+
+struct local_rules_definition {
+ char *avp_name;
+ enum rule_position position;
+ int min;
+ int max;
+};
+
+#define RULE_ORDER( _position ) ((((_position) == RULE_FIXED_HEAD) || ((_position) == RULE_FIXED_TAIL)) ? 1 : 0 )
+
+#define PARSE_loc_rules( _rulearray, _parent) { \
+ int __ar; \
+ for (__ar=0; __ar < sizeof(_rulearray) / sizeof((_rulearray)[0]); __ar++) { \
+ struct dict_rule_data __data = { NULL, \
+ (_rulearray)[__ar].position, \
+ 0, \
+ (_rulearray)[__ar].min, \
+ (_rulearray)[__ar].max}; \
+ __data.rule_order = RULE_ORDER(__data.rule_position); \
+ CHECK_FCT( fd_dict_search( \
+ fd_g_config->cnf_dict, \
+ DICT_AVP, \
+ AVP_BY_NAME, \
+ (_rulearray)[__ar].avp_name, \
+ &__data.rule_avp, 0 ) ); \
+ if ( !__data.rule_avp ) { \
+ TRACE_DEBUG(INFO, "AVP Not found: '%s'", (_rulearray)[__ar].avp_name ); \
+ return ENOENT; \
+ } \
+ CHECK_FCT_DO( fd_dict_new( fd_g_config->cnf_dict, DICT_RULE, &__data, _parent, NULL), \
+ { \
+ TRACE_DEBUG(INFO, "Error on rule with AVP '%s'", \
+ (_rulearray)[__ar].avp_name ); \
+ return EINVAL; \
+ } ); \
+ } \
+}
+
+#define enumval_def_u32( _val_, _str_ ) \
+ { _str_, { .u32 = _val_ }}
+
+#define enumval_def_os( _len_, _val_, _str_ ) \
+ { _str_, { .os = { .data = (unsigned char *)_val_, .len = _len_ }}}
+
+
+static int dict_dcca_3gpp_entry(char * conffile)
+{
+ TRACE_ENTRY("%p", conffile);
+
+ /* Applications section */
+ {
+ /* Create the vendors */
+ {
+ struct dict_vendor_data vendor_data = { 10415, "3GPP" };
+ CHECK_FCT(fd_dict_new(fd_g_config->cnf_dict, DICT_VENDOR, &vendor_data, NULL, NULL));
+ }
+
+ }
+
+
+ /* AVP section */
+ {
+ struct dict_object * Address_type;
+ struct dict_object * UTF8String_type;
+ struct dict_object * DiameterIdentity_type;
+ struct dict_object * DiameterURI_type;
+ struct dict_object * Time_type;
+
+ CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "Address", &Address_type);
+ CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "UTF8String", &UTF8String_type);
+ CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "DiameterIdentity", &DiameterIdentity_type);
+ CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "DiameterURI", &DiameterURI_type);
+ CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "Time", &Time_type);
+
+ /* Reporting-Reason */
+ {
+ /*
+ Enumerated. Will be present if quota was
+ exhausted for one or more metering types. Only
+ one Reporting-Reason AVP can be present in the
+ Used-Service-Unit AVP. (Note that the Reporting-
+ Reason AVP may be present also at the MSCC
+ level; see below.)
+ The following values are supported:
+
+ QUOTA_EXHAUSTED(3); Quota for the
+ associated metering type has been
+ exhausted. With this reporting reason there is
+ only one metering type in this Used-Service-
+ Unit AVP.
+
+ OTHER_QUOTA_TYPE(5); Quota for one or
+ more of the other metering types has been
+ exhausted. With this reporting reason there
+ may be multiple metering types in Used-
+ Service-Unit AVP.
+
+ POOL_EXHAUSTED(8); Quota from the
+ credit pool has been exhausted. This reporting
+ reason is used if the quota for the associated
+ metering type was granted from a credit pool
+ by using the GSU-Pool-Reference AVP in the
+ CCA. With this reporting reason there is only
+ one metering type in the Used-Service-Unit
+ AVP.
+ */
+
+ struct dict_object *type;
+ struct dict_type_data tdata = { AVP_TYPE_INTEGER32, "Enumerated(Reporting-Reason)" , NULL, NULL, NULL };
+ struct dict_enumval_data t_1 = { "QHT", { .i32 = 1 }};
+ struct dict_enumval_data t_2 = { "FINAL", { .i32 = 2 }};
+ struct dict_enumval_data t_3 = { "QUOTA_EXHAUSTED", { .i32 = 3 }};
+ struct dict_enumval_data t_4 = { "VALIDITY_TIME", { .i32 = 4 }};
+ struct dict_enumval_data t_5 = { "OTHER_QUOTA_TYPE", { .i32 = 5 }};
+ struct dict_enumval_data t_6 = { "RATING_CONDITION_CHANGE", { .i32 = 6 }};
+ struct dict_enumval_data t_7 = { "FORCED_REAUTHORIZATION", { .i32 = 7 }};
+ struct dict_enumval_data t_8 = { "POOL_EXHAUSTED", { .i32 = 8 }};
+
+ struct dict_avp_data data = {
+ 872, /* Code */
+ 10415, /* Vendor */
+ "Reporting-Reason", /* Name */
+ AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, /* Fixed flags */
+ AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, /* Fixed flag values */
+ AVP_TYPE_INTEGER32 /* base type of data */
+ };
+ /* Create the Enumerated type, and then the AVP */
+ CHECK_dict_new( DICT_TYPE, &tdata , NULL, &type);
+ CHECK_dict_new( DICT_ENUMVAL, &t_3 , type, NULL);
+ CHECK_dict_new( DICT_ENUMVAL, &t_5 , type, NULL);
+ CHECK_dict_new( DICT_ENUMVAL, &t_8 , type, NULL);
+ CHECK_dict_new( DICT_AVP, &data , type, NULL);
+ }
+
+ /* Trigger */
+ {
+ /*
+ Grouped. The presence of the Trigger AVP in the
+ CCR identifies the event(s) triggering the CCR.
+ */
+
+ struct dict_avp_data data = {
+ 1264, /* Code */
+ 10415, /* Vendor */
+ "Trigger", /* Name */
+ AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, /* Fixed flags */
+ AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, /* Fixed flag values */
+ AVP_TYPE_GROUPED /* base type of data */
+ };
+ CHECK_dict_new( DICT_AVP, &data , NULL, NULL);
+ }
+
+ /* Trigger-Type */
+ {
+ /*
+ Enumerated. One or more of these AVPs may be
+ present. Indicates the event that triggered the
+ MSCC. Supported values are:
+
+ CHANGE_IN_SGSN_IP_ADDRESS (1), a change in the SGSN address.
+
+ CHANGEINQOS_ANY (2), a change in the QoS profile
+
+ CHANGEINRAT (4), a change in radio access technology
+
+ */
+
+ struct dict_object *type;
+ struct dict_type_data tdata = { AVP_TYPE_INTEGER32, "Enumerated(Trigger-Type)" , NULL, NULL, NULL };
+ struct dict_enumval_data t_1 = { "CHANGE_IN_SGSN_IP_ADDRESS", { .i32 = 1 }};
+ struct dict_enumval_data t_2 = { "CHANGEINQOS_ANY", { .i32 = 2 }};
+ struct dict_enumval_data t_4 = { "CHANGEINRAT", { .i32 = 4 }};
+
+ struct dict_avp_data data = {
+ 870, /* Code */
+ 10415, /* Vendor */
+ "Trigger-Type", /* Name */
+ AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, /* Fixed flags */
+ AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, /* Fixed flag values */
+ AVP_TYPE_INTEGER32 /* base type of data */
+ };
+ /* Create the Enumerated type, and then the AVP */
+ CHECK_dict_new( DICT_TYPE, &tdata , NULL, &type);
+ CHECK_dict_new( DICT_ENUMVAL, &t_1 , type, NULL);
+ CHECK_dict_new( DICT_ENUMVAL, &t_2 , type, NULL);
+ CHECK_dict_new( DICT_ENUMVAL, &t_4 , type, NULL);
+ CHECK_dict_new( DICT_AVP, &data , type, NULL);
+ }
+
+ /* Service-Information */
+ {
+ /*
+ Grouped. The Service-Information purpose is to
+ allow the transmission of additional 3GPP service
+ specific information elements (3GPP 32.299
+ Rel7).
+ */
+
+ struct dict_avp_data data = {
+ 873, /* Code */
+ 10415, /* Vendor */
+ "Service-Information", /* Name */
+ AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, /* Fixed flags */
+ AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, /* Fixed flag values */
+ AVP_TYPE_GROUPED /* base type of data */
+ };
+ CHECK_dict_new( DICT_AVP, &data , NULL, NULL);
+ }
+
+ /* PS-Information */
+ {
+ /*
+ Grouped. Its purpose is to allow the transmission
+ of additional PS service specific information
+ elements (3GPP 32.299 Rel7).
+ */
+
+ struct dict_avp_data data = {
+ 874, /* Code */
+ 10415, /* Vendor */
+ "PS-Information", /* Name */
+ AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, /* Fixed flags */
+ AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, /* Fixed flag values */
+ AVP_TYPE_GROUPED /* base type of data */
+ };
+ CHECK_dict_new( DICT_AVP, &data , NULL, NULL);
+ }
+
+ /* PDP-Address */
+ {
+ /*
+ Address. Present only in the initial CCR. Contains
+ the user equipment IP address. This AVP is
+ defined in 3GPP 32.299 Rel7.
+ */
+
+ struct dict_avp_data data = {
+ 1227, /* Code */
+ 10415, /* Vendor */
+ "PDP-Address", /* Name */
+ AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, /* Fixed flags */
+ AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, /* Fixed flag values */
+ AVP_TYPE_OCTETSTRING /* base type of data */
+ };
+ CHECK_dict_new( DICT_AVP, &data , Address_type, NULL);
+ }
+
+ /* 3GPP-IMSI */
+ {
+ /*
+ IMSI encoded in UTF-8 per 3GPP TS 23.003. No
+ padding. Maximum length of data: 15.
+ */
+ struct dict_avp_data data = {
+ 1, /* Code */
+ 10415, /* Vendor */
+ "3GPP-IMSI", /* Name */
+ AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, /* Fixed flags */
+ AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, /* Fixed flag values */
+ AVP_TYPE_OCTETSTRING /* base type of data */
+ };
+ CHECK_dict_new( DICT_AVP, &data , UTF8String_type, NULL);
+ }
+
+ /* 3GPP-Charging-Id */
+ {
+ /*
+ Unsigned32. (3GPP TS 29.061 Rel7) . The
+ charging identifier for the PDP context. The Flexi
+ ISN generates the 3GPP charging ID for both
+ virtual and normal PDP contexts with one excep-
+ tion. If the Flexi ISN acts as a NAS server and the
+ charging ID selection is set to NAS Client, the
+ charging ID will be the NAand not the 3GPP charging ID of Flexi ISN.
+ Present in the initial CCR only.S client
+ */
+ struct dict_avp_data data = {
+ 2, /* Code */
+ 10415, /* Vendor */
+ "3GPP-Charging-Id", /* Name */
+ AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, /* Fixed flags */
+ AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, /* Fixed flag values */
+ AVP_TYPE_UNSIGNED32 /* base type of data */
+ };
+ CHECK_dict_new( DICT_AVP, &data , NULL, NULL);
+ }
+
+ /* 3GPP-PDP-Type */
+ {
+ /*
+ Enumerated. (3GPP TS 29.061 Rel7 ). Type of
+ PDP context, for example, IP or PPP. Present in
+ the initial CCR only.
+ 0 = IPv4
+ 1 = PPP
+ 2 = IPv6
+ 3 = IPv4v6
+ */
+ struct dict_avp_data data = {
+ 3, /* Code */
+ 10415, /* Vendor */
+ "3GPP-PDP-Type", /* Name */
+ AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, /* Fixed flags */
+ AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, /* Fixed flag values */
+ AVP_TYPE_UNSIGNED32 /* base type of data */
+ };
+ CHECK_dict_new( DICT_AVP, &data , NULL, NULL);
+ }
+
+ /* 3GPP-CG-Address */
+ {
+ /*
+ OctetString. (3GPP TS 29.061 Rel4). The address
+ of the charging gateway that has been marked as
+ the default charging gateway for the PDP context.
+ The address is expressed as a four-byte integer.
+ Present in the initial CCR only.
+ */
+ struct dict_avp_data data = {
+ 4, /* Code */
+ 10415, /* Vendor */
+ "3GPP-CG-Address", /* Name */
+ AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, /* Fixed flags */
+ AVP_FLAG_VENDOR, /* Fixed flag values */
+ AVP_TYPE_OCTETSTRING /* base type of data */
+ };
+ CHECK_dict_new( DICT_AVP, &data , Address_type, NULL);
+ }
+
+ /* 3GPP-GPRS-Negotiated-QoS-Profile */
+ {
+ /*
+ UTF8String. (3GPP TS 29.061 Rel7 ). The QoS
+ profile applied by the Flexi ISN. In update and ter-
+ mination requests, this AVP is present only when
+ the CCR has been triggered by a PDP context
+ update affecting the negotiated QoS
+ Each octet is described by two UTF-8-encoded
+ characters denoting the hexadecimal
+ representation.
+ */
+ struct dict_avp_data data = {
+ 5, /* Code */
+ 10415, /* Vendor */
+ "3GPP-GPRS-Negotiated-QoS-Profile", /* Name */
+ AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, /* Fixed flags */
+ AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, /* Fixed flag values */
+ AVP_TYPE_OCTETSTRING /* base type of data */
+ };
+ CHECK_dict_new( DICT_AVP, &data , UTF8String_type, NULL);
+ }
+
+ /* 3GPP-SGSN-Address */
+ {
+ /*
+ OctetString. (3GPP TS 29.061 Rel4). The address
+ of the charging gateway that has been marked as
+ the default charging gateway for the PDP context.
+ The address is expressed as a four-byte integer.
+ Present in the initial CCR only.
+ */
+ struct dict_avp_data data = {
+ 6, /* Code */
+ 10415, /* Vendor */
+ "3GPP-SGSN-Address", /* Name */
+ AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, /* Fixed flags */
+ AVP_FLAG_VENDOR, /* Fixed flag values */
+ AVP_TYPE_OCTETSTRING /* base type of data */
+ };
+ CHECK_dict_new( DICT_AVP, &data , Address_type, NULL);
+ }
+
+ /* 3GPP-GGSN-Address */
+ {
+ /*
+ OctetString. (3GPP TS 29.061 Rel4). Usually the
+ IP address of Flexi ISN. The only exception is
+ when the Flexi ISN acts as a NAS server and the
+ charging ID selection is set to NAS Client; then the
+ GGSN IP address will be the NAIP address. Present in the initial CCR only.S client
+ */
+ struct dict_avp_data data = {
+ 7, /* Code */
+ 10415, /* Vendor */
+ "3GPP-GGSN-Address", /* Name */
+ AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, /* Fixed flags */
+ AVP_FLAG_VENDOR, /* Fixed flag values */
+ AVP_TYPE_OCTETSTRING /* base type of data */
+ };
+ CHECK_dict_new( DICT_AVP, &data , Address_type, NULL);
+ }
+
+ /* 3GPP-IMSI-MCC-MNC */
+ {
+ /*
+ UTF8String. MCC and MNC extracted from the
+ user's IMSI (first 5 or 6 digits, as applicable from
+ the presented IMSI). The MCC-MNCs are
+ extracted from the tables configured in FlexiISN
+ configuration under the General and Roaming
+ configurations.
+ */
+ struct dict_avp_data data = {
+ 8, /* Code */
+ 10415, /* Vendor */
+ "3GPP-IMSI-MCC-MNC", /* Name */
+ AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, /* Fixed flags */
+ AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, /* Fixed flag values */
+ AVP_TYPE_OCTETSTRING /* base type of data */
+ };
+ CHECK_dict_new( DICT_AVP, &data , UTF8String_type, NULL);
+ }
+
+ /* 3GPP-GGSN-MCC-MNC */
+ {
+ /*
+ UTF8String. (3GPP TS 29.061 Rel7 ). Contains
+ the mobile country and network code of the PLMN
+ that the Flexi ISN belongs to. Present in the initial
+ CCR only. The first entry in the list of local PLMNs
+ in the Flexi ISN configuration determines the value
+ of this AVP.
+ */
+ struct dict_avp_data data = {
+ 9, /* Code */
+ 10415, /* Vendor */
+ "3GPP-GGSN-MCC-MNC", /* Name */
+ AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, /* Fixed flags */
+ AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, /* Fixed flag values */
+ AVP_TYPE_OCTETSTRING /* base type of data */
+ };
+ CHECK_dict_new( DICT_AVP, &data , UTF8String_type, NULL);
+ }
+
+ /* 3GPP-NSAPI */
+ {
+ /*
+ UTF8String. (3GPP TS 29.061 Rel7 ). Indicates
+ the NSAPI of the PDP context. Contains one octet
+ consisting of a single digit. Present in the initial
+ CCR only.
+ */
+ struct dict_avp_data data = {
+ 10, /* Code */
+ 10415, /* Vendor */
+ "3GPP-NSAPI", /* Name */
+ AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, /* Fixed flags */
+ AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, /* Fixed flag values */
+ AVP_TYPE_OCTETSTRING /* base type of data */
+ };
+ CHECK_dict_new( DICT_AVP, &data , UTF8String_type, NULL);
+ }
+
+ /* 3GPP-Session-Stop-Indicator */
+ {
+ /*
+ OctetString. (3GPP TS 29.061 Rel4). The
+ presence of this AVP indicates that the last
+ context of the PDP session has been deleted. May
+ be present in the termination CCR only. Contains
+ one octet that has a value of 0xff.
+ */
+ struct dict_avp_data data = {
+ 11, /* Code */
+ 10415, /* Vendor */
+ "3GPP-Session-Stop-Indicator", /* Name */
+ AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, /* Fixed flags */
+ AVP_FLAG_VENDOR, /* Fixed flag values */
+ AVP_TYPE_OCTETSTRING /* base type of data */
+ };
+ CHECK_dict_new( DICT_AVP, &data , NULL, NULL);
+ }
+
+ /* 3GPP-Selection-Mode */
+ {
+ /*
+ UTF8String. (3GPP TS 29.061 Rel7 ). Consists of
+ one octet containing the selection mode as
+ received from SGSN in the Create PDP Context
+ Request. Present in the initial CCR only.
+ */
+ struct dict_avp_data data = {
+ 12, /* Code */
+ 10415, /* Vendor */
+ "3GPP-Selection-Mode", /* Name */
+ AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, /* Fixed flags */
+ AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, /* Fixed flag values */
+ AVP_TYPE_OCTETSTRING /* base type of data */
+ };
+ CHECK_dict_new( DICT_AVP, &data , UTF8String_type, NULL);
+ }
+
+ /* 3GPP-Charging-Characteristics */
+ {
+ /*
+ UTF8String. (3GPP TS 29.061 Rel7 ). The
+ charging characteristics for the PDP context.
+ Present in the initial CCR only. Consists of four
+ octets. Each octet contains a single UTF-8
+ encoded digit. The content of the charging charac-
+ teristics is described in 3GPP TS 32.215.
+ */
+ struct dict_avp_data data = {
+ 13, /* Code */
+ 10415, /* Vendor */
+ "3GPP-Charging-Characteristics", /* Name */
+ AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, /* Fixed flags */
+ AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, /* Fixed flag values */
+ AVP_TYPE_OCTETSTRING /* base type of data */
+ };
+ CHECK_dict_new( DICT_AVP, &data , UTF8String_type, NULL);
+ }
+
+ /* 3GPP-CG-IPv6-Address */
+ {
+ /*
+ UTF8String.. (3GPP TS 29.061 Rel? (<=10) ). The
+ IPv6 address of the charging gateway.
+ */
+ struct dict_avp_data data = {
+ 14, /* Code */
+ 10415, /* Vendor */
+ "3GPP-CG-IPv6-Address", /* Name */
+ AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, /* Fixed flags */
+ AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, /* Fixed flag values */
+ AVP_TYPE_OCTETSTRING /* base type of data */
+ };
+ CHECK_dict_new( DICT_AVP, &data , UTF8String_type, NULL);
+ }
+
+ /* 3GPP-SGSN-IPv6-Address */
+ {
+ /*
+ UTF8String.. (3GPP TS 29.061 Rel? (<=10) ). The
+ IPv6 address of the SGSN.
+ */
+ struct dict_avp_data data = {
+ 15, /* Code */
+ 10415, /* Vendor */
+ "3GPP-SGSN-IPv6-Address", /* Name */
+ AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, /* Fixed flags */
+ AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, /* Fixed flag values */
+ AVP_TYPE_OCTETSTRING /* base type of data */
+ };
+ CHECK_dict_new( DICT_AVP, &data , UTF8String_type, NULL);
+ }
+
+ /* 3GPP-GGSN-IPv6-Address */
+ {
+ /*
+ UTF8String.. (3GPP TS 29.061 Rel? (<=10) ). The
+ IPv6 address of the GGSN.
+ */
+ struct dict_avp_data data = {
+ 16, /* Code */
+ 10415, /* Vendor */
+ "3GPP-GGSN-IPv6-Address", /* Name */
+ AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, /* Fixed flags */
+ AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, /* Fixed flag values */
+ AVP_TYPE_OCTETSTRING /* base type of data */
+ };
+ CHECK_dict_new( DICT_AVP, &data , UTF8String_type, NULL);
+ }
+
+ /* 3GPP-GGSN-IPv6-DNS-Servers */
+ {
+ /*
+ UTF8String.. (3GPP TS 29.061 Rel? (<=10) ). List
+ of IPv6 addresses of DNS servers for an APN in
+ order of preference (max. 15 servers, 16 bytes
+ each).
+ */
+ struct dict_avp_data data = {
+ 17, /* Code */
+ 10415, /* Vendor */
+ "3GPP-GGSN-IPv6-DNS-Servers", /* Name */
+ AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, /* Fixed flags */
+ AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, /* Fixed flag values */
+ AVP_TYPE_OCTETSTRING /* base type of data */
+ };
+ CHECK_dict_new( DICT_AVP, &data , UTF8String_type, NULL);
+ }
+
+ /* 3GPP-SGSN-MCC-MNC */
+ {
+ /*
+ UTF8String. (3GPP TS 29.061 Rel7 ). MCC and
+ MNC extracted from the RAI within Create or
+ Update PDP Context Request. In update and ter-
+ mination requests, this AVP is present only when
+ the CCR has been triggered by a routing area
+ update.
+ */
+ struct dict_avp_data data = {
+ 18, /* Code */
+ 10415, /* Vendor */
+ "3GPP-SGSN-MCC-MNC", /* Name */
+ AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, /* Fixed flags */
+ AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, /* Fixed flag values */
+ AVP_TYPE_OCTETSTRING /* base type of data */
+ };
+ CHECK_dict_new( DICT_AVP, &data , UTF8String_type, NULL);
+ }
+
+ /* Missing: 3GPP-Teardown-Indicator (19) */
+
+ /* 3GPP-IMEISV */
+ {
+ /*
+ IMEI(SV) encoded as sequence of UTF8 characters.
+ */
+ struct dict_avp_data data = {
+ 20, /* Code */
+ 10415, /* Vendor */
+ "3GPP-IMEISV", /* Name */
+ AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, /* Fixed flags */
+ AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, /* Fixed flag values */
+ AVP_TYPE_OCTETSTRING /* base type of data */
+ };
+ CHECK_dict_new( DICT_AVP, &data , UTF8String_type, NULL);
+ }
+
+ /* 3GPP-RAT-Type */
+ {
+ /*
+ OctetString. (3GPP TS 29.061 Rel7 ) Defines the
+ method used to access the network. Consists of a
+ single octet. The following values may be sent:
+ UTRAN (1), GERAN (2), WLAN (3), NAS (254),
+ Unspecified (255).
+ This AVP is included in the initial CCR and in
+ update or termination CCRs if the value changes.
+ */
+ struct dict_avp_data data = {
+ 21, /* Code */
+ 10415, /* Vendor */
+ "3GPP-RAT-Type", /* Name */
+ AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, /* Fixed flags */
+ AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, /* Fixed flag values */
+ AVP_TYPE_OCTETSTRING /* base type of data */
+ };
+ CHECK_dict_new( DICT_AVP, &data , NULL, NULL);
+ }
+
+ /* 3GPP-User-Location-Info */
+ {
+ /*
+ OctetString. (3GPP TS 29.061 Rel7 ) Contains
+ information about the user's current geographical
+ location as received from the SGSN. Present
+ always in initial CCR if the value is known and in
+ update and termination CCRs if the value
+ changes.
+ */
+ struct dict_avp_data data = {
+ 22, /* Code */
+ 10415, /* Vendor */
+ "3GPP-User-Location-Info", /* Name */
+ AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, /* Fixed flags */
+ AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, /* Fixed flag values */
+ AVP_TYPE_OCTETSTRING /* base type of data */
+ };
+ CHECK_dict_new( DICT_AVP, &data , NULL, NULL);
+ }
+
+ /* 3GPP-MS-TimeZone */
+ {
+ /*
+ OctetString. (3GPP TS 29.061 Rel7 ) 3GPP-MS-
+ TimeZone is AVP is present always in the initial CCR if the
+ value is known and in the update and termination
+ CCRs if the value changes. This IE is encoded
+ according to 3GPP TS 29.061 Rel7
+ */
+ struct dict_avp_data data = {
+ 23, /* Code */
+ 10415, /* Vendor */
+ "3GPP-MS-TimeZone", /* Name */
+ AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, /* Fixed flags */
+ AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, /* Fixed flag values */
+ AVP_TYPE_OCTETSTRING /* base type of data */
+ };
+ CHECK_dict_new( DICT_AVP, &data , NULL, NULL);
+ }
+
+ /* Missing: 3GPP-CAMEL-Charging-Info (24) */
+ /* Missing: 3GPP-Packet-Filter (25) */
+ /* Missing: 3GPP-Negotiated-DSCP (26) */
+ /* Missing: 3GPP-Allocate-IP-Type (27) */
+
+ /* PDP-Context-Type */
+ {
+ /*
+ Enumerated. Indicates the type of a PDP context
+ and is only included in CCR initial.
+
+ values are 0 for primary and 1 for secondary
+ (3GPP 32.299 Rel7)
+ */
+ struct dict_object *type;
+ struct dict_type_data tdata = { AVP_TYPE_INTEGER32, "Enumerated(PDP-Context-Type)" , NULL, NULL, NULL };
+ struct dict_enumval_data t_0 = { "PRIMARY", { .i32 = 0 }};
+ struct dict_enumval_data t_1 = { "SECONDARY", { .i32 = 1 }};
+
+ struct dict_avp_data data = {
+ 1247, /* Code */
+ 10415, /* Vendor */
+ "PDP-Context-Type", /* Name */
+ AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, /* Fixed flags */
+ AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, /* Fixed flag values */
+ AVP_TYPE_INTEGER32 /* base type of data */
+ };
+ /* Create the Enumerated type, and then the AVP */
+ CHECK_dict_new( DICT_TYPE, &tdata , NULL, &type);
+ CHECK_dict_new( DICT_ENUMVAL, &t_0 , type, NULL);
+ CHECK_dict_new( DICT_ENUMVAL, &t_1 , type, NULL);
+ CHECK_dict_new( DICT_AVP, &data , type, NULL);
+ }
+
+ /* IMS-Information */
+ {
+ /*
+ Grouped. Its purpose is to allow the transmission
+ of additional IMS service specific information ele-
+ ments. (3GPP 32.299 Rel7)
+ */
+ struct dict_avp_data data = {
+ 876, /* Code */
+ 10415, /* Vendor */
+ "IMS-Information", /* Name */
+ AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, /* Fixed flags */
+ AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, /* Fixed flag values */
+ AVP_TYPE_GROUPED /* base type of data */
+ };
+ CHECK_dict_new( DICT_AVP, &data , NULL, NULL);
+ }
+
+ /* IMS-Charging-Identifier */
+ {
+ /*
+ UTF8String. Contains the IMS charging identifier
+ as given to the Flexi ISN by the IMS. This AVP is
+ defined in 3GPP TS 32.225. This AVP is present
+ in IMS sessions only. Present in the initial CCR
+ only.
+ */
+ struct dict_avp_data data = {
+ 841, /* Code */
+ 10415, /* Vendor */
+ "IMS-Charging-Identifier", /* Name */
+ AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, /* Fixed flags */
+ AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, /* Fixed flag values */
+ AVP_TYPE_OCTETSTRING /* base type of data */
+ };
+ CHECK_dict_new( DICT_AVP, &data , UTF8String_type, NULL);
+ }
+
+
+
+
+ /* Max-Requested-Bandwidth-UL */
+ {
+ /*
+ Unsigned32. The Max-Requested-Bandwidth-
+ UL/DL AVP indicates the maximum allowed bit
+ rate (in bits per second) for the uplink direction.
+ (Re-used from 3GPP 29.214)
+ */
+ struct dict_avp_data data = {
+ 515, /* Code */
+ 10415, /* Vendor */
+ "Max-Requested-Bandwidth-UL", /* Name */
+ AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, /* Fixed flags */
+ AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, /* Fixed flag values */
+ AVP_TYPE_UNSIGNED32 /* base type of data */
+ };
+ CHECK_dict_new( DICT_AVP, &data , NULL, NULL);
+ }
+
+ /* Max-Requested-Bandwidth-DL */
+ {
+ /*
+ Unsigned32. The Max-Requested-Bandwidth-
+ UL/DL AVP indicates the maximum allowed bit
+ rate (in bits per second) for the uplink direction.
+ */
+ struct dict_avp_data data = {
+ 516, /* Code */
+ 10415, /* Vendor */
+ "Max-Requested-Bandwidth-DL", /* Name */
+ AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, /* Fixed flags */
+ AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, /* Fixed flag values */
+ AVP_TYPE_UNSIGNED32 /* base type of data */
+ };
+ CHECK_dict_new( DICT_AVP, &data , NULL, NULL);
+ }
+
+ /* QoS-Information */
+ {
+ /*
+ Grouped. This is the QoS that the DCCA
+ server requests from Flexi ISN to be applied for
+ this PDP context. This AVP and all AVPs con-
+ tained within are described in 3GPP TS 29.212
+ Release 7. The ARP AVP is introduced with
+ Release 8. The relevant types are defined on
+ table 5.3.1 of TS 29.212.
+ */
+
+ struct dict_avp_data data = {
+ 1016, /* Code */
+ 10415, /* Vendor */
+ "QoS-Information", /* Name */
+ AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, /* Fixed flags */
+ AVP_FLAG_VENDOR, /* Fixed flag values */
+ AVP_TYPE_GROUPED /* base type of data */
+ };
+ CHECK_dict_new( DICT_AVP, &data , NULL, NULL);
+ }
+ }
+
+
+
+ TRACE_DEBUG(INFO, "Extension 'Dictionary definitions for DCCA 3GPP' initialized");
+ return 0;
+}
+
+EXTENSION_ENTRY("dict_dcca_3gpp", dict_dcca_3gpp_entry, "dict_dcca");
diff --git a/contrib/dict_dcca/dict_dcca_nokia.c b/contrib/dict_dcca/dict_dcca_nokia.c
new file mode 100644
index 0000000..5ff7420
--- /dev/null
+++ b/contrib/dict_dcca/dict_dcca_nokia.c
@@ -0,0 +1,281 @@
+/*
+ * Dictionary definitions of objects specified in DCCA (Nokia, 3GPP).
+ */
+#include <freeDiameter/extension.h>
+
+
+/* The content of this file follows the same structure as dict_base_proto.c */
+
+#define CHECK_dict_new( _type, _data, _parent, _ref ) \
+ CHECK_FCT( fd_dict_new( fd_g_config->cnf_dict, (_type), (_data), (_parent), (_ref)) );
+
+#define CHECK_dict_search( _type, _criteria, _what, _result ) \
+ CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, (_type), (_criteria), (_what), (_result), ENOENT) );
+
+struct local_rules_definition {
+ char *avp_name;
+ enum rule_position position;
+ int min;
+ int max;
+};
+
+#define RULE_ORDER( _position ) ((((_position) == RULE_FIXED_HEAD) || ((_position) == RULE_FIXED_TAIL)) ? 1 : 0 )
+
+#define PARSE_loc_rules( _rulearray, _parent) { \
+ int __ar; \
+ for (__ar=0; __ar < sizeof(_rulearray) / sizeof((_rulearray)[0]); __ar++) { \
+ struct dict_rule_data __data = { NULL, \
+ (_rulearray)[__ar].position, \
+ 0, \
+ (_rulearray)[__ar].min, \
+ (_rulearray)[__ar].max}; \
+ __data.rule_order = RULE_ORDER(__data.rule_position); \
+ CHECK_FCT( fd_dict_search( \
+ fd_g_config->cnf_dict, \
+ DICT_AVP, \
+ AVP_BY_NAME, \
+ (_rulearray)[__ar].avp_name, \
+ &__data.rule_avp, 0 ) ); \
+ if ( !__data.rule_avp ) { \
+ TRACE_DEBUG(INFO, "AVP Not found: '%s'", (_rulearray)[__ar].avp_name ); \
+ return ENOENT; \
+ } \
+ CHECK_FCT_DO( fd_dict_new( fd_g_config->cnf_dict, DICT_RULE, &__data, _parent, NULL), \
+ { \
+ TRACE_DEBUG(INFO, "Error on rule with AVP '%s'", \
+ (_rulearray)[__ar].avp_name ); \
+ return EINVAL; \
+ } ); \
+ } \
+}
+
+#define enumval_def_u32( _val_, _str_ ) \
+ { _str_, { .u32 = _val_ }}
+
+#define enumval_def_os( _len_, _val_, _str_ ) \
+ { _str_, { .os = { .data = (unsigned char *)_val_, .len = _len_ }}}
+
+
+static int dict_dcca_nokia_entry(char * conffile)
+{
+ TRACE_ENTRY("%p", conffile);
+
+ /* Applications section */
+ {
+ /* Create the vendors */
+ {
+ struct dict_vendor_data vendor_data = { 94, "Nokia" };
+ CHECK_FCT(fd_dict_new(fd_g_config->cnf_dict, DICT_VENDOR, &vendor_data, NULL, NULL));
+ }
+
+ }
+
+
+ /* AVP section */
+ {
+ struct dict_object * Address_type;
+ struct dict_object * UTF8String_type;
+ struct dict_object * DiameterIdentity_type;
+ struct dict_object * DiameterURI_type;
+ struct dict_object * Time_type;
+
+ CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "Address", &Address_type);
+ CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "UTF8String", &UTF8String_type);
+ CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "DiameterIdentity", &DiameterIdentity_type);
+ CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "DiameterURI", &DiameterURI_type);
+ CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "Time", &Time_type);
+
+ /* NSN-Token-Value */
+ {
+ /*
+ OctetString. A token that was received, for
+ example, from the subscription portal [14]. The
+ maximum length of the token is 64 octets.
+ When this AVP is included in the MSCC, the USU
+ and Reporting-Reason AVPs will not be included
+ (because the token is not a trigger to report quota
+ usage). Additionally, the Rating-Group and
+ Service-Id AVPs will have the values received
+ from the subscription portal.
+ */
+ struct dict_avp_data data = {
+ 5113, /* Code */
+ 94, /* Vendor */
+ "NSN-Token-Value", /* Name */
+ AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, /* Fixed flags */
+ AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, /* Fixed flag values */
+ AVP_TYPE_OCTETSTRING /* base type of data */
+ };
+ CHECK_dict_new( DICT_AVP, &data , NULL, NULL);
+ }
+
+ /* Quota-Consumption-Time */
+ {
+ /*
+ Unsigned32. Contains the time quota envelope
+ expiration time in seconds. This is the time
+ elapsed from the previous service request, to
+ the moment the Flexi ISN considers that the
+ time envelope finishes. The value of this AVP
+ will be in effect for the remainder of the session
+ or until a new value is received. If this AVP is
+ not present, the default value configured for the
+ rating group will be used. The OCS may
+ disable the time quota envelope expiration by
+ setting the value of this AVP to 0. The value of
+ QCT sent from the OCS for a certain MSCC
+ instance is stored in the Flexi ISN and it is used
+ if the OCS does not sent a new value in the
+ CCAs that follow
+ */
+ struct dict_avp_data data = {
+ 5109, /* Code */
+ 94, /* Vendor */
+ "Quota-Consumption-Time", /* Name */
+ AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, /* Fixed flags */
+ AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, /* Fixed flag values */
+ AVP_TYPE_UNSIGNED32 /* base type of data */
+ };
+ CHECK_dict_new( DICT_AVP, &data , NULL, NULL);
+ }
+
+ /* Quota-Holding-Time */
+ {
+ /*
+ Unsigned32. Indicates how long the Flexi ISN
+ will keep the granted quota after a service
+ request has been received. The unit is in
+ seconds. When this time elapses, the Flexi ISN
+ ends the MSCC instance and reports the used
+ quota without requesting more. The value of
+ this AVP will be in effect for the remainder of
+ the session or until a new value is received. If
+ this AVP is not present, the default value con-
+ figured for the rating group will be used. The
+ OCS may disable the Quota Holding Timer by
+ setting the value of this AVP to 0. The value of
+ the QHT sent from the OCS for a certain
+ MSCC instance is stored in the Flexi ISN, and
+ it is used if the OCS does not sent a new value
+ in the CCAs that follow.
+ */
+ struct dict_avp_data data = {
+ 5110, /* Code */
+ 94, /* Vendor */
+ "Quota-Holding-Time", /* Name */
+ AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, /* Fixed flags */
+ AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, /* Fixed flag values */
+ AVP_TYPE_UNSIGNED32 /* base type of data */
+ };
+ CHECK_dict_new( DICT_AVP, &data , NULL, NULL);
+ }
+
+ /* Default-Quota */
+ {
+ /*
+ Grouped. Indicates the absolute number of
+ units that are available for consumption during
+ each upcoming OCS interrogation (e.g. after a
+ CCR has been sent but before the CCA is
+ received). If this AVP is not present, the Flexi
+ ISN will use the configured or earlier received
+ default quota. If this AVP is present but does
+ not include the default quota for a certain unit
+ type, that unit type is considered to have no
+ default quota.
+ The usage of default quota can be disabled in
+ certain situations by modifying the Flexi ISN
+ settings
+ */
+ struct dict_avp_data data = {
+ 5111, /* Code */
+ 94, /* Vendor */
+ "Default-Quota", /* Name */
+ AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, /* Fixed flags */
+ AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, /* Fixed flag values */
+ AVP_TYPE_GROUPED /* base type of data */
+ };
+ CHECK_dict_new( DICT_AVP, &data , NULL, NULL);
+ }
+
+ /* Session-Start-Indicator */
+ {
+ /*
+ OctetString. (3GPP TS 29.061 Rel4). The address
+ of the charging gateway that has been marked as
+ the default charging gateway for the PDP context.
+ The address is expressed as a four-byte integer.
+ Present in the initial CCR only.
+ */
+ struct dict_avp_data data = {
+ 5105, /* Code */
+ 94, /* Vendor */
+ "Session-Start-Indicator", /* Name */
+ AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, /* Fixed flags */
+ AVP_FLAG_VENDOR, /* Fixed flag values */
+ AVP_TYPE_OCTETSTRING /* base type of data */
+ };
+ CHECK_dict_new( DICT_AVP, &data , NULL, NULL);
+ }
+
+ /* Rulebase-id */
+ {
+ /*
+ */
+ struct dict_avp_data data = {
+ 5106, /* Code */
+ 94, /* Vendor */
+ "Rulebase-id", /* Name */
+ AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, /* Fixed flags */
+ AVP_FLAG_VENDOR, /* Fixed flag values */
+ AVP_TYPE_OCTETSTRING /* base type of data */
+ };
+ CHECK_dict_new( DICT_AVP, &data , UTF8String_type, NULL);
+ }
+
+ /* Time-Of-First-Usage */
+ {
+ /*
+ Time. Contains a time-stamp identifying the date
+ and time of the first increment of the used units
+ counter since the previous report. If no used units
+ were gathered during the previous reporting inter-
+ val, this AVP will not be present.
+ */
+ struct dict_avp_data data = {
+ 5103, /* Code */
+ 94, /* Vendor */
+ "Time-Of-First-Usage", /* Name */
+ AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, /* Fixed flags */
+ AVP_FLAG_VENDOR, /* Fixed flag values */
+ AVP_TYPE_OCTETSTRING /* base type of data */
+ };
+ CHECK_dict_new( DICT_AVP, &data , Time_type, NULL);
+ }
+
+ /* Time-Of-Last-Usage */
+ {
+ /*
+ Time. Contains a time-stamp identifying the date
+ and time of the first increment of the used units
+ counter since the previous report. If no used units
+ were gathered during the previous reporting inter-
+ val, this AVP will not be present.
+ */
+ struct dict_avp_data data = {
+ 5104, /* Code */
+ 94, /* Vendor */
+ "Time-Of-Last-Usage", /* Name */
+ AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, /* Fixed flags */
+ AVP_FLAG_VENDOR, /* Fixed flag values */
+ AVP_TYPE_OCTETSTRING /* base type of data */
+ };
+ CHECK_dict_new( DICT_AVP, &data , Time_type, NULL);
+ }
+ }
+
+ TRACE_DEBUG(INFO, "Extension 'Dictionary definitions for DCCA Nokia' initialized");
+ return 0;
+}
+
+EXTENSION_ENTRY("dict_dcca_nokia", dict_dcca_nokia_entry, "dict_dcca");
diff --git a/contrib/dict_gx/README b/contrib/dict_gx/README
new file mode 100644
index 0000000..ce5b548
--- /dev/null
+++ b/contrib/dict_gx/README
@@ -0,0 +1,3 @@
+File sent to the mailing-list by German Barros <gbarros@ipcomsa.com>.
+To be used with the dict_legacy_xml extension.
+
diff --git a/contrib/dict_gx/dict_gx.xml b/contrib/dict_gx/dict_gx.xml
new file mode 100644
index 0000000..c985fe5
--- /dev/null
+++ b/contrib/dict_gx/dict_gx.xml
@@ -0,0 +1,709 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE dictionary SYSTEM "dictionary.dtd">
+
+<!--******************* Diccionario Gx === German Barros ******************************************************************* -->
+
+<dictionary>
+
+
+
+ <!-- ******************************************************** -->
+ <!-- ********************* Vendors ************************** -->
+ <!-- ******************************************************** -->
+
+ <vendor id="10415" name="3GPP" />
+
+ <!-- ******************************************************** -->
+ <!-- ***************** Gx Application ********************* -->
+ <!-- ******************************************************** -->
+
+ <application id="16777238" name="Gx">
+
+
+ <!-- ====================================================================== -->
+ <!-- ========================== COMMAND CODES =========================== -->
+ <!-- ====================================================================== -->
+
+ <!-- *** Command-Codes *** -->
+
+ <!-- [3GPP TS 29.212 V7.7.0] , clause 5.6.2 and 5.6.3 -->
+ <command name="CC" code="272" vendor-id="10415">
+
+ </command>
+
+ <!-- [3GPP TS 29.212 V7.7.0] , clause 5.6.4 and 5.6.5 -->
+ <command name="RA" code="258" vendor-id="10415" />
+
+
+ <!-- ====================================================================== -->
+ <!-- ========================= Gx Specific AVPs ======================== -->
+ <!-- ====================================================================== -->
+
+
+ <!-- Ref = [3GPP - 29.214] 5.3.2 -->
+ <avp name="Access-Network-Charging-Address" code="501" mandatory="must"
+ may-encrypt="yes" vendor-id="10415">
+ <type type-name="Address" />
+ </avp>
+
+
+ <!-- [3GPP TS 29.212 V7.7.0] , clause 5.3.1 -->
+ <avp name="Bearer-Usage" vendor-id="10415" code="1000" mandatory="must"
+ may-encrypt="yes">
+ <type type-name="Enumerated" />
+ <enum name="GENERAL" code="0" />
+ <enum name="IMS_SIGNALLING" code="1" />
+ </avp>
+
+ <!-- [3GPP TS 29.212 V7.7.0] , clause 5.3.23 -->
+ <avp name="Bearer-Control-Mode" vendor-id="10415" code="1023"
+ mandatory="must" may-encrypt="yes">
+
+ <type type-name="Enumerated" />
+ <enum name="UE_ONLY" code="0" />
+ <enum name="RESERVED" code="1" />
+ <enum name="UE_NW" code="2" />
+
+ </avp>
+
+ <!-- [3GPP TS 29.212 V7.7.0] , clause 5.3.8 -->
+ <avp name="Metering-Method" vendor-id="10415" code="1007"
+ mandatory="must" may-encrypt="yes" protected="may" type="Enumerated">
+ <type type-name="Enumerated" />
+ <enum name="DURATION" code="0" />
+ <enum name="VOLUME" code="1" />
+ <enum name="DURATION_VOLUME" code="2" />
+ </avp>
+ <!-- [3GPP TS 29.229 V7.7.0] , clause 6.3.20 -->
+ <avp name="Primary-Event-Charging-Function-Name" vendor-id="10415"
+ code="619" mandatory="must" may-encrypt="yes">
+ <type type-name="DiameterURI" />
+ </avp>
+
+ <!-- [3GPP TS 29.229 V7.7.0] , clause 6.3.21 -->
+ <avp name="Secondary-Event-Charging-Function-Name" vendor-id="10415"
+ code="620" mandatory="must" may-encrypt="yes">
+ <type type-name="DiameterURI" />
+ </avp>
+
+ <!-- [3GPP TS 29.229 V7.7.0] , clause 6.3.22 -->
+ <avp name="Primary-Charging-Collection-Function-Name" vendor-id="10415"
+ code="621" mandatory="must" may-encrypt="yes">
+ <type type-name="DiameterURI" />
+ </avp>
+
+ <!-- [3GPP TS 29.229 V7.7.0] , clause 6.3.23 -->
+ <avp name="Secondary-Charging-Collection-Function-Name" vendor-id="10415"
+ code="622" mandatory="must" may-encrypt="yes">
+ <type type-name="DiameterURI" />
+ </avp>
+
+ <!-- [3GPP TS 29.214 v7.3.0] , clause 5.3.4 -->
+ <avp name="Access-Network-Charging-Identifier-Value" vendor-id="10415"
+ code="503" mandatory="must" may-encrypt="yes">
+ <type type-name="OctetString" />
+ </avp>
+
+
+ <!-- [3GPP TS 29.061 V7.9.0] , clause 16.4.7 -->
+ <avp name="3GPP-RAT-Type" vendor-id="10415" code="21" mandatory="mustnot"
+ may-encrypt="yes">
+ <type type-name="OctetString" />
+ </avp>
+
+
+ <!-- Ref = RFC 4006 chap 8.48 -->
+ <avp name="Subscription-Id-Data" code="444" mandatory="must"
+ may-encrypt="yes">
+ <type type-name="UTF8String" />
+ </avp>
+ <!-- Ref = RFC 4006 chap 8.47 -->
+ <avp name="Subscription-Id-Type" code="450" mandatory="must"
+ protected="may" may-encrypt="yes">
+ <type type-name="Enumerated" />
+ <enum name="END_USER_E164" code="0" />
+ <enum name="END_USER_IMSI" code="1" />
+ <enum name="END_USER_SIP_URI" code="2" />
+ <enum name="END_USER_NAI" code="3" />
+ <enum name="END_USER_PRIVATE" code="4" />
+ </avp>
+
+ <!-- [RFC 4006] , clause 8.2 -->
+ <avp name="CC-Request-Number" code="415" mandatory="must"
+ may-encrypt="yes">
+ <type type-name="Unsigned32" />
+ </avp>
+
+ <!-- [RFC 4006] , clause 8.3 -->
+ <avp name="CC-Request-Type" code="416" mandatory="must"
+ may-encrypt="yes">
+ <type type-name="Enumerated" />
+ <enum name="INITIAL_REQUEST" code="1" />
+ <enum name="UPDATE_REQUEST" code="2" />
+ <enum name="TERMINATION_REQUEST" code="3" />
+ <enum name="EVENT_REQUEST" code="4" />
+ </avp>
+
+ <!-- [RFC 4006] , clause 8.38 -->
+ <avp name="Redirect-Address-Type" code="433" mandatory="must"
+ may-encrypt="yes">
+ <type type-name="Enumerated" />
+ <enum name="IPV4_ADDRESS" code="0" />
+ <enum name="IPV6_ADDRESS" code="1" />
+ <enum name="URL" code="2" />
+ <enum name="SIP_URI" code="3" />
+ </avp>
+<!-- [RFC 4006] , clause 8.39 -->
+ <avp name="Redirect-Server-Address" code="435" mandatory="must"
+ may-encrypt="yes">
+ <type type-name="UTF8String" />
+ </avp>
+
+ <!-- [3GPP TS 29.212 V7.7.0] , clause 5.3.19 -->
+ <avp name="PCC-Rule-Status" vendor-id="10415" code="1019"
+ mandatory="must" may-encrypt="yes">
+ <type type-name="Enumerated" />
+ <enum name="ACTIVE" code="0" />
+ <enum name="INACTIVE" code="1" />
+ <enum name="TEMPORARILY INACTIVE" code="2" />
+ </avp>
+
+ <!-- [RFC 4005] , clause 6.11.1 -->
+ <avp name="Framed-IP-Address" code="8" mandatory="must"
+ may-encrypt="yes">
+ <type type-name="OctetString" />
+ </avp>
+
+ <!-- [RFC 4005] , clause 6.11.6 -->
+ <avp name="Framed-IPv6-Prefix" code="97" mandatory="must"
+ may-encrypt="yes">
+ <type type-name="OctetString" />
+ </avp>
+
+ <!-- [RFC 4005] , clause 4.5 -->
+ <avp name="Called-Station-Id" code="30" mandatory="must"
+ may-encrypt="yes">
+ <type type-name="UTF8String" />
+ </avp>
+
+ <!-- [RFC 4005] , clause 6.7 -->
+ <avp name="Filter-Id" code="11" mandatory="must" may-encrypt="yes">
+ <type type-name="UTF8String" />
+ </avp>
+
+ <!-- [3GPP TS 29.212 V7.7.0] , clause 5.3.21 -->
+ <avp name="Bearer-Operation" vendor-id="10415" code="1021"
+ mandatory="must" may-encrypt="yes">
+ <type type-name="Enumerated" />
+ <enum name="TERMINATION" code="0" />
+ <enum name="ESTABLISHMENT" code="1" />
+ <enum name="MODIFICATION" code="2" />
+ </avp>
+
+ <!-- [3GPP TS 29.212 V7.7.0] , clause 5.3.24 -->
+ <avp name="Network-Request-Support" vendor-id="10415" code="1024"
+ mandatory="must" may-encrypt="yes">
+ <type type-name="Enumerated"/>
+
+ <enum name="NETWORK_REQUEST_NOT_SUPPORTED" code="0" />
+ <enum name="NETWORK_REQUEST_SUPPORTED" code="1" />
+ </avp>
+
+ <!-- [3GPP TS 29.212 V7.7.0] , clause 5.3.5 -->
+ <avp name="Charging-Rule-Base-Name" vendor-id="10415" code="1004"
+ mandatory="must" may-encrypt="yes">
+ <type type-name="UTF8String" />
+ </avp>
+ <!-- [3GPP TS 29.212 V7.7.0] , clause 5.3.15 -->
+ <avp name="ToS-Traffic-Class" vendor-id="10415" code="1014"
+ mandatory="must" may-encrypt="yes">
+ <type type-name="OctetString" />
+ </avp>
+
+ <!-- [3GPP TS 29.212 V7.7.0] , clause 5.3.27 -->
+ <avp name="IP-CAN-Type" vendor-id="10415" code="1027" mandatory="must"
+ may-encrypt="yes">
+ <type type-name="Enumerated" />
+ <enum name="3GPP" code="0" />
+ <enum name="DOCSIS" code="1" />
+ <enum name="xDSL" code="2" />
+ <enum name="WiMAX" code="3" />
+ <enum name="3GPP2" code="4" />
+ </avp>
+
+ <!-- [3GPP TS 29.212 V7.7.0] , clause 5.3.28 -->
+ <avp name="QoS-Negotiation" vendor-id="10415" code="1029"
+ mandatory="must" may-encrypt="yes">
+ <type type-name="Enumerated" />
+ <enum name="NO_QOS_NEGOTIATION" code="0" />
+ <enum name="QOS_NEGOTIATION_SUPPORTED" code="1" />
+ </avp>
+
+ <!-- [3GPP TS 29.212 V7.7.0] , clause 5.3.29 -->
+ <avp name="QoS-Upgrade" vendor-id="10415" code="1030" mandatory="must"
+ may-encrypt="yes">
+ <type type-name="Enumerated" />
+ <enum name="QOS_UPGRADE_NOT_SUPPORTED" code="0" />
+ <enum name="QOS_UPGRADE_SUPPORTED" code="1" />
+ </avp>
+
+ <!-- [3GPP TS 29.212 V7.7.0] , clause 5.3.30 -->
+ <avp name="Rule-Failure-Code" vendor-id="10415" code="1031"
+ mandatory="must" may-encrypt="yes">
+ <type type-name="Enumerated" />
+ <enum name="UNKNOWN_RULE_NAME" code="1" />
+ <enum name="RATING_GROUP_ERROR" code="2" />
+ <enum name="SERVICE_IDENTIFIER_ERROR" code="3" />
+ <enum name="GW/PCEF_MALFUNCTION" code="4" />
+ <enum name="RESOURCES_LIMITATION" code="5" />
+ <enum name="MAX_NR_BEARERS_REACHED" code="6" />
+ <enum name="UNKNOWN_BEARER_ID" code="7" />
+ <enum name="MISSING_BEARER_ID" code="8" />
+ <enum name="MISSING_FLOW_DESCRIPTION" code="9" />
+ </avp>
+
+ <!-- [3GPP TS 29.212 V7.7.0] , clause 5.3.34 -->
+ <avp name="Session-Release-Cause" vendor-id="10415" code="1035"
+ mandatory="must" may-encrypt="yes">
+ <type type-name="Enumerated" />
+ <enum name="UNSPECIFIED_REASONS" code="0" />
+ <enum name="UE_SUBSCRIPTION_REASON" code="1" />
+ <enum name="INSUFFICIENT_SERVER_RESOURCES" code="2" />
+ </avp>
+
+
+
+ <!-- [3GPP TS 29.061 V7.9.0] , clause 16.4.7. -->
+ <avp name="3GPP-SGSN-MCC-MNC" vendor-id="10415" code="18"
+ mandatory="mustnot" may-encrypt="yes">
+ <type type-name="UTF8String" />
+ </avp>
+
+ <!-- [3GPP TS 29.061 V7.9.0] , clause 16.4.7 -->
+ <avp name="3GPP-User-Location-Info" vendor-id="10415" code="22"
+ mandatory="mustnot" may-encrypt="yes">
+ <type type-name="OctetString" />
+ </avp>
+
+
+ <!-- [3GPP TS 29.212 V7.7.0] , clause 5.3.31 -->
+ <avp name="Revalidation-Time" vendor-id="10415" code="1032"
+ mandatory="must" may-encrypt="yes">
+ <type type-name="Time" />
+ </avp>
+
+ <!-- [3GPP TS 29.212 V7.7.0] , clause 5.3.32 -->
+ <avp name="Rule-Activation-Time" code="1033" mandatory="must"
+ may-encrypt="yes">
+ <type type-name="Time" />
+ </avp>
+
+
+ <!-- [3GPP TS 29.212 V7.7.0] , clause 5.3.33 -->
+ <avp name="Rule-Deactivation-Time" vendor-id="10415" code="1034"
+ mandatory="must" may-encrypt="yes">
+ <type type-name="Time" />
+ </avp>
+
+ <!-- [3GPP TS 29.061 V7.7.0] , clause 16.4.7.1 -->
+ <avp name="3GPP-SGSN-Address" vendor-id="10415" code="6" mandatory="mustnot"
+ may-encrypt="yes">
+ <type type-name="OctetString" />
+ </avp>
+
+ <!-- [3GPP TS 29.061 V7.7.0] , clause 16.4.7.1 -->
+ <avp name="3GPP-SGSN-IPv6-Address" vendor-id="10415" code="15"
+ mandatory="mustnot" may-encrypt="yes">
+ <type type-name="OctetString" />
+ </avp>
+
+ <!-- [3GPP TS 29.061 V7.7.0] , clause 17.7.12 -->
+ <avp name="RAI" vendor-id="10415" code="909" mandatory="must"
+ may-encrypt="yes">
+ <type type-name="UTF8String" />
+ </avp>
+
+ <!-- [3GPP TS 29.061 V7.7.0] , clause 16.4.7 -->
+ <avp name="3GPP-MS-TimeZone" vendor-id="10415" code="23" mandatory="mustnot"
+ may-encrypt="yes">
+ <type type-name="OctetString" />
+ </avp>
+
+ <!-- [3GPP TS 29.212 V7.7.0] , clause 5.3.20 -->
+ <avp name="Bearer-Identifier" vendor-id="10415" code="1020"
+ mandatory="must" may-encrypt="yes">
+ <type type-name="OctetString" />
+ </avp>
+
+ <!-- [3GPP TS 29.212 V7.7.0] , clause 5.3.6 -->
+ <avp name="Charging-Rule-Name" vendor-id="10415" code="1005"
+ mandatory="must" may-encrypt="yes">
+ <type type-name="OctetString" />
+ </avp>
+
+
+ <!-- [RFC 4006] , clause 8.28 -->
+ <avp name="Service-Identifier" code="439" mandatory="must"
+ may-encrypt="yes">
+ <type type-name="Unsigned32" />
+ </avp>
+
+ <!-- [RFC 4006] , clause 8.29 -->
+ <avp name="Rating-Group" code="432" mandatory="must" may-encrypt="yes">
+ <type type-name="Unsigned32" />
+ </avp>
+ <!-- [3GPP TS 29.214 V7.3.0] , clause 5.3.11 -->
+ <avp name="Flow-Status" vendor-id="10415" code="511" mandatory="must"
+ may-encrypt="yes">
+ <type type-name="Enumerated" />
+ <enum name="ENABLED-UPLINK" code="0" />
+ <enum name="ENABLED-DOWNLINK" code="1" />
+ <enum name="ENABLED" code="2" />
+ <enum name="DISABLED" code="3" />
+ <enum name="REMOVED" code="4" />
+ </avp>
+ <!-- [3GPP TS 29.212 V7.7.0] , clause 5.3.17 -->
+ <avp name="QoS-Class-Identifier" vendor-id="10415" code="1028"
+ mandatory="must" may-encrypt="yes">
+ <type type-name="Enumerated" />
+ <enum name="FINAL_SERVICE_INFORMATION" code="0" />
+ <enum name="PRELIMINARY_SERVICE_INFORMATION" code="1" />
+ </avp>
+ <!-- Ref = [3GPP - 29.214] 5.3.15 -->
+ <avp name="Max-Requested-Bandwidth-UL" code="516" vendor-id="10415"
+ mandatory="must" may-encrypt="yes">
+ <type type-name="Unsigned32" />
+ </avp>
+ <!-- [3GPP TS 29.212 V7.7.0] , clause 5.3.25 -->
+ <avp name="Guaranteed-Bitrate-DL" vendor-id="10415" code="1025"
+ mandatory="must" may-encrypt="yes">
+ <type type-name="Unsigned32" />
+ </avp>
+
+ <!-- [3GPP TS 29.212 V7.7.0] , clause 5.3.26 -->
+ <avp name="Guaranteed-Bitrate-UL" vendor-id="10415" code="1026"
+ mandatory="must" may-encrypt="yes">
+ <type type-name="Unsigned32" />
+ </avp>
+ <!-- [3GPP TS 29.212 V7.7.0] , clause 5.3.20 -->
+ <avp name="Bearer-Identifier" vendor-id="10415" code="1020"
+ mandatory="must" may-encrypt="yes">
+ <type type-name="OctetString" />
+ </avp>
+ <avp name="Max-Requested-Bandwidth-UL" code="516" mandatory="must" vendor-id="10415" may-encrypt="yes">
+ <type type-name="Unsigned32"/>
+ </avp>
+ <avp name="Max-Requested-Bandwidth-DL" code="515" mandatory="must" vendor-id="10415" may-encrypt="yes">
+ <type type-name="Unsigned32"/>
+ </avp>
+ <!-- [3GPP TS 29.212 V7.7.0] , clause 5.3.16 -->
+ <avp name="QoS-Information" vendor-id="10415" code="1016"
+ mandatory="must" may-encrypt="yes">
+ <grouped>
+ <required>
+ <avprule name="QoS-Class-Identifier" minimum="1" maximum="1" />
+ <avprule name="Max-Requested-Bandwidth-UL" minimum="1"
+ maximum="1" />
+ <avprule name="Max-Requested-Bandwidth-DL" minimum="1"
+ maximum="1" />
+ <avprule name="Guaranteed-Bitrate-UL" minimum="1" maximum="1" />
+ <avprule name="Guaranteed-Bitrate-DL" minimum="1" maximum="1" />
+ <avprule name="Bearer-Identifier" minimum="1" maximum="1" />
+ </required>
+ </grouped>
+ </avp>
+ <!-- [3GPP TS 29.214 V7.3.0] , clause 5.3.8 -->
+ <avp name="Flow-Description" vendor-id="10415" code="507"
+ mandatory="must" may-encrypt="yes">
+ <type type-name="IPFilterRule" />
+ </avp>
+ <!-- [3GPP TS 29.212 V7.7.0] , clause 5.3.12 -->
+ <avp name="Reporting-Level" vendor-id="10415" code="1011"
+ mandatory="must" may-encrypt="yes">
+ <type type-name="Enumerated" />
+ <enum name="SERVICE_IDENTIFIER_LEVEL" code="0" />
+ <enum name="RATING_GROUP_LEVEL" code="1" />
+ </avp>
+ <!-- [3GPP TS 29.212 V7.7.0] , clause 5.3.9 -->
+ <avp name="Offline" vendor-id="10415" code="1008" mandatory="must"
+ may-encrypt="yes">
+ <type type-name="Enumerated" />
+ <enum name="DISABLE_OFFLINE" code="0" />
+ <enum name="ENABLE_OFFLINE" code="1" />
+ </avp>
+
+ <!-- [3GPP TS 29.212 V7.7.0] , clause 5.3.10 -->
+ <avp name="Online" vendor-id="10415" code="1009" mandatory="must"
+ may-encrypt="yes">
+ <type type-name="Enumerated" />
+ <enum name="DISABLE_ONLINE" code="0" />
+ <enum name="ENABLE_ONLINE" code="1" />
+ </avp>
+
+ <!-- [3GPP TS 29.212 V7.7.0] , clause 5.3.11 -->
+ <avp name="Precedence" vendor-id="10415" code="1010" mandatory="must"
+ may-encrypt="yes">
+ <type type-name="Unsigned32" />
+ </avp>
+
+ <!-- [3GPP TS 29.214 V7.3.0] , clause 5.3.6 -->
+ <avp name="AF-Charging-Identifier" vendor-id="10415" code="505"
+ mandatory="must" may-encrypt="yes">
+ <type type-name="OctetString" />
+ </avp>
+
+ <!-- Ref = [3GPP - 29.214] 5.3.14 -->
+ <avp name="Max-Requested-Bandwidth-DL" code="515" vendor-id="10415"
+ mandatory="must" may-encrypt="yes">
+ <type type-name="Unsigned32" />
+ </avp>
+ <!-- [3GPP TS 29.214 V7.3.0] , clause 5.3.17 -->
+ <avp name="Media-Component-Number" vendor-id="10415" code="518"
+ mandatory="must" may-encrypt="yes">
+ <type type-name="Unsigned32" />
+ </avp>
+
+ <!-- [3GPP TS 29.214 V7.3.0] , clause 5.3.9 -->
+ <avp name="Flow-Number" vendor-id="10415" code="509" mandatory="must"
+ may-encrypt="yes">
+ <type type-name="Unsigned32" />
+ </avp>
+<!-- [3GPP TS 29.214 V7.3.0] , clause 5.3.10 -->
+ <avp name="Flows" vendor-id="10415" code="510" mandatory="must"
+ may-encrypt="yes">
+ <grouped>
+ <required>
+ <avprule name="Media-Component-Number" minimum="1" maximum="1" />
+ </required>
+ <optional>
+ <avprule name="Flow-Number" maximum="1" />
+ </optional>
+ </grouped>
+ </avp>
+ <!-- [3GPP TS 29.212 V7.7.0] , clause 5.3.4 -->
+ <avp name="Charging-Rule-Definition" vendor-id="10415" code="1003"
+ mandatory="must" may-encrypt="yes">
+ <grouped>
+ <required>
+ <avprule name="Charging-Rule-Name" minimum="1" maximum="1" />
+ <avprule name="Service-Identifier" maximum="1" />
+ <avprule name="Rating-Group" maximum="1" />
+ </required>
+ <optional>
+ <avprule name="Flow-Description" maximum="1" />
+ </optional>
+ <required>
+ <avprule name="Flow-Status" maximum="1" />
+ <avprule name="QoS-Information" maximum="1" />
+ <avprule name="Reporting-Level" maximum="1" />
+ <avprule name="Online" maximum="1" />
+ <avprule name="Offline" maximum="1" />
+ <avprule name="Metering-Method" maximum="1" />
+ <avprule name="Precedence" maximum="1" />
+ <avprule name="AF-Charging-Identifier" maximum="1" />
+ </required>
+ <optional>
+ <avprule name="Flows" maximum="1" />
+ </optional>
+ </grouped>
+ </avp>
+
+ <!-- [3GPP TS 29.212 V7.7.0] , clause 5.3.2 -->
+ <avp name="Charging-Rule-Install" vendor-id="10415" code="1001"
+ mandatory="must" may-encrypt="yes">
+ <grouped>
+ <optional>
+ <avprule name="Charging-Rule-Definition" maximum="1" />
+ <avprule name="Charging-Rule-Name" maximum="1" />
+ <avprule name="Charging-Rule-Base-Name" maximum="1" />
+ </optional>
+ <required>
+ <avprule name="Bearer-Identifier" minumin="1" maximum="1" />
+ </required>
+ <optional>
+ <avprule name="Rule-Activation-Time" maximum="1" />
+ <avprule name="Rule-Deactivation-Time" maximum="1" />
+ </optional>
+ </grouped>
+ </avp>
+
+ <!-- [3GPP TS 29.212 V7.7.0] , clause 5.3.3 -->
+ <avp name="Charging-Rule-Remove" vendor-id="10415" code="1002"
+ mandatory="must" may-encrypt="yes">
+ <grouped>
+ <optional>
+ <avprule name="Charging-Rule-Name" maximum="1" />
+ <avprule name="Charging-Rule-Base-Name" maximum="1" />
+ </optional>
+ </grouped>
+ </avp>
+
+
+
+
+
+
+
+ <!-- [3GPP TS 29.212 V7.7.0] , clause 5.3.7 -->
+ <avp name="Event-Trigger" vendor-id="10415" code="1006" mandatory="must"
+ may-encrypt="yes">
+ <type type-name="Enumerated" />
+ <enum name="SGSN_CHANGE" code="0" />
+ <enum name="QOS_CHANGE" code="1" />
+ <enum name="RAT_CHANGE" code="2" />
+ <enum name="TFT_CHANGE" code="3" />
+ <enum name="PLMN_CHANGE" code="4" />
+ <enum name="LOSS_OF_BEARER" code="5" />
+ <enum name="RECOVERY_OF_BEARER" code="6" />
+ <enum name="IP-CAN_CHANGE" code="7" />
+ <enum name="PCEF_MALFUNCTION" code="8" />
+ <enum name="RESOURCES_LIMITATION" code="9" />
+ <enum name="MAX_NR_BEARERS_REACHED" code="10" />
+ <enum name="QOS_CHANGE_EXCEEDING_AUTHORIZATION" code="11" />
+ <enum name="RAI_CHANGE" code="12" />
+ <enum name="USER_LOCATION_CHANGE" code="13" />
+ <enum name="NO_EVENT_TRIGGERS" code="14" />
+ <enum name="OUT_OF_CREDIT" code="15" />
+ <enum name="REALLOCATION_OF_CREDIT" code="16" />
+ <enum name="REVALIDATION_TIMEOUT" code="17" />
+ </avp>
+
+
+
+
+
+
+
+ <!-- [3GPP TS 29.212 V7.7.0] , clause 5.3.13 -->
+ <avp name="TFT-Filter" vendor-id="10415" code="1012" mandatory="must"
+ may-encrypt="yes">
+ <type type-name="IPFilterRule" />
+ </avp>
+
+
+ <!-- [3GPP TS 29.212 V7.7.0] , clause 5.3.14 -->
+ <avp name="TFT-Packet-Filter-Information" vendor-id="10415" code="1013"
+ mandatory="must" may-encrypt="yes">
+ <grouped>
+ <required>
+ <avprule name="Precedence" minimum="1" maximum="1" />
+ <avprule name="TFT-Filter" minimum="1" maximum="1" />
+ <avprule name="ToS-Traffic-Class" minimum="1" maximum="1" />
+ </required>
+ </grouped>
+ </avp>
+
+<!-- [RFC 4006] , clause 8.35 -->
+ <avp name="Final-Unit-Action" code="449" mandatory="must"
+ may-encrypt="yes">
+ <type type-name="Enumerated" />
+ <enum name="TERMINATE" code="0" />
+ <enum name="REDIRECT" code="1" />
+ <enum name="RESTRICT_ACCESS" code="2" />
+ </avp>
+
+ <!-- [RFC 4006] , clause 8.36 -->
+ <avp name="Restriction-Filter-Rule" code="438" mandatory="must"
+ may-encrypt="yes">
+ <type type-name="IPFilterRule" />
+ </avp>
+ <!-- [RFC 4006] , clause 8.37 -->
+ <avp name="Redirect-Server" code="434" mandatory="must"
+ may-encrypt="yes">
+ <grouped>
+ <required>
+ <avprule name="Redirect-Address-Type" minimum="1" maximum="1" />
+ <avprule name="Redirect-Server-Address" minimum="1"
+ maximum="1" />
+ </required>
+ </grouped>
+ </avp>
+ <!-- [RFC 4006] , clause 8.34 -->
+ <avp name="Final-Unit-Indication" code="430" mandatory="must"
+ may-encrypt="yes">
+ <grouped>
+ <required>
+ <avprule name="Final-Unit-Action" minimum="1" maximum="1" />
+ <avprule name="Restriction-Filter-Rule" minimum="1"
+ maximum="1" />
+ <avprule name="Filter-Id" minimum="1" maximum="1" />
+ <avprule name="Redirect-Server" minimum="1" maximum="1" />
+ </required>
+ </grouped>
+ </avp>
+
+ <!-- [3GPP TS 29.212 V7.7.0] , clause 5.3.18 -->
+ <avp name="Charging-Rule-Report" vendor-id="10415" code="1018"
+ mandatory="must" may-encrypt="yes">
+ <grouped>
+ <optional>
+ <avprule name="Charging-Rule-Name" maximum="1" />
+ <avprule name="Charging-Rule-Base-Name" maximum="1" />
+ </optional>
+ <required>
+ <avprule name="PCC-Rule-Status" minimum="1" maximum="1" />
+ </required>
+ <optional>
+ <avprule name="Rule-Failure-Code" maximum="1" />
+ <avprule name="Final-Unit-Indication" maximum="1" />
+ </optional>
+ </grouped>
+ </avp>
+
+
+
+ <!-- [3GPP TS 29.212 V7.7.0] , clause 5.3.22 -->
+ <avp name="Access-Network-Charging-Identifier-Gx" vendor-id="10415"
+ code="1022" mandatory="must" may-encrypt="yes">
+ <grouped>
+ <required>
+ <avprule name="Access-Network-Charging-Identifier-Value"
+ minimum="1" maximum="1" />
+ </required>
+ <optional>
+ <avprule name="Charging-Rule-Base-Name" maximum="1" />
+ <avprule name="Charging-Rule-Name" maximum="1" />
+ </optional>
+ </grouped>
+ </avp>
+
+
+
+ <!-- [3GPP TS 29.229 V7.7.0] , clause 6.3.19 -->
+ <avp name="Charging-Information" vendor-id="10415" code="618"
+ mandatory="must" may-encrypt="yes">
+ <grouped>
+ <required>
+ <avprule name="Primary-Event-Charging-Function-Name"
+ minimum="1" maximum="1" />
+ <avprule name="Secondary-Event-Charging-Function-Name"
+ minimum="1" maximum="1" />
+ <avprule name="Primary-Charging-Collection-Function-Name"
+ minimum="1" maximum="1" />
+ <avprule name="Secondary-Charging-Collection-Function-Name"
+ minimum="1" maximum="1" />
+ </required>
+ </grouped>
+ </avp>
+
+
+
+
+
+ <!-- Ref = RFC 4006 chap 8.46 -->
+ <avp name="Subscription-Id" code="443" mandatory="must"
+ may-encrypt="yes">
+ <grouped>
+ <required>
+ <avprule name="Subscription-Id-Type" />
+ <avprule name="Subscription-Id-Data" />
+ </required>
+ </grouped>
+ </avp>
+
+
+
+
+ </application>
+</dictionary>
+
diff --git a/contrib/dict_legacy/README b/contrib/dict_legacy/README
new file mode 100644
index 0000000..86b2418
--- /dev/null
+++ b/contrib/dict_legacy/README
@@ -0,0 +1,14 @@
+The dictionary.dtd file originates from draft-frascone-xml-dictionary-00.
+A few modifications may have been performed (see file history in Mercurial)
+However, no DTD validation is performed by the parser, but the extension
+expects a known format therefore the flexibility is limited.
+
+
+Additional XML dictionary files can be found:
+ - Circum project (circum.sf.net)
+ under share/*.xml
+
+ - OpenDiameter project (diameter.sf.net)
+ under libdiameter/config/dictionary.xml (will probably require some stripping)
+
+
diff --git a/contrib/dict_legacy/dictionary.dtd b/contrib/dict_legacy/dictionary.dtd
new file mode 100644
index 0000000..a2fced9
--- /dev/null
+++ b/contrib/dict_legacy/dictionary.dtd
@@ -0,0 +1,69 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!ELEMENT dictionary (vendor*, base*, application*)>
+
+<!ELEMENT vendor EMPTY>
+<!ATTLIST vendor
+ id CDATA #REQUIRED
+ name CDATA #REQUIRED
+>
+
+<!ELEMENT base (command*, typedefn*, avp*)>
+<!ATTLIST base
+ uri CDATA #IMPLIED
+>
+
+<!ELEMENT application (command*, typedefn*, avp*)>
+<!ATTLIST application
+ id CDATA #REQUIRED
+ name CDATA #IMPLIED
+ uri CDATA #IMPLIED
+>
+<!ELEMENT command (requestrules*, answerrules*)>
+<!ATTLIST command
+ name CDATA #REQUIRED
+ code CDATA #REQUIRED
+ vendor-id CDATA #IMPLIED
+ pbit (0 | 1) "1"
+>
+
+<!ELEMENT typedefn EMPTY>
+<!ATTLIST typedefn
+ type-name ID #REQUIRED
+ type-parent IDREF #IMPLIED
+ description CDATA #IMPLIED
+>
+<!ELEMENT avp ((type | grouped), (enum*))>
+<!ATTLIST avp
+ name ID #REQUIRED
+ description CDATA #IMPLIED
+ code CDATA #REQUIRED
+ mandatory CDATA #IMPLIED
+ vendor-id CDATA #IMPLIED
+>
+<!ELEMENT type EMPTY>
+<!ATTLIST type
+ type-name IDREF #REQUIRED
+>
+<!ELEMENT grouped (fixed*, required*, optional*)>
+<!ELEMENT enum EMPTY>
+<!ATTLIST enum
+ name CDATA #REQUIRED
+ code CDATA #REQUIRED
+>
+
+<!ELEMENT requestrules (fixed*, required*, optional*)>
+<!ELEMENT answerrules (fixed*, required*, optional*)>
+
+<!ELEMENT fixed (avprule*)>
+<!ELEMENT required (avprule*)>
+<!ELEMENT optional (avprule*)>
+
+<!ELEMENT avprule EMPTY>
+<!ATTLIST avprule
+ name IDREF #REQUIRED
+ position (first | last | unspecified) "unspecified"
+ maximum CDATA #IMPLIED
+ minimum CDATA #IMPLIED
+>
+
+
diff --git a/contrib/nightly_tests/README b/contrib/nightly_tests/README
new file mode 100644
index 0000000..67d97e9
--- /dev/null
+++ b/contrib/nightly_tests/README
@@ -0,0 +1,86 @@
+This folder contains information and scripts to run a new test configuration for nightly builds
+and reporting the results to freeDiameter dashboard at:
+ http://www.freediameter.net/CDash/index.php?project=freeDiameter
+
+The information gathered here mostly comes from the following pages:
+ http://www.itk.org/Wiki/CMake_Testing_With_CTest
+ http://www.itk.org/Wiki/CMake_Scripting_Of_CTest
+ http://www.itk.org/Wiki/CTest:Buildserver
+
+=============
+
+INSTRUCTIONS to setup a new build slave for the freeDiameter buildserver:
+-- note: the build slave should have cmake version 2.8 at least so that ctest will update the source tree properly.
+
+1) Install all dependencies for freeDiameter as follow:
+ a) Debian / Ubuntu: See the "prereqs.ubuntu" file
+ $ sudo aptitude install `wget http://www.freediameter.net/hg/freeDiameter/raw-file/tip/contrib/nightly_tests/prereqs.ubuntu -O - | grep -v -e "^#"`
+
+ b) FreeBSD: See the "prereqs.freebsd" file
+ - install base system and ports
+ - install freediameter dependencies as follow:
+ # pkg_add -r -v wget
+ # pkg_add -r -v `wget http://www.freediameter.net/hg/freeDiameter/raw-file/tip/contrib/nightly_tests/prereqs.freebsd -O - | grep -v -e "^#"`
+
+ c) OpenSUSE:
+ $ sudo zypper install `wget http://www.freediameter.net/hg/freeDiameter/raw-file/tip/contrib/nightly_tests/prereqs.opensuse -O - | grep -v -e "^#"`
+
+ d) Fedora:
+ $ sudo yum install wget
+ $ sudo yum install `wget http://www.freediameter.net/hg/freeDiameter/raw-file/tip/contrib/nightly_tests/prereqs.fedora -O - | grep -v -e "^#"`
+
+ You may also have issues with SELinux later, an easy workaround is to disable it (until better solution)
+ # setenforce Permissive
+
+
+2) Create the "test" database for app_acct test (we assume the tests are run as user "test" here)
+ - check INSTALL.FreeBSD file for specific PostgreSQL pre-install instructions.
+ - These are the instructions for Debian/Ubuntu/OpenSUSE, adjust as needed:
+ # su - postgres
+ # createuser --interactive test
+ Shall the new role be a superuser? (y/n) n
+ Shall the new role be allowed to create databases? (y/n) y
+ Shall the new role be allowed to create more new roles? (y/n) n
+ # logout
+ $ whoami
+ test
+ $ createdb test
+ $ psql test
+ psql (8.4.4)
+ Type "help" for help.
+
+ test=>
+ CREATE TABLE incoming_test (
+ recorded_on timestamp with time zone NOT NULL,
+ "Accounting-Record-Type" integer,
+ "Session-Id" bytea,
+ "Accounting-Record-Number" integer,
+ "Route-Record1" bytea,
+ "Route-Record2" bytea,
+ "Route-Record3" bytea,
+ "Route-Record4" bytea );
+ \q
+
+
+3) Create a directory ~/fDtests
+ $ cd
+ $ mkdir fDtests
+ $ cd fDtests
+
+4) Retrieve the runtests.sh script and save in this directory
+ $ wget http://www.freediameter.net/hg/freeDiameter/raw-file/tip/contrib/nightly_tests/runtests.sh
+ $ chmod +x runtests.sh
+
+5) Create a file local.cmake defining the name of the build slave in this directory also.
+ $ echo "SET(CTEST_SITE \""`hostname`"\")" > local.cmake
+
+ For FreeBSD, in addition do:
+ $ echo "set(CTEST_BUILD_OPTIONS \"\${CTEST_BUILD_OPTIONS} -DFLEX_EXECUTABLE:FILEPATH=/usr/local/bin/flex\")" >> local.cmake
+
+6) Run the runtests.sh script once to check it works properly (freeBSD might require: ln -s /usr/local/bin/bash /bin/bash)
+
+7) Set up a crontab to run the script
+ $ wget http://www.freediameter.net/hg/freeDiameter/raw-file/tip/contrib/nightly_tests/cronjob.sh
+ $ chmod +x cronjob.sh
+ $ crontab -l
+0 0 * * * /home/test/fDtests/cronjob.sh > /home/test/fDtests/cronjob.log 2>&1
diff --git a/contrib/nightly_tests/alldefault.conf b/contrib/nightly_tests/alldefault.conf
new file mode 100644
index 0000000..0376918
--- /dev/null
+++ b/contrib/nightly_tests/alldefault.conf
@@ -0,0 +1,2 @@
+
+set(CTEST_BUILD_NAME "Default")
diff --git a/contrib/nightly_tests/allext.conf b/contrib/nightly_tests/allext.conf
new file mode 100644
index 0000000..ba94a09
--- /dev/null
+++ b/contrib/nightly_tests/allext.conf
@@ -0,0 +1,9 @@
+
+# This configuration compiles all the extensions. It also performs a coverage test.
+# For this to pass, you need to setup the pg database for app_acct test.
+
+set(CTEST_BUILD_NAME "All extensions (default)")
+
+set(CTEST_BUILD_OPTIONS "${CTEST_BUILD_OPTIONS} -DALL_EXTENSIONS:BOOL=ON")
+set(CTEST_BUILD_OPTIONS "${CTEST_BUILD_OPTIONS} -DTEST_APP_ACCT:BOOL=ON -DTEST_APP_ACCT_CONNINFO:STRING=user=test\\ dbname=test")
+
diff --git a/contrib/nightly_tests/allextdbg.conf b/contrib/nightly_tests/allextdbg.conf
new file mode 100644
index 0000000..60e9df6
--- /dev/null
+++ b/contrib/nightly_tests/allextdbg.conf
@@ -0,0 +1,11 @@
+
+# This configuration compiles all the extensions. It also performs a coverage test.
+# For this to pass, you need to setup the pg database for app_acct test.
+
+set(WITH_COVERAGE TRUE)
+set(CTEST_BUILD_NAME "All extensions (Debug)")
+
+set(CTEST_BUILD_OPTIONS "${CTEST_BUILD_OPTIONS} -DALL_EXTENSIONS:BOOL=ON")
+set(CTEST_BUILD_OPTIONS "${CTEST_BUILD_OPTIONS} -DCMAKE_BUILD_TYPE:STRING=Debug")
+set(CTEST_BUILD_OPTIONS "${CTEST_BUILD_OPTIONS} -DTEST_APP_ACCT:BOOL=ON -DTEST_APP_ACCT_CONNINFO:STRING=user=test\\ dbname=test")
+
diff --git a/contrib/nightly_tests/allextdeb.conf b/contrib/nightly_tests/allextdeb.conf
new file mode 100644
index 0000000..876baaf
--- /dev/null
+++ b/contrib/nightly_tests/allextdeb.conf
@@ -0,0 +1,10 @@
+
+# This configuration compiles all the extensions. It also performs a coverage test.
+# For this to pass, you need to setup the pg database for app_acct test.
+
+set(CTEST_BUILD_NAME "All extensions (DebianPackage)")
+
+set(CTEST_BUILD_OPTIONS "${CTEST_BUILD_OPTIONS} -DALL_EXTENSIONS:BOOL=ON")
+set(CTEST_BUILD_OPTIONS "${CTEST_BUILD_OPTIONS} -DCMAKE_BUILD_TYPE:STRING=DebianPackage")
+set(CTEST_BUILD_OPTIONS "${CTEST_BUILD_OPTIONS} -DTEST_APP_ACCT:BOOL=ON -DTEST_APP_ACCT_CONNINFO:STRING=user=test\\ dbname=test")
+
diff --git a/contrib/nightly_tests/allextmax.conf b/contrib/nightly_tests/allextmax.conf
new file mode 100644
index 0000000..a67468e
--- /dev/null
+++ b/contrib/nightly_tests/allextmax.conf
@@ -0,0 +1,10 @@
+
+# This configuration compiles all the extensions. It also performs a coverage test.
+# For this to pass, you need to setup the pg database for app_acct test.
+
+set(CTEST_BUILD_NAME "All extensions (MaxPerformance)")
+
+set(CTEST_BUILD_OPTIONS "${CTEST_BUILD_OPTIONS} -DALL_EXTENSIONS:BOOL=ON")
+set(CTEST_BUILD_OPTIONS "${CTEST_BUILD_OPTIONS} -DCMAKE_BUILD_TYPE:STRING=MaxPerformance")
+set(CTEST_BUILD_OPTIONS "${CTEST_BUILD_OPTIONS} -DTEST_APP_ACCT:BOOL=ON -DTEST_APP_ACCT_CONNINFO:STRING=user=test\\ dbname=test")
+
diff --git a/contrib/nightly_tests/allextprof.conf b/contrib/nightly_tests/allextprof.conf
new file mode 100644
index 0000000..9d6d66c
--- /dev/null
+++ b/contrib/nightly_tests/allextprof.conf
@@ -0,0 +1,11 @@
+
+# This configuration compiles all the extensions. It also performs a coverage test.
+# For this to pass, you need to setup the pg database for app_acct test.
+
+set(WITH_COVERAGE TRUE)
+set(CTEST_BUILD_NAME "All extensions (Profiling)")
+
+set(CTEST_BUILD_OPTIONS "${CTEST_BUILD_OPTIONS} -DALL_EXTENSIONS:BOOL=ON")
+set(CTEST_BUILD_OPTIONS "${CTEST_BUILD_OPTIONS} -DCMAKE_BUILD_TYPE:STRING=Profiling")
+set(CTEST_BUILD_OPTIONS "${CTEST_BUILD_OPTIONS} -DTEST_APP_ACCT:BOOL=ON -DTEST_APP_ACCT_CONNINFO:STRING=user=test\\ dbname=test")
+
diff --git a/contrib/nightly_tests/allextrel.conf b/contrib/nightly_tests/allextrel.conf
new file mode 100644
index 0000000..60457cb
--- /dev/null
+++ b/contrib/nightly_tests/allextrel.conf
@@ -0,0 +1,10 @@
+
+# This configuration compiles all the extensions. It also performs a coverage test.
+# For this to pass, you need to setup the pg database for app_acct test.
+
+set(CTEST_BUILD_NAME "All extensions (Release)")
+
+set(CTEST_BUILD_OPTIONS "${CTEST_BUILD_OPTIONS} -DALL_EXTENSIONS:BOOL=ON")
+set(CTEST_BUILD_OPTIONS "${CTEST_BUILD_OPTIONS} -DCMAKE_BUILD_TYPE:STRING=Release")
+set(CTEST_BUILD_OPTIONS "${CTEST_BUILD_OPTIONS} -DTEST_APP_ACCT:BOOL=ON -DTEST_APP_ACCT_CONNINFO:STRING=user=test\\ dbname=test")
+
diff --git a/contrib/nightly_tests/allextval.conf b/contrib/nightly_tests/allextval.conf
new file mode 100644
index 0000000..48e32aa
--- /dev/null
+++ b/contrib/nightly_tests/allextval.conf
@@ -0,0 +1,11 @@
+
+# This configuration compiles all the extensions. It also performs a coverage test.
+# For this to pass, you need to setup the pg database for app_acct test.
+
+set(WITH_COVERAGE TRUE)
+set(CTEST_BUILD_NAME "All extensions (DebugValgrind)")
+
+set(CTEST_BUILD_OPTIONS "${CTEST_BUILD_OPTIONS} -DALL_EXTENSIONS:BOOL=ON")
+set(CTEST_BUILD_OPTIONS "${CTEST_BUILD_OPTIONS} -DCMAKE_BUILD_TYPE:STRING=DebugValgrind")
+set(CTEST_BUILD_OPTIONS "${CTEST_BUILD_OPTIONS} -DTEST_APP_ACCT:BOOL=ON -DTEST_APP_ACCT_CONNINFO:STRING=user=test\\ dbname=test")
+
diff --git a/contrib/nightly_tests/cronjob.sh b/contrib/nightly_tests/cronjob.sh
new file mode 100644
index 0000000..de1809f
--- /dev/null
+++ b/contrib/nightly_tests/cronjob.sh
@@ -0,0 +1,9 @@
+#!/bin/bash
+
+# This script will simply retrieve the latest "runtest" script and run it.
+pushd ~/fDtests
+mv -f runtests.sh runtests.sh.prev
+wget "http://www.freediameter.net/hg/freeDiameter/raw-file/tip/contrib/nightly_tests/runtests.sh"
+chmod +x runtests.sh
+popd
+~/fDtests/runtests.sh
diff --git a/contrib/nightly_tests/idnaignore.conf b/contrib/nightly_tests/idnaignore.conf
new file mode 100644
index 0000000..5c344ac
--- /dev/null
+++ b/contrib/nightly_tests/idnaignore.conf
@@ -0,0 +1,4 @@
+
+set(CTEST_BUILD_OPTIONS "${CTEST_BUILD_OPTIONS} -DDIAMID_IDNA_IGNORE:BOOL=ON")
+
+set(CTEST_BUILD_NAME "IDNA Ignore")
diff --git a/contrib/nightly_tests/idnareject.conf b/contrib/nightly_tests/idnareject.conf
new file mode 100644
index 0000000..dbcbe69
--- /dev/null
+++ b/contrib/nightly_tests/idnareject.conf
@@ -0,0 +1,4 @@
+
+set(CTEST_BUILD_OPTIONS "${CTEST_BUILD_OPTIONS} -DDIAMID_IDNA_REJECT:BOOL=ON")
+
+set(CTEST_BUILD_NAME "IDNA Reject")
diff --git a/contrib/nightly_tests/nosctp.conf b/contrib/nightly_tests/nosctp.conf
new file mode 100644
index 0000000..f37aa3e
--- /dev/null
+++ b/contrib/nightly_tests/nosctp.conf
@@ -0,0 +1,5 @@
+
+# Remove SCTP support at compilation
+set(CTEST_BUILD_OPTIONS "${CTEST_BUILD_OPTIONS} -DDISABLE_SCTP:BOOL=ON")
+
+set(CTEST_BUILD_NAME "No SCTP")
diff --git a/contrib/nightly_tests/prereqs.fedora b/contrib/nightly_tests/prereqs.fedora
new file mode 100644
index 0000000..9be4305
--- /dev/null
+++ b/contrib/nightly_tests/prereqs.fedora
@@ -0,0 +1,15 @@
+# Fedora packages names of dependencies for nightly tests (using "yum install <packages>"):
+cmake make gcc gcc-c++ flex bison gnutls-devel libgcrypt-devel mercurial
+lksctp-tools-devel kernel-modules-extra
+postgresql-server postgresql-devel
+mysql-server mysql-devel
+libxml2 libxml2-devel libidn-devel
+swig python-devel
+
+# For postgresql server to start automatically, you may have to issue:
+# service postgresql initdb
+# chkconfig --level 345 postgresql on
+
+# To allow SCTP sockets to be bound in SELinux, I don't know the command,
+# so let's disable SELinux for the moment:
+# setenforce Permissive
diff --git a/contrib/nightly_tests/prereqs.freebsd b/contrib/nightly_tests/prereqs.freebsd
new file mode 100644
index 0000000..86a239e
--- /dev/null
+++ b/contrib/nightly_tests/prereqs.freebsd
@@ -0,0 +1,5 @@
+# 1: install base system and ports
+# 2: install wget with command: pkg_add -r -v wget
+# Finally, install the other packages from this file
+# pkg_add -r -F -v `wget http://www.freediameter.net/hg/freeDiameter/raw-file/tip/contrib/nightly_tests/prereqs.freebsd -O - | grep -v -e "^#"`
+bash cmake mercurial flex bison libgcrypt gnutls postgresql84-client postgresql84-server mysql50-client libxml2 swig
diff --git a/contrib/nightly_tests/prereqs.opensuse b/contrib/nightly_tests/prereqs.opensuse
new file mode 100644
index 0000000..2ece2dc
--- /dev/null
+++ b/contrib/nightly_tests/prereqs.opensuse
@@ -0,0 +1,9 @@
+# OpenSUSE packages names of dependencies for nightly tests (using "zypper install <packages>"):
+# zypper install `wget http://www.freediameter.net/hg/freeDiameter/raw-file/tip/contrib/nightly_tests/prereqs.opensuse -O - | grep -v -e "^#"`
+cmake mercurial make gcc gcc-c++ flex bison lksctp-tools-devel libgnutls-devel libgcrypt-devel
+postgresql-server postgresql-devel libmysqlclient-devel libxml2-devel swig python-devel
+
+# Afterwards, you may need to issue the following command so that postgresql starts at boot:
+# insserv postgresql
+# or for open Suse 12.x:
+# systemctl enable postgresql.service
diff --git a/contrib/nightly_tests/prereqs.ubuntu b/contrib/nightly_tests/prereqs.ubuntu
new file mode 100644
index 0000000..02ea907
--- /dev/null
+++ b/contrib/nightly_tests/prereqs.ubuntu
@@ -0,0 +1,3 @@
+# Packages (Ubuntu names)
+cmake mercurial make gcc g++ flex bison binutils libsctp-dev libgnutls-dev valgrind wget libpq-dev postgresql libmysqlclient-dev libxml2-dev libxml2 swig python-dev
+
diff --git a/contrib/nightly_tests/runtests.sh b/contrib/nightly_tests/runtests.sh
new file mode 100644
index 0000000..e339b9b
--- /dev/null
+++ b/contrib/nightly_tests/runtests.sh
@@ -0,0 +1,133 @@
+#!/bin/bash -x
+
+# This script will retrieve the list of tests to run from the freediameter website,
+# and execute them one by one.
+
+ROOTDIR=$HOME/fDtests
+if [ ! -d $ROOTDIR ]; then
+ echo "The working directory $ROOTDIR does not exist. Please create it or edit the script."
+ exit 1;
+fi
+
+WORKDIR=$ROOTDIR/data
+
+# The script requires a local.cmake file to exist and define the following:
+# CTEST_SITE=
+# the name of the build slave.
+# Example: SET(CTEST_SITE "Ubuntu-Lucid-64b")
+if [ ! -e $ROOTDIR/local.cmake ]; then
+ echo "Missing $ROOTDIR/local.cmake file, generating one (edit as needed, and run the script again)";
+ echo "SET(CTEST_SITE \""`hostname --fqdn`"\")" > $ROOTDIR/local.cmake
+ exit 1;
+fi
+
+# Now, cleanup any previous built data, but keep the sources (to get the diffs)
+if [ ! -d $WORKDIR ]; then
+ mkdir $WORKDIR
+else
+ rm -rf $WORKDIR/*/build
+fi
+
+echo "Starting Nightly tests, time: "`date`
+
+# Retrieve the default parameters.
+wget "http://www.freediameter.net/hg/freeDiameter/raw-file/tip/CTestConfig.cmake" -O $WORKDIR/1_default.cmake
+if [ ! -e $WORKDIR/1_default.cmake ]; then
+ echo "Error retrieving CTestConfig.cmake file";
+ exit 1;
+fi
+
+# Retrieve the list of build names
+wget "http://www.freediameter.net/hg/freeDiameter/raw-file/tip/contrib/nightly_tests/tests.list" -O $WORKDIR/2_tests.list
+if [ ! -e $WORKDIR/2_tests.list ]; then
+ echo "Error retrieving tests.list file";
+ exit 1;
+fi
+
+# Now, for each test in the list
+for t in $(cat $WORKDIR/2_tests.list | grep -v -e "^#"); do
+ # Create the work environment if needed
+ if [ ! -d $WORKDIR/$t ]; then
+ mkdir $WORKDIR/$t
+ fi
+
+ #### Create the script
+
+ # Project name, nightly time
+ cp $WORKDIR/1_default.cmake $WORKDIR/$t/CTestScript.cmake
+
+ # Create path names, default build configuration, ...
+ cat >> $WORKDIR/$t/CTestScript.cmake << EOF
+ ##########################
+ SET(CTEST_SOURCE_DIRECTORY "$WORKDIR/$t/source")
+ SET(CTEST_BINARY_DIRECTORY "$WORKDIR/$t/build")
+
+ set(CTEST_CMAKE_GENERATOR "Unix Makefiles")
+
+ set(CTEST_BUILD_CONFIGURATION "Profiling")
+ set(WITH_MEMCHECK FALSE)
+ set(WITH_COVERAGE FALSE)
+
+ set(CTEST_BUILD_OPTIONS "")
+ set(CTEST_BUILD_NAME "Unnamed")
+
+ ##########################
+EOF
+
+ wget "http://www.freediameter.net/hg/freeDiameter/raw-file/tip/contrib/nightly_tests/$t.conf" -O $WORKDIR/$t/params.conf
+ if [ ! -e $WORKDIR/$t/params.conf ]; then
+ echo "Error retrieving $t.conf file";
+ continue;
+ fi
+
+ # The retrieved parameters will overwrite the defaults
+ cat $WORKDIR/$t/params.conf >> $WORKDIR/$t/CTestScript.cmake
+
+ # Overwrite with all the local data (site name, ...)
+ echo "######## Local site data: " >> $WORKDIR/$t/CTestScript.cmake
+ cat $ROOTDIR/local.cmake >> $WORKDIR/$t/CTestScript.cmake
+
+ # Now, the remaining of the script
+ cat >> $WORKDIR/$t/CTestScript.cmake << EOF
+ #######################################################################
+
+ # ctest_empty_binary_directory(\${CTEST_BINARY_DIRECTORY})
+
+ find_program(CTEST_HG_COMMAND NAMES hg)
+ find_program(CTEST_COVERAGE_COMMAND NAMES gcov)
+ find_program(CTEST_MEMORYCHECK_COMMAND NAMES valgrind)
+
+ # set(CTEST_MEMORYCHECK_SUPPRESSIONS_FILE \${CTEST_SOURCE_DIRECTORY}/tests/valgrind.supp)
+
+ if(NOT EXISTS "\${CTEST_SOURCE_DIRECTORY}")
+ set(CTEST_CHECKOUT_COMMAND "\${CTEST_HG_COMMAND} clone http://www.freediameter.net/hg/freeDiameter \${CTEST_SOURCE_DIRECTORY}")
+ endif()
+
+ set(CTEST_UPDATE_COMMAND "\${CTEST_HG_COMMAND}")
+
+ set(CTEST_CONFIGURE_COMMAND "\${CMAKE_COMMAND} -DCMAKE_BUILD_TYPE:STRING=\${CTEST_BUILD_CONFIGURATION}")
+ set(CTEST_CONFIGURE_COMMAND "\${CTEST_CONFIGURE_COMMAND} -DBUILD_TESTING:BOOL=ON -DOPT_TEST_ARGUMENTS:STRING=-d \${CTEST_BUILD_OPTIONS}")
+ set(CTEST_CONFIGURE_COMMAND "\${CTEST_CONFIGURE_COMMAND} \\"-G\${CTEST_CMAKE_GENERATOR}\\"")
+ set(CTEST_CONFIGURE_COMMAND "\${CTEST_CONFIGURE_COMMAND} \\"\${CTEST_SOURCE_DIRECTORY}\\"")
+
+ ctest_start("Nightly")
+ ctest_update()
+ ctest_configure()
+ ctest_build()
+ ctest_test()
+ if (WITH_COVERAGE AND CTEST_COVERAGE_COMMAND)
+ ctest_coverage()
+ endif (WITH_COVERAGE AND CTEST_COVERAGE_COMMAND)
+ if (WITH_MEMCHECK AND CTEST_MEMORYCHECK_COMMAND)
+ ctest_memcheck()
+ endif (WITH_MEMCHECK AND CTEST_MEMORYCHECK_COMMAND)
+ ctest_submit()
+EOF
+
+ # OK, now run this test, it will submit its results.
+ ctest -S $WORKDIR/$t/CTestScript.cmake -V
+done
+
+echo "Completed Nightly tests, time: "`date`
+
+
diff --git a/contrib/nightly_tests/tests.list b/contrib/nightly_tests/tests.list
new file mode 100644
index 0000000..afd2124
--- /dev/null
+++ b/contrib/nightly_tests/tests.list
@@ -0,0 +1,12 @@
+allext
+allextdbg
+allextval
+allextret
+allextprof
+allextmax
+allextdeb
+alldefault
+nosctp
+idnaignore
+idnareject
+#noext
diff --git a/contrib/test_Gx/CMakeLists.txt b/contrib/test_Gx/CMakeLists.txt
new file mode 100644
index 0000000..c9b0283
--- /dev/null
+++ b/contrib/test_Gx/CMakeLists.txt
@@ -0,0 +1,13 @@
+# The dict_nasreq extension
+PROJECT("Gx Interface for freediameter" C)
+
+# Compile as a module
+FD_ADD_EXTENSION(app_gx main_gx.c)
+
+
+####
+## INSTALL section ##
+
+INSTALL(TARGETS app_gx
+ LIBRARY DESTINATION ${INSTALL_EXTENSIONS_SUFFIX}
+ COMPONENT freeDiameter-rx-interface)
diff --git a/contrib/test_Gx/main_gx.c b/contrib/test_Gx/main_gx.c
new file mode 100644
index 0000000..7811661
--- /dev/null
+++ b/contrib/test_Gx/main_gx.c
@@ -0,0 +1,819 @@
+/****************
+ Contributed by: Krishnan Srinivasan <hsirk_6@yahoo.com>
+ License: to be specified.
+ TODO:
+
+ ****************/
+
+
+#include <freeDiameter/extension.h>
+#include <signal.h>
+#include <time.h>
+#define AUTH_APP_ID 16777238
+#define VENDOR_ID_3GPP 10415
+/* The content of this file follows the same structure as dict_base_proto.c */
+
+#if 0
+#define CHECK_dict_new( _type, _data, _parent, _ref ) \
+ CHECK_FCT( fd_dict_new( fd_g_config->cnf_dict, (_type), (_data), (_parent), (_ref)) );
+#endif
+
+void dump_sess_eyec(struct session *sess, const char *);
+
+static int ccr_cb( struct msg ** msg, struct avp * avp, struct session * sess, void * opaque, enum disp_action * act);
+static int reauth_cb( struct msg ** msg, struct avp * avp, struct session * sess, void * opaque, enum disp_action * act);
+static int cca_cb( struct msg ** msg, struct avp * avp, struct session * sess, void * opaque, enum disp_action * act);
+static struct disp_hdl * ccr_cb_hdl = NULL; /* handler for ccr req cb */
+static struct disp_hdl * cca_cb_hdl = NULL; /* handler for cca req cb */
+static struct disp_hdl * reauth_cb_hdl = NULL; /* handler for cca req cb */
+
+struct dict_object *ccr_cmd = NULL;
+struct dict_object *cca_cmd = NULL;
+struct dict_object *dataobj_re_auth_request_type = NULL;
+struct dict_object * origin_host = NULL;
+struct dict_object * origin_realm = NULL;
+struct dict_object * dest_host = NULL;
+struct dict_object * dest_realm = NULL;
+struct dict_object *reauth_cmd = NULL;
+struct dict_object * auth_app_id = NULL;
+struct dict_object * service_cxt_id = NULL ;
+struct dict_object * cc_req_type = NULL;
+struct dict_object * cc_req_num = NULL;
+struct dict_object * bearer_usage = NULL;
+struct dict_object * pflt_oper = NULL;
+struct dict_object * pflt_info = NULL;
+struct dict_object * pflt_id = NULL;
+struct dict_object * gx_inf;
+struct dict_object * term_cause = NULL;
+
+struct session *g_sess = NULL;
+struct session_handler *g_hdlr = NULL;
+
+enum gx_state {
+ STATE_INIT = 0,
+ STATE_INTERMEDIATE ,
+ STATE_FINAL
+};
+struct gx_sm_t {
+ enum gx_state state;
+ pthread_t tid;
+ struct fifo *events;
+ pthread_mutex_t p_sm_mtx;
+ int req_num;
+ struct session *sess;
+} g_gx_sm;
+
+int snd_ccr_msg(struct gx_sm_t **gx_sm , struct dict_object *cmd_r ) ;
+
+void sig_hdlr(void);
+
+void *gx_sm_th(void *sm);
+#define press_key_continue() { printf("%s %d\n", __FUNCTION__, __LINE__);}
+static int app_gx_entry(char * conffile)
+{
+// TRACE_ENTRY("%p", conffile);
+ {
+ application_id_t dcca_id = AUTH_APP_ID;
+ application_id_t ccr_id = 272;
+ application_id_t cca_id = 272;
+ application_id_t reauth_id = 258;
+ CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_APPLICATION, APPLICATION_BY_ID, &dcca_id, &gx_inf, ENOENT));
+ CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_COMMAND, CMD_BY_CODE_R, &ccr_id, &ccr_cmd, ENOENT));
+ CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_COMMAND, CMD_BY_CODE_A, &cca_id, &cca_cmd, ENOENT));
+ // CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_COMMAND, CMD_BY_CODE_R, &reauth_id, &reauth_cmd, ENOENT));
+
+ }
+
+ /* Applications section */
+#if 0
+ {
+ // Gx interface
+ {
+ struct dict_application_data data = { AUTH_APP_ID, "3GPP-Gx Application" };
+ CHECK_dict_new( DICT_APPLICATION, &data, NULL, &gx_inf);
+
+ }
+
+ }
+#endif
+
+
+ // Do registeration and init stuff
+ {
+ struct disp_when data;
+
+ TRACE_DEBUG(FULL, "Initializing dispatch callbacks for Gx interface");
+
+ memset(&data, 0, sizeof(data));
+ data.app = gx_inf;
+ data.command = ccr_cmd;
+ /* Now specific handler for CCR-CMD */
+ CHECK_FCT( fd_disp_register( ccr_cb, DISP_HOW_CC, &data, NULL, &ccr_cb_hdl ) );
+
+
+ memset(&data, 0, sizeof(data));
+ data.app = gx_inf;
+ data.command = cca_cmd;
+
+ CHECK_FCT( fd_disp_register( cca_cb, DISP_HOW_CC, &data, NULL, &cca_cb_hdl ) );
+
+#ifdef REAUTH
+ CHECK_FCT(fd_dict_search(fd_g_config->cnf_dict, DICT_COMMAND, CMD_BY_NAME,
+ "Re-Auth-Request", &reauth_cmd, ENOENT));
+ memset(&data, 0, sizeof(data));
+ data.app = gx_inf;
+ data.command = reauth_cmd;
+ printf("register REAUTH\n");
+ CHECK_FCT( fd_disp_register( reauth_cb, DISP_HOW_CC, &data, NULL, &reauth_cb_hdl ) );
+#endif
+
+
+ }
+
+
+ CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict,
+ DICT_AVP, AVP_BY_NAME,
+ "Origin-Host",
+ &origin_host,
+ ENOENT) );
+
+ CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict,
+ DICT_AVP,
+ AVP_BY_NAME,
+ "Origin-Realm",
+ &origin_realm,
+ ENOENT) );
+
+ CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict,
+ DICT_AVP,
+ AVP_BY_NAME,
+ "Destination-Host",
+ &dest_host,
+ ENOENT) );
+
+ CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict,
+ DICT_AVP,
+ AVP_BY_NAME,
+ "Destination-Realm",
+ &dest_realm,
+ ENOENT) );
+
+
+ CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict,
+ DICT_AVP,
+ AVP_BY_NAME,
+ "Auth-Application-Id",
+ &auth_app_id,
+ ENOENT) );
+
+
+ CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict,
+ DICT_AVP,
+ AVP_BY_NAME,
+ "Service-Context-Id",
+ &service_cxt_id,
+ ENOENT) );
+
+ CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict,
+ DICT_AVP,
+ AVP_BY_NAME,
+ "CC-Request-Type",
+ &cc_req_type,
+ ENOENT) );
+
+ CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict,
+ DICT_AVP,
+ AVP_BY_NAME,
+ "Termination-Cause",
+ &term_cause,
+ ENOENT) );
+
+ CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict,
+ DICT_AVP,
+ AVP_BY_NAME,
+ "CC-Request-Number",
+ &cc_req_num,
+ ENOENT) );
+ {
+ struct dict_avp_request req = { VENDOR_ID_3GPP, 0, "Bearer-Usage"};
+
+ CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict,
+ DICT_AVP,
+ AVP_BY_NAME_AND_VENDOR,
+ &req,
+ &bearer_usage,
+ ENOENT) );
+ }
+ {
+ struct dict_avp_request req = { VENDOR_ID_3GPP, 0, "Packet-Filter-Operation"};
+
+ CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict,
+ DICT_AVP,
+ AVP_BY_NAME_AND_VENDOR,
+ &req,
+ &pflt_oper,
+ ENOENT) );
+ }
+ {
+ struct dict_avp_request req = { VENDOR_ID_3GPP, 0, "Packet-Filter-Information"};
+
+ CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict,
+ DICT_AVP,
+ AVP_BY_NAME_AND_VENDOR,
+ &req,
+ &pflt_info,
+ ENOENT) );
+ }
+ {
+ struct dict_avp_request req = { VENDOR_ID_3GPP, 0, "Packet-Filter-Identifier"};
+
+ CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict,
+ DICT_AVP,
+ AVP_BY_NAME_AND_VENDOR,
+ &req,
+ &pflt_id,
+ ENOENT) );
+ }
+
+ CHECK_FCT(fd_sess_handler_create( &g_hdlr, free, NULL));
+ CHECK_FCT( fd_fifo_new(&g_gx_sm.events));
+ CHECK_FCT( fd_disp_app_support( gx_inf, NULL, 1 , 0));
+
+ CHECK_FCT( fd_event_trig_regcb(SIGUSR1, "app_gx", sig_hdlr ) );
+
+
+ TRACE_DEBUG(INFO, "Extension 'Gx' initialized");
+ return 0;
+}
+
+void * gx_sm_th(void *sm)
+{
+ struct gx_sm_t *gx_sm = (struct gx_sm_t *) sm;
+ struct timespec tout;
+ int evt_code;
+
+ CHECK_SYS_DO( clock_gettime( CLOCK_REALTIME, &tout), goto out);
+ tout.tv_sec =+ 60 ;
+
+ while(1) {
+
+ fd_event_timedget(gx_sm->events, &tout , ETIMEDOUT, &evt_code, NULL, NULL );
+ CHECK_SYS_DO( clock_gettime( CLOCK_REALTIME, &tout), goto out);
+ printf("in tout sec %d\n", tout.tv_sec);
+ if(evt_code == ETIMEDOUT) {
+
+ snd_ccr_msg(&gx_sm, ccr_cmd);
+ gx_sm->req_num++ ;
+ gx_sm->state = STATE_INTERMEDIATE;
+ CHECK_SYS_DO( clock_gettime( CLOCK_REALTIME, &tout), goto out);
+ tout.tv_sec += 30 ;
+
+ }
+ // printf("press enter\n");
+ // getchar();
+ }
+
+ out:
+ return NULL;
+}
+//TBD
+int init_gx_sm(struct gx_sm_t *sm)
+{
+ sm->state = STATE_INIT;
+ sm->tid = 0;//
+ sm->events = NULL;
+ pthread_mutex_t p_sm_mtx;
+ sm->req_num = 0;
+ sm->sess = NULL;
+
+return 0;
+}
+int free_gx_sm(struct gx_sm_t *sm)
+{
+
+ free(sm);
+}
+struct gx_sm_t *gl_gx_sm = NULL;
+
+void sig_hdlr()
+{
+struct gx_sm_t *gx_sm = gl_gx_sm;
+
+ if( gx_sm) {
+
+ fd_sess_dump( 0 , g_gx_sm.sess);
+
+ } else {
+
+ if(gx_sm= (struct gx_sm_t *)malloc(sizeof(struct gx_sm_t))) {
+ init_gx_sm(gx_sm);
+ }
+ gl_gx_sm = gx_sm;
+ }
+
+ snd_ccr_msg( &gx_sm, ccr_cmd);
+ return;
+}
+
+static void cr_cb_ans(void *data, struct msg **msg)
+{
+ printf("call back \n");
+ return;
+}
+
+/* < Session-Id >
+ { Origin-Host }
+ { Origin-Realm }
+ { Destination-Realm }
+ { Auth-Application-Id }
+ { Service-Context-Id }
+ { CC-Request-Type }
+ { CC-Request-Number }
+*/
+
+int snd_ccr_msg(struct gx_sm_t **sm , struct dict_object *cmd_r )
+{
+ struct msg * req = NULL;
+ struct avp * avp = NULL;
+ union avp_value val;
+ struct ta_mess_info * mi = NULL, *svg;
+ struct session *sess = NULL;
+ struct gx_sm_t *gx_sm = NULL;
+ struct gx_sm_t *ptr = NULL;
+
+ TRACE_DEBUG(FULL, "Creating a new CCR message for sending. %p", gx_sm);
+
+ /* Create the request from template */
+ CHECK_FCT_DO( fd_msg_new( cmd_r, MSGFL_ALLOC_ETEID, &req ), goto out );
+
+ gx_sm = *sm;
+ /* Create a new session */
+ if(!gx_sm->sess) {
+
+ CHECK_FCT_DO( fd_sess_new( &sess,
+ fd_g_config->cnf_diamid,
+ fd_g_config->cnf_diamid_len,
+ "CCR_SESSION", strlen("CCR_SESSION") ), goto out );
+
+ printf("statemachine: %p %p %p\n", *(&gx_sm), gx_sm , *sm);
+ gx_sm->sess = sess;
+ printf("new session %p \n", sess);
+ //Hold the session till terminate happens
+ CHECK_FCT( fd_sess_ref_msg(sess) );
+
+ } else {
+
+ sess = gx_sm->sess;
+ printf("use previous session %p \n", sess);
+
+ }
+
+ fd_sess_dump( 0 , sess);
+
+
+// dump_sess_eyec( sess, __FUNCTION__);
+ /* Now set all AVPs values */
+
+ /* Session-Id */
+ {
+ os0_t sid;
+ size_t sidlen;
+ struct dict_object *sess_id = NULL;
+
+ CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict
+ , DICT_AVP, AVP_BY_NAME
+ , "Session-Id"
+ , &sess_id, ENOENT) );
+
+ CHECK_FCT_DO( fd_sess_getsid ( sess, &sid, &sidlen ), goto out );
+ CHECK_FCT_DO( fd_msg_avp_new ( sess_id, 0, &avp ), goto out );
+ val.os.data = sid;
+ val.os.len = sidlen;
+ CHECK_FCT_DO( fd_msg_avp_setvalue( avp, &val ), goto out );
+ CHECK_FCT_DO( fd_msg_avp_add( req, MSG_BRW_FIRST_CHILD, avp ), goto out );
+ }
+
+ /* Set the Destination-Realm AVP */
+ {
+ CHECK_FCT_DO( fd_msg_avp_new ( dest_realm, 0, &avp ), goto out );
+ val.os.data = (unsigned char *)("vm");
+ val.os.len = strlen("vm");
+ CHECK_FCT_DO( fd_msg_avp_setvalue( avp, &val ), goto out );
+ CHECK_FCT_DO( fd_msg_avp_add( req, MSG_BRW_LAST_CHILD, avp ), goto out );
+ }
+
+
+ /* Set the Destination-Host AVP if needed*/
+ {
+ CHECK_FCT_DO( fd_msg_avp_new ( dest_host, 0, &avp ), goto out );
+ val.os.data = (unsigned char *)("192.168.101.3");
+ val.os.len = strlen("192.168.101.3");
+ CHECK_FCT_DO( fd_msg_avp_setvalue( avp, &val ), goto out );
+ CHECK_FCT_DO( fd_msg_avp_add( req, MSG_BRW_LAST_CHILD, avp ), goto out );
+ }
+
+
+ /* Set Origin-Host & Origin-Realm */
+ CHECK_FCT_DO( fd_msg_add_origin ( req, 0 ), goto out );
+
+
+ /* Set Auth-Application ID */
+ {
+ CHECK_FCT_DO( fd_msg_avp_new ( auth_app_id, 0, &avp ), goto out );
+ val.i32 = AUTH_APP_ID; // Auth-App id is 4 for CCR
+ CHECK_FCT_DO( fd_msg_avp_setvalue( avp, &val ), goto out );
+ CHECK_FCT_DO( fd_msg_avp_add( req, MSG_BRW_LAST_CHILD, avp ), goto out );
+ }
+
+ /* Set Service Context ID */
+ {
+
+ CHECK_FCT_DO( fd_msg_avp_new ( service_cxt_id, 0, &avp ), goto out );
+ val.os.data = (unsigned char *)("test@tst");
+ CHECK_FCT_DO( fd_msg_avp_setvalue( avp, &val ), goto out );
+ CHECK_FCT_DO( fd_msg_avp_add( req, MSG_BRW_LAST_CHILD, avp ), goto out );
+
+ }
+
+ /* Set Request Type */
+ {
+#define CCR_INIT_REQUEST 1
+#define CCR_UPDATE_REQUEST 2
+#define CCR_TERMINATION_REQUEST 3
+#define CCR_EVENT_REQUEST 4
+//TODO Change this to use enum object
+ CHECK_FCT_DO( fd_msg_avp_new ( cc_req_type, 0, &avp ), goto out );
+ if(gx_sm->state == STATE_INIT)
+ val.i32 = CCR_INIT_REQUEST;
+ else if(gx_sm->state == STATE_FINAL)
+ val.i32 = CCR_TERMINATION_REQUEST;
+ else
+ val.i32 = CCR_UPDATE_REQUEST;
+
+ CHECK_FCT_DO( fd_msg_avp_setvalue( avp, &val ), goto out );
+ CHECK_FCT_DO( fd_msg_avp_add( req, MSG_BRW_LAST_CHILD, avp ), goto out );
+
+ }
+
+ /* Set Request Number */
+ {
+ CHECK_FCT_DO( fd_msg_avp_new ( cc_req_num, 0, &avp ), goto out );
+ val.i32 = gx_sm->req_num;
+ CHECK_FCT_DO( fd_msg_avp_setvalue( avp, &val ), goto out );
+ CHECK_FCT_DO( fd_msg_avp_add( req, MSG_BRW_LAST_CHILD, avp ), goto out );
+ gx_sm->req_num++;
+ }
+
+ switch(gx_sm->state) {
+
+ case STATE_INIT:
+
+ {
+ //Set Bearer-Usage
+ //TODO Change this to use enum object
+ CHECK_FCT_DO( fd_msg_avp_new ( bearer_usage, 0, &avp ), goto out );
+ val.i32 = 1;//IMS
+ CHECK_FCT_DO( fd_msg_avp_setvalue( avp, &val ), goto out );
+ CHECK_FCT_DO( fd_msg_avp_add( req, MSG_BRW_LAST_CHILD, avp ), goto out );
+ }
+ {
+ //Set Packet Filter Operation
+ //TODO Change this to use enum object
+ CHECK_FCT_DO( fd_msg_avp_new ( pflt_oper, 0, &avp ), goto out );
+ val.i32 = 1;//ADDITION
+ CHECK_FCT_DO( fd_msg_avp_setvalue( avp, &val ), goto out );
+ CHECK_FCT_DO( fd_msg_avp_add( req, MSG_BRW_LAST_CHILD, avp ), goto out );
+ }
+ struct avp *flt_info = NULL;
+ {
+ //Set Packet Filter Information
+ CHECK_FCT_DO( fd_msg_avp_new ( pflt_info, 0, &flt_info ), goto out );
+
+
+ CHECK_FCT_DO( fd_msg_avp_add( req, MSG_BRW_LAST_CHILD, flt_info ), goto out );
+ }
+ // Set Packet Filter Identity
+ {
+
+ CHECK_FCT_DO( fd_msg_avp_new ( pflt_id, 0, &avp ), goto out );
+ val.os.data = (unsigned char *)("ID");
+ val.os.len = strlen("ID");
+ CHECK_FCT_DO( fd_msg_avp_setvalue( avp, &val ), goto out );
+ if(flt_info) {
+ CHECK_FCT_DO( fd_msg_avp_add( flt_info, MSG_BRW_LAST_CHILD, avp ), goto out );
+ }else {
+ printf("flt_info NULL\n");
+ }
+
+ }
+ CHECK_FCT(fd_sess_state_store(g_hdlr, sess, &gx_sm));
+
+ break;
+ case STATE_FINAL:
+ {
+ //Set Packet Filter Operation
+ //TODO Change this to use enum object
+ CHECK_FCT_DO( fd_msg_avp_new ( term_cause, 0, &avp ), goto out );
+ val.i32 = 1;//Diameter logout
+ CHECK_FCT_DO( fd_msg_avp_setvalue( avp, &val ), goto out );
+ CHECK_FCT_DO( fd_msg_avp_add( req, MSG_BRW_LAST_CHILD, avp ), goto out );
+ }
+ break;
+ default:
+ printf("State mismatch \n");
+ }
+ fflush(stderr);
+
+ /* Send the request */
+ printf("CCA %p\n",req);
+// Everthing Done Store the state: reply should retreive it
+ CHECK_FCT_DO( fd_msg_send( &req, NULL, NULL ), goto out );
+
+out:
+ return;
+}
+
+
+static int reauth_cb( struct msg ** msg, struct avp * avp, struct session * sess, void * opaque, enum disp_action * act)
+{
+ struct msg *ans, *qry;
+ struct avp * a;
+
+ TRACE_ENTRY("%p %p %p %p", msg, avp, sess, act);
+
+ if (msg == NULL)
+ return EINVAL;
+
+
+ /* Create answer header */
+ qry = *msg;
+ CHECK_FCT( fd_msg_new_answer_from_req ( fd_g_config->cnf_dict, msg, 0 ) );
+ ans = *msg;
+
+ /* Set the Origin-Host, Origin-Realm, Result-Code AVPs */
+ CHECK_FCT( fd_msg_rescode_set( ans, "DIAMETER_SUCCESS", NULL, NULL, 1 ) );
+
+ /* Send the answer */
+ CHECK_FCT( fd_msg_send( msg, NULL, NULL ) );
+
+
+
+}
+static int dcca_ans_from_req( struct dict_object * obj, struct msg *qry, struct msg **msg)
+{
+ struct avp *avp = NULL;
+ struct avp_hdr * avpdata;
+ int rc = -1;
+
+ CHECK_FCT(fd_msg_search_avp( qry, obj, &avp));
+ CHECK_FCT(fd_msg_avp_hdr(avp, &avpdata));
+ avp = NULL;
+
+ CHECK_FCT_DO( fd_msg_avp_new ( obj, 0, &avp ), goto out );
+ CHECK_FCT_DO( fd_msg_avp_setvalue( avp, avpdata->avp_value ), goto out );
+ CHECK_FCT_DO( fd_msg_avp_add( *msg, MSG_BRW_LAST_CHILD, avp ), goto out );
+
+ rc = 0;
+out:
+ return rc;
+
+}
+/* Dummy ccr which :
+ Read the cc-req-type && cc-req-number from the msg and stick it back
+ in the reply
+
+*/
+static int ccr_cb( struct msg ** msg, struct avp * r_avp, struct session * sess, void * opaque, enum disp_action * act)
+{
+ struct msg *ans, *qry;
+ struct avp *avp = NULL;
+ struct avp_hdr * avp_data;
+ int rc = - 1;
+
+ TRACE_ENTRY("%p %p %p %p", msg, r_avp, sess, act);
+
+ if (msg == NULL)
+ return EINVAL;
+
+
+ /* Create answer header */
+ qry = *msg;
+ CHECK_FCT_DO( fd_msg_new_answer_from_req ( fd_g_config->cnf_dict, msg, 0 ) , goto out);
+ ans = *msg;
+
+ /* Set the Origin-Host, Origin-Realm, Result-Code AVPs */
+ CHECK_FCT_DO( fd_msg_rescode_set( ans, "DIAMETER_SUCCESS", NULL, NULL, 1 ), goto out );
+
+// Get the auth_app_id and from the reply and set it in the reply
+ CHECK_FCT_DO(dcca_ans_from_req( auth_app_id, qry, msg), goto out);
+ CHECK_FCT_DO(dcca_ans_from_req( cc_req_type, qry, msg), goto out);
+ CHECK_FCT_DO(dcca_ans_from_req( cc_req_num, qry, msg), goto out);
+
+ /* Send the answer */
+ CHECK_FCT_DO( fd_msg_send( msg, NULL, NULL ), goto out );
+ rc = 0;
+ out:
+ //Free up the memory
+ return rc ;
+
+}
+int send_reauth_req()
+
+{
+ struct dict_application_data appdata;
+ struct avp *avp = NULL;
+ union avp_value val ;
+ struct msg *qry, *ans = NULL;
+ struct msg *req = NULL;
+ struct msg *tst = NULL;
+ struct dict_object * auth_app_id = NULL, *reauth_req_type = NULL;
+
+// qry = *msg;
+
+
+ { // Send new reauth request
+
+ CHECK_FCT_DO( fd_msg_new( reauth_cmd, MSGFL_ALLOC_ETEID, &req ), goto out );
+ CHECK_FCT( fd_dict_getval(gx_inf, &appdata) );
+
+ struct msg_hdr * header = NULL;
+ CHECK_FCT( fd_msg_hdr ( req, &header ) );
+ header->msg_appl = appdata.application_id;
+
+ }
+
+ /* Session-Id */
+ {
+ os0_t sid;
+ size_t sidlen;
+ struct dict_object *sess_id = NULL;
+ CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Session-Id", &sess_id, ENOENT) );
+
+ //CHECK_FCT_DO( fd_sess_getsid ( sess, &sid, &sidlen ), goto out );
+ CHECK_FCT_DO( fd_msg_avp_new ( sess_id, 0, &avp ), goto out );
+ val.os.data = sid;
+ val.os.len = sidlen;
+ CHECK_FCT_DO( fd_msg_avp_setvalue( avp, &val ), goto out );
+ CHECK_FCT_DO( fd_msg_avp_add( req, MSG_BRW_FIRST_CHILD, avp ), goto out );
+
+ }
+
+ /* Set the Destination-Realm AVP */
+ {
+ CHECK_FCT_DO( fd_msg_avp_new ( dest_realm, 0, &avp ), goto out );
+ val.os.data = (unsigned char *)("vm");
+ val.os.len = strlen("vm");
+ CHECK_FCT_DO( fd_msg_avp_setvalue( avp, &val ), goto out );
+ CHECK_FCT_DO( fd_msg_avp_add( req, MSG_BRW_LAST_CHILD, avp ), goto out );
+ }
+
+ /* Set the Destination-Host AVP if needed*/
+// if (ta_conf->dest_host) {
+ CHECK_FCT_DO( fd_msg_avp_new ( dest_host, 0, &avp ), goto out );
+ val.os.data = (unsigned char *)("cli.vm");
+ val.os.len = strlen("cli.vm");
+ CHECK_FCT_DO( fd_msg_avp_setvalue( avp, &val ), goto out );
+ CHECK_FCT_DO( fd_msg_avp_add( req, MSG_BRW_LAST_CHILD, avp ), goto out );
+// }
+
+ /* Set Origin-Host & Origin-Realm */
+ CHECK_FCT_DO( fd_msg_add_origin ( req, 0 ), goto out );
+
+ /* AUTH_Application-ID */
+ CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Auth-Application-Id", &auth_app_id, ENOENT) );
+ CHECK_FCT_DO( fd_msg_avp_new ( auth_app_id, 0, &avp ), goto out );
+ val.i32 = appdata.application_id;
+ CHECK_FCT_DO( fd_msg_avp_setvalue( avp, &val ), goto out );
+ CHECK_FCT_DO( fd_msg_avp_add( req, MSG_BRW_LAST_CHILD, avp ), goto out );
+
+ /* Re-Auth Request Type */
+ CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Re-Auth-Request-Type", &reauth_req_type, ENOENT) );
+ CHECK_FCT_DO( fd_msg_avp_new ( reauth_req_type, 0, &avp ), goto out );
+ val.i32 = 0;
+ CHECK_FCT_DO( fd_msg_avp_setvalue( avp, &val ), goto out );
+ CHECK_FCT_DO( fd_msg_avp_add( req, MSG_BRW_LAST_CHILD, avp ), goto out );
+
+
+ CHECK_FCT_DO( fd_msg_send( &req, cr_cb_ans, NULL ), goto out );
+out:
+ return 0 ;
+
+
+}
+/* Search a given AVP model in an AVP (extracted from libfreediameter/message.c ) */
+int fd_avp_search_avp ( struct avp * groupedavp, struct dict_object * what, struct avp ** avp )
+{
+ struct avp * nextavp;
+ struct avp_hdr * nextavphdr;
+ struct dict_avp_data dictdata;
+
+
+ TRACE_ENTRY("%p %p %p", groupedavp, what, avp);
+
+ CHECK_FCT( fd_dict_getval(what, &dictdata) );
+
+ // Loop only in the group AVP
+ CHECK_FCT( fd_msg_browse(groupedavp, MSG_BRW_FIRST_CHILD, (void *)&nextavp, NULL) );
+ CHECK_FCT( fd_msg_avp_hdr( nextavp, &nextavphdr ) );
+
+ while (nextavphdr) {
+
+ if ( (nextavphdr->avp_code == dictdata.avp_code) && (nextavphdr->avp_vendor == dictdata.avp_vendor) ) // always 0 if no Vendor flag
+ {
+ break;
+ }
+
+ // Otherwise move to next AVP in the grouped AVP
+ CHECK_FCT( fd_msg_browse(nextavp, MSG_BRW_NEXT, (void *)&nextavp, NULL) );
+
+ if(nextavp!=NULL)
+ {
+ CHECK_FCT( fd_msg_avp_hdr( nextavp, &nextavphdr ) );
+ }
+ else
+ nextavphdr=NULL;
+ }
+ if (avp)
+ *avp = nextavp;
+
+ if (avp && nextavp) {
+ struct dictionary * dict;
+ CHECK_FCT( fd_dict_getdict( what, &dict) );
+ CHECK_FCT_DO( fd_msg_parse_dict( nextavp, dict, NULL ), );
+ }
+
+ if (avp || nextavp)
+ return 0;
+ else
+ return ENOENT;
+}
+
+static int cca_cb( struct msg ** msg,
+ struct avp * t_avp ,
+ struct session * sess,
+ void * opaque,
+ enum disp_action * act)
+{
+ struct avp *avp = NULL, *g_avp = NULL;
+ struct msg *req = *msg;
+ struct dict_object *chrg_rule_name = NULL ;
+ struct dict_object *chrg_rule_grp = NULL ;
+ struct avp_hdr * avpdata = NULL;
+ struct dict_avp_request grule_req = {VENDOR_ID_3GPP, 0,"Charging-Rule-Install"};
+ struct dict_avp_request rule_req = {VENDOR_ID_3GPP, 0,"Charging-Rule-Name"};
+ struct timespec sess_timeout;
+ struct gx_sm_t *gx_sm = NULL;
+ // struct session *sess = NULL;
+
+
+ CHECK_FCT(fd_sess_state_retrieve( g_hdlr, sess, &gx_sm));
+ fd_sess_dump( 0, sess);
+ if(gx_sm->state != STATE_FINAL) {
+
+ CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict
+ , DICT_AVP, AVP_BY_NAME_AND_VENDOR
+ , &grule_req
+ , &chrg_rule_grp
+ , ENOENT));
+
+ CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict
+ , DICT_AVP, AVP_BY_NAME_AND_VENDOR
+ , &rule_req
+ , &chrg_rule_name
+ , ENOENT));
+
+
+ CHECK_FCT(fd_msg_search_avp ( *msg, chrg_rule_grp, &g_avp ));
+ CHECK_FCT(fd_avp_search_avp(g_avp, chrg_rule_name, &avp));
+
+ if(avp) {
+ CHECK_FCT(fd_msg_avp_hdr(avp, &avpdata));
+ } else {
+ printf("NULL AVP \n");
+ }
+ printf("charging-rule-name %s\n", avpdata->avp_value->os.data);
+ gx_sm->state = STATE_FINAL;
+ dump_sess_eyec( sess, __FUNCTION__);
+ printf("next dump\n");
+ CHECK_FCT(fd_sess_state_store( g_hdlr, sess, &gx_sm));
+ fd_msg_free(*msg);
+ *msg = NULL;
+
+ } else {
+ printf("Session terminated\n");
+ free_gx_sm(gx_sm);
+ fd_msg_free(*msg);
+ fd_sess_reclaim(&sess);
+ *msg = NULL;
+ }
+ fd_sess_dump( 0 , sess);
+
+ return 0;
+}
+
+static int gx_entry(char * conffile)
+{
+ return 0;
+}
+EXTENSION_ENTRY( "app_gx", app_gx_entry, "dict_dcca_3gpp");
+//EXTENSION_ENTRY( "app_gx", gx_entry);
diff --git a/contrib/test_Gx/readme.txt b/contrib/test_Gx/readme.txt
new file mode 100644
index 0000000..127d517
--- /dev/null
+++ b/contrib/test_Gx/readme.txt
@@ -0,0 +1,6 @@
+This content was contributed by Krishnan Srinivasan from Allot Communication.
+
+The dictionary entries may need some adjustments to
+match the content of the dict_dcca_3gpp extension.
+
+Thank you Krishnan!
diff --git a/contrib/tools/README b/contrib/tools/README
new file mode 100644
index 0000000..bbb235d
--- /dev/null
+++ b/contrib/tools/README
@@ -0,0 +1,2 @@
+org_to_fd.pl converts org files like diameter-rfcs.org to C fragments
+that can be included in freeDiameter code.
diff --git a/contrib/tools/diameter-rfcs.org b/contrib/tools/diameter-rfcs.org
new file mode 100644
index 0000000..5d92cae
--- /dev/null
+++ b/contrib/tools/diameter-rfcs.org
@@ -0,0 +1,188 @@
+| Attribute Name | Code | Section | Data | MUST | MAY | SHLD NOT | MUST NOT | Encr |
+| # RFC 3588 - Diameter # | | | | | | | | |
+| Acct-Interim-Interval | 85 | 9.8.2 | Unsigned32 | M | P | | V | Y |
+| Accounting-Realtime-Required | 483 | 9.8.7 | Enumerated | M | P | | V | Y |
+| Acct-Multi-Session-Id | 50 | 9.8.5 | UTF8String | M | P | | V | Y |
+| Accounting-Record-Number | 485 | 9.8.3 | Unsigned32 | M | P | | V | Y |
+| Accounting-Record-Type | 480 | 9.8.1 | Enumerated | M | P | | V | Y |
+| Accounting-Session-Id | 44 | 9.8.4 | OctetString | M | P | | V | Y |
+| Accounting-Sub-Session-Id | 287 | 9.8.6 | Unsigned64 | M | P | | V | Y |
+| Acct-Application-Id | 259 | 6.9 | Unsigned32 | M | P | | V | N |
+| Auth-Application-Id | 258 | 6.8 | Unsigned32 | M | P | | V | N |
+| Auth-Request-Type | 274 | 8.7 | Enumerated | M | P | | V | N |
+| Authorization-Lifetime | 291 | 8.9 | Unsigned32 | M | P | | V | N |
+| Auth-Grace-Period | 276 | 8.10 | Unsigned32 | M | P | | V | N |
+| Auth-Session-State | 277 | 8.11 | Enumerated | M | P | | V | N |
+| Re-Auth-Request-Type | 285 | 8.12 | Enumerated | M | P | | V | N |
+| Class | 25 | 8.20 | OctetString | M | P | | V | Y |
+| Destination-Host | 293 | 6.5 | DiamIdent | M | P | | V | N |
+| Destination-Realm | 283 | 6.6 | DiamIdent | M | P | | V | N |
+| Disconnect-Cause | 273 | 5.4.3 | Enumerated | M | P | | V | N |
+| E2E-Sequence-AVP | 300 | 6.15 | Grouped | M | P | | V | Y |
+| Error-Message | 281 | 7.3 | UTF8String | | P | | V,M | N |
+| Error-Reporting-Host | 294 | 7.4 | DiamIdent | | P | | V,M | N |
+| Event-Timestamp | 55 | 8.21 | Time | M | P | | V | N |
+| Experimental-Result | 297 | 7.6 | Grouped | M | P | | V | N |
+| Experimental-Result-Code | 298 | 7.7 | Unsigned32 | M | P | | V | N |
+| Failed-AVP | 279 | 7.5 | Grouped | M | P | | V | N |
+| Firmware-Revision | 267 | 5.3.4 | Unsigned32 | | | | P,V,M | N |
+| Host-IP-Address | 257 | 5.3.5 | Address | M | P | | V | N |
+| Inband-Security-Id | 299 | 6.10 | Unsigned32 | M | P | | V | N |
+| Multi-Round-Time-Out | 272 | 8.19 | Unsigned32 | M | P | | V | Y |
+| Origin-Host | 264 | 6.3 | DiamIdent | M | P | | V | N |
+| Origin-Realm | 296 | 6.4 | DiamIdent | M | P | | V | N |
+| Origin-State-Id | 278 | 8.16 | Unsigned32 | M | P | | V | N |
+| Product-Name | 269 | 5.3.7 | UTF8String | | | | P,V,M | N |
+| Proxy-Host | 280 | 6.7.3 | DiamIdent | M | | | P,V | N |
+| Proxy-Info | 284 | 6.7.2 | Grouped | M | | | P,V | N |
+| Proxy-State | 33 | 6.7.4 | OctetString | M | | | P,V | N |
+| Redirect-Host | 292 | 6.12 | DiamURI | M | P | | V | N |
+| Redirect-Host-Usage | 261 | 6.13 | Enumerated | M | P | | V | N |
+| Redirect-Max-Cache-Time | 262 | 6.14 | Unsigned32 | M | P | | V | N |
+| Result-Code | 268 | 7.1 | Unsigned32 | M | P | | V | N |
+| Route-Record | 282 | 6.7.1 | DiamIdent | M | | | P,V | N |
+| Session-Id | 263 | 8.8 | UTF8String | M | P | | V | Y |
+| Session-Timeout | 27 | 8.13 | Unsigned32 | M | P | | V | N |
+| Session-Binding | 270 | 8.17 | Unsigned32 | M | P | | V | Y |
+| Session-Server-Failover | 271 | 8.18 | Enumerated | M | P | | V | Y |
+| Supported-Vendor-Id | 265 | 5.3.6 | Unsigned32 | M | P | | V | N |
+| Termination-Cause | 295 | 8.15 | Enumerated | M | P | | V | N |
+| User-Name | 1 | 8.14 | UTF8String | M | P | | V | Y |
+| Vendor-Id | 266 | 5.3.3 | Unsigned32 | M | P | | V | N |
+| Vendor-Specific-Application-Id | 260 | 6.11 | Grouped | M | P | | V | N |
+| # RFC 4005 - NAS # | | | | | | | | |
+| NAS-Port | 5 | 4.2 | Unsigned32 | M | P | | V | Y |
+| NAS-Port-Id | 87 | 4.3 | UTF8String | M | P | | V | Y |
+| NAS-Port-Type | 61 | 4.4 | Enumerated | M | P | | V | Y |
+| Called-Station-Id | 30 | 4.5 | UTF8String | M | P | | V | Y |
+| Calling-Station-Id | 31 | 4.6 | UTF8String | M | P | | V | Y |
+| Connect-Info | 77 | 4.7 | UTF8String | M | P | | V | Y |
+| Originating-Line-Info | 94 | 4.8 | OctetString | | M,P | | V | Y |
+| Reply-Message | 18 | 4.9 | UTF8String | M | P | | V | Y |
+| User-Password | 2 | 5.1 | OctetString | M | P | | V | Y |
+| Password-Retry | 75 | 5.2 | Unsigned32 | M | P | | V | Y |
+| Prompt | 76 | 5.3 | Enumerated | M | P | | V | Y |
+| CHAP-Auth | 402 | 5.4 | Grouped | M | P | | V | Y |
+| CHAP-Algorithm | 403 | 5.5 | Enumerated | M | P | | V | Y |
+| CHAP-Ident | 404 | 5.6 | OctetString | M | P | | V | Y |
+| CHAP-Response | 405 | 5.7 | OctetString | M | P | | V | Y |
+| CHAP-Challenge | 60 | 5.8 | OctetString | M | P | | V | Y |
+| ARAP-Password | 70 | 5.9 | OctetString | M | P | | V | Y |
+| ARAP-Challenge-Response | 84 | 5.10 | OctetString | M | P | | V | Y |
+| ARAP-Security | 73 | 5.11 | Unsigned32 | M | P | | V | Y |
+| ARAP-Security-Data | 74 | 5.12 | OctetString | M | P | | V | Y |
+| Service-Type | 6 | 6.1 | Enumerated | M | P | | V | Y |
+| Callback-Number | 19 | 6.2 | UTF8String | M | P | | V | Y |
+| Callback-Id | 20 | 6.3 | UTF8String | M | P | | V | Y |
+| Idle-Timeout | 28 | 6.4 | Unsigned32 | M | P | | V | Y |
+| Port-Limit | 62 | 6.5 | Unsigned32 | M | P | | V | Y |
+| NAS-Filter-Rule | 400 | 6.6 | IPFltrRule | M | P | | V | Y |
+| Filter-Id | 11 | 6.7 | UTF8String | M | P | | V | Y |
+| Configuration-Token | 78 | 6.8 | OctetString | M | | | P,V | |
+| QoS-Filter-Rule | 407 | 6.9 | QoSFltrRule | | | | | |
+| Framed-Protocol | 7 | 6.10.1 | Enumerated | M | P | | V | Y |
+| Framed-Routing | 10 | 6.10.2 | Enumerated | M | P | | V | Y |
+| Framed-MTU | 12 | 6.10.3 | Unsigned32 | M | P | | V | Y |
+| Framed-Compression | 13 | 6.10.4 | Enumerated | M | P | | V | Y |
+| Framed-IP-Address | 8 | 6.11.1 | OctetString | M | P | | V | Y |
+| Framed-IP-Netmask | 9 | 6.11.2 | OctetString | M | P | | V | Y |
+| Framed-Route | 22 | 6.11.3 | UTF8String | M | P | | V | Y |
+| Framed-Pool | 88 | 6.11.4 | OctetString | M | P | | V | Y |
+| Framed-Interface-Id | 96 | 6.11.5 | Unsigned64 | M | P | | V | Y |
+| Framed-IPv6-Prefix | 97 | 6.11.6 | OctetString | M | P | | V | Y |
+| Framed-IPv6-Route | 99 | 6.11.7 | UTF8String | M | P | | V | Y |
+| Framed-IPv6-Pool | 100 | 6.11.8 | OctetString | M | P | | V | Y |
+| Framed-IPX-Network | 23 | 6.12.1 | UTF8String | M | P | | V | Y |
+| Framed-Appletalk-Link | 37 | 6.13.1 | Unsigned32 | M | P | | V | Y |
+| Framed-Appletalk-Network | 38 | 6.13.2 | Unsigned32 | M | P | | V | Y |
+| Framed-Appletalk-Zone | 39 | 6.13.3 | OctetString | M | P | | V | Y |
+| ARAP-Features | 71 | 6.14.1 | OctetString | M | P | | V | Y |
+| ARAP-Zone-Access | 72 | 6.14.2 | Enumerated | M | P | | V | Y |
+| Login-IP-Host | 14 | 6.15.1 | OctetString | M | P | | V | Y |
+| Login-IPv6-Host | 98 | 6.15.2 | OctetString | M | P | | V | Y |
+| Login-Service | 15 | 6.15.3 | Enumerated | M | P | | V | Y |
+| Login-TCP-Port | 16 | 6.16.1 | Unsigned32 | M | P | | V | Y |
+| Login-LAT-Service | 34 | 6.17.1 | OctetString | M | P | | V | Y |
+| Login-LAT-Node | 35 | 6.17.2 | OctetString | M | P | | V | Y |
+| Login-LAT-Group | 36 | 6.17.3 | OctetString | M | P | | V | Y |
+| Login-LAT-Port | 63 | 6.17.4 | OctetString | M | P | | V | Y |
+| Tunneling | 401 | 7.1 | Grouped | M | P | | V | N |
+| Tunnel-Type | 64 | 7.2 | Enumerated | M | P | | V | Y |
+| Tunnel-Medium-Type | 65 | 7.3 | Enumerated | M | P | | V | Y |
+| Tunnel-Client-Endpoint | 66 | 7.4 | UTF8String | M | P | | V | Y |
+| Tunnel-Server-Endpoint | 67 | 7.5 | UTF8String | M | P | | V | Y |
+| Tunnel-Password | 69 | 7.6 | OctetString | M | P | | V | Y |
+| Tunnel-Private-Group-Id | 81 | 7.7 | OctetString | M | P | | V | Y |
+| Tunnel-Assignment-Id | 82 | 7.8 | OctetString | M | P | | V | Y |
+| Tunnel-Preference | 83 | 7.9 | Unsigned32 | M | P | | V | Y |
+| Tunnel-Client-Auth-Id | 90 | 7.10 | UTF8String | M | P | | V | Y |
+| Tunnel-Server-Auth-Id | 91 | 7.11 | UTF8String | M | P | | V | Y |
+| Accounting-Input-Octets | 363 | 8.1 | Unsigned64 | M | P | | V | Y |
+| Accounting-Output-Octets | 364 | 8.2 | Unsigned64 | M | P | | V | Y |
+| Accounting-Input-Packets | 365 | 8.3 | Unsigned64 | M | P | | V | Y |
+| Accounting-Output-Packets | 366 | 8.4 | Unsigned64 | M | P | | V | Y |
+| Acct-Session-Time | 46 | 8.5 | Unsigned32 | M | P | | V | Y |
+| Acct-Authentic | 45 | 8.6 | Enumerated | M | P | | V | Y |
+| Acounting-Auth-Method | 406 | 8.7 | Enumerated | M | P | | V | Y |
+| Acct-Delay-Time | 41 | 8.8 | Unsigned32 | M | P | | V | Y |
+| Acct-Link-Count | 51 | 8.9 | Unsigned32 | M | P | | V | Y |
+| Acct-Tunnel-Connection | 68 | 8.10 | OctetString | M | P | | V | Y |
+| Acct-Tunnel-Packets-Lost | 86 | 8.11 | Unsigned32 | M | P | | V | Y |
+| NAS-Identifier | 32 | 9.3.1 | UTF8String | M | P | | V | Y |
+| NAS-IP-Address | 4 | 9.3.2 | OctetString | M | P | | V | Y |
+| NAS-IPv6-Address | 95 | 9.3.3 | OctetString | M | P | | V | Y |
+| State | 24 | 9.3.4 | OctetString | M | P | | V | Y |
+| Termination-Cause | 295 | 9.3.5 | Enumerated | M | P | | V | Y |
+| Origin-AAA-Protocol | 408 | 9.3.6 | Enumerated | M | P | | V | Y |
+| # RFC 4006 - DCCA # | | | | | | | | |
+| CC-Correlation-Id | 411 | 8.1 | OctetString | | P,M | | V | Y |
+| CC-Input-Octets | 412 | 8.24 | Unsigned64 | M | P | | V | Y |
+| CC-Money | 413 | 8.22 | Grouped | M | P | | V | Y |
+| CC-Output-Octets | 414 | 8.25 | Unsigned64 | M | P | | V | Y |
+| CC-Request-Number | 415 | 8.2 | Unsigned32 | M | P | | V | Y |
+| CC-Request-Type | 416 | 8.3 | Enumerated | M | P | | V | Y |
+| CC-Service-Specific-Units | 417 | 8.26 | Unsigned64 | M | P | | V | Y |
+| CC-Session-Failover | 418 | 8.4 | Enumerated | M | P | | V | Y |
+| CC-Sub-Session-Id | 419 | 8.5 | Unsigned64 | M | P | | V | Y |
+| CC-Time | 420 | 8.21 | Unsigned32 | M | P | | V | Y |
+| CC-Total-Octets | 421 | 8.23 | Unsigned64 | M | P | | V | Y |
+| CC-Unit-Type | 454 | 8.32 | Enumerated | M | P | | V | Y |
+| Check-Balance-Result | 422 | 8.6 | Enumerated | M | P | | V | Y |
+| Cost-Information | 423 | 8.7 | Grouped | M | P | | V | Y |
+| Cost-Unit | 424 | 8.12 | UTF8String | M | P | | V | Y |
+| Credit-Control | 426 | 8.13 | Enumerated | M | P | | V | Y |
+| Credit-Control-Failure-Handling | 427 | 8.14 | Enumerated | M | P | | V | Y |
+| Currency-Code | 425 | 8.11 | Unsigned32 | M | P | | V | Y |
+| Direct-Debiting-Failure-Handling | 428 | 8.15 | Enumerated | M | P | | V | Y |
+| Exponent | 429 | 8.9 | Integer32 | M | P | | V | Y |
+| Final-Unit-Action | 449 | 8.35 | Enumerated | M | P | | V | Y |
+| Final-Unit-Indication | 430 | 8.34 | Grouped | M | P | | V | Y |
+| Granted-Service-Unit | 431 | 8.17 | Grouped | M | P | | V | Y |
+| G-S-U-Pool-Identifier | 453 | 8.31 | Unsigned32 | M | P | | V | Y |
+| G-S-U-Pool-Reference | 457 | 8.30 | Grouped | M | P | | V | Y |
+| Multiple-Services-Credit-Control | 456 | 8.16 | Grouped | M | P | | V | Y |
+| Multiple-Services-Indicator | 455 | 8.40 | Enumerated | M | P | | V | Y |
+| Rating-Group | 432 | 8.29 | Unsigned32 | M | P | | V | Y |
+| Redirect-Address-Type | 433 | 8.38 | Enumerated | M | P | | V | Y |
+| Redirect-Server | 434 | 8.37 | Grouped | M | P | | V | Y |
+| Redirect-Server-Address | 435 | 8.39 | UTF8String | M | P | | V | Y |
+| Requested-Action | 436 | 8.41 | Enumerated | M | P | | V | Y |
+| Requested-Service-Unit | 437 | 8.18 | Grouped | M | P | | V | Y |
+| Restriction-Filter-Rule | 438 | 8.36 | IPFiltrRule | M | P | | V | Y |
+| Service-Context-Id | 461 | 8.42 | UTF8String | M | P | | V | Y |
+| Service-Identifier | 439 | 8.28 | Unsigned32 | M | P | | V | Y |
+| Service-Parameter-Info | 440 | 8.43 | Grouped | | P,M | | V | Y |
+| Service-Parameter-Type | 441 | 8.44 | Unsigned32 | | P,M | | V | Y |
+| Service-Parameter-Value | 442 | 8.45 | OctetString | | P,M | | V | Y |
+| Subscription-Id | 443 | 8.46 | Grouped | M | P | | V | Y |
+| Subscription-Id-Data | 444 | 8.48 | UTF8String | M | P | | V | Y |
+| Subscription-Id-Type | 450 | 8.47 | Enumerated | M | P | | V | Y |
+| Tariff-Change-Usage | 452 | 8.27 | Enumerated | M | P | | V | Y |
+| Tariff-Time-Change | 451 | 8.20 | Time | M | P | | V | Y |
+| Unit-Value | 445 | 8.8 | Grouped | M | P | | V | Y |
+| Used-Service-Unit | 446 | 8.19 | Grouped | M | P | | V | Y |
+| User-Equipment-Info | 458 | 8.49 | Grouped | | P,M | | V | Y |
+| User-Equipment-Info-Type | 459 | 8.50 | Enumerated | | P,M | | V | Y |
+| User-Equipment-Info-Value | 460 | 8.51 | OctetString | | P,M | | V | Y |
+| Value-Digits | 447 | 8.10 | Integer64 | M | P | | V | Y |
+| Validity-Time | 448 | 8.33 | Unsigned32 | M | P | | V | Y |
diff --git a/contrib/tools/org_to_fd.pl b/contrib/tools/org_to_fd.pl
new file mode 100755
index 0000000..9cc0631
--- /dev/null
+++ b/contrib/tools/org_to_fd.pl
@@ -0,0 +1,96 @@
+#!/usr/bin/env perl
+use strict;
+use Getopt::Std;
+
+our ($opt_V, $opt_v);
+
+# default to 3GPP
+my ($vendor) = 10415;
+my ($vendor_name) = "3GPP";
+
+sub convert_must_to_flags($) {
+ my ($allmust) = @_;
+ my ($mustfields) = "";
+ $mustfields .= "AVP_FLAG_VENDOR |" if ($allmust =~ m/V/);
+ $mustfields .= "AVP_FLAG_MANDATORY |" if ($allmust =~ m/M/);
+ $mustfields =~ s/ \|$//;
+ return $mustfields;
+}
+
+sub base_type($) {
+ my ($type) = @_;
+
+ return "AVP_TYPE_GROUPED" if ($type =~ m/Grouped/);
+ return "AVP_TYPE_OCTETSTRING" if ($type =~ m/(Address|DiameterIdentity|DiameterURI|OctetString|IPFilterRule|Time|UTF8String)/);
+ return "AVP_TYPE_INTEGER32" if ($type =~ m/Enumerated|Integer32/);
+ return "AVP_TYPE_INTEGER64" if ($type =~ m/Integer64/);
+ return "AVP_TYPE_UNSIGNED32" if ($type =~ m/Unsigned32/);
+ return "AVP_TYPE_UNSIGNED64" if ($type =~ m/Unsigned64/);
+ return "AVP_TYPE_FLOAT32" if ($type =~ m/Float32/);
+ return "AVP_TYPE_FLOAT64" if ($type =~ m/Float64/);
+
+ return "UNKNOWN TYPE: $type";
+}
+
+sub print_insert($$) {
+ my ($type, $name) = @_;
+ my $avp_type;
+
+ if ($type =~ m/(Grouped|OctetString|Integer32|Integer64|Unsigned32|Unsigned64|Float32|Float64)/) {
+ $avp_type = "NULL";
+ } elsif ($type =~ m/Enumerated/) {
+ print "\t\tstruct dict_object *type;\n";
+ print "\t\tstruct dict_type_data tdata = { AVP_TYPE_INTEGER32, \"" . ($vendor_name ? "$vendor_name/" : "") ."Enumerated($name)\", NULL, NULL, NULL };\n";
+ # XXX: add enumerated values
+ print "\t\tCHECK_dict_new(DICT_TYPE, &tdata, NULL, &type);\n";
+ $avp_type = "type";
+ } else {
+ $avp_type = "${type}_type";
+ }
+
+ print "\t\tCHECK_dict_new(DICT_AVP, &data, $avp_type, NULL);\n";
+}
+
+sub usage($) {
+ die("usage: org_to_fd.pl [-V vendor_name -v vendor_code] [file ...]\n");
+ exit(@_);
+}
+
+getopts("V:v:") || usage(1);
+
+if (defined($opt_v)) {
+ $vendor = $opt_v;
+ if (!defined($opt_V)) {
+ usage(1);
+ }
+ $vendor_name = $opt_V;
+}
+
+print "\t/* The following is created automatically. Do not modify. */\n";
+print "\t/* Changes will be lost during the next update. Modify the source org file instead. */\n\n";
+
+while (<>) {
+ my ($dummy, $name, $code, $section, $type, $must, $may, $shouldnot, $mustnot, $encr) = split /\|/;
+
+ next if ($name =~ m/Attribute Name/);
+ if ($name =~ m/ # (.*)/) {
+ print "\t/* $1 */\n";
+ next;
+ }
+
+
+ $name =~ s/ *//g;
+ $code =~ s/ *//g;
+ $type =~ s/ *//g;
+
+ print "\t/* $name */\n\t{\n\t\tstruct dict_avp_data data = {\n";
+ print "\t\t\t$code,\t/* Code */\n";
+ print "\t\t\t$vendor,\t/* Vendor */\n";
+ print "\t\t\t\"$name\",\t/* Name */\n";
+ print "\t\t\t" . convert_must_to_flags("$must, $mustnot") . ",\t/* Fixed flags */\n";
+ print "\t\t\t" . convert_must_to_flags("$must") . ",\t/* Fixed flag values */\n";
+ print "\t\t\t" . base_type($type) . "\t/* base type of data */\n";
+ print "\t\t};\n";
+ print_insert($type, $name);
+ print "\t};\n\n";
+}
diff --git a/contrib/update_copyright.sh b/contrib/update_copyright.sh
new file mode 100755
index 0000000..64e4465
--- /dev/null
+++ b/contrib/update_copyright.sh
@@ -0,0 +1,33 @@
+#!/bin/bash -x
+
+# This script will search all copyrights dates from source files, and update these if
+# the file has been modified at a later date.
+
+if [ ! -f include/freeDiameter/libfdcore.h ];
+then echo "This script must be run from the source top directory"
+exit 1;
+fi;
+
+# Create a clean working copy
+TMPDIR=`mktemp -d up_cop.XXXXXXX` || exit 1
+hg clone . $TMPDIR/fD || exit 1
+pushd $TMPDIR/fD
+
+# Now, for each file with a copyright
+for SRC_FILE in `find . -name .hg -prune -or -type f -exec grep -q 'Copyright (c) 20.., WIDE Project and NICT' {} \; -print`;
+do
+HG_YEAR=`hg log --template '{date|shortdate}' $SRC_FILE | tr - ' ' | awk '{print \$1}'`
+CPY_YEAR=`grep 'Copyright (c) 20.., WIDE Project and NICT' $SRC_FILE | awk '{print substr(\$4, 1, 4) }'`
+if [ $HG_YEAR -gt $CPY_YEAR ];
+then
+echo "Updating copyright $CPY_YEAR -> $HG_YEAR in $SRC_FILE";
+sed -i -e "s/Copyright (c) $CPY_YEAR, WIDE Project and NICT/Copyright (c) $HG_YEAR, WIDE Project and NICT/" $SRC_FILE
+fi;
+done
+
+hg commit -m"Updated copyright information"
+hg push
+popd
+rm -rf $TMPDIR
+hg update
+
diff --git a/contrib/wireshark/HOWTO b/contrib/wireshark/HOWTO
new file mode 100644
index 0000000..d6d9123
--- /dev/null
+++ b/contrib/wireshark/HOWTO
@@ -0,0 +1,68 @@
+ --------
+ FOREWORD
+ --------
+
+The patch in this folder allows Wireshark to process packets that contain TLS-protected
+Diameter messages over SCTP multi-stream associations. Each SCTP stream pairs is handled
+as a separate TLS channel (RFC3436), which is consistent with freeDiameter 1.0.x mechanism.
+
+It should be noted however that rfc3588bis (revised Diameter) recommends that DTLS is used
+instead of TLS over SCTP, for the reasons highlighted in the introduction of RFC6083.
+When this new mechanism is implemented in freeDiameter, a different patch will probably
+be required for wireshark.
+
+
+The instructions in this file will change your wireshark binary in a way suitable for
+analysis of Diameter over TLS over SCTP, but may have unexpected side-effects
+on some other protocols analysis (including DTLS).
+
+The instructions refer to Debian-style packaging (apt), you should adapt
+the process to build a new modified package of wireshark for your distribution.
+
+The provided patch has been successfully tested with:
+ - wireshark-1.2.7 (Ubuntu Lucid)
+ - wireshark-1.2.11 (Ubuntu Maverick)
+It may or may not work on more recent or ancient versions.
+
+
+ ------------
+ INSTRUCTIONS
+ ------------
+
+The steps are:
+ - get your wireshark source
+ apt-get source wireshark
+ cd wireshark-1.2.*
+
+ - apply the patch
+ cat ~/wireshark-1.2.7-diameter-tls.patch | patch -p1
+
+ - increase the version number
+ dch -lfD "Added support for Diameter over TLS over SCTP"
+
+ - Create a new package, this might take a while
+ fakeroot debian/rules binary
+
+ - Install the modified version
+ sudo dpkg --install ../wireshark-common_*fD*.deb ../wireshark_*fD*.deb
+
+ - Start the new wireshark:
+ wireshark &
+
+To analyze a capture file, you will need the private keys of both peers involved.
+
+Let's imagine for example:
+ peer A with IP address 192.168.0.10 has private key privA.pem
+ peer B with IP address 192.168.0.11 has private key privB.pem
+
+In wireshark you must do the following:
+ - go to menu Edit->Preferences
+ - In the left panel, under Protocols, scroll to "SSL" and select it.
+ - In the right panel, fill "RSA keys list" as follow:
+ 192.168.0.10,3869,diameter,/absolute/path/to/privA.pem;192.168.0.11,3869,diameter,/absolute/path/to/privB.pem
+ - You may find also useful to select an SSL debug file to get a hint of any problem.
+
+Once this configuration is complete, you should be able to see the contents of SCTP packets,
+including protected Diameter payload.
+
+Check the "sample" subdirectory for a test capture file.
diff --git a/contrib/wireshark/sample/192.168.103.10.priv.pem b/contrib/wireshark/sample/192.168.103.10.priv.pem
new file mode 100644
index 0000000..9da15dd
--- /dev/null
+++ b/contrib/wireshark/sample/192.168.103.10.priv.pem
@@ -0,0 +1,15 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIICXAIBAAKBgQDMcXy2iVqcXkGaY44yNihVNzW/zHptqID49/ZyyyOinxHenvf9
+o/fr613XvUuyquaapL99yiMPuLU3I1UxxacWBSAb496eGd7fY1Udw1RtqKCeb60c
+jpTc3zKySGPHtnzOxeSMDK/R6uqkFirF6Lnu18mKZyAwJtvFYnh0wK3SwwIDAQAB
+AoGAa6kX08hhPxcj1Pm4WBjNBJMeavJzRmwF/xYVYj43ddvuvR1Z2ugOFt7LfGDj
+DCOTbLx1Wvinng/W3kJtCtjbM3w3k5cuFJdJcURXda73IHSaJOHnBAw5RlvFCE79
+12yKqGOBgy80gGHDlqnSIjISCGb/9wLcHYLccakekckPc4ECQQDubt5fWzN4wUwU
+yW+e/SO9Vz4j+FiIC2aZy2OM9XXt6cgh4v0hQ3l0sWVJ6lTvK17aD9LXE5rluAOI
+thnPZElFAkEA24GH8Po/+3K6A5d5Zh1+hwoMLbWrykQDWSOgtmaOtbAvezlolF8O
+W18pVdvyMJg3gUiCA/rHG+r+OBxa4sx4ZwJAH4c1jHJo2fzlbJI+Wk2q3iydIPCD
+9GldhdSpM0h58Z3KQwDa6/0aIF4cwKtl08JuZnNVM+95ugqdHQTHYO8n6QJBAIgO
+m+KEWxBSpnX/d+IRuhGd6rqSdu8ihSjFaqJko2R+1o98oBQHb3C3ZXmwoUf5sb3S
+4bPxx2TIndbNzI/zyVUCQGqN7eyoeTxtPD8P08lUGTUnC2n0imZ1mU5p8Bnv8gw5
+lwt9qxuz0Ujr7uFPPu58bvGsYeoFUV23WRmS0rKLXv0=
+-----END RSA PRIVATE KEY-----
diff --git a/contrib/wireshark/sample/192.168.103.20.priv.pem b/contrib/wireshark/sample/192.168.103.20.priv.pem
new file mode 100644
index 0000000..9f69f7a
--- /dev/null
+++ b/contrib/wireshark/sample/192.168.103.20.priv.pem
@@ -0,0 +1,15 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIICXgIBAAKBgQDef8CrqawfvmCLBwmlPRlWjwB6V4TvVMRhivAYlwwFbUSoU5bm
+2D780IBr3fNL3zP38ySa7r9cXxPgk7mbj3PhcJbI0Ix0AjQdFSB08AOXev4gqU8p
+qgEODFV04tnFhOcDysp77qH/DFuNwxd2xtFUbGKfGhroAssHxJuogOmiWQIDAQAB
+AoGAP6H7wVyCLIXu6HP3zzkdIQM+2L5k92mfzGHG7tFsD7VDWHyngJfB093xjGfq
+p/1KyJPSGTlEoy9R6P12rMWnFv7sYYKmPGfKdRUMxZYIXbplw6+L/gwW3MCiOMDD
+zRzRjknE3a+Mjo3e2XMHh6Z+GJ61megMeGInODP05/h66AECQQDyFhT+D8DVj1hp
+RlaYTFDKCmS9rgMQ+g4YyqMLzuakkKwaJwbCIlMbQortGBvY9I+0uZC4jklcOpnl
+YYcGIUEBAkEA60l5uAVBk6vKWKWX2cksBP/VlJM2B9pkvmlL7tPwJVEfoaAzZx4N
+rPpC9sOsFlX1ShpirAmIqmvY16in4xEJWQJBAOvULSEOcZjZapQrjEIS3gTkOR06
+fgw0vDTUeh8PsEmSEcXsTL4jt/fvS+0KNl6UZ8Xzm5LeMYLiJ3d4GZQUIwECQQCb
+vYLoH/KMQMYrb1DYQ6TzmjRRqC+3ewP8Vc6BQ6BN0yjQ3y2nL+l1eiIhHNwn3LYE
+Wvq9TYI87C4YcfbPAlPhAkEA0bNU/Utgdbv/yT4lUmw+0toqFHkcT5s13RFWzNJU
+KdQ308kwz9rSDmuQ8eYzn5V02TioJKV4r0NZz+WcCyDY3A==
+-----END RSA PRIVATE KEY-----
diff --git a/contrib/wireshark/sample/README b/contrib/wireshark/sample/README
new file mode 100644
index 0000000..c75cfa1
--- /dev/null
+++ b/contrib/wireshark/sample/README
@@ -0,0 +1,56 @@
+This folder contains an example capture file, as well as the two
+private keys required to decode the TLS-protected exchanges.
+
+In order to decrypt properly the packets, you'll need a patched wireshark (see parent directory)
+and the SSL "RSA Private Keys" properties set to (replace with real full path):
+ 192.168.103.10,3869,diameter,freeDiameter/contrib/wireshark/sample/192.168.103.10.priv.pem;192.168.103.20,3869,diameter,freeDiameter/contrib/wireshark/sample/192.168.103.20.priv.pem
+
+
+This capture contains everything that was exchanged by the peer since it boot up.
+The captured peer is "relay.a.rt.freediameter.net" with IP address 192.168.103.20.
+
+Here is the detail of what you can see in the capture, if the decyphering
+works as expected, in chronological order:
+
+-----------------------------------------------------------------------------
+Frames | Comments
+-----------------------------------------------------------------------------
+1-24 | Peer booting up: DHCP, NTP, ...
+ |
+25-29 | Connection attempt from 192.168.103.10
+ | first attempt on SCTP (frames 26-27)
+ | then on TCP (frames 28-29)
+ |
+32-35 | freeDiameter starting: Diameter Identities
+ | from the peer's configuration file are
+ | DNS resolved.
+ |
+36-39 | SCTP connection to 192.168.103.10
+ |
+40-45 | Failed attempt to connect to 192.168.103.30
+ | where freeDiameter was not started.
+ |
+46-49 | (I think this is trigged by Debug output,
+ | I have to check)
+ |
+50-73 | TLS handshake on first stream pair (#0).
+ |
+74-90 | Resumed handshakes on streams #1 and #2 in parallel.
+ | (not sure where to find that it is resumed,
+ | except that certificates are not re-exchanged)
+ |
+91-92 | CER/CEA exchange.
+93-96 | DWR/DWA exchange.
+ |
+103-118 | SCTP heartbeats are exchanged more frequently than DWR/DWA.
+ |
+119-124 | Concurrent DWR/DWA (it happens sometimes)
+ |
+125-128 | Another failed attempt to 192.168.103.30 (cf. frames 40-45)
+ |
+137-140 | DPR/DPA exchange.
+ |
+141-153 | TLS clean shutdown on all streams in parallel.
+ |
+154-157 | SCTP association is closed.
+-----------------------------------------------------------------------------
diff --git a/contrib/wireshark/sample/capture.cap b/contrib/wireshark/sample/capture.cap
new file mode 100644
index 0000000..a680590
--- /dev/null
+++ b/contrib/wireshark/sample/capture.cap
Binary files differ
diff --git a/contrib/wireshark/wireshark-1.2.7-diameter-tls.patch b/contrib/wireshark/wireshark-1.2.7-diameter-tls.patch
new file mode 100644
index 0000000..02a1824
--- /dev/null
+++ b/contrib/wireshark/wireshark-1.2.7-diameter-tls.patch
@@ -0,0 +1,685 @@
+diff -Nur wireshark-1.2.7/epan/conversation.c wireshark-1.2.7-fD/epan/conversation.c
+--- wireshark-1.2.7/epan/conversation.c 2010-04-01 01:44:39.000000000 +0900
++++ wireshark-1.2.7-fD/epan/conversation.c 2011-02-23 14:26:35.000000000 +0900
+@@ -40,6 +40,11 @@
+ static GHashTable *conversation_hashtable_exact = NULL;
+
+ /*
++ * Hash table for conversations without strid.
++ */
++static GHashTable *conversation_hashtable_no_strid = NULL;
++
++/*
+ * Hash table for conversations with one wildcard address.
+ */
+ static GHashTable *conversation_hashtable_no_addr2 = NULL;
+@@ -63,6 +68,7 @@
+ port_type ptype;
+ guint32 port1;
+ guint32 port2;
++ guint32 strid;
+ } conversation_key;
+ #endif
+ /*
+@@ -193,6 +199,7 @@
+ hash_val += key->port1;
+ ADD_ADDRESS_TO_HASH(hash_val, &key->addr2);
+ hash_val += key->port2;
++ hash_val += key->strid;
+
+ return hash_val;
+ }
+@@ -217,6 +224,78 @@
+ */
+ if (v1->port1 == v2->port1 &&
+ v1->port2 == v2->port2 &&
++ v1->strid == v2->strid &&
++ ADDRESSES_EQUAL(&v1->addr1, &v2->addr1) &&
++ ADDRESSES_EQUAL(&v1->addr2, &v2->addr2)) {
++ /*
++ * Yes. It's the same conversation, and the two
++ * address/port pairs are going in the same direction.
++ */
++ return 1;
++ }
++
++ /*
++ * Is the first port 2 the same as the second port 1, the first
++ * port 1 the same as the second port 2, the first address 2
++ * the same as the second address 1, and the first address 1
++ * the same as the second address 2?
++ */
++ if (v1->port2 == v2->port1 &&
++ v1->port1 == v2->port2 &&
++ v1->strid == v2->strid &&
++ ADDRESSES_EQUAL(&v1->addr2, &v2->addr1) &&
++ ADDRESSES_EQUAL(&v1->addr1, &v2->addr2)) {
++ /*
++ * Yes. It's the same conversation, and the two
++ * address/port pairs are going in opposite directions.
++ */
++ return 1;
++ }
++
++ /*
++ * The addresses or the ports don't match.
++ */
++ return 0;
++}
++
++/*
++ * Compute the hash value for two given address/port pairs if the match
++ * has a wildcard stream id.
++ */
++static guint
++conversation_hash_no_strid(gconstpointer v)
++{
++ const conversation_key *key = (const conversation_key *)v;
++ guint hash_val;
++
++ hash_val = 0;
++ ADD_ADDRESS_TO_HASH(hash_val, &key->addr1);
++ hash_val += key->port1;
++ hash_val += key->port2;
++
++ return hash_val;
++}
++
++/*
++ * Compare two conversation keys, except for the stream id value.
++ */
++static gint
++conversation_match_no_strid(gconstpointer v, gconstpointer w)
++{
++ const conversation_key *v1 = (const conversation_key *)v;
++ const conversation_key *v2 = (const conversation_key *)w;
++
++ if (v1->ptype != v2->ptype)
++ return 0; /* different types of port */
++
++ /*
++ * Are the first and second port 1 values the same, the first and
++ * second port 2 values the same, the first and second address
++ * 1 values the same, and the first and second address 2 values
++ * the same?
++ */
++ if (v1->port1 == v2->port1 &&
++ v1->port2 == v2->port2 &&
+ ADDRESSES_EQUAL(&v1->addr1, &v2->addr1) &&
+ ADDRESSES_EQUAL(&v1->addr2, &v2->addr2)) {
+ /*
+@@ -263,6 +342,7 @@
+ ADD_ADDRESS_TO_HASH(hash_val, &key->addr1);
+ hash_val += key->port1;
+ hash_val += key->port2;
++ hash_val += key->strid;
+
+ return hash_val;
+ }
+@@ -289,6 +369,7 @@
+ */
+ if (v1->port1 == v2->port1 &&
+ v1->port2 == v2->port2 &&
++ v1->strid == v2->strid &&
+ ADDRESSES_EQUAL(&v1->addr1, &v2->addr1)) {
+ /*
+ * Yes. It's the same conversation, and the two
+@@ -317,6 +398,7 @@
+ ADD_ADDRESS_TO_HASH(hash_val, &key->addr1);
+ hash_val += key->port1;
+ ADD_ADDRESS_TO_HASH(hash_val, &key->addr2);
++ hash_val += key->strid;
+
+ return hash_val;
+ }
+@@ -342,6 +424,7 @@
+ * address 2 values the same?
+ */
+ if (v1->port1 == v2->port1 &&
++ v1->strid == v2->strid &&
+ ADDRESSES_EQUAL(&v1->addr1, &v2->addr1) &&
+ ADDRESSES_EQUAL(&v1->addr2, &v2->addr2)) {
+ /*
+@@ -370,6 +453,7 @@
+ hash_val = 0;
+ ADD_ADDRESS_TO_HASH(hash_val, &key->addr1);
+ hash_val += key->port1;
++ hash_val += key->strid;
+
+ return hash_val;
+ }
+@@ -394,6 +478,7 @@
+ * and second address 1 values the same?
+ */
+ if (v1->port1 == v2->port1 &&
++ v1->strid == v2->strid &&
+ ADDRESSES_EQUAL(&v1->addr1, &v2->addr1)) {
+ /*
+ * Yes. It's the same conversation, and the two
+@@ -420,6 +505,8 @@
+ conversation_keys = NULL;
+ if (conversation_hashtable_exact != NULL)
+ g_hash_table_destroy(conversation_hashtable_exact);
++ if (conversation_hashtable_no_strid != NULL)
++ g_hash_table_destroy(conversation_hashtable_no_strid);
+ if (conversation_hashtable_no_addr2 != NULL)
+ g_hash_table_destroy(conversation_hashtable_no_addr2);
+ if (conversation_hashtable_no_port2 != NULL)
+@@ -438,6 +525,9 @@
+ conversation_hashtable_exact =
+ g_hash_table_new(conversation_hash_exact,
+ conversation_match_exact);
++ conversation_hashtable_no_strid =
++ g_hash_table_new(conversation_hash_no_strid,
++ conversation_match_no_strid);
+ conversation_hashtable_no_addr2 =
+ g_hash_table_new(conversation_hash_no_addr2,
+ conversation_match_no_addr2);
+@@ -466,6 +556,15 @@
+ conversation_new(guint32 setup_frame, address *addr1, address *addr2, port_type ptype,
+ guint32 port1, guint32 port2, guint options)
+ {
++ return conversation_new_ext(setup_frame, addr1, addr2, ptype,
++ port1, port2, options & ~(DISTINCT_SCTP_STREAMID), 0);
++
++}
++
++conversation_t *
++conversation_new_ext(guint32 setup_frame, address *addr1, address *addr2, port_type ptype,
++ guint32 port1, guint32 port2, guint options, guint16 strid)
++{
+ /*
+ DISSECTOR_ASSERT(!(options | CONVERSATION_TEMPLATE) || ((options | (NO_ADDR2 | NO_PORT2 | NO_PORT2_FORCE))) &&
+ "A conversation template may not be constructed without wildcard options");
+@@ -486,7 +585,11 @@
+ if (options & (NO_PORT2|NO_PORT2_FORCE)) {
+ hashtable = conversation_hashtable_no_port2;
+ } else {
+- hashtable = conversation_hashtable_exact;
++ if (options & DISTINCT_SCTP_STREAMID) {
++ hashtable = conversation_hashtable_exact;
++ } else {
++ hashtable = conversation_hashtable_no_strid;
++ }
+ }
+ }
+
+@@ -495,6 +598,7 @@
+ existing_key.ptype = ptype;
+ existing_key.port1 = port1;
+ existing_key.port2 = port2;
++ existing_key.strid = strid;
+
+ conversation = g_hash_table_lookup(hashtable, &existing_key);
+ tc = conversation; /* Remember if lookup was successful */
+@@ -507,6 +611,7 @@
+ new_key->ptype = ptype;
+ new_key->port1 = port1;
+ new_key->port2 = port2;
++ new_key->strid = strid;
+
+ if (conversation) {
+ for (; conversation->next; conversation = conversation->next)
+@@ -568,8 +673,13 @@
+ g_hash_table_insert(conversation_hashtable_no_addr2,
+ conv->key_ptr, conv);
+ } else {
+- g_hash_table_insert(conversation_hashtable_exact,
+- conv->key_ptr, conv);
++ if (conv->options & DISTINCT_SCTP_STREAMID) {
++ g_hash_table_insert(conversation_hashtable_exact,
++ conv->key_ptr, conv);
++ } else {
++ g_hash_table_insert(conversation_hashtable_no_strid,
++ conv->key_ptr, conv);
++ }
+ }
+ }
+
+@@ -602,18 +712,23 @@
+ g_hash_table_insert(conversation_hashtable_no_port2,
+ conv->key_ptr, conv);
+ } else {
+- g_hash_table_insert(conversation_hashtable_exact,
+- conv->key_ptr, conv);
++ if (conv->options & DISTINCT_SCTP_STREAMID) {
++ g_hash_table_insert(conversation_hashtable_exact,
++ conv->key_ptr, conv);
++ } else {
++ g_hash_table_insert(conversation_hashtable_no_strid,
++ conv->key_ptr, conv);
++ }
+ }
+ }
+
+ /*
+ * Search a particular hash table for a conversation with the specified
+- * {addr1, port1, addr2, port2} and set up before frame_num.
++ * {addr1, port1, addr2, port2, strid} and set up before frame_num.
+ */
+ static conversation_t *
+ conversation_lookup_hashtable(GHashTable *hashtable, guint32 frame_num, address *addr1, address *addr2,
+- port_type ptype, guint32 port1, guint32 port2)
++ port_type ptype, guint32 port1, guint32 port2, guint16 strid)
+ {
+ conversation_t* conversation;
+ conversation_t* match;
+@@ -628,6 +743,7 @@
+ key.ptype = ptype;
+ key.port1 = port1;
+ key.port2 = port2;
++ key.strid = strid;
+
+ match = g_hash_table_lookup(hashtable, &key);
+
+@@ -685,12 +801,19 @@
+ find_conversation(guint32 frame_num, address *addr_a, address *addr_b, port_type ptype,
+ guint32 port_a, guint32 port_b, guint options)
+ {
++ return find_conversation_ext(frame_num, addr_a, addr_b, ptype,
++ port_a, port_b, options | IGNORE_SCTP_STREAMID, 0);
++}
++conversation_t *
++find_conversation_ext(guint32 frame_num, address *addr_a, address *addr_b, port_type ptype,
++ guint32 port_a, guint32 port_b, guint options, guint16 strid)
++{
+ conversation_t *conversation;
+
+ /*
+- * First try an exact match, if we have two addresses and ports.
++ * First try an exact match, if we have two addresses and ports and strid.
+ */
+- if (!(options & (NO_ADDR_B|NO_PORT_B))) {
++ if (!(options & (NO_ADDR_B|NO_PORT_B|IGNORE_SCTP_STREAMID))) {
+ /*
+ * Neither search address B nor search port B are wildcarded,
+ * start out with an exact match.
+@@ -699,7 +822,7 @@
+ conversation =
+ conversation_lookup_hashtable(conversation_hashtable_exact,
+ frame_num, addr_a, addr_b, ptype,
+- port_a, port_b);
++ port_a, port_b, strid);
+ if ((conversation == NULL) && (addr_a->type == AT_FC)) {
+ /* In Fibre channel, OXID & RXID are never swapped as
+ * TCP/UDP ports are in TCP/IP.
+@@ -707,7 +830,33 @@
+ conversation =
+ conversation_lookup_hashtable(conversation_hashtable_exact,
+ frame_num, addr_b, addr_a, ptype,
+- port_a, port_b);
++ port_a, port_b, strid);
++ }
++ if (conversation != NULL)
++ return conversation;
++ }
++
++ /*
++ * Then, ignoring strid try an exact match, if we have two addresses and ports.
++ */
++ if (!(options & (NO_ADDR_B|NO_PORT_B|NO_IGNORE_SCTP_STREAMID))) {
++ /*
++ * Neither search address B nor search port B are wildcarded,
++ * start out with an exact match.
++ * Exact matches check both directions.
++ */
++ conversation =
++ conversation_lookup_hashtable(conversation_hashtable_no_strid,
++ frame_num, addr_a, addr_b, ptype,
++ port_a, port_b, strid);
++ if ((conversation == NULL) && (addr_a->type == AT_FC)) {
++ /* In Fibre channel, OXID & RXID are never swapped as
++ * TCP/UDP ports are in TCP/IP.
++ */
++ conversation =
++ conversation_lookup_hashtable(conversation_hashtable_no_strid,
++ frame_num, addr_b, addr_a, ptype,
++ port_a, port_b, strid);
+ }
+ if (conversation != NULL)
+ return conversation;
+@@ -729,7 +878,7 @@
+ */
+ conversation =
+ conversation_lookup_hashtable(conversation_hashtable_no_addr2,
+- frame_num, addr_a, addr_b, ptype, port_a, port_b);
++ frame_num, addr_a, addr_b, ptype, port_a, port_b, strid);
+ if ((conversation == NULL) && (addr_a->type == AT_FC)) {
+ /* In Fibre channel, OXID & RXID are never swapped as
+ * TCP/UDP ports are in TCP/IP.
+@@ -737,7 +886,7 @@
+ conversation =
+ conversation_lookup_hashtable(conversation_hashtable_no_addr2,
+ frame_num, addr_b, addr_a, ptype,
+- port_a, port_b);
++ port_a, port_b, strid);
+ }
+ if (conversation != NULL) {
+ /*
+@@ -779,7 +928,7 @@
+ if (!(options & NO_ADDR_B)) {
+ conversation =
+ conversation_lookup_hashtable(conversation_hashtable_no_addr2,
+- frame_num, addr_b, addr_a, ptype, port_b, port_a);
++ frame_num, addr_b, addr_a, ptype, port_b, port_a, strid);
+ if (conversation != NULL) {
+ /*
+ * If this is for a connection-oriented
+@@ -821,14 +970,14 @@
+ */
+ conversation =
+ conversation_lookup_hashtable(conversation_hashtable_no_port2,
+- frame_num, addr_a, addr_b, ptype, port_a, port_b);
++ frame_num, addr_a, addr_b, ptype, port_a, port_b, strid);
+ if ((conversation == NULL) && (addr_a->type == AT_FC)) {
+ /* In Fibre channel, OXID & RXID are never swapped as
+ * TCP/UDP ports are in TCP/IP
+ */
+ conversation =
+ conversation_lookup_hashtable(conversation_hashtable_no_port2,
+- frame_num, addr_b, addr_a, ptype, port_a, port_b);
++ frame_num, addr_b, addr_a, ptype, port_a, port_b, strid);
+ }
+ if (conversation != NULL) {
+ /*
+@@ -870,7 +1019,7 @@
+ if (!(options & NO_PORT_B)) {
+ conversation =
+ conversation_lookup_hashtable(conversation_hashtable_no_port2,
+- frame_num, addr_b, addr_a, ptype, port_b, port_a);
++ frame_num, addr_b, addr_a, ptype, port_b, port_a, strid);
+ if (conversation != NULL) {
+ /*
+ * If this is for a connection-oriented
+@@ -907,7 +1056,7 @@
+ */
+ conversation =
+ conversation_lookup_hashtable(conversation_hashtable_no_addr2_or_port2,
+- frame_num, addr_a, addr_b, ptype, port_a, port_b);
++ frame_num, addr_a, addr_b, ptype, port_a, port_b, strid);
+ if (conversation != NULL) {
+ /*
+ * If this is for a connection-oriented protocol:
+@@ -952,11 +1101,11 @@
+ if (addr_a->type == AT_FC)
+ conversation =
+ conversation_lookup_hashtable(conversation_hashtable_no_addr2_or_port2,
+- frame_num, addr_b, addr_a, ptype, port_a, port_b);
++ frame_num, addr_b, addr_a, ptype, port_a, port_b, strid);
+ else
+ conversation =
+ conversation_lookup_hashtable(conversation_hashtable_no_addr2_or_port2,
+- frame_num, addr_b, addr_a, ptype, port_b, port_a);
++ frame_num, addr_b, addr_a, ptype, port_b, port_a, strid);
+ if (conversation != NULL) {
+ /*
+ * If this is for a connection-oriented protocol, set the
+diff -Nur wireshark-1.2.7/epan/conversation.h wireshark-1.2.7-fD/epan/conversation.h
+--- wireshark-1.2.7/epan/conversation.h 2010-04-01 01:44:39.000000000 +0900
++++ wireshark-1.2.7-fD/epan/conversation.h 2011-02-23 14:25:44.000000000 +0900
+@@ -39,11 +39,13 @@
+ * TEMPLATE flag will be altered once the first connections (connection
+ * oriented protocols only) to include the newly found information which
+ * matched the wildcard options.
++ * DISTINCT_SCTP_STREAMID will also save the SCTP stream identifier, if any.
+ */
+ #define NO_ADDR2 0x01
+ #define NO_PORT2 0x02
+ #define NO_PORT2_FORCE 0x04
+ #define CONVERSATION_TEMPLATE 0x08
++#define DISTINCT_SCTP_STREAMID 0x10
+
+ /*
+ * Flags to pass to "find_conversation()" to indicate that the address B
+@@ -51,6 +53,8 @@
+ */
+ #define NO_ADDR_B 0x01
+ #define NO_PORT_B 0x02
++#define IGNORE_SCTP_STREAMID 0x04
++#define NO_IGNORE_SCTP_STREAMID 0x08
+
+ #include "packet.h" /* for conversation dissector type */
+
+@@ -64,6 +68,7 @@
+ port_type ptype;
+ guint32 port1;
+ guint32 port2;
++ guint16 strid;
+ } conversation_key;
+
+ typedef struct conversation {
+@@ -85,6 +90,13 @@
+ extern conversation_t *find_conversation(guint32 frame_num, address *addr_a, address *addr_b,
+ port_type ptype, guint32 port_a, guint32 port_b, guint options);
+
++/* for SCTP stream */
++extern conversation_t *conversation_new_ext(guint32 setup_frame, address *addr1, address *addr2,
++ port_type ptype, guint32 port1, guint32 port2, guint options, guint16 strid);
++extern conversation_t *find_conversation_ext(guint32 frame_num, address *addr_a, address *addr_b,
++ port_type ptype, guint32 port_a, guint32 port_b, guint options, guint16 strid);
++
++
+ extern void conversation_add_proto_data(conversation_t *conv, int proto,
+ void *proto_data);
+ extern void *conversation_get_proto_data(conversation_t *conv, int proto);
+diff -Nur wireshark-1.2.7/epan/dissectors/packet-diameter.c wireshark-1.2.7-fD/epan/dissectors/packet-diameter.c
+--- wireshark-1.2.7/epan/dissectors/packet-diameter.c 2010-04-01 01:44:21.000000000 +0900
++++ wireshark-1.2.7-fD/epan/dissectors/packet-diameter.c 2011-02-23 13:33:10.000000000 +0900
+@@ -63,8 +63,10 @@
+ #include "packet-ntp.h"
+ #include "packet-diameter.h"
+ #include "diam_dict.h"
++#include "packet-ssl.h"
+
+ #define SCTP_PORT_DIAMETER 3868
++#define SCTP_TLS_PORT_DIAMETER 3869
+
+ /* Diameter Header Flags */
+ /* RPETrrrrCCCCCCCCCCCCCCCCCCCCCCCC */
+@@ -271,10 +273,13 @@
+
+
+ static guint gbl_diameterSctpPort=SCTP_PORT_DIAMETER;
++static guint gbl_diameterSctpTlsPort=SCTP_TLS_PORT_DIAMETER;
+
+ static dissector_handle_t diameter_tcp_handle;
+ static range_t *global_diameter_tcp_port_range;
++static range_t *global_diameter_tcp_tls_port_range;
+ #define DEFAULT_DIAMETER_PORT_RANGE "3868"
++#define DEFAULT_DIAMETER_TLS_PORT_RANGE "3869"
+
+ /* desegmentation of Diameter over TCP */
+ static gboolean gbl_diameter_desegment = TRUE;
+@@ -1358,13 +1363,27 @@
+ dissector_add("tcp.port", port, diameter_tcp_handle);
+ }
+
++static void
++range_delete_callback_sec(guint32 port)
++{
++ ssl_dissector_delete(port, "diameter", TRUE);
++}
++
++static void
++range_add_callback_sec(guint32 port)
++{
++ ssl_dissector_add(port, "diameter", TRUE);
++}
++
+ void
+ proto_reg_handoff_diameter(void)
+ {
+ static gboolean Initialized=FALSE;
+ static guint SctpPort;
++ static guint SctpsPort;
+ static dissector_handle_t diameter_handle;
+ static range_t *diameter_tcp_port_range;
++ static range_t *diameters_tcp_port_range;
+
+ if (!Initialized) {
+ diameter_handle = find_dissector("diameter");
+@@ -1382,20 +1401,27 @@
+ /* AVP Code: 463 EAP-Reissued-Payload */
+ dissector_add("diameter.base", 463,
+ new_create_dissector_handle(dissect_diameter_eap_payload, proto_diameter));
++
++ /* set port for future deletes */
++ diameter_tcp_port_range = range_copy(global_diameter_tcp_port_range);
++ range_foreach(diameter_tcp_port_range, range_add_callback);
++ diameters_tcp_port_range = range_copy(global_diameter_tcp_tls_port_range);
++ range_foreach(diameters_tcp_port_range, range_add_callback_sec);
++
++ dissector_add("sctp.port", gbl_diameterSctpPort, diameter_handle);
++ ssl_dissector_add(gbl_diameterSctpTlsPort, "diameter", TRUE);
+
+ Initialized=TRUE;
+ } else {
+ range_foreach(diameter_tcp_port_range, range_delete_callback);
+ g_free(diameter_tcp_port_range);
++ range_foreach(diameters_tcp_port_range, range_delete_callback_sec);
++ g_free(diameters_tcp_port_range);
+ dissector_delete("sctp.port", SctpPort, diameter_handle);
+ }
+
+- /* set port for future deletes */
+- diameter_tcp_port_range = range_copy(global_diameter_tcp_port_range);
+- range_foreach(diameter_tcp_port_range, range_add_callback);
+
+- SctpPort=gbl_diameterSctpPort;
+- dissector_add("sctp.port", gbl_diameterSctpPort, diameter_handle);
++
+ }
+
+ /* registration with the filtering engine */
+@@ -1543,8 +1569,9 @@
+ diameter_dissector_table = register_dissector_table("diameter.base", "DIAMETER_3GPP_AVPS", FT_UINT32, BASE_DEC);
+ diameter_3gpp_avp_dissector_table = register_dissector_table("diameter.3gpp", "DIAMETER_3GPP_AVPS", FT_UINT32, BASE_DEC);
+
+- /* Set default TCP ports */
++ /* Set default TCP & TLS ports */
+ range_convert_str(&global_diameter_tcp_port_range, DEFAULT_DIAMETER_PORT_RANGE, MAX_UDP_PORT);
++ range_convert_str(&global_diameter_tcp_tls_port_range, DEFAULT_DIAMETER_TLS_PORT_RANGE, MAX_UDP_PORT);
+
+ /* Register configuration options for ports */
+ diameter_module = prefs_register_protocol(proto_diameter,
+diff -Nur wireshark-1.2.7/epan/dissectors/packet-sctp.c wireshark-1.2.7-fD/epan/dissectors/packet-sctp.c
+--- wireshark-1.2.7/epan/dissectors/packet-sctp.c 2010-04-01 01:44:28.000000000 +0900
++++ wireshark-1.2.7-fD/epan/dissectors/packet-sctp.c 2011-02-23 13:54:13.000000000 +0900
+@@ -2693,6 +2693,7 @@
+ b_bit = tvb_get_guint8(chunk_tvb, CHUNK_FLAGS_OFFSET) & SCTP_DATA_CHUNK_B_BIT;
+ u_bit = tvb_get_guint8(chunk_tvb, CHUNK_FLAGS_OFFSET) & SCTP_DATA_CHUNK_U_BIT;
+ stream_id = tvb_get_ntohs(chunk_tvb, DATA_CHUNK_STREAM_ID_OFFSET);
++ pinfo->strid = stream_id;
+ stream_seq_num = tvb_get_ntohs(chunk_tvb, DATA_CHUNK_STREAM_SEQ_NUMBER_OFFSET);
+ tsn = tvb_get_ntohl(chunk_tvb, DATA_CHUNK_TSN_OFFSET);
+
+diff -Nur wireshark-1.2.7/epan/dissectors/packet-ssl.c wireshark-1.2.7-fD/epan/dissectors/packet-ssl.c
+--- wireshark-1.2.7/epan/dissectors/packet-ssl.c 2010-04-01 01:44:34.000000000 +0900
++++ wireshark-1.2.7-fD/epan/dissectors/packet-ssl.c 2011-02-23 14:56:36.000000000 +0900
+@@ -500,6 +500,7 @@
+ guint* conv_version;
+ Ssl_private_key_t * private_key;
+ guint32 port;
++ guint16 strid;
+
+ ti = NULL;
+ ssl_tree = NULL;
+@@ -507,9 +508,14 @@
+ first_record_in_frame = TRUE;
+ ssl_session = NULL;
+ port = 0;
++ strid = 0;
+
+
+ ssl_debug_printf("\ndissect_ssl enter frame #%u (%s)\n", pinfo->fd->num, (pinfo->fd->flags.visited)?"already visited":"first time");
++
++ if (pinfo->ptype == PT_SCTP) {
++ ssl_debug_printf("\ndissect_ssl SCTP stream %hd\n", pinfo->strid);
++ }
+
+ /* Track the version using conversations to reduce the
+ * chance that a packet that simply *looks* like a v2 or
+@@ -523,14 +529,14 @@
+ * the conv_version, must set the copy in the conversation
+ * in addition to conv_version
+ */
+- conversation = find_conversation(pinfo->fd->num, &pinfo->src, &pinfo->dst, pinfo->ptype,
+- pinfo->srcport, pinfo->destport, 0);
++ conversation = find_conversation_ext(pinfo->fd->num, &pinfo->src, &pinfo->dst, pinfo->ptype,
++ pinfo->srcport, pinfo->destport, NO_IGNORE_SCTP_STREAMID, pinfo->strid);
+
+ if (!conversation)
+ {
+ /* create a new conversation */
+- conversation = conversation_new(pinfo->fd->num, &pinfo->src, &pinfo->dst, pinfo->ptype,
+- pinfo->srcport, pinfo->destport, 0);
++ conversation = conversation_new_ext(pinfo->fd->num, &pinfo->src, &pinfo->dst, pinfo->ptype,
++ pinfo->srcport, pinfo->destport, (pinfo->ptype == PT_SCTP) ? DISTINCT_SCTP_STREAMID : 0, pinfo->strid);
+ ssl_debug_printf(" new conversation = %p created\n", (void *)conversation);
+ }
+ conv_data = conversation_get_proto_data(conversation, proto_ssl);
+@@ -549,7 +555,7 @@
+ conversation_add_proto_data(conversation, proto_ssl, ssl_session);
+
+ /* we need to know which side of the conversation is speaking */
+- if (ssl_packet_from_server(ssl_associations, pinfo->srcport, pinfo->ptype == PT_TCP)) {
++ if (ssl_packet_from_server(ssl_associations, pinfo->srcport, pinfo->ptype != PT_UDP)) {
+ dummy.addr = pinfo->src;
+ dummy.port = port = pinfo->srcport;
+ } else {
+@@ -762,7 +768,7 @@
+ * add decrypted data to this packet info */
+ ssl_debug_printf("decrypt_ssl3_record: app_data len %d ssl, state 0x%02X\n",
+ record_length, ssl->state);
+- direction = ssl_packet_from_server(ssl_associations, pinfo->srcport, pinfo->ptype == PT_TCP);
++ direction = ssl_packet_from_server(ssl_associations, pinfo->srcport, pinfo->ptype != PT_UDP);
+
+ /* retrieve decoder for this packet direction */
+ if (direction != 0) {
+@@ -1504,7 +1510,7 @@
+ col_append_str(pinfo->cinfo, COL_INFO, "Change Cipher Spec");
+ dissect_ssl3_change_cipher_spec(tvb, ssl_record_tree,
+ offset, conv_version, content_type);
+- if (ssl) ssl_change_cipher(ssl, ssl_packet_from_server(ssl_associations, pinfo->srcport, pinfo->ptype == PT_TCP));
++ if (ssl) ssl_change_cipher(ssl, ssl_packet_from_server(ssl_associations, pinfo->srcport, pinfo->ptype != PT_UDP));
+ break;
+ case SSL_ID_ALERT:
+ {
+@@ -1566,8 +1572,8 @@
+ /* we need dissector information when the selected packet is shown.
+ * ssl session pointer is NULL at that time, so we can't access
+ * info cached there*/
+- association = ssl_association_find(ssl_associations, pinfo->srcport, pinfo->ptype == PT_TCP);
+- association = association ? association: ssl_association_find(ssl_associations, pinfo->destport, pinfo->ptype == PT_TCP);
++ association = ssl_association_find(ssl_associations, pinfo->srcport, pinfo->ptype != PT_UDP);
++ association = association ? association: ssl_association_find(ssl_associations, pinfo->destport, pinfo->ptype != PT_UDP);
+
+ proto_item_set_text(ssl_record_tree,
+ "%s Record Layer: %s Protocol: %s",
+diff -Nur wireshark-1.2.7/epan/dissectors/packet-ssl-utils.c wireshark-1.2.7-fD/epan/dissectors/packet-ssl-utils.c
+--- wireshark-1.2.7/epan/dissectors/packet-ssl-utils.c 2010-04-01 01:44:27.000000000 +0900
++++ wireshark-1.2.7-fD/epan/dissectors/packet-ssl-utils.c 2011-02-23 13:33:10.000000000 +0900
+@@ -2713,9 +2713,10 @@
+ fprintf(stderr, "association_add() could not find handle for protocol:%s\n",protocol);
+ } else {
+ if(port) {
+- if(tcp)
++ if(tcp) {
+ dissector_add("tcp.port", port, handle);
+- else
++ dissector_add("sctp.port", port, handle);
++ } else
+ dissector_add("udp.port", port, handle);
+ }
+ g_tree_insert(associations, assoc, assoc);
+diff -Nur wireshark-1.2.7/epan/packet_info.h wireshark-1.2.7-fD/epan/packet_info.h
+--- wireshark-1.2.7/epan/packet_info.h 2010-04-01 01:44:40.000000000 +0900
++++ wireshark-1.2.7-fD/epan/packet_info.h 2011-02-23 13:54:52.000000000 +0900
+@@ -169,6 +169,7 @@
+ tvbuff_t *gssapi_decrypted_tvb;
+ gboolean gssapi_data_encrypted;
+
++ guint16 strid; /* Stream Id of the last DATA chunk in the packet */
+ guint32 ppid; /* SCTP PPI of current DATA chunk */
+ guint32 ppids[MAX_NUMBER_OF_PPIDS]; /* The first NUMBER_OF_PPIDS PPIDS which are present
+ * in the SCTP packet