view include/waaad/dictionary-api.h @ 401:860f41038ea2

Updated copyright information
author Sebastien Decugis <sdecugis@nict.go.jp>
date Tue, 02 Jun 2009 15:10:55 +0900
parents 316bb3f38d04
children
line wrap: on
line source

/*********************************************************************************************************
* Software License Agreement (BSD License)                                                               *
* Author: Sebastien Decugis <sdecugis@nict.go.jp>							 *
*													 *
* Copyright (c) 2009, WIDE Project and NICT								 *
* All rights reserved.											 *
* 													 *
* Redistribution and use of this software in source and binary forms, with or without modification, are  *
* permitted provided that the following conditions are met:						 *
* 													 *
* * Redistributions of source code must retain the above 						 *
*   copyright notice, this list of conditions and the 							 *
*   following disclaimer.										 *
*    													 *
* * Redistributions in binary form must reproduce the above 						 *
*   copyright notice, this list of conditions and the 							 *
*   following disclaimer in the documentation and/or other						 *
*   materials provided with the distribution.								 *
* 													 *
* * Neither the name of the WIDE Project or NICT nor the 						 *
*   names of its contributors may be used to endorse or 						 *
*   promote products derived from this software without 						 *
*   specific prior written permission of WIDE Project and 						 *
*   NICT.												 *
* 													 *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED *
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR *
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 	 *
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 	 *
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR *
* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF   *
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.								 *
*********************************************************************************************************/

/* This file contains the definitions of types and functions related to the dictionary
 and that can be called by extensions. */
 
#ifndef _DICTIONARY_API_H
#define _DICTIONARY_API_H
#include <stdint.h>

/*
 ***************************************************************************
 *
 * General API functions 
 *
 * These functions are used to manage Dictionary objects in a generic way.
 *
 ***************************************************************************
 */

/* types of object in the dictionary */
typedef enum {
	DICT_VENDOR	= 1,	/* Vendor */
	DICT_APPLICATION,	/* Diameter Application */
	DICT_TYPE,		/* AVP data type */
	DICT_TYPE_ENUM,		/* Enumerated type value (named constant) */
	DICT_AVP,		/* AVP */
	DICT_COMMAND,		/* Diameter Command */
	DICT_RULE		/* a Rule for AVP in command or grouped AVP */
#define DICT_TYPE_MAX	DICT_RULE
} dict_object_type_t;

/* Generic type to refer any dictionary object (opaque type) */
typedef void dict_object_t;

#ifndef IN_EXTENSION

/*
 * FUNCTION:	dict_new
 *
 * PARAMETERS:
 *  type 	: What kind of object must be created
 *  data 	: pointer to the data for the object. 
 *          	 type parameter is used to determine the type of data.
 *  parent 	: a reference to a parent object, if needed.
 *  ref 	: upon successful creation, reference to new object is stored here if !null.
 *
 * DESCRIPTION: 
 *  Create a new object in the dictionary. 
 *  See following object sections in this header file for more information on data and parent parameters format.
 *
 * RETURN VALUE:
 *  0      	: The object is created in the dictionary.
 *  EINVAL 	: A parameter is invalid.
 *  EEXIST 	: This object is already defined in the dictionary. 
 *                If "ref" is not NULL, it points to the existing element on return.
 *  (other standard errors may be returned, too, with their standard meaning. Example:
 *    ENOMEM 	: Memory allocation for the new object element failed.)
 */
int dict_new ( dict_object_type_t type, void * data, dict_object_t * parent, dict_object_t **ref );

/*
 * FUNCTION: 	dict_search
 *
 * PARAMETERS:
 *  type 	: type of object that is being searched
 *  criteria 	: how the object must be searched. See object-related sections bellow for more information.
 *  what 	: depending on criteria, the data that must be searched.
 *  result 	: On successful return, pointer to the object is stored here.
 *  retval	: this value is returned if the object is not found and result is not NULL.
 *
 * DESCRIPTION: 
 *   Perform a search in the dictionary. 
 *   See the object-specific sections bellow to find how to look for each objects.
 *   If the "result" parameter is NULL, the function is used to check if an object is in the dictionary.
 *   Otherwise, a reference to the object is stored in result if found.
 *   If result is not NULL and the object is not found, retval is returned (should be 0 or ENOENT usually)
 *
 * RETURN VALUE:
 *  0      	: The object has been found in the dictionary, or *result is NULL.
 *  EINVAL 	: A parameter is invalid.
 *  ENOENT	: No matching object has been found, and result was NULL.
 */
int dict_search ( dict_object_type_t type, int criteria, void * what, dict_object_t **result, int retval );

/*
 * FUNCTION:	dict_gettype
 *
 * PARAMETERS:
 *  object 	: Pointer to a dictionary object.
 *  type 	: Location where the dict_object_type_t of this object must be written.
 *
 * DESCRIPTION: 
 *  Write the type of an object. Mainly for debug purpose...
 *
 * RETURN VALUE:
 *  0      	: The type of the object has been retrieved.
 *  EINVAL 	: A parameter is invalid.
 */
int dict_gettype ( dict_object_t * object, dict_object_type_t * type);

/*
 * FUNCTION:	dict_getval
 *
 * PARAMETERS:
 *  object 	: Pointer to a dictionary object.
 *  data 	: pointer to a structure to hold the data for the object.
 *          	  The type is the same as "data" parameter in dict_new function.
 *
 * DESCRIPTION: 
 *  Retrieve content of a dictionary object.
 *  See following object sections in this header file for more information on data and parent parameters format.
 *
 * RETURN VALUE:
 *  0      	: The content of the object has been retrieved.
 *  EINVAL 	: A parameter is invalid.
 */
int dict_getval ( dict_object_t * object, void * val);

#endif /* ! IN_EXTENSION */

/* The version of this API, to check binary compatibility -- increment each time a change is made in api_dict_t */
#define WAAAD_API_DICT_VER	2

/* Now define the type of the structure that contains the callback to pass to extensions */
typedef struct {
	/* The header is common to all sub-API pieces */
	size_t	length;		/* The size of this structure, may be useful for extensions not using the dictionary */
	int	version;	/* The version of this API/ABI, must be WAAAD_API_DICT_VER */
	
	/* the remaining is dictionary-specific */
	int (*dict_new)    ( dict_object_type_t type, void * data, dict_object_t * parent, dict_object_t **ref );
	int (*dict_search) ( dict_object_type_t type, int criteria, void * what, dict_object_t **result, int retval );
	int (*dict_gettype)( dict_object_t * object, dict_object_type_t * type);
	int (*dict_getval) ( dict_object_t * object, void * val);
} api_dict_t;

#ifdef IN_EXTENSION

/* From within the extensions, we register callbacks in the following global structure */
#ifdef DECLARE_API_POINTERS
api_dict_t * g_api_dict=NULL;
#else /* DECLARE_API_POINTERS */
extern api_dict_t * g_api_dict;
#endif /* DECLARE_API_POINTERS */

/* These defines allow to call functions from extension in the same way as in waaad */
#define dict_new	g_api_dict->dict_new
#define dict_search	g_api_dict->dict_search
#define dict_gettype	g_api_dict->dict_gettype
#define dict_getval	g_api_dict->dict_getval

#else /* IN_EXTENSION */

/* From the daemon, we must initialize the API object, in extension.c */
# define MY_WAAAD_API_DICT_VER 2
# if MY_WAAAD_API_DICT_VER != WAAAD_API_DICT_VER
#  error "You must update API_INIT_DICTIONARY also"
# endif

#define API_INIT_DICTIONARY( api_dict ) 		\
{							\
	(api_dict).length      = sizeof(api_dict_t);	\
	(api_dict).version     = WAAAD_API_DICT_VER;	\
	(api_dict).dict_new    = dict_new;		\
	(api_dict).dict_search = dict_search;		\
	(api_dict).dict_gettype= dict_gettype;		\
	(api_dict).dict_getval = dict_getval;		\
}							

#endif /* IN_EXTENSION */




/*
 ***************************************************************************
 *
 * Vendor object 
 *
 * These types are used to manage vendors in the dictionary
 *
 ***************************************************************************
 */

/* Type to hold a Vendor ID: "SMI Network Management Private Enterprise Codes" (RFC3232) */
typedef uint32_t	vendor_id_t;

/* Type to hold data associated to a vendor */
typedef struct {
	vendor_id_t	 vendor_id;	/* ID of a vendor */
	char 		*vendor_name;	/* The name of this vendor */
} dict_vendor_data_t;

/* The criteria for searching a vendor object in the dictionary */
typedef enum {
	VENDOR_BY_ID_REF = 1,	/* "what" points to a vendor_id_t */
	VENDOR_BY_ID_VAL,	/* "what" is directly casted from vendor_id_t (may malfunction on some architectures!) */
	VENDOR_BY_NAME,		/* "what" points to a string */
	VENDOR_OF_APPLICATION	/* "what" points to a dict_object_t containing an application (see bellow) */
} dict_criter_vendor_t;

/***
 *  API usage :

Note: the value of "vendor_name" is copied when the object is created, and the string may be disposed afterwards.
On the other side, when value is retrieved with dict_getval, the string is not copied and MUST NOT be freed. It will
be freed automatically along with the object itself with call to dict_fini later.
 

- dict_new:
 The "parent" parameter is not used for vendors. 
 Sample code to create a vendor:
 {
	 int ret;
	 dict_object_t * myvendor;
	 dict_vendor_data_t myvendordata = { 23455, "my vendor name" };  -- just an example...
	 ret = dict_new ( DICT_VENDOR, &myvendordata, NULL, &myvendor );
 }

- dict_search:
 Sample codes to look for a vendor object, by its id or name:
 {
	 int ret;
	 dict_object_t * vendor_found;
	 vendor_id_t vendor = 23455;
	 ret = dict_search ( DICT_VENDOR, VENDOR_BY_ID_REF, &vendor, &vendor_found, ENOENT);
	 - or -
	 ret = dict_search ( DICT_VENDOR, VENDOR_BY_ID_VAL, 23455, &vendor_found, ENOENT);
	 - or -
	 ret = dict_search ( DICT_VENDOR, VENDOR_BY_NAME, "my vendor name", &vendor_found, ENOENT);
 }
 
 - dict_getval:
 Sample code to retrieve the data from a vendor object:
 {
	 int ret;
	 dict_object_t * myvendor;
	 dict_vendor_data_t myvendordata;
	 ret = dict_search ( DICT_VENDOR, VENDOR_BY_ID_VAL, 23455, &myvendor, ENOENT);
	 ret = dict_getval ( myvendor, &myvendordata );
	 printf("myvendor name: %s\n", myvendordata.vendor_name );
 }
		 
 
*/
	 
/*
 ***************************************************************************
 *
 * Application object 
 *
 * These types are used to manage Diameter applications in the dictionary
 *
 ***************************************************************************
 */

/* Type to hold a Diameter application ID: IANA assigned value for this application. */
typedef uint32_t	application_id_t;

/* Type to hold data associated to an application */
typedef struct {
	application_id_t	 application_id;	/* ID of the application */
	char 			*application_name;	/* The name of this application */
} dict_application_data_t;

/* The criteria for searching an application object in the dictionary */
typedef enum {
	APPLICATION_BY_ID_REF = 1,	/* "what" points to a application_id_t */
	APPLICATION_BY_ID_VAL,		/* "what" is directly casted from application_id_t (may malfunction on some architectures!) */
	APPLICATION_BY_NAME,		/* "what" points to a string */
	APPLICATION_OF_TYPE,		/* "what" points to a dict_object_t containing a type object (see bellow) */
	APPLICATION_OF_COMMAND		/* "what" points to a dict_object_t containing a command (see bellow) */
} dict_criter_application_t;

/***
 *  API usage :

The "parent" parameter of dict_new may point to a vendor object to inform of what vendor defines the application.
for standard-track applications, the "parent" parameter should be NULL.
The vendor associated to an application is retrieved with VENDOR_OF_APPLICATION search criteria on vendors.

- dict_new:
 Sample code for application creation:
 {
	 int ret;
	 dict_object_t * vendor;
	 dict_object_t * appl;
	 dict_vendor_data_t vendor_data = {
		 23455,
		 "my vendor name"
	 };
	 dict_application_data_t app_data = {
		 9789,
		 "my vendor's application"
	 };
	
	 ret = dict_new ( DICT_VENDOR, &vendor_data, NULL, &vendor );
	 ret = dict_new ( DICT_APPLICATION, &app_data, vendor, &appl );
 }

- dict_search:
 Sample code to retrieve the vendor of an application
 {
	 int ret;
	 dict_object_t * vendor, * appli;
	 
	 ret = dict_search ( DICT_APPLICATION, APPLICATION_BY_ID_VAL, (void *)9789, &appli, ENOENT);
	 ret = dict_search ( DICT_VENDOR, VENDOR_OF_APPLICATION, appli, &vendor, ENOENT);
 }
 
 - dict_getval:
 Sample code to retrieve the data from an application object:
 {
	 int ret;
	 dict_object_t * appli;
	 dict_application_data_t appl_data;
	 ret = dict_search ( DICT_APPLICATION, APPLICATION_BY_ID_VAL, (void *)9789, &appli, ENOENT);
	 ret = dict_getval ( appli, &appl_data );
	 printf("my application name: %s\n", appl_data.application_name );
 }

*/

/*
 ***************************************************************************
 *
 * Type object 
 *
 * These types are used to manage AVP data types in the dictionary
 *
 ***************************************************************************
 */

/* Type to store any AVP value */ 
typedef union {
	struct {
		unsigned char *	data;	/* bytes buffer */
		size_t   	len;	/* length of the data buffer */
	}           os;		/* Storage for an octet string, data is alloc'd and must be freed */
	int32_t     i32;	/* integer 32 */
	int64_t     i64;	/* integer 64 */
	uint32_t    u32;	/* unsigned 32 */
	uint64_t    u64;	/* unsigned 64 */
	float       f32;	/* float 32 */
	double 	    f64;	/* float 64 */
} avp_value_t;

/* These are the basic AVP types defined in RFC3588bis */
typedef enum {
	AVP_TYPE_GROUPED,
	AVP_TYPE_OCTETSTRING,
	AVP_TYPE_INTEGER32,
	AVP_TYPE_INTEGER64,
	AVP_TYPE_UNSIGNED32,
	AVP_TYPE_UNSIGNED64,
	AVP_TYPE_FLOAT32,
	AVP_TYPE_FLOAT64
#define AVP_TYPE_MAX AVP_TYPE_FLOAT64
} dict_base_type_t;

/* Callbacks that can be associated with a derived type to further interpret the values. */
/*
 * CALLBACK:	type_data_interpret
 *
 * PARAMETERS:
 *   avp_value   : Pointer to the AVP value that must be interpreted.
 *   interpreted : The result of interpretation is stored here. The format and meaning depends on each type.
 *
 * DESCRIPTION: 
 *   This callback can be provided with a derived type in order to facilitate the interpretation of formated data.
 *  For example, when an AVP of type "Address" is received, it can be used to convert the octetstring into a struct sockaddr.
 *  This callback is usually not called directly, but through the message's API msg_avp_value_interpret function.
 *
 * RETURN VALUE:
 *  0      	: Operation complete.
 *  !0 		: An error occurred, the error code is returned.
 */
typedef int (*type_data_interpret) (avp_value_t * avp_value, void * interpreted);
/*
 * CALLBACK:	type_data_encode
 *
 * PARAMETERS:
 *   data	: The formated data that must be stored in the AVP value.
 *   avp_value	: Pointer to the AVP value storage area where the data must be stored.
 *
 * DESCRIPTION: 
 *   This callback can be provided with a derived type in order to facilitate the encoding of formated data.
 *  For example, it can be used to convert a struct sockaddr in an AVP value of type Address.
 *  This callback is usually not called directly, but through the message's API msg_avp_value_encode function.
 *  If the callback is defined for an OctetString based type, the created string must be malloc'd. free will be called 
 *  automatically later.
 *
 * RETURN VALUE:
 *  0      	: Operation complete.
 *  !0 		: An error occurred, the error code is returned.
 */
typedef int (*type_data_encode) (void * data, avp_value_t * avp_value);



/* Type to hold data associated to a derived AVP data type */
typedef struct {
	dict_base_type_t	 type_base;	/* How the data of such AVP must be interpreted */
	char 			*type_name;	/* The name of this application */
	type_data_interpret	 type_interpret;/* Convert the AVP value in more comprehensive format */
	type_data_encode	 type_encode;	/* Convert formatted data into an AVP value */
} dict_type_data_t;

/* The criteria for searching a type object in the dictionary */
typedef enum {
	TYPE_BY_NAME = 1,		/* "what" points to a string */
	TYPE_OF_ENUM,			/* "what" points to a dict_object_t containing an enumerated constant (TYPE_ENUM). */
	TYPE_OF_AVP			/* "what" points to a dict_object_t containing an AVP object. */
} dict_criter_type_t;

/***
 *  API usage :


- dict_new:
 The "parent" parameter may point to an application object, when a type is defined by a Diameter application. 
 
 Sample code:
 {
	 int ret;
	 dict_object_t * mytype;
	 dict_type_data_t mytypedata = 
		{ 
		 AVP_TYPE_OCTETSTRING,
		 "Address"
		};
	 ret = dict_new ( DICT_TYPE, &mytypedata, NULL, &mytype );
 }

- dict_search:
 Sample code:
 {
	 int ret;
	 dict_object_t * address_type;
	 ret = dict_search ( DICT_TYPE, TYPE_BY_NAME, "Address", &address_type, ENOENT);
 }
 
*/
	 
/*
 ***************************************************************************
 *
 * Enumerated values object 
 *
 * These types are used to manage named constants of AVP values, 
 * for enumerated types
 *
 ***************************************************************************
 */

/* Type to hold data of named constants for AVP values */
typedef struct {
	char 		*enum_name;	/* The name of this constant */
	avp_value_t 	 enum_value;	/* Value of the constant. Union term depends on parent type's base type. */
} dict_type_enum_data_t;

/* The criteria for searching a constant object in the dictionary */
typedef enum {
	ENUM_BY_STRUCT = 1,	/* "what" points to a dict_type_enum_request_t as defined bellow */
} dict_criter_enum_t;

typedef struct {
	/* Identifier of the parent type, one of the following must not be NULL */
	dict_object_t		*type_obj;
	char			*type_name;
	
	/* Data to search in the enumerated constants of this type */
	dict_type_enum_data_t 	 search; /* search.enum_value is used only if search.enum_name = NULL */
} dict_type_enum_request_t;

/***
 *  API usage :

- dict_new:
 The "parent" parameter must point to a derived type object. 
 Sample code to create a type "Boolean" with two constants "True" and "False":
 {
	 int ret;
	 dict_object_t * type_boolean;
	 dict_type_data_t type_boolean_data = 
		{ 
		 AVP_TYPE_INTEGER32,
		 "Boolean"
		};
	 dict_type_enum_data_t boolean_false =
	 	{
		 .enum_name="False",
		 .enum_value.i32 = 0
	 	};
	 dict_type_enum_data_t boolean_true =
	 	{
		 .enum_name="True",
		 .enum_value.i32 = -1
	 	};
	 ret = dict_new ( DICT_TYPE, &type_boolean_data, NULL, &type_boolean );
	 ret = dict_new ( DICT_TYPE_ENUM, &boolean_false, type_boolean, NULL );
	 ret = dict_new ( DICT_TYPE_ENUM, &boolean_true , type_boolean, NULL );
	 
 }

- dict_search:
 Sample code to look for a constant name, by its value:
 {
	 int ret;
	 dict_object_t * value_found;
	 dict_type_enum_request_t boolean_by_value =
	 	{
		 .type_name = "Boolean",
		 .search.enum_name=NULL,
		 .search.enum_value.i32 = -1
	 	};
	 
	 ret = dict_search ( DICT_TYPE_ENUM, ENUM_BY_STRUCT, &boolean_by_value, &value_found, ENOENT);
 }
 
 - dict_getval:
 Sample code to retrieve the data from a constant object:
 {
	 int ret;
	 dict_object_t * myvendor;
	 dict_vendor_data_t myvendordata;
	 ret = dict_search ( DICT_VENDOR, VENDOR_BY_ID_VAL, 23455, &myvendor, ENOENT);
	 ret = dict_getval ( myvendor, &myvendordata );
	 printf("myvendor name: %s\n", myvendordata.vendor_name );
 }
		 
 
*/
	 
/*
 ***************************************************************************
 *
 * AVP object 
 *
 * These types are used to manage AVP data types in the dictionary
 *
 ***************************************************************************
 */

/* Type to hold an AVP code. For vendor 0, these codes are assigned by IANA. Otherwise, it is managed by the vendor */
typedef uint32_t	avp_code_t;

/* Values of AVP flags */
#define	AVP_FLAG_VENDOR	  	0x80
#define	AVP_FLAG_MANDATORY	0x40
#define	AVP_FLAG_RESERVED3	0x20
#define	AVP_FLAG_RESERVED4	0x10
#define	AVP_FLAG_RESERVED5	0x08
#define	AVP_FLAG_RESERVED6	0x04
#define	AVP_FLAG_RESERVED7	0x02
#define	AVP_FLAG_RESERVED8	0x01


/* Type to hold data associated to an avp */
typedef struct {
	avp_code_t	 avp_code;	/* code of the avp */
	vendor_id_t	 avp_vendor;	/* Vendor of the AVP, or 0 */
	char		*avp_name;	/* Name of this AVP */
	uint8_t		 avp_flag_mask;	/* Mask of fixed-value flags */
	uint8_t		 avp_flag_val;	/* values of the fixed flags */
	dict_base_type_t avp_basetype;	/* how to interpret data found in the AVP */
} dict_avp_data_t;

/* The criteria for searching an avp object in the dictionary */
typedef enum {
	AVP_BY_CODE_REF = 1,	/* "what" points to an avp_code_t, vendor is always 0 */
	AVP_BY_CODE_VAL,	/* "what" is a casted avp_code_t (may not work on some architectures), vendor is always 0 */
	AVP_BY_NAME,		/* "what" points to a string, vendor is always 0 */
	AVP_BY_CODE_AND_VENDOR,	/* "what" points to a dict_avp_request_t (see bellow), where avp_vendor and avp_code are set */
	AVP_BY_NAME_AND_VENDOR	/* "what" points to a dict_avp_request_t (see bellow), where avp_vendor and avp_name are set */
} dict_criter_avp_t;

/* Struct used for some researchs */
typedef struct {
	vendor_id_t	 avp_vendor;
	avp_code_t	 avp_code;
	char		*avp_name;
} dict_avp_request_t;


/***
 *  API usage :

If "parent" parameter is not NULL during AVP creation, it must point to a DICT_TYPE object. 
The extended type is then attached to the AVP. In case where it is an enumerated type, the value of 
AVP is automatically interpreted in debug messages, and in message checks.
The derived type of an AVP can be retrieved with: dict_search ( DICT_TYPE, TYPE_OF_AVP, ... )

To create the rules for children of Grouped AVP, see the DICT_RULE related part.

- dict_new:
 Sample code for AVP creation:
 {
	 int ret;
	 dict_object_t * user_name_avp;
	 dict_object_t * boolean_type;
	 dict_object_t * sample_boolean_avp;
	 dict_avp_data_t user_name_data = {
		 1,
		 0,
		 "User-Name",
		 AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,
		 AVP_FLAG_MANDATORY,
		 AVP_TYPE_OCTETSTRING
	 };
	 dict_avp_data_t sample_boolean_data = {
		 31337,
		 23455,
		 "Sample-Boolean",
		 AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,
		 AVP_FLAG_VENDOR,
		 AVP_TYPE_INTEGER32
	 };
	
 	 -- Create an AVP with a base type --
	 ret = dict_new ( DICT_AVP, &user_name_data, NULL, &user_name_avp );
	 
	 -- Create an AVP with a derived type --
	 ret = dict_search ( DICT_TYPE, TYPE_BY_NAME, "Boolean", &boolean_type, ENOENT);
	 ret = dict_new ( DICT_AVP, &sample_boolean_data , boolean_type, &sample_boolean_avp );
	 
 }

- dict_search:
 Sample code to look for an AVP
 {
	 int ret;
	 dict_object_t * avp_username;
	 dict_object_t * avp_sampleboolean;
	 dict_avp_request_t avp_by_name =
	 	{
		 .avp_vendor = 23455,
		 .avp_name   = "Sample-Boolean"
	 	};
	 
	 ret = dict_search ( DICT_AVP, AVP_BY_NAME, "User-Name", &avp_username, ENOENT);
	 
	 ret = dict_search ( DICT_AVP, AVP_BY_NAME_AND_VENDOR, &avp_by_name, &avp_sampleboolean, ENOENT);
	 
 }
 
 - dict_getval:
 Sample code to retrieve the data from an AVP object:
 {
	 int ret;
	 dict_object_t * avp_username;
	 dict_avp_data_t user_name_data;
	 ret = dict_search ( DICT_AVP, AVP_BY_NAME, "User-Name", &avp_username, ENOENT);
	 ret = dict_getval ( avp_username, &user_name_data );
	 printf("User-Name code: %d\n", user_name_data.avp_code );
 }

*/

/*
 ***************************************************************************
 *
 * Command object 
 *
 * These types are used to manage commands objects in the dictionary
 *
 ***************************************************************************
 */

/* Type to hold a Diameter command code: IANA assigned values. 0x0-0x7fffff=standard, 0x800000-0xfffffd=vendors, 0xfffffe-0xffffff=experimental */
typedef uint32_t	command_code_t;

/* Values of command flags */
#define CMD_FLAG_REQUEST	0x80
#define CMD_FLAG_PROXIABLE	0x40
#define CMD_FLAG_ERROR		0x20
#define CMD_FLAG_RETRANSMIT	0x10
#define CMD_FLAG_RESERVED5	0x08
#define CMD_FLAG_RESERVED6	0x04
#define CMD_FLAG_RESERVED7	0x02
#define CMD_FLAG_RESERVED8	0x01

/* Type to hold data associated to a command */
typedef struct {
	command_code_t	 cmd_code;	/* code of the command */
	char		*cmd_name;	/* Name of the command */
	uint8_t		 cmd_flag_mask;	/* Mask of fixed-value flags */
	uint8_t		 cmd_flag_val;	/* values of the fixed flags */
} dict_cmd_data_t;

/* The criteria for searching an avp object in the dictionary */
typedef enum {
	CMD_BY_NAME = 1,	/* "what" points to a string */
	CMD_BY_CODE_R_VAL,	/* "what" is a casted command_code_t (may not work on some architectures). The "Request" command is returned. */
	CMD_BY_CODE_A_VAL,	/* "what" is a casted command_code_t (may not work on some architectures). The "Answer" command is returned. */
	CMD_BY_CODE_R_REF,	/* "what" points to a command_code_t. The "Request" command is returned. */
	CMD_BY_CODE_A_REF,	/* "what" points to a command_code_t. The "Answer" command is returned. */
	CMD_ANSWER		/* "what" points to a dict_object_t of a request command. The "Answer" command is returned. */
} dict_criter_cmd_t;


/***
 *  API usage :

The "parent" parameter of dict_new may point to an application object to inform of what application defines the command.
Note that this is not mandatory since this information is not very useful.
The application associated to a command is retrieved with APPLICATION_OF_COMMAND search criteria on applications.

To create the rules for children of commands, see the DICT_RULE related part.

Note that the "Request" and "Answer" commands are two independant objects. This allows to have different rules for each.

- dict_new:
 Sample code for command creation:
 {
	 int ret;
	 dict_object_t * cer;
	 dict_object_t * cea;
	 dict_cmd_data_t ce_data = {
		 257,
		 "Capabilities-Exchange-Request",
		 CMD_FLAG_REQUEST,
		 CMD_FLAG_REQUEST
	 };
	
	 ret = dict_new ( DICT_COMMAND, &ce_data, NULL, &cer );
	 
	 ce_data.cmd_name = "Capabilities-Exchange-Answer";
	 ce_data.cmd_flag_val = 0;

	 ret = dict_new ( DICT_COMMAND, &ce_data, NULL, &cea );
 }

- dict_search:
 Sample code to look for a command
 {
	 int ret;
	 dict_object_t * cer;
	 ret = dict_search ( DICT_COMMAND, CMD_BY_NAME, "Capabilities-Exchange-Request", &cer, ENOENT);
	 - or -
	 ret = dict_search ( DICT_COMMAND, CMD_BY_CODE_R_VAL, 257, &cer, ENOENT);
 }
 
 - dict_getval:
 Sample code to retrieve the data from a command object:
 {
	 int ret;
	 dict_object_t * cer;
	 dict_object_t * cea;
	 dict_cmd_data_t cea_data;
	 ret = dict_search ( DICT_COMMAND, CMD_BY_NAME, "Capabilities-Exchange-Request", &cer, ENOENT);
	 ret = dict_search ( DICT_COMMAND, CMD_ANSWER, cer, &cea, ENOENT);
	 ret = dict_getval ( cea, &cea_data );
	 printf("Answer to CER: %s\n", cea_data.cmd_name );
 }

*/

/*
 ***************************************************************************
 *
 * Rule object
 *
 * These types are used to manage rules in the dictionary
 *
 ***************************************************************************
 */

/* This type defines the kind of rule that must be defined */
typedef enum {
	RULE_FIXED_HEAD = 1,		/* The AVP must be at the head of the group. The rule_order field is used to specify the position. */
	RULE_REQUIRED,			/* The AVP must be present in the parent, but its position is not defined. */
	RULE_OPTIONAL,			/* The AVP may be present in the message. Used to specify a max number of occurences for example */
	RULE_FIXED_TAIL			/* The AVP must be at the end of the group. The rule_order field is used to specify the position. */
} rule_position_t;

/* This type holds the values for the rule being defined */
typedef struct {
	dict_object_t	*rule_avp;	/* Pointer to the AVP object that is concerned by this rule */
	rule_position_t	 rule_position;	/* The position in which the rule_avp must appear in the parent */
	int		 rule_order;	/* for RULE_FIXED_* rules, the place. 1,2,3.. for HEAD rules; ...,3,2,1 for TAIL rules. */
	int	 	 rule_min;	/* Minimum number of occurences. -1 means "default": 0 for optional rules, 1 for other rules */
	int		 rule_max;	/* Maximum number of occurences. -1 means no maximum. 0 means the AVP is forbidden. */
	int		 rule_template;	/* Number of this AVP to place in a template message. Must be between rule_min and rule_max */
} dict_rule_data_t;

/* The criteria for searching a rule in the dictionary */
typedef enum {
	RULE_BY_AVP_AND_PARENT = 1	/* "what" points to a dict_rule_request_t -- see bellow */
} dict_criter_rule_t;

/* Data to pass a request for rule */
typedef struct {
	dict_object_t	*rule_parent;	/* The grouped avp or command to which the rule apply */
	dict_object_t	*rule_avp;	/* The AVP concerned by this rule */
} dict_rule_request_t;


/***
 *  API usage :

The "parent" parameter can not be NULL. It points to the object (grouped avp or command) to which this rule apply.

- dict_new:
 Sample code for rule creation. Let's create the Proxy-Info grouped AVP for example.
 {
	int ret;
	dict_object_t * proxy_info_avp;
	dict_object_t * proxy_host_avp;
	dict_object_t * proxy_state_avp;
	dict_object_t * diameteridentity_type;
	dict_rule_data_t rule_data;
	dict_type_data_t di_type_data = { AVP_TYPE_OCTETSTRING, "DiameterIdentity" };
	dict_avp_data_t proxy_info_data = { 284, 0, "Proxy-Info", AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, AVP_FLAG_MANDATORY, AVP_TYPE_GROUPED };
	dict_avp_data_t proxy_host_data = { 280, 0, "Proxy-Host", AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, AVP_FLAG_MANDATORY, AVP_TYPE_OCTETSTRING };
	dict_avp_data_t proxy_state_data = { 33, 0, "Proxy-State",AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, AVP_FLAG_MANDATORY, AVP_TYPE_OCTETSTRING };
	
	-- Create the parent AVP
	ret = dict_new ( DICT_AVP, &proxy_info_data, NULL, &proxy_info_avp );
	
	-- Create the first child AVP.
	ret = dict_new ( DICT_TYPE, &di_type_data, NULL, &diameteridentity_type );
	ret = dict_new ( DICT_AVP, &proxy_host_data, diameteridentity_type, &proxy_host_avp );
	
	-- Create the other child AVP
	ret = dict_new ( DICT_AVP, &proxy_state_data, NULL, &proxy_state_avp );
	
	-- Now we can create the rules. Both child AVP are mandatory.
	rule_data.rule_position = RULE_REQUIRED;
	rule_data.rule_min = -1;
	rule_data.rule_max = -1;
	rule_data.rule_template = 1;
	
	rule_data.rule_avp = proxy_host_avp;
	ret = dict_new ( DICT_RULE, &rule_data, proxy_info_avp, NULL );
	
	rule_data.rule_avp = proxy_state_avp;
	ret = dict_new ( DICT_RULE, &rule_data, proxy_info_avp, NULL );
}

- dict_search and dict_getval are similar to previous examples.

*/

#endif /*  _DICTIONARY_API_H  */
"Welcome to our mercurial repository"