Navigation


source: freeDiameter/include/freeDiameter/libfreeDiameter.h @ 29:5ba91682f0bc

Last change on this file since 29:5ba91682f0bc was 29:5ba91682f0bc, checked in by Sebastien Decugis <sdecugis@nict.go.jp>, 11 years ago

Added a test for cnxctx (tbc) and fixed some bugs

File size: 93.4 KB
Line 
1/*********************************************************************************************************
2* Software License Agreement (BSD License)                                                               *
3* Author: Sebastien Decugis <sdecugis@nict.go.jp>                                                        *
4*                                                                                                        *
5* Copyright (c) 2009, WIDE Project and NICT                                                              *
6* All rights reserved.                                                                                   *
7*                                                                                                        *
8* Redistribution and use of this software in source and binary forms, with or without modification, are  *
9* permitted provided that the following conditions are met:                                              *
10*                                                                                                        *
11* * Redistributions of source code must retain the above                                                 *
12*   copyright notice, this list of conditions and the                                                    *
13*   following disclaimer.                                                                                *
14*                                                                                                        *
15* * Redistributions in binary form must reproduce the above                                              *
16*   copyright notice, this list of conditions and the                                                    *
17*   following disclaimer in the documentation and/or other                                               *
18*   materials provided with the distribution.                                                            *
19*                                                                                                        *
20* * Neither the name of the WIDE Project or NICT nor the                                                 *
21*   names of its contributors may be used to endorse or                                                  *
22*   promote products derived from this software without                                                  *
23*   specific prior written permission of WIDE Project and                                                *
24*   NICT.                                                                                                *
25*                                                                                                        *
26* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED *
27* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
28* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR *
29* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT     *
30* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS    *
31* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR *
32* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF   *
33* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.                                                             *
34*********************************************************************************************************/
35
36/* This file contains the definitions of functions and types used by the libfreeDiameter library.
37 *
38 * This library is meant to be used by both the freeDiameter daemon and its extensions.
39 * It provides the tools to manipulate Diameter messages and related data.
40 * This file should always be included as #include <freeDiameter/libfreeDiameter.h>
41 *
42 * The file contains the following parts:
43 *      DEBUG
44 *      MACROS
45 *      THREADS
46 *      LISTS
47 *      DICTIONARY
48 *      SESSIONS
49 *      MESSAGES
50 *      DISPATCH
51 *      QUEUES
52 */
53
54#ifndef _LIBFREEDIAMETER_H
55#define _LIBFREEDIAMETER_H
56
57#ifndef FD_IS_CONFIG
58#error "You must include 'freeDiameter-host.h' before this file."
59#endif /* FD_IS_CONFIG */
60
61#include <pthread.h>
62#include <string.h>
63#include <assert.h>
64#include <errno.h>
65#include <arpa/inet.h>
66#include <sys/socket.h>
67#include <netdb.h>
68#include <stdio.h>
69#include <stdlib.h>
70#include <unistd.h>
71
72/*============================================================*/
73/*                          DEBUG                             */
74/*============================================================*/
75#ifndef ASSERT
76#define ASSERT(x) assert(x)
77#endif /* ASSERT */
78
79/*
80 * FUNCTION:    fd_log_debug
81 *
82 * PARAMETERS:
83 *  format      : Same format string as in the printf function
84 *  ...         : Same list as printf
85 *
86 * DESCRIPTION:
87 *  Log internal information for use of developpers only.
88 * The format and arguments may contain UTF-8 encoded data. The
89 * output medium (file or console) is expected to support this encoding.
90 *
91 * This function assumes that a global mutex called "fd_log_lock" exists
92 * in the address space of the current process.
93 *
94 * RETURN VALUE:
95 *  None.
96 */
97void fd_log_debug ( char * format, ... );
98extern pthread_mutex_t  fd_log_lock;
99
100/*
101 * FUNCTION:    fd_log_threadname
102 *
103 * PARAMETERS:
104 *  name        : \0-terminated string containing a name to identify the current thread.
105 *
106 * DESCRIPTION:
107 *  Name the current thread, useful for debugging multi-threaded problems.
108 *
109 * This function assumes that a global thread-specific key called "fd_log_thname" exists
110 * in the address space of the current process.
111 *
112 * RETURN VALUE:
113 *  None.
114 */
115void fd_log_threadname ( char * name );
116extern pthread_key_t    fd_log_thname;
117
118/*
119 * FUNCTION:    fd_log_time
120 *
121 * PARAMETERS:
122 *  ts          : The timestamp to log, or NULL for "now"
123 *  buf         : An array where the time must be stored
124 *  len         : size of the buffer
125 *
126 * DESCRIPTION:
127 *  Writes the timestamp (in human readable format) in a buffer.
128 *
129 * RETURN VALUE:
130 *  pointer to buf.
131 */
132char * fd_log_time ( struct timespec * ts, char * buf, size_t len );
133
134
135/* levels definitions */
136#define NONE 0  /* Display no debug message */
137#define INFO 1  /* Display errors only */
138#define FULL 2  /* Display additional information to follow code execution */
139#define ANNOYING 4 /* Very verbose, for example in loops */
140#define FCTS 6  /* Display entry parameters of most functions */
141#define CALL 9  /* Display calls to most functions (with CHECK macros) */
142
143/* Default level is INFO */
144#ifndef TRACE_LEVEL
145#define TRACE_LEVEL INFO
146#endif /* TRACE_LEVEL */
147
148/* The level of the file being compiled. */
149static int local_debug_level = TRACE_LEVEL;
150
151/* A global level, changed by configuration or cmd line for example. default is 0. */
152extern int fd_g_debug_lvl;
153
154/* Some portability code to get nice function name in __PRETTY_FUNCTION__ */
155#if __STDC_VERSION__ < 199901L
156# if __GNUC__ >= 2
157#  define __func__ __FUNCTION__
158# else /* __GNUC__ >= 2 */
159#  define __func__ "<unknown>"
160# endif /* __GNUC__ >= 2 */
161#endif /* __STDC_VERSION__ < 199901L */
162#ifndef __PRETTY_FUNCTION__
163#define __PRETTY_FUNCTION__ __func__
164#endif /* __PRETTY_FUNCTION__ */
165
166/* Boolean for tracing at a certain level */
167#define TRACE_BOOL(_level_) ( (_level_) <= local_debug_level + fd_g_debug_lvl )
168
169/* The general debug macro, each call results in two lines of debug messages (change the macro for more compact output) */
170#define TRACE_DEBUG(level,format,args... ) {                                                                                    \
171        if ( TRACE_BOOL(level) ) {                                                                                              \
172                char __buf[25];                                                                                                 \
173                char * __thn = ((char *)pthread_getspecific(fd_log_thname) ?: "unnamed");                                       \
174                fd_log_debug("\t | tid:%-20s\t%s\tin %s@%s:%d\n"                                                                \
175                          "\t%s|%*s" format "\n",                                                                               \
176                                        __thn, fd_log_time(NULL, __buf, sizeof(__buf)), __PRETTY_FUNCTION__, __FILE__, __LINE__,        \
177                                        (level < FULL)?"@":" ",level, "", ## args);                                             \
178        }                                                                                                                       \
179}
180
181/* Helper for function entry -- for very detailed trace of the execution */
182#define TRACE_ENTRY(_format,_args... ) \
183        TRACE_DEBUG(FCTS, "[enter] %s(" _format ") {" #_args "}", __PRETTY_FUNCTION__, ##_args );
184
185/* Helper for debugging by adding traces -- for debuging a specific location of the code */
186#define TRACE_HERE()    \
187        TRACE_DEBUG(NONE, " -- debug checkpoint -- ");
188
189/* Helper for tracing the CHECK_* macros bellow -- very very verbose code execution! */
190#define TRACE_DEBUG_ALL( str )  \
191        TRACE_DEBUG(CALL, str );
192
193/* For development only, to keep track of TODO locations in the code */
194#ifndef ERRORS_ON_TODO
195#define TODO( _msg, _args... ) \
196        TRACE_DEBUG(NONE, "TODO: " _msg , ##_args);
197#else /* ERRORS_ON_TODO */
198#define TODO( _msg, _args... ) \
199        "TODO" = _msg ## _args; /* just a stupid compilation error to spot the todo */
200#endif /* ERRORS_ON_TODO */
201
202
203/* Macros to check a return value and branch out in case of error.
204 * These macro must be used only when errors are highly improbable, not for expected errors.
205 */
206
207/* Check the return value of a system function and execute fallback in case of error */
208#define CHECK_SYS_DO( __call__, __fallback__  ) {                                       \
209        int __ret__;                                                                    \
210        TRACE_DEBUG_ALL( "Check SYS: " #__call__ );                                     \
211        __ret__ = (__call__);                                                           \
212        if (__ret__ < 0) {                                                              \
213                int __err__ = errno;    /* We may handle EINTR here */                  \
214                TRACE_DEBUG(NONE, "ERROR: in '" #__call__ "' :\t%s", strerror(__err__));\
215                __fallback__;                                                           \
216        }                                                                               \
217}
218/* Check the return value of a system function, return error code on error */
219#define CHECK_SYS( __call__  ) {                                                        \
220        int __ret__;                                                                    \
221        TRACE_DEBUG_ALL( "Check SYS: " #__call__ );                                     \
222        __ret__ = (__call__);                                                           \
223        if (__ret__ < 0) {                                                              \
224                int __err__ = errno;    /* We may handle EINTR here */                  \
225                TRACE_DEBUG(NONE, "ERROR: in '" #__call__ "' :\t%s", strerror(__err__));\
226                return __err__;                                                         \
227        }                                                                               \
228}
229
230/* Check the return value of a POSIX function and execute fallback in case of error or special value */
231#define CHECK_POSIX_DO2( __call__, __speval__, __fallback1__, __fallback2__ ) {                 \
232        int __ret__;                                                                            \
233        TRACE_DEBUG_ALL( "Check POSIX: " #__call__ );                                           \
234        __ret__ = (__call__);                                                                   \
235        if (__ret__ != 0) {                                                                     \
236                if (__ret__ == (__speval__)) {                                                  \
237                        __fallback1__;                                                          \
238                } else {                                                                        \
239                        TRACE_DEBUG(NONE, "ERROR: in '" #__call__ "':\t%s", strerror(__ret__)); \
240                        __fallback2__;                                                          \
241                }                                                                               \
242        }                                                                                       \
243}
244
245/* Check the return value of a POSIX function and execute fallback in case of error */
246#define CHECK_POSIX_DO( __call__, __fallback__ )                                        \
247        CHECK_POSIX_DO2( (__call__), 0, , __fallback__ );
248
249/* Check the return value of a POSIX function and return it if error */
250#define CHECK_POSIX( __call__ ) {                                                       \
251        int __v__;                                                                      \
252        CHECK_POSIX_DO( __v__ = (__call__), return __v__ );                             \
253}
254
255/* Check that a memory allocator did not return NULL, otherwise log an error and execute fallback */
256#define CHECK_MALLOC_DO( __call__, __fallback__ ) {                                     \
257        void *  __ret__;                                                                \
258        TRACE_DEBUG_ALL( "Check MALLOC: " #__call__ );                                  \
259        __ret__ = (void *)( __call__ );                                                 \
260        if (__ret__ == NULL) {                                                          \
261                int __err__ = errno;                                                    \
262                TRACE_DEBUG(NONE, "ERROR: in '" #__call__ "':\t%s", strerror(__err__)); \
263                __fallback__;                                                           \
264        }                                                                               \
265}
266
267/* Check that a memory allocator did not return NULL, otherwise return ENOMEM */
268#define CHECK_MALLOC( __call__ )                                                        \
269        CHECK_MALLOC_DO( __call__, return ENOMEM );
270
271
272/* The next macros can be used also for expected errors */
273
274/* Check parameters at function entry, execute fallback on error */
275#define CHECK_PARAMS_DO( __bool__, __fallback__ )                                       \
276        TRACE_DEBUG_ALL( "Check PARAMS: " #__bool__ );                                  \
277        if ( ! (__bool__) ) {                                                           \
278                TRACE_DEBUG(INFO, "Invalid parameter received in '" #__bool__ "'");     \
279                __fallback__;                                                           \
280        }
281/* Check parameters at function entry, return EINVAL if the boolean is false (similar to assert) */
282#define CHECK_PARAMS( __bool__ )                                                        \
283        CHECK_PARAMS_DO( __bool__, return EINVAL );
284
285/* Check the return value of an internal function, log and propagate */
286#define CHECK_FCT_DO( __call__, __fallback__ ) {                                        \
287        int __ret__;                                                                    \
288        TRACE_DEBUG_ALL( "Check FCT: " #__call__ );                                     \
289        __ret__ = (__call__);                                                           \
290        if (__ret__ != 0) {                                                             \
291                TRACE_DEBUG(INFO, "Error in '" #__call__ "':\t%s", strerror(__ret__));  \
292                __fallback__;                                                           \
293        }                                                                               \
294}
295/* Check the return value of a function call, return any error code */
296#define CHECK_FCT( __call__ ) {                                                         \
297        int __v__;                                                                      \
298        CHECK_FCT_DO( __v__ = (__call__), return __v__ );                               \
299}
300
301
302/*============================================================*/
303/*                          MACROS                            */
304/*============================================================*/
305
306/* helper macros (pre-processor hacks to allow macro arguments) */
307#define __str( arg )  #arg
308#define _stringize( arg ) __str( arg )
309#define __agr( arg1, arg2 ) arg1 ## arg2
310#define _aggregate( arg1, arg2 ) __agr( arg1, arg2 )
311
312/* Some aliases to socket addresses structures */
313#define sSS     struct sockaddr_storage
314#define sSA     struct sockaddr
315#define sSA4    struct sockaddr_in
316#define sSA6    struct sockaddr_in6
317
318/* Dump one sockaddr Node information */
319#define sSA_DUMP_NODE( sa, flag ) {                             \
320        sSA * __sa = (sSA *)(sa);                               \
321        char __addrbuf[INET6_ADDRSTRLEN];                       \
322        if (__sa) {                                             \
323          int __rc = getnameinfo(__sa,                          \
324                        sizeof(sSS),                            \
325                        __addrbuf,                              \
326                        sizeof(__addrbuf),                      \
327                        NULL,                                   \
328                        0,                                      \
329                        flag);                                  \
330          if (__rc)                                             \
331                fd_log_debug("%s", (char *)gai_strerror(__rc)); \
332          else                                                  \
333                fd_log_debug("%s", &__addrbuf[0]);              \
334        } else {                                                \
335                fd_log_debug("(NULL / ANY)");                   \
336        }                                                       \
337}
338/* Same but with the port (service) also */
339#define sSA_DUMP_NODE_SERV( sa, flag ) {                                \
340        sSA * __sa = (sSA *)(sa);                                       \
341        char __addrbuf[INET6_ADDRSTRLEN];                               \
342        char __servbuf[32];                                             \
343        if (__sa) {                                                     \
344          int __rc = getnameinfo(__sa,                                  \
345                        sizeof(sSS),                                    \
346                        __addrbuf,                                      \
347                        sizeof(__addrbuf),                              \
348                        __servbuf,                                      \
349                        sizeof(__servbuf),                              \
350                        flag);                                          \
351          if (__rc)                                                     \
352                fd_log_debug("%s", (char *)gai_strerror(__rc));         \
353          else                                                          \
354                fd_log_debug("[%s]:%s", &__addrbuf[0],&__servbuf[0]);   \
355        } else {                                                        \
356                fd_log_debug("(NULL / ANY)");                           \
357        }                                                               \
358}
359/* Inside a debug trace */
360#define TRACE_DEBUG_sSA(level, prefix, sa, flags, suffix ) {                                                                            \
361        if ( TRACE_BOOL(level) ) {                                                                                              \
362                char __buf[25];                                                                                                 \
363                char * __thn = ((char *)pthread_getspecific(fd_log_thname) ?: "unnamed");                                       \
364                fd_log_debug("\t | tid:%-20s\t%s\tin %s@%s:%d\n"                                                                \
365                          "\t%s|%*s" prefix ,                                                                                   \
366                                        __thn, fd_log_time(NULL, __buf, sizeof(__buf)), __PRETTY_FUNCTION__, __FILE__, __LINE__,\
367                                        (level < FULL)?"@":" ",level, "");                                                      \
368                sSA_DUMP_NODE_SERV( sa, flags );                                                                                \
369                fd_log_debug(suffix "\n");                                                                                      \
370        }                                                                                                                       \
371}
372
373
374/* A l4 protocol name (TCP / SCTP) */
375#define IPPROTO_NAME( _proto )                                  \
376        ( ((_proto) == IPPROTO_TCP) ? "TCP" :                   \
377                (((_proto) == IPPROTO_SCTP) ? "SCTP" :          \
378                        "Unknown"))
379
380/* The sockaddr length of a sSS structure */
381#define sSSlen( _ss_ )  \
382        ( (socklen_t) ( ((_ss_)->ss_family == AF_INET) ? (sizeof(sSA4)) :               \
383                                (((_ss_)->ss_family == AF_INET6) ? (sizeof(sSA6)) :     \
384                                        0 ) ) )
385
386/* Define the value of IP loopback address */
387#ifndef INADDR_LOOPBACK
388#define INADDR_LOOPBACK inet_addr("127.0.0.1")
389#endif /* INADDR_LOOPBACK */
390
391/* create a V4MAPPED address */
392#define IN6_ADDR_V4MAP( a6, a4 ) {                      \
393        ((uint32_t *)(a6))[0] = 0;                      \
394        ((uint32_t *)(a6))[1] = 0;                      \
395        ((uint32_t *)(a6))[2] = htonl(0xffff);          \
396        ((uint32_t *)(a6))[3] = (uint32_t)(a4);         \
397}
398
399/* Retrieve a v4 value from V4MAPPED address ( takes a s6_addr as param) */
400#define IN6_ADDR_V4UNMAP( a6 )                          \
401        (((in_addr_t *)(a6))[3])
402
403
404/* We provide macros to convert 64 bit values to and from network byte-order, on systems where it is not already provided. */
405#ifndef HAVE_NTOHLL     /* Defined in config.h, if the ntohll symbol is defined on the system */
406# if HOST_BIG_ENDIAN
407    /* In big-endian systems, we don't have to change the values, since the order is the same as network */
408#   define ntohll(x) (x)
409#   define htonll(x) (x)
410# else /* HOST_BIG_ENDIAN */
411    /* For these systems, we must reverse the bytes. Use ntohl and htonl on sub-32 blocs, and inverse these blocs. */
412#   define ntohll(x) (typeof (x))( (((uint64_t)ntohl( (uint32_t)(x))) << 32 ) | ((uint64_t) ntohl( ((uint64_t)(x)) >> 32 )))
413#   define htonll(x) (typeof (x))( (((uint64_t)htonl( (uint32_t)(x))) << 32 ) | ((uint64_t) htonl( ((uint64_t)(x)) >> 32 )))
414# endif /* HOST_BIG_ENDIAN */
415#endif /* HAVE_NTOHLL */
416
417/* This macro will give the next multiple of 4 for an integer (used for padding sizes of AVP). */
418#define PAD4(_x) ((_x) + ( (4 - (_x)) & 3 ) )
419
420/* Useful to display as safe ASCII a value (will garbage UTF-8 output...) */
421#define ASCII(_c) ( ((_c < 32) || (_c > 127)) ? ( _c ? '?' : ' ' ) : _c )
422
423/* Compare timespec structures */
424#define TS_IS_INFERIOR( ts1, ts2 )              \
425        (    ((ts1)->tv_sec  < (ts2)->tv_sec )  \
426          || (((ts1)->tv_sec  == (ts2)->tv_sec ) && ((ts1)->tv_nsec < (ts2)->tv_nsec) ))
427
428
429/* Trace a binary buffer content */
430#define TRACE_DEBUG_BUFFER(level, prefix, buf, bufsz, suffix ) {                                                                \
431        if ( TRACE_BOOL(level) ) {                                                                                              \
432                int __i;                                                                                                        \
433                size_t __sz = (size_t)(bufsz);                                                                                  \
434                uint8_t * __buf = (uint8_t *)(buf);                                                                             \
435                char * __thn = ((char *)pthread_getspecific(fd_log_thname) ?: "unnamed");                                       \
436                fd_log_debug("\t | tid:%-20s\t%s\tin %s@%s:%d\n"                                                                \
437                          "\t%s|%*s" prefix ,                                                                                   \
438                                        __thn, fd_log_time(NULL, __buf, sizeof(__buf)), __PRETTY_FUNCTION__, __FILE__, __LINE__,\
439                                        (level < FULL)?"@":" ",level, "");                                                      \
440                for (__i = 0; __i < __sz; __i++) {                                                                              \
441                        fd_log_debug("%02.2hhx", __buf[__i]);                                                                   \
442                }                                                                                                               \
443                fd_log_debug(suffix "\n");                                                                                      \
444        }                                                                                                                       \
445}
446
447
448
449/*============================================================*/
450/*                          THREADS                           */
451/*============================================================*/
452
453/* Terminate a thread */
454static __inline__ int fd_thr_term(pthread_t * th)
455{
456        int ret = 0;
457        void * th_ret = NULL;
458       
459        CHECK_PARAMS(th);
460       
461        /* Test if it was already terminated */
462        if (*th == (pthread_t)NULL)
463                return 0;
464       
465        /* Cancel the thread if it is still running - ignore error if it was already terminated */
466        (void) pthread_cancel(*th);
467       
468        /* Then join the thread */
469        CHECK_POSIX_DO( ret = pthread_join(*th, &th_ret), /* continue */ );
470       
471        if (th_ret != NULL) {
472                TRACE_DEBUG(ANNOYING, "The thread returned the following value: %p (ignored)", th_ret);
473        }
474       
475        /* Clean the location */
476        *th = (pthread_t)NULL;
477       
478        return ret;
479}
480
481/* Cleanups for cancellation (all threads should be safely cancelable...) */
482static __inline__ void fd_cleanup_mutex( void * mutex )
483{
484        CHECK_POSIX_DO( pthread_mutex_unlock((pthread_mutex_t *)mutex), /* */);
485}
486               
487static __inline__ void fd_cleanup_rwlock( void * rwlock )
488{
489        CHECK_POSIX_DO( pthread_rwlock_unlock((pthread_rwlock_t *)rwlock), /* */);
490}
491
492static __inline__ void fd_cleanup_buffer( void * buffer )
493{
494        free(buffer);
495}
496static __inline__ void fd_cleanup_socket(void * sockptr)
497{
498        if (sockptr) {
499                shutdown(*(int *)sockptr, SHUT_RDWR);
500                *(int *)sockptr = 0;
501        }
502}
503
504
505/*============================================================*/
506/*                          LISTS                             */
507/*============================================================*/
508
509/* The following structure represents a chained list element  */
510struct fd_list {
511        struct fd_list  *next; /* next element in the list */
512        struct fd_list  *prev; /* previous element in the list */
513        struct fd_list  *head; /* head of the list */
514        void            *o;    /* additional avialbe pointer used for start of the parento object or other purpose */
515};
516
517/* Initialize a list element */
518#define FD_LIST_INITIALIZER( _list_name ) \
519        { .next = & _list_name, .prev = & _list_name, .head = & _list_name, .o = NULL }
520#define FD_LIST_INITIALIZER_O( _list_name, _obj ) \
521        { .next = & _list_name, .prev = & _list_name, .head = & _list_name, .o = _obj }
522void fd_list_init ( struct fd_list * list, void *obj );
523
524/* Return boolean, true if the list is empty */
525#define FD_IS_LIST_EMPTY( _list ) ((((struct fd_list *)(_list))->head == (_list)) && (((struct fd_list *)(_list))->next == (_list)))
526
527/* Insert an item in a list at known position */
528void fd_list_insert_after  ( struct fd_list * ref, struct fd_list * item );
529void fd_list_insert_before ( struct fd_list * ref, struct fd_list * item );
530
531/* Move a list at the end of another */
532void fd_list_move_end(struct fd_list * ref, struct fd_list * senti);
533
534/* Insert an item in an ordered list -- ordering function provided. If duplicate object found, EEXIST and it is returned in ref_duplicate */
535int fd_list_insert_ordered( struct fd_list * head, struct fd_list * item, int (*cmp_fct)(void *, void *), void ** ref_duplicate);
536
537/* Unlink an item from a list */
538void fd_list_unlink ( struct fd_list * item );
539
540/* Compute a hash value of a string (session id, diameter id, ...) */
541uint32_t fd_hash ( char * string, size_t len );
542
543
544
545/*============================================================*/
546/*                        DICTIONARY                          */
547/*============================================================*/
548/* Structure that contains the complete dictionary definitions */
549struct dictionary;
550
551/* Structure that contains a dictionary object */
552struct dict_object;
553
554/* Types of object in the dictionary. */
555enum dict_object_type {
556        DICT_VENDOR     = 1,    /* Vendor */
557        DICT_APPLICATION,       /* Diameter Application */
558        DICT_TYPE,              /* AVP data type */
559        DICT_ENUMVAL,           /* Named constant (value of an enumerated AVP type) */
560        DICT_AVP,               /* AVP */
561        DICT_COMMAND,           /* Diameter Command */
562        DICT_RULE               /* a Rule for AVP in command or grouped AVP */
563#define DICT_TYPE_MAX   DICT_RULE
564};
565       
566/* Initialize a dictionary */
567int fd_dict_init(struct dictionary ** dict);
568/* Destroy a dictionary */
569int fd_dict_fini(struct dictionary ** dict);
570
571/*
572 * FUNCTION:    fd_dict_new
573 *
574 * PARAMETERS:
575 *  dict        : Pointer to the dictionnary where the object is created
576 *  type        : What kind of object must be created
577 *  data        : pointer to the data for the object.
578 *               type parameter is used to determine the type of data (see bellow for detail).
579 *  parent      : a reference to a parent object, if needed.
580 *  ref         : upon successful creation, reference to new object is stored here if !null.
581 *
582 * DESCRIPTION:
583 *  Create a new object in the dictionary.
584 *  See following object sections in this header file for more information on data and parent parameters format.
585 *
586 * RETURN VALUE:
587 *  0           : The object is created in the dictionary.
588 *  EINVAL      : A parameter is invalid.
589 *  EEXIST      : This object is already defined in the dictionary (with conflicting data).
590 *                If "ref" is not NULL, it points to the existing element on return.
591 *  (other standard errors may be returned, too, with their standard meaning. Example:
592 *    ENOMEM    : Memory allocation for the new object element failed.)
593 */
594int fd_dict_new ( struct dictionary * dict, enum dict_object_type type, void * data, struct dict_object * parent, struct dict_object **ref );
595
596/*
597 * FUNCTION:    fd_dict_search
598 *
599 * PARAMETERS:
600 *  dict        : Pointer to the dictionnary where the object is searched
601 *  type        : type of object that is being searched
602 *  criteria    : how the object must be searched. See object-related sections bellow for more information.
603 *  what        : depending on criteria, the data that must be searched.
604 *  result      : On successful return, pointer to the object is stored here.
605 *  retval      : this value is returned if the object is not found and result is not NULL.
606 *
607 * DESCRIPTION:
608 *   Perform a search in the dictionary.
609 *   See the object-specific sections bellow to find how to look for each objects.
610 *   If the "result" parameter is NULL, the function is used to check if an object is in the dictionary.
611 *   Otherwise, a reference to the object is stored in result if found.
612 *   If result is not NULL and the object is not found, retval is returned (should be 0 or ENOENT usually)
613 *
614 * RETURN VALUE:
615 *  0           : The object has been found in the dictionary, or *result is NULL.
616 *  EINVAL      : A parameter is invalid.
617 *  ENOENT      : No matching object has been found, and result was NULL.
618 */
619int fd_dict_search ( struct dictionary * dict, enum dict_object_type type, int criteria, void * what, struct dict_object **result, int retval );
620
621/* Special case: get the generic error command object */
622int fd_dict_get_error_cmd(struct dictionary * dict, struct dict_object **obj);
623
624/*
625 * FUNCTION:    fd_dict_getval
626 *
627 * PARAMETERS:
628 *  object      : Pointer to a dictionary object.
629 *  data        : pointer to a structure to hold the data for the object.
630 *                The type is the same as "data" parameter in fd_dict_new function.
631 *
632 * DESCRIPTION:
633 *  Retrieve content of a dictionary object.
634 *  See following object sections in this header file for more information on data and parent parameters format.
635 *
636 * RETURN VALUE:
637 *  0           : The content of the object has been retrieved.
638 *  EINVAL      : A parameter is invalid.
639 */
640int fd_dict_getval ( struct dict_object * object, void * val);
641int fd_dict_gettype ( struct dict_object * object, enum dict_object_type * type);
642int fd_dict_getdict ( struct dict_object * object, struct dictionary ** dict);
643
644/* Debug functions */
645void fd_dict_dump_object(struct dict_object * obj);
646void fd_dict_dump(struct dictionary * dict);
647
648
649/*
650 ***************************************************************************
651 *
652 * Vendor object
653 *
654 * These types are used to manage vendors in the dictionary
655 *
656 ***************************************************************************
657 */
658
659/* Type to hold a Vendor ID: "SMI Network Management Private Enterprise Codes" (RFC3232) */
660typedef uint32_t        vendor_id_t;
661
662/* Type to hold data associated to a vendor */
663struct dict_vendor_data {
664        vendor_id_t      vendor_id;     /* ID of a vendor */
665        char            *vendor_name;   /* The name of this vendor */
666};
667
668/* The criteria for searching a vendor object in the dictionary */
669enum {
670        VENDOR_BY_ID = 10,      /* "what" points to a vendor_id_t */
671        VENDOR_BY_NAME,         /* "what" points to a string */
672        VENDOR_OF_APPLICATION   /* "what" points to a struct dict_object containing an application (see bellow) */
673};
674
675/***
676 *  API usage :
677
678Note: the value of "vendor_name" is copied when the object is created, and the string may be disposed afterwards.
679On the other side, when value is retrieved with dict_getval, the string is not copied and MUST NOT be freed. It will
680be freed automatically along with the object itself with call to dict_fini later.
681 
682- fd_dict_new:
683 The "parent" parameter is not used for vendors.
684 Sample code to create a vendor:
685 {
686         int ret;
687         struct dict_object * myvendor;
688         struct dict_vendor_data myvendordata = { 23455, "my vendor name" };  -- just an example...
689         ret = fd_dict_new ( dict, DICT_VENDOR, &myvendordata, NULL, &myvendor );
690 }
691
692- fd_dict_search:
693 Sample codes to look for a vendor object, by its id or name:
694 {
695         int ret;
696         struct dict_object * vendor_found;
697         vendor_id_t vendorid = 23455;
698         ret = fd_dict_search ( dict, DICT_VENDOR, VENDOR_BY_ID, &vendorid, &vendor_found, ENOENT);
699         - or -
700         ret = fd_dict_search ( dict, DICT_VENDOR, VENDOR_BY_NAME, "my vendor name", &vendor_found, ENOENT);
701 }
702 
703 - fd_dict_getval:
704 Sample code to retrieve the data from a vendor object:
705 {
706         int ret;
707         struct dict_object * myvendor;
708         struct dict_vendor_data myvendordata;
709         ret = fd_dict_search ( dict, DICT_VENDOR, VENDOR_BY_NAME, "my vendor name", &myvendor, ENOENT);
710         ret = fd_dict_getval ( myvendor, &myvendordata );
711         printf("my vendor id: %d\n", myvendordata.vendor_id );
712 }
713                 
714 
715*/
716         
717/*
718 ***************************************************************************
719 *
720 * Application object
721 *
722 * These types are used to manage Diameter applications in the dictionary
723 *
724 ***************************************************************************
725 */
726
727/* Type to hold a Diameter application ID: IANA assigned value for this application. */
728typedef uint32_t        application_id_t;
729
730/* Type to hold data associated to an application */
731struct dict_application_data {
732        application_id_t         application_id;        /* ID of the application */
733        char                    *application_name;      /* The name of this application */
734};
735
736/* The criteria for searching an application object in the dictionary */
737enum {
738        APPLICATION_BY_ID = 20,         /* "what" points to a application_id_t */
739        APPLICATION_BY_NAME,            /* "what" points to a string */
740        APPLICATION_OF_TYPE,            /* "what" points to a struct dict_object containing a type object (see bellow) */
741        APPLICATION_OF_COMMAND          /* "what" points to a struct dict_object containing a command (see bellow) */
742};
743
744/***
745 *  API usage :
746
747The "parent" parameter of dict_new may point to a vendor object to inform of what vendor defines the application.
748for standard-track applications, the "parent" parameter should be NULL.
749The vendor associated to an application is retrieved with VENDOR_OF_APPLICATION search criteria on vendors.
750
751- fd_dict_new:
752 Sample code for application creation:
753 {
754         int ret;
755         struct dict_object * vendor;
756         struct dict_object * appl;
757         struct dict_vendor_data vendor_data = {
758                 23455,
759                 "my vendor name"
760         };
761         struct dict_application_data app_data = {
762                 9789,
763                 "my vendor's application"
764         };
765       
766         ret = fd_dict_new ( dict, DICT_VENDOR, &vendor_data, NULL, &vendor );
767         ret = fd_dict_new ( dict, DICT_APPLICATION, &app_data, vendor, &appl );
768 }
769
770- fd_dict_search:
771 Sample code to retrieve the vendor of an application
772 {
773         int ret;
774         struct dict_object * vendor, * appli;
775         
776         ret = fd_dict_search ( dict, DICT_APPLICATION, APPLICATION_BY_NAME, "my vendor's application", &appli, ENOENT);
777         ret = fd_dict_search ( dict, DICT_VENDOR, VENDOR_OF_APPLICATION, appli, &vendor, ENOENT);
778 }
779 
780 - fd_dict_getval:
781 Sample code to retrieve the data from an application object:
782 {
783         int ret;
784         struct dict_object * appli;
785         struct dict_application_data appl_data;
786         ret = fd_dict_search ( dict, DICT_APPLICATION, APPLICATION_BY_NAME, "my vendor's application", &appli, ENOENT);
787         ret = fd_dict_getval ( appli, &appl_data );
788         printf("my application id: %s\n", appl_data.application_id );
789 }
790
791*/
792
793/*
794 ***************************************************************************
795 *
796 * Type object
797 *
798 * These types are used to manage AVP data types in the dictionary
799 *
800 ***************************************************************************
801 */
802
803/* Type to store any AVP value */ 
804union avp_value {
805        struct {
806                uint8_t *data;  /* bytes buffer */
807                size_t   len;   /* length of the data buffer */
808        }           os;         /* Storage for an octet string, data is alloc'd and must be freed */
809        int32_t     i32;        /* integer 32 */
810        int64_t     i64;        /* integer 64 */
811        uint32_t    u32;        /* unsigned 32 */
812        uint64_t    u64;        /* unsigned 64 */
813        float       f32;        /* float 32 */
814        double      f64;        /* float 64 */
815};
816
817/* These are the basic AVP types defined in RFC3588bis */
818enum dict_avp_basetype {
819        AVP_TYPE_GROUPED,
820        AVP_TYPE_OCTETSTRING,
821        AVP_TYPE_INTEGER32,
822        AVP_TYPE_INTEGER64,
823        AVP_TYPE_UNSIGNED32,
824        AVP_TYPE_UNSIGNED64,
825        AVP_TYPE_FLOAT32,
826        AVP_TYPE_FLOAT64
827#define AVP_TYPE_MAX AVP_TYPE_FLOAT64
828};
829
830/* Callbacks that can be associated with a derived type to easily interpret the AVP value. */
831/*
832 * CALLBACK:    dict_avpdata_interpret
833 *
834 * PARAMETERS:
835 *   val         : Pointer to the AVP value that must be interpreted.
836 *   interpreted : The result of interpretation is stored here. The format and meaning depends on each type.
837 *
838 * DESCRIPTION:
839 *   This callback can be provided with a derived type in order to facilitate the interpretation of formated data.
840 *  For example, when an AVP of type "Address" is received, it can be used to convert the octetstring into a struct sockaddr.
841 *  This callback is not called directly, but through the message's API msg_avp_value_interpret function.
842 *
843 * RETURN VALUE:
844 *  0           : Operation complete.
845 *  !0          : An error occurred, the error code is returned.
846 */
847typedef int (*dict_avpdata_interpret) (union avp_value * value, void * interpreted);
848/*
849 * CALLBACK:    dict_avpdata_encode
850 *
851 * PARAMETERS:
852 *   data       : The formated data that must be stored in the AVP value.
853 *   val        : Pointer to the AVP value storage area where the data must be stored.
854 *
855 * DESCRIPTION:
856 *   This callback can be provided with a derived type in order to facilitate the encoding of formated data.
857 *  For example, it can be used to convert a struct sockaddr in an AVP value of type Address.
858 *  This callback is not called directly, but through the message's API msg_avp_value_encode function.
859 *  If the callback is defined for an OctetString based type, the created string must be malloc'd. free will be called
860 *  automatically later.
861 *
862 * RETURN VALUE:
863 *  0           : Operation complete.
864 *  !0          : An error occurred, the error code is returned.
865 */
866typedef int (*dict_avpdata_encode) (void * data, union avp_value * val);
867
868
869/* Type to hold data associated to a derived AVP data type */
870struct dict_type_data {
871        enum dict_avp_basetype   type_base;     /* How the data of such AVP must be interpreted */
872        char                    *type_name;     /* The name of this type */
873        dict_avpdata_interpret   type_interpret;/* cb to convert the AVP value in more comprehensive format (or NULL) */
874        dict_avpdata_encode      type_encode;   /* cb to convert formatted data into an AVP value (or NULL) */
875};
876
877/* The criteria for searching a type object in the dictionary */
878enum {
879        TYPE_BY_NAME = 30,              /* "what" points to a string */
880        TYPE_OF_ENUMVAL,                /* "what" points to a struct dict_object containing an enumerated constant (DICT_ENUMVAL, see bellow). */
881        TYPE_OF_AVP                     /* "what" points to a struct dict_object containing an AVP object. */
882};
883
884
885/***
886 *  API usage :
887
888- fd_dict_new:
889 The "parent" parameter may point to an application object, when a type is defined by a Diameter application.
890 
891 Sample code:
892 {
893         int ret;
894         struct dict_object * mytype;
895         struct dict_type_data mytypedata =
896                {
897                 AVP_TYPE_OCTETSTRING,
898                 "Address",
899                 NULL,
900                 NULL
901                };
902         ret = fd_dict_new ( dict, DICT_TYPE, &mytypedata, NULL, &mytype );
903 }
904
905- fd_dict_search:
906 Sample code:
907 {
908         int ret;
909         struct dict_object * address_type;
910         ret = fd_dict_search ( dict, DICT_TYPE, TYPE_BY_NAME, "Address", &address_type, ENOENT);
911 }
912 
913*/
914         
915/*
916 ***************************************************************************
917 *
918 * Enumerated values object
919 *
920 * These types are used to manage named constants of some AVP,
921 * for enumerated types. Waaad allows contants for types others than Unsigned32
922 *
923 ***************************************************************************
924 */
925
926/* Type to hold data of named constants for AVP */
927struct dict_enumval_data {
928        char            *enum_name;     /* The name of this constant */
929        union avp_value  enum_value;    /* Value of the constant. Union term depends on parent type's base type. */
930};
931
932/* The criteria for searching a constant in the dictionary */
933enum {
934        ENUMVAL_BY_STRUCT = 40, /* "what" points to a struct dict_enumval_request as defined bellow */
935};
936
937struct dict_enumval_request {
938        /* Identifier of the parent type, one of the following must not be NULL */
939        struct dict_object      *type_obj;
940        char                    *type_name;
941       
942        /* Search criteria for the constant */
943        struct dict_enumval_data search; /* search.enum_value is used only if search.enum_name == NULL */
944};
945
946/***
947 *  API usage :
948
949- fd_dict_new:
950 The "parent" parameter must point to a derived type object.
951 Sample code to create a type "Boolean" with two constants "True" and "False":
952 {
953         int ret;
954         struct dict_object * type_boolean;
955         struct dict_type_data type_boolean_data =
956                {
957                 AVP_TYPE_INTEGER32,
958                 "Boolean",
959                 NULL,
960                 NULL
961                };
962         struct dict_enumval_data boolean_false =
963                {
964                 .enum_name="False",
965                 .enum_value.i32 = 0
966                };
967         struct dict_enumval_data boolean_true =
968                {
969                 .enum_name="True",
970                 .enum_value.i32 = -1
971                };
972         ret = fd_dict_new ( dict, DICT_TYPE, &type_boolean_data, NULL, &type_boolean );
973         ret = fd_dict_new ( dict, DICT_ENUMVAL, &boolean_false, type_boolean, NULL );
974         ret = fd_dict_new ( dict, DICT_ENUMVAL, &boolean_true , type_boolean, NULL );
975         
976 }
977
978- fd_dict_search:
979 Sample code to look for a constant name, by its value:
980 {
981         int ret;
982         struct dict_object * value_found;
983         struct dict_enumval_request boolean_by_value =
984                {
985                 .type_name = "Boolean",
986                 .search.enum_name=NULL,
987                 .search.enum_value.i32 = -1
988                };
989         
990         ret = fd_dict_search ( dict, DICT_ENUMVAL, ENUMVAL_BY_STRUCT, &boolean_by_value, &value_found, ENOENT);
991 }
992 
993 - fd_dict_getval:
994 Sample code to retrieve the data from a constant object:
995 {
996         int ret;
997         struct dict_object * value_found;
998         struct dict_enumval_data boolean_data = NULL;
999         struct dict_enumval_request boolean_by_value =
1000                {
1001                 .type_name = "Boolean",
1002                 .search.enum_name=NULL,
1003                 .search.enum_value.i32 = 0
1004                };
1005         
1006         ret = fd_dict_search ( dict, DICT_ENUMVAL, ENUMVAL_BY_STRUCT, &boolean_by_value, &value_found, ENOENT);
1007         ret = fd_dict_getval ( value_found, &boolean_data );
1008         printf(" Boolean with value 0: %s", boolean_data.enum_name );
1009 }
1010*/
1011         
1012/*
1013 ***************************************************************************
1014 *
1015 * AVP object
1016 *
1017 * These objects are used to manage AVP definitions in the dictionary
1018 *
1019 ***************************************************************************
1020 */
1021
1022/* Type to hold an AVP code. For vendor 0, these codes are assigned by IANA. Otherwise, it is managed by the vendor */
1023typedef uint32_t        avp_code_t;
1024
1025/* Values of AVP flags */
1026#define AVP_FLAG_VENDOR         0x80
1027#define AVP_FLAG_MANDATORY      0x40
1028#define AVP_FLAG_RESERVED3      0x20
1029#define AVP_FLAG_RESERVED4      0x10
1030#define AVP_FLAG_RESERVED5      0x08
1031#define AVP_FLAG_RESERVED6      0x04
1032#define AVP_FLAG_RESERVED7      0x02
1033#define AVP_FLAG_RESERVED8      0x01
1034
1035/* For dumping flags and values */
1036#define DUMP_AVPFL_str  "%c%c"
1037#define DUMP_AVPFL_val(_val) (_val & AVP_FLAG_VENDOR)?'V':'-' , (_val & AVP_FLAG_MANDATORY)?'M':'-'
1038
1039/* Type to hold data associated to an avp */
1040struct dict_avp_data {
1041        avp_code_t               avp_code;      /* Code of the avp */
1042        vendor_id_t              avp_vendor;    /* Vendor of the AVP, or 0 */
1043        char                    *avp_name;      /* Name of this AVP */
1044        uint8_t                  avp_flag_mask; /* Mask of fixed AVP flags */
1045        uint8_t                  avp_flag_val;  /* Values of the fixed flags */
1046        enum dict_avp_basetype   avp_basetype;  /* Basic type of data found in the AVP */
1047};
1048
1049/* The criteria for searching an avp object in the dictionary */
1050enum {
1051        AVP_BY_CODE = 50,       /* "what" points to an avp_code_t, vendor is always 0 */
1052        AVP_BY_NAME,            /* "what" points to a string, vendor is always 0 */
1053        AVP_BY_CODE_AND_VENDOR, /* "what" points to a struct dict_avp_request (see bellow), where avp_vendor and avp_code are set */
1054        AVP_BY_NAME_AND_VENDOR  /* "what" points to a struct dict_avp_request (see bellow), where avp_vendor and avp_name are set */
1055};
1056
1057/* Struct used for some researchs */
1058struct dict_avp_request {
1059        vendor_id_t      avp_vendor;
1060        avp_code_t       avp_code;
1061        char            *avp_name;
1062};
1063
1064
1065/***
1066 *  API usage :
1067
1068If "parent" parameter is not NULL during AVP creation, it must point to a DICT_TYPE object.
1069The extended type is then attached to the AVP. In case where it is an enumerated type, the value of
1070AVP is automatically interpreted in debug messages, and in message checks.
1071The derived type of an AVP can be retrieved with: dict_search ( DICT_TYPE, TYPE_OF_AVP, avp, ... )
1072
1073To create the rules (ABNF) for children of Grouped AVP, see the DICT_RULE related part.
1074
1075- fd_dict_new:
1076 Sample code for AVP creation:
1077 {
1078         int ret;
1079         struct dict_object * user_name_avp;
1080         struct dict_object * boolean_type;
1081         struct dict_object * sample_boolean_avp;
1082         struct dict_avp_data user_name_data = {
1083                 1,                                     // code
1084                 0,                                     // vendor
1085                 "User-Name",                           // name
1086                 AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,  // fixed mask: V and M values must always be defined as follow. other flags can be set or cleared
1087                 AVP_FLAG_MANDATORY,                    // the V flag must be cleared, the M flag must be set.
1088                 AVP_TYPE_OCTETSTRING                   // User-Name AVP contains OctetString data (further precision such as UTF8String can be given with a parent derived type)
1089         };
1090         struct dict_avp_data sample_boolean_data = {
1091                 31337,
1092                 23455,
1093                 "Sample-Boolean",
1094                 AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY,
1095                 AVP_FLAG_VENDOR,
1096                 AVP_TYPE_INTEGER32                     // This MUST be the same as parent type's
1097         };
1098       
1099         -- Create an AVP with a base type --
1100         ret = fd_dict_new ( dict, DICT_AVP, &user_name_data, NULL, &user_name_avp );
1101         
1102         -- Create an AVP with a derived type --
1103         ret = fd_dict_search ( dict, DICT_TYPE, TYPE_BY_NAME, "Boolean", &boolean_type, ENOENT);
1104         ret = fd_dict_new ( dict, DICT_AVP, &sample_boolean_data , boolean_type, &sample_boolean_avp );
1105         
1106 }
1107
1108- fd_dict_search:
1109 Sample code to look for an AVP
1110 {
1111         int ret;
1112         struct dict_object * avp_username;
1113         struct dict_object * avp_sampleboolean;
1114         struct dict_avp_request avpvendorboolean =
1115                {
1116                 .avp_vendor = 23455,
1117                 .avp_name   = "Sample-Boolean"
1118                };
1119         
1120         ret = fd_dict_search ( dict, DICT_AVP, AVP_BY_NAME, "User-Name", &avp_username, ENOENT);
1121         
1122         ret = fd_dict_search ( dict, DICT_AVP, AVP_BY_NAME_AND_VENDOR, &avpvendorboolean, &avp_sampleboolean, ENOENT);
1123         
1124 }
1125 
1126 - fd_dict_getval:
1127 Sample code to retrieve the data from an AVP object:
1128 {
1129         int ret;
1130         struct dict_object * avp_username;
1131         struct dict_avp_data user_name_data;
1132         ret = fd_dict_search ( dict, DICT_AVP, AVP_BY_NAME, "User-Name", &avp_username, ENOENT);
1133         ret = fd_dict_getval ( avp_username, &user_name_data );
1134         printf("User-Name code: %d\n", user_name_data.avp_code );
1135 }
1136
1137*/
1138
1139/*
1140 ***************************************************************************
1141 *
1142 * Command object
1143 *
1144 * These types are used to manage commands objects in the dictionary
1145 *
1146 ***************************************************************************
1147 */
1148
1149/* Type to hold a Diameter command code: IANA assigned values. 0x0-0x7fffff=standard, 0x800000-0xfffffd=vendors, 0xfffffe-0xffffff=experimental */
1150typedef uint32_t        command_code_t;
1151
1152/* Values of command flags */
1153#define CMD_FLAG_REQUEST        0x80
1154#define CMD_FLAG_PROXIABLE      0x40
1155#define CMD_FLAG_ERROR          0x20
1156#define CMD_FLAG_RETRANSMIT     0x10
1157#define CMD_FLAG_RESERVED5      0x08
1158#define CMD_FLAG_RESERVED6      0x04
1159#define CMD_FLAG_RESERVED7      0x02
1160#define CMD_FLAG_RESERVED8      0x01
1161
1162/* For dumping flags and values */
1163#define DUMP_CMDFL_str  "%c%c%c%c"
1164#define DUMP_CMDFL_val(_val) (_val & CMD_FLAG_REQUEST)?'R':'-' , (_val & CMD_FLAG_PROXIABLE)?'P':'-' , (_val & CMD_FLAG_ERROR)?'E':'-' , (_val & CMD_FLAG_RETRANSMIT)?'T':'-'
1165
1166/* Type to hold data associated to a command */
1167struct dict_cmd_data {
1168        command_code_t   cmd_code;      /* code of the command */
1169        char            *cmd_name;      /* Name of the command */
1170        uint8_t          cmd_flag_mask; /* Mask of fixed-value flags */
1171        uint8_t          cmd_flag_val;  /* values of the fixed flags */
1172};
1173
1174/* The criteria for searching an avp object in the dictionary */
1175enum {
1176        CMD_BY_NAME = 60,       /* "what" points to a string */
1177        CMD_BY_CODE_R,          /* "what" points to a command_code_t. The "Request" command is returned. */
1178        CMD_BY_CODE_A,          /* "what" points to a command_code_t. The "Answer" command is returned. */
1179        CMD_ANSWER              /* "what" points to a struct dict_object of a request command. The corresponding "Answer" command is returned. */
1180};
1181
1182
1183/***
1184 *  API usage :
1185
1186The "parent" parameter of dict_new may point to an application object to inform of what application defines the command.
1187The application associated to a command is retrieved with APPLICATION_OF_COMMAND search criteria on applications.
1188
1189To create the rules for children of commands, see the DICT_RULE related part.
1190
1191Note that the "Request" and "Answer" commands are two independant objects. This allows to have different rules for each.
1192
1193- fd_dict_new:
1194 Sample code for command creation:
1195 {
1196         int ret;
1197         struct dict_object * cer;
1198         struct dict_object * cea;
1199         struct dict_cmd_data ce_data = {
1200                 257,                                   // code
1201                 "Capabilities-Exchange-Request",       // name
1202                 CMD_FLAG_REQUEST,                      // mask
1203                 CMD_FLAG_REQUEST                       // value. Only the "R" flag is constrained here, set.
1204         };
1205       
1206         ret = fd_dict_new (dict,  DICT_COMMAND, &ce_data, NULL, &cer );
1207         
1208         ce_data.cmd_name = "Capabilities-Exchange-Answer";
1209         ce_data.cmd_flag_val = 0;                      // Same constraint on "R" flag, but this time it must be cleared.
1210
1211         ret = fd_dict_new ( dict, DICT_COMMAND, &ce_data, NULL, &cea );
1212 }
1213
1214- fd_dict_search:
1215 Sample code to look for a command
1216 {
1217         int ret;
1218         struct dict_object * cer, * cea;
1219         command_code_t code = 257;
1220         ret = fd_dict_search ( dict, DICT_COMMAND, CMD_BY_NAME, "Capabilities-Exchange-Request", &cer, ENOENT);
1221         ret = fd_dict_search ( dict, DICT_COMMAND, CMD_BY_CODE_R, &code, &cer, ENOENT);
1222 }
1223 
1224 - fd_dict_getval:
1225 Sample code to retrieve the data from a command object:
1226 {
1227         int ret;
1228         struct dict_object * cer;
1229         struct dict_object * cea;
1230         struct dict_cmd_data cea_data;
1231         ret = fd_dict_search ( dict, DICT_COMMAND, CMD_BY_NAME, "Capabilities-Exchange-Request", &cer, ENOENT);
1232         ret = fd_dict_search ( dict, DICT_COMMAND, CMD_ANSWER, cer, &cea, ENOENT);
1233         ret = fd_dict_getval ( cea, &cea_data );
1234         printf("Answer to CER: %s\n", cea_data.cmd_name );
1235 }
1236
1237*/
1238
1239/*
1240 ***************************************************************************
1241 *
1242 * Rule object
1243 *
1244 * These objects are used to manage rules in the dictionary (ABNF implementation)
1245 * This is used for checking messages validity (more powerful than a DTD)
1246 *
1247 ***************************************************************************
1248 */
1249
1250/* This defines the kind of rule that is defined */
1251enum rule_position {
1252        RULE_FIXED_HEAD = 1,    /* The AVP must be at the head of the group. The rule_order field is used to specify the position. */
1253        RULE_REQUIRED,          /* The AVP must be present in the parent, but its position is not defined. */
1254        RULE_OPTIONAL,          /* The AVP may be present in the message. Used to specify a max number of occurences for example */
1255        RULE_FIXED_TAIL         /* The AVP must be at the end of the group. The rule_order field is used to specify the position. */
1256};
1257
1258/* Content of a RULE object data */
1259struct dict_rule_data {
1260        struct dict_object      *rule_avp;      /* Pointer to the AVP object that is concerned by this rule */
1261        enum rule_position       rule_position; /* The position in which the rule_avp must appear in the parent */
1262        unsigned                 rule_order;    /* for RULE_FIXED_* rules, the place. 1,2,3.. for HEAD rules; ...,3,2,1 for TAIL rules. */
1263        int                      rule_min;      /* Minimum number of occurences. -1 means "default": 0 for optional rules, 1 for other rules */
1264        int                      rule_max;      /* Maximum number of occurences. -1 means no maximum. 0 means the AVP is forbidden. */
1265};
1266
1267/* The criteria for searching a rule in the dictionary */
1268enum {
1269        RULE_BY_AVP_AND_PARENT = 70     /* "what" points to a struct dict_rule_request -- see bellow. This is used to query "what is the rule for this AVP in this group?" */
1270};
1271
1272/* Structure for querying the dictionary about a rule */
1273struct dict_rule_request {
1274        struct dict_object      *rule_parent;   /* The grouped avp or command to which the rule apply */
1275        struct dict_object      *rule_avp;      /* The AVP concerned by this rule */
1276};
1277
1278
1279/***
1280 *  API usage :
1281
1282The "parent" parameter can not be NULL. It points to the object (grouped avp or command) to which this rule apply (i.e. for which the ABNF is defined).
1283
1284- fd_dict_new:
1285 Sample code for rule creation. Let's create the Proxy-Info grouped AVP for example.
1286 {
1287        int ret;
1288        struct dict_object * proxy_info_avp;
1289        struct dict_object * proxy_host_avp;
1290        struct dict_object * proxy_state_avp;
1291        struct dict_object * diameteridentity_type;
1292        struct dict_rule_data rule_data;
1293        struct dict_type_data di_type_data = { AVP_TYPE_OCTETSTRING, "DiameterIdentity", NULL, NULL };
1294        struct dict_avp_data proxy_info_data = { 284, 0, "Proxy-Info", AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, AVP_FLAG_MANDATORY, AVP_TYPE_GROUPED };
1295        struct dict_avp_data proxy_host_data = { 280, 0, "Proxy-Host", AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, AVP_FLAG_MANDATORY, AVP_TYPE_OCTETSTRING };
1296        struct dict_avp_data proxy_state_data = { 33, 0, "Proxy-State",AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, AVP_FLAG_MANDATORY, AVP_TYPE_OCTETSTRING };
1297       
1298        -- Create the parent AVP
1299        ret = fd_dict_new ( dict, DICT_AVP, &proxy_info_data, NULL, &proxy_info_avp );
1300       
1301        -- Create the first child AVP.
1302        ret = fd_dict_new ( dict, DICT_TYPE, &di_type_data, NULL, &diameteridentity_type );
1303        ret = fd_dict_new ( dict, DICT_AVP, &proxy_host_data, diameteridentity_type, &proxy_host_avp );
1304       
1305        -- Create the other child AVP
1306        ret = fd_dict_new ( dict, DICT_AVP, &proxy_state_data, NULL, &proxy_state_avp );
1307       
1308        -- Now we can create the rules. Both children AVP are mandatory.
1309        rule_data.rule_position = RULE_REQUIRED;
1310        rule_data.rule_min = -1;
1311        rule_data.rule_max = -1;
1312       
1313        rule_data.rule_avp = proxy_host_avp;
1314        ret = fd_dict_new ( dict, DICT_RULE, &rule_data, proxy_info_avp, NULL );
1315       
1316        rule_data.rule_avp = proxy_state_avp;
1317        ret = fd_dict_new ( dict, DICT_RULE, &rule_data, proxy_info_avp, NULL );
1318}
1319
1320- fd_dict_search and fd_dict_getval are similar to previous examples.
1321
1322*/
1323               
1324/* Define some hard-coded values */
1325/* Commands Codes */
1326#define CC_CAPABILITIES_EXCHANGE        257
1327#define CC_RE_AUTH                      258
1328#define CC_ACCOUNTING                   271
1329#define CC_ABORT_SESSION                274
1330#define CC_SESSION_TERMINATION          275
1331#define CC_DEVICE_WATCHDOG              280
1332#define CC_DISCONNECT_PEER              282
1333
1334/* AVPs (Vendor 0) */
1335#define AC_PROXY_STATE                  33
1336#define AC_HOST_IP_ADDRESS              257
1337#define AC_AUTH_APPLICATION_ID          258
1338#define AC_ACCT_APPLICATION_ID          259
1339#define AC_VENDOR_SPECIFIC_APPLICATION_ID 260
1340#define AC_REDIRECT_HOST_USAGE          261
1341#define AC_REDIRECT_MAX_CACHE_TIME      262
1342#define AC_SESSION_ID                   263
1343#define AC_ORIGIN_HOST                  264
1344#define AC_SUPPORTED_VENDOR_ID          265
1345#define AC_VENDOR_ID                    266
1346#define AC_FIRMWARE_REVISION            267
1347#define AC_RESULT_CODE                  268
1348#define AC_PRODUCT_NAME                 269
1349#define AC_DISCONNECT_CAUSE             273
1350#define ACV_DC_REBOOTING                        0
1351#define ACV_DC_BUSY                             1
1352#define ACV_DC_NOT_FRIEND                       2
1353#define AC_ORIGIN_STATE_ID              278
1354#define AC_FAILED_AVP                   279
1355#define AC_PROXY_HOST                   280
1356#define AC_ERROR_MESSAGE                281
1357#define AC_ROUTE_RECORD                 282
1358#define AC_DESTINATION_REALM            283
1359#define AC_PROXY_INFO                   284
1360#define AC_REDIRECT_HOST                292
1361#define AC_DESTINATION_HOST             293
1362#define AC_ERROR_REPORTING_HOST         294
1363#define AC_ORIGIN_REALM                 296
1364#define AC_INBAND_SECURITY_ID           299
1365
1366/* Error codes */
1367#define ER_DIAMETER_SUCCESS                     2001
1368#define ER_DIAMETER_REALM_NOT_SERVED            3003
1369#define ER_DIAMETER_TOO_BUSY                    3004
1370#define ER_DIAMETER_REDIRECT_INDICATION         3006
1371
1372
1373/*============================================================*/
1374/*                         SESSIONS                           */
1375/*============================================================*/
1376
1377/* Modules that want to associate a state with a Session-Id must first register a handler of this type */
1378struct session_handler;
1379
1380/* This opaque structure represents a session associated with a Session-Id */
1381struct session;
1382
1383/* The state information that a module associate with a session -- each module define its own data format */
1384typedef void session_state;
1385
1386/*
1387 * FUNCTION:    fd_sess_handler_create
1388 *
1389 * PARAMETERS:
1390 *  handler     : location where the new handler must be stored.
1391 *  cleanup     : a callback function that must be called when the session with associated data is destroyed.
1392 *
1393 * DESCRIPTION:
1394 *  Create a new session handler. This is needed by a module to associate a state with a session object.
1395 * The cleanup handler is called when the session timeout expires, or fd_sess_destroy is called. It must free
1396 * the state associated with the session, and eventually trig other actions (send a STR, ...).
1397 *
1398 * RETURN VALUE:
1399 *  0           : The new handler has been created.
1400 *  EINVAL      : A parameter is invalid.
1401 *  ENOMEM      : Not enough memory to complete the operation
1402 */
1403int fd_sess_handler_create_internal ( struct session_handler ** handler, void (*cleanup)(char * sid, session_state * state) );
1404/* Macro to avoid casting everywhere */
1405#define fd_sess_handler_create( _handler, _cleanup ) \
1406        fd_sess_handler_create_internal( (_handler), (void (*)(char *, session_state *))(_cleanup) )
1407
1408/*
1409 * FUNCTION:    fd_sess_handler_destroy
1410 *
1411 * PARAMETERS:
1412 *  handler     : location of an handler created by fd_sess_handler_create.
1413 *
1414 * DESCRIPTION:
1415 *  This destroys a session handler (typically called when an application is shutting down).
1416 * If sessions states are registered with this handler, the cleanup callback is called on them.
1417 *
1418 * RETURN VALUE:
1419 *  0           : The handler was destroyed.
1420 *  EINVAL      : A parameter is invalid.
1421 *  ENOMEM      : Not enough memory to complete the operation
1422 */
1423int fd_sess_handler_destroy ( struct session_handler ** handler );
1424
1425
1426
1427/*
1428 * FUNCTION:    fd_sess_new
1429 *
1430 * PARAMETERS:
1431 *  session       : The location where the session object will be created upon success.
1432 *  diamId        : \0-terminated string containing a Diameter Identity.
1433 *  opt           : Additional string. Usage is described bellow.
1434 *  optlen        : if opt is \0-terminated, this can be 0. Otherwise, the length of opt.
1435 *
1436 * DESCRIPTION:
1437 *   Create a new session object. The Session-Id string associated with this session is generated as follow:
1438 *  If diamId parameter is provided, the string is created according to the RFC: <diamId>;<high32>;<low32>[;opt] where
1439 *    diamId is a Diameter Identity.
1440 *    high32 and low32 are the parts of a monotonic 64 bits counter initialized to (time, 0) at startup.
1441 *    opt is an optional string that can be concatenated to the identifier.
1442 *  If diamId is NULL, the string is exactly the content of opt.
1443 *
1444 * RETURN VALUE:
1445 *  0           : The session is created.
1446 *  EINVAL      : A parameter is invalid.
1447 *  EALREADY    : A session with the same name already exists (returned in *session)
1448 *  ENOMEM      : Not enough memory to complete the operation
1449 */
1450int fd_sess_new ( struct session ** session, char * diamId, char * opt, size_t optlen );
1451
1452/*
1453 * FUNCTION:    fd_sess_fromsid
1454 *
1455 * PARAMETERS:
1456 *  sid         : pointer to a string containing a Session-Id (UTF-8).
1457 *  len         : length of the sid string (which does not need to be '\0'-terminated)
1458 *  session     : On success, pointer to the session object created / retrieved.
1459 *  new         : if not NULL, set to 1 on return if the session object has been created, 0 if it was simply retrieved.
1460 *
1461 * DESCRIPTION:
1462 *   Retrieve a session object from a Session-Id string. Calling this function makes an implicit call to the
1463 *  fd_sess_link function on the returned session. In case no session object was previously existing with this
1464 *  id, a new object is silently created (equivalent to fd_sess_new with flag SESSION_NEW_FULL).
1465 *
1466 * RETURN VALUE:
1467 *  0           : The session parameter has been updated.
1468 *  EINVAL      : A parameter is invalid.
1469 *  ENOMEM      : Not enough memory to complete the operation
1470 */
1471int fd_sess_fromsid ( char * sid, size_t len, struct session ** session, int * new);
1472
1473/*
1474 * FUNCTION:    fd_sess_getsid
1475 *
1476 * PARAMETERS:
1477 *  session     : Pointer to a session object.
1478 *  sid         : On success, the location of a (\0-terminated) string is stored here.
1479 *
1480 * DESCRIPTION:
1481 *   Retrieve the session identifier (Session-Id) corresponding to a session object.
1482 *  The returned sid is an UTF-8 string terminated by \0, suitable for calls to strlen and strcpy.
1483 *  It may be used for example to set the value of an AVP.
1484 *  Note that the sid string is not copied, just its reference... do not free it!
1485 *
1486 * RETURN VALUE:
1487 *  0           : The sid parameter has been updated.
1488 *  EINVAL      : A parameter is invalid.
1489 */
1490int fd_sess_getsid ( struct session * session, char ** sid );
1491
1492/*
1493 * FUNCTION:    fd_sess_settimeout
1494 *
1495 * PARAMETERS:
1496 *  session     : The session for which to set the timeout.
1497 *  timeout     : The date when the session times out.
1498 *
1499 * DESCRIPTION:
1500 *   Set the lifetime for a given session object. This function may be
1501 * called several times on the same object to update the timeout value.
1502 *   When the timeout date is reached, the cleanup handler of each
1503 * module that registered data with this session is called, then the
1504 * session is cleared.
1505 *
1506 *   There is a possible race condition between cleanup of the session
1507 * and use of its data; applications should ensure that they are not
1508 * using data from a session that is about to expire / expired.
1509 *
1510 * RETURN VALUE:
1511 *  0           : The session timeout has been updated.
1512 *  EINVAL      : A parameter is invalid.
1513 */
1514int fd_sess_settimeout( struct session * session, const struct timespec * timeout );
1515
1516/*
1517 * FUNCTION:    fd_sess_destroy
1518 *
1519 * PARAMETERS:
1520 *  session     : Pointer to a session object.
1521 *
1522 * DESCRIPTION:
1523 *   Destroys a session an all associated data, if any.
1524 * Equivalent to a session timeout expired, but the effect is immediate.
1525 *
1526 * RETURN VALUE:
1527 *  0           : The session no longer exists.
1528 *  EINVAL      : A parameter is invalid.
1529 */
1530int fd_sess_destroy ( struct session ** session );
1531
1532/*
1533 * FUNCTION:    fd_sess_reclaim
1534 *
1535 * PARAMETERS:
1536 *  session     : Pointer to a session object.
1537 *
1538 * DESCRIPTION:
1539 *   Destroys the resources of a session, only if no session_state is associated with it.
1540 *
1541 * RETURN VALUE:
1542 *  0           : The session no longer exists.
1543 *  EINVAL      : A parameter is invalid.
1544 */
1545int fd_sess_reclaim ( struct session ** session );
1546
1547
1548
1549
1550/*
1551 * FUNCTION:    fd_sess_state_store
1552 *
1553 * PARAMETERS:
1554 *  handler     : The handler with which the state is registered.
1555 *  session     : The session object with which the state is registered.
1556 *  state       : An application state (opaque data) to store with the session.
1557 *
1558 * DESCRIPTION:
1559 *  Stores an application state with a session. This state can later be retrieved
1560 * with fd_sess_state_retrieve, or implicitly in the cleanup handler when the session
1561 * is destroyed.
1562 *
1563 * RETURN VALUE:
1564 *  0           : The state has been stored.
1565 *  EINVAL      : A parameter is invalid.
1566 *  EALREADY    : Data was already associated with this session and client.
1567 *  ENOMEM      : Not enough memory to complete the operation
1568 */
1569int fd_sess_state_store_internal ( struct session_handler * handler, struct session * session, session_state ** state );
1570#define fd_sess_state_store( _handler, _session, _state ) \
1571        fd_sess_state_store_internal( (_handler), (_session), (void *)(_state) )
1572
1573/*
1574 * FUNCTION:    fd_sess_state_retrieve
1575 *
1576 * PARAMETERS:
1577 *  handler     : The handler with which the state was registered.
1578 *  session     : The session object with which the state was registered.
1579 *  state       : Location where the state must be saved if it is found.
1580 *
1581 * DESCRIPTION:
1582 *  Retrieves a state saved by fd_sess_state_store.
1583 * After this function has been called, the state is no longer associated with
1584 * the session. A new call to fd_sess_state_store must be performed in order to
1585 * store again the data with the session.
1586 *
1587 * RETURN VALUE:
1588 *  0           : *state is updated (NULL or points to the state if it was found).
1589 *  EINVAL      : A parameter is invalid.
1590 */
1591int fd_sess_state_retrieve_internal ( struct session_handler * handler, struct session * session, session_state ** state ); 
1592#define fd_sess_state_retrieve( _handler, _session, _state ) \
1593        fd_sess_state_retrieve_internal( (_handler), (_session), (void *)(_state) )
1594
1595
1596/* For debug */
1597void fd_sess_dump(int level, struct session * session);
1598void fd_sess_dump_hdl(int level, struct session_handler * handler);
1599
1600
1601/*============================================================*/
1602/*                         MESSAGES                           */
1603/*============================================================*/
1604
1605/* The following types are opaque */
1606struct  msg;    /* A message: command with children AVPs (possibly grand children) */
1607struct  avp;    /* AVP object */
1608
1609/* Some details about chaining:
1610 *
1611 *  A message is made of a header ( msg ) and 0 or more AVPs ( avp ).
1612 * The structure is a kind of tree, where some AVPs (grouped AVPs) can contain other AVPs.
1613 * Exemple:
1614 * msg
1615 *  |-avp
1616 *  |-gavp
1617 *  |   |-avp
1618 *  |   |-avp
1619 *  |   \-avp
1620 *  |-avp
1621 *  \-avp
1622 *
1623 */
1624
1625/* The following type is used to point to either a msg or an AVP */
1626typedef void msg_or_avp;
1627
1628/* The Diameter protocol version */
1629#define DIAMETER_VERSION        1
1630
1631/* In the two following types, some fields are marked (READONLY).
1632 * This means that the content of these fields will be overwritten by the daemon so modifying it is useless.
1633 */
1634
1635/* The following structure represents the header of a message. All data is in host byte order. */
1636struct msg_hdr {
1637        uint8_t          msg_version;           /* (READONLY) Version of Diameter: must be DIAMETER_VERSION. */
1638        uint32_t         msg_length;            /* (READONLY)(3 bytes) indicates the length of the message */
1639        uint8_t          msg_flags;             /* Message flags: CMD_FLAG_* */
1640        command_code_t   msg_code;              /* (3 bytes) the command-code. See dictionary-api.h for more detail */
1641        application_id_t msg_appl;              /* The application issuing this message */
1642        uint32_t         msg_hbhid;             /* The Hop-by-Hop identifier of the message */
1643        uint32_t         msg_eteid;             /* The End-to-End identifier of the message */
1644};
1645
1646/* The following structure represents the visible content of an AVP. All data is in host byte order. */
1647struct avp_hdr {
1648        avp_code_t       avp_code;              /* the AVP Code */
1649        uint8_t          avp_flags;             /* AVP_FLAG_* flags */
1650        uint32_t         avp_len;               /* (READONLY)(Only 3 bytes are used) the length of the AVP as described in the RFC */
1651        vendor_id_t      avp_vendor;            /* Only used if AVP_FLAG_VENDOR is present */
1652        union avp_value *avp_value;             /* pointer to the value of the AVP. NULL means that the value is not set / not understood.
1653                                                   One should not directly change this value. Use the msg_avp_setvalue function instead.
1654                                                   The content of the pointed structure can be changed directly, with this restriction:
1655                                                     if the AVP is an OctetString, and you change the value of the pointer avp_value->os.data, then
1656                                                     you must call free() on the previous value, and the new one must be free()-able.
1657                                                 */
1658};
1659
1660/* The following enum is used to browse inside message hierarchy (msg, gavp, avp) */
1661enum msg_brw_dir {
1662        MSG_BRW_NEXT = 1,       /* Get the next element at the same level, or NULL if this is the last element. */
1663        MSG_BRW_PREV,           /* Get the previous element at the same level, or NULL if this is the first element. */
1664        MSG_BRW_FIRST_CHILD,    /* Get the first child AVP of this element, if any. */
1665        MSG_BRW_LAST_CHILD,     /* Get the last child AVP of this element, if any. */
1666        MSG_BRW_PARENT,         /* Get the parent element of this element, if any. Only the msg_t object has no parent. */
1667        MSG_BRW_WALK            /* This is equivalent to FIRST_CHILD or NEXT or PARENT->next, first that is not NULL. Use this to walk inside all AVPs. */
1668};
1669
1670/* Some flags used in the functions bellow */
1671#define MSGFL_ALLOC_ETEID       0x01    /* When creating a message, a new end-to-end ID is allocated and set in the message */
1672#define MSGFL_ANSW_ERROR        0x02    /* When creating an answer message, set the 'E' bit and use the generic error ABNF instead of command-specific ABNF */
1673#define MSGFL_MAX               MSGFL_ANSW_ERROR        /* The biggest valid flag value */
1674
1675/**************************************************/
1676/*   Message creation, manipulation, disposal     */
1677/**************************************************/
1678/*
1679 * FUNCTION:    fd_msg_avp_new
1680 *
1681 * PARAMETERS:
1682 *  model       : Pointer to a DICT_AVP dictionary object describing the avp to create, or NULL.
1683 *  flags       : Flags to use in creation (not used yet, should be 0).
1684 *  avp         : Upon success, pointer to the new avp is stored here.
1685 *
1686 * DESCRIPTION:
1687 *   Create a new AVP instance.
1688 *
1689 * RETURN VALUE:
1690 *  0           : The AVP is created.
1691 *  EINVAL      : A parameter is invalid.
1692 *  (other standard errors may be returned, too, with their standard meaning. Example:
1693 *    ENOMEM    : Memory allocation for the new avp failed.)
1694 */
1695int fd_msg_avp_new ( struct dict_object * model, int flags, struct avp ** avp );
1696
1697/*
1698 * FUNCTION:    fd_msg_new
1699 *
1700 * PARAMETERS:
1701 *  model       : Pointer to a DICT_COMMAND dictionary object describing the message to create, or NULL.
1702 *  flags       : combination of MSGFL_* flags.
1703 *  msg         : Upon success, pointer to the new message is stored here.
1704 *
1705 * DESCRIPTION:
1706 *   Create a new empty Diameter message.
1707 *
1708 * RETURN VALUE:
1709 *  0           : The message is created.
1710 *  EINVAL      : A parameter is invalid.
1711 *  (other standard errors may be returned, too, with their standard meaning. Example:
1712 *    ENOMEM    : Memory allocation for the new message failed.)
1713 */
1714int fd_msg_new ( struct dict_object * model, int flags, struct msg ** msg );
1715
1716/*
1717 * FUNCTION:    msg_new_answer_from_req
1718 *
1719 * PARAMETERS:
1720 *  dict        : Pointer to the dictionary containing the model of the query.
1721 *  msg         : The location of the query on function call. Updated by the location of answer message on return.
1722 *  flag        : Pass MSGFL_ANSW_ERROR to indicate if the answer is an error message (will set the 'E' bit)
1723 *
1724 * DESCRIPTION:
1725 *   This function creates the empty answer message corresponding to a request.
1726 *  The header is set properly (R flag, ccode, appid, hbhid, eteid)
1727 *  The Session-Id AVP is copied if present.
1728 *  The calling code should usually call fd_msg_rescode_set function on the answer.
1729 *  Upon return, the original query may be retrieved by calling fd_msg_answ_getq on the message.
1730 *
1731 * RETURN VALUE:
1732 *  0           : Operation complete.
1733 *  !0          : an error occurred.
1734 */
1735int fd_msg_new_answer_from_req ( struct dictionary * dict, struct msg ** msg, int flag );
1736
1737/*
1738 * FUNCTION:    fd_msg_browse
1739 *
1740 * PARAMETERS:
1741 *  reference   : Pointer to a struct msg or struct avp.
1742 *  dir         : Direction for browsing
1743 *  found       : If not NULL, updated with the element that has been found, if any, or NULL if no element was found / an error occurred.
1744 *  depth       : If not NULL, points to an integer representing the "depth" of this object in the tree. This is a relative value, updated on return.
1745 *
1746 * DESCRIPTION:
1747 *   Explore the content of a message object (hierarchy). If "found" is null, only error checking is performed.
1748 *  If "depth" is provided, it is updated as follow on successful function return:
1749 *   - not modified for MSG_BRW_NEXT and MSG_BRW_PREV.
1750 *   - *depth = *depth + 1 for MSG_BRW_FIRST_CHILD and MSG_BRW_LAST_CHILD.
1751 *   - *depth = *depth - 1 for MSG_BRW_PARENT.
1752 *   - *depth = *depth + X for MSG_BRW_WALK, with X between 1 (returned the 1st child) and -N (returned the Nth parent's next).
1753 *
1754 * RETURN VALUE:
1755 *  0           : found has been updated (if non NULL).
1756 *  EINVAL      : A parameter is invalid.
1757 *  ENOENT      : No element has been found where requested, and "found" was NULL (otherwise, *found is set to NULL and 0 is returned).
1758 */
1759int fd_msg_browse_internal ( msg_or_avp * reference, enum msg_brw_dir dir, msg_or_avp ** found, int * depth );
1760/* Macro to avoid having to cast the third parameter everywhere */
1761#define fd_msg_browse( ref, dir, found, depth ) \
1762        fd_msg_browse_internal( (ref), (dir), (void *)(found), (depth) )
1763
1764
1765/*
1766 * FUNCTION:    fd_msg_avp_add
1767 *
1768 * PARAMETERS:
1769 *  reference   : Pointer to a valid msg or avp.
1770 *  dir         : location where the new AVP should be inserted, relative to the reference. MSG_BRW_PARENT and MSG_BRW_WALK are not valid.
1771 *  avp         : pointer to the AVP object that must be inserted.
1772 *
1773 * DESCRIPTION:
1774 *   Adds an AVP into an object that can contain it: grouped AVP or message.
1775 *
1776 * RETURN VALUE:
1777 *  0           : The AVP has been added.
1778 *  EINVAL      : A parameter is invalid.
1779 */
1780int fd_msg_avp_add ( msg_or_avp * reference, enum msg_brw_dir dir, struct avp *avp);
1781
1782/*
1783 * FUNCTION:    fd_msg_search_avp
1784 *
1785 * PARAMETERS:
1786 *  msg         : The message structure in which to search the AVP.
1787 *  what        : The dictionary model of the AVP to search.
1788 *  avp         : location where the AVP reference is stored if found.
1789 *
1790 * DESCRIPTION:
1791 *   Search the first top-level AVP of a given model inside a message.
1792 * Note: only the first instance of the AVP is returned by this function.
1793 * Note: only top-level AVPs are searched, not inside grouped AVPs.
1794 * Use msg_browse if you need more advanced research features.
1795 *
1796 * RETURN VALUE:
1797 *  0           : The AVP has been found.
1798 *  EINVAL      : A parameter is invalid.
1799 *  ENOENT      : No AVP has been found, and "avp" was NULL (otherwise, *avp is set to NULL and 0 returned).
1800 */
1801int fd_msg_search_avp ( struct msg * msg, struct dict_object * what, struct avp ** avp );
1802
1803/*
1804 * FUNCTION:    fd_msg_free
1805 *
1806 * PARAMETERS:
1807 *  object      : pointer to the message or AVP object that must be unlinked and freed.
1808 *
1809 * DESCRIPTION:
1810 *   Unlink and free a message or AVP object and its children.
1811 *  If the object is an AVP linked into a message, the AVP is removed before being freed.
1812 *
1813 * RETURN VALUE:
1814 *  0           : The message has been freed.
1815 *  EINVAL      : A parameter is invalid.
1816 */
1817int fd_msg_free ( msg_or_avp * object );
1818
1819/***************************************/
1820/*   Dump functions                    */
1821/***************************************/
1822/*
1823 * FUNCTION:    fd_msg_dump_*
1824 *
1825 * PARAMETERS:
1826 *  level       : the log level (INFO, FULL, ...) at which the object is dumped
1827 *  obj         : A msg or avp object.
1828 *
1829 * DESCRIPTION:
1830 *   These functions dump the content of a message to the debug log
1831 * either recursively or only the object itself.
1832 *
1833 * RETURN VALUE:
1834 *   -
1835 */
1836void fd_msg_dump_walk ( int level, msg_or_avp *obj );
1837void fd_msg_dump_one  ( int level, msg_or_avp *obj );
1838
1839
1840/*********************************************/
1841/*   Message metadata management functions   */
1842/*********************************************/
1843/*
1844 * FUNCTION:    fd_msg_model
1845 *
1846 * PARAMETERS:
1847 *  reference   : Pointer to a valid msg or avp.
1848 *  model       : on success, pointer to the dictionary model of this command or AVP. NULL if the model is unknown.
1849 *
1850 * DESCRIPTION:
1851 *   Retrieve the dictionary object describing this message or avp. If the object is unknown or the fd_msg_parse_dict has not been called,
1852 *  *model is set to NULL.
1853 *
1854 * RETURN VALUE:
1855 *  0           : The model has been set.
1856 *  EINVAL      : A parameter is invalid.
1857 */
1858int fd_msg_model ( msg_or_avp * reference, struct dict_object ** model );
1859
1860/*
1861 * FUNCTION:    fd_msg_hdr
1862 *
1863 * PARAMETERS:
1864 *  msg         : Pointer to a valid message object.
1865 *  pdata       : Upon success, pointer to the msg_hdr structure of this message. The fields may be modified.
1866 *
1867 * DESCRIPTION:
1868 *   Retrieve location of modifiable section of a message.
1869 *
1870 * RETURN VALUE:
1871 *  0           : The location has been written.
1872 *  EINVAL      : A parameter is invalid.
1873 */
1874int fd_msg_hdr ( struct msg *msg, struct msg_hdr **pdata );
1875
1876/*
1877 * FUNCTION:    fd_msg_avp_hdr
1878 *
1879 * PARAMETERS:
1880 *  avp         : Pointer to a valid avp object.
1881 *  pdata       : Upon success, pointer to the avp_hdr structure of this avp. The fields may be modified.
1882 *
1883 * DESCRIPTION:
1884 *   Retrieve location of modifiable data of an avp.
1885 *
1886 * RETURN VALUE:
1887 *  0           : The location has been written.
1888 *  EINVAL      : A parameter is invalid.
1889 */
1890int fd_msg_avp_hdr ( struct avp *avp, struct avp_hdr **pdata );
1891
1892/*
1893 * FUNCTION:    fd_msg_answ_associate, fd_msg_answ_getq, fd_msg_answ_detach
1894 *
1895 * PARAMETERS:
1896 *  answer      : the received answer message
1897 *  query       : the corresponding query that had been sent
1898 *
1899 * DESCRIPTION:
1900 *  fd_msg_answ_associate associates a query msg with the received answer.
1901 * Query is retrieved with fd_msg_answ_getq.
1902 * If answer message is freed, the query is also freed.
1903 * If the msg_answ_detach function is called, the association is removed.
1904 * This is meant to be called from the daemon only.
1905 *
1906 * RETURN VALUE:
1907 *  0     : ok
1908 *  EINVAL: a parameter is invalid
1909 */
1910int fd_msg_answ_associate( struct msg * answer, struct msg * query );
1911int fd_msg_answ_getq     ( struct msg * answer, struct msg ** query );
1912int fd_msg_answ_detach   ( struct msg * answer );
1913
1914/*
1915 * FUNCTION:    fd_msg_anscb_associate, fd_msg_anscb_get
1916 *
1917 * PARAMETERS:
1918 *  msg         : the answer message
1919 *  anscb       : the callback to associate with the message
1920 *  data        : the data to pass to the callback
1921 *
1922 * DESCRIPTION:
1923 *  Associate or retrieve a callback with an answer message.
1924 * This is meant to be called from the daemon only.
1925 *
1926 * RETURN VALUE:
1927 *  0     : ok
1928 *  EINVAL: a parameter is invalid
1929 */
1930int fd_msg_anscb_associate( struct msg * msg, void ( *anscb)(void *, struct msg **), void  * data );
1931int fd_msg_anscb_get      ( struct msg * msg, void (**anscb)(void *, struct msg **), void ** data );
1932
1933/*
1934 * FUNCTION:    fd_msg_rt_associate, fd_msg_rt_get
1935 *
1936 * PARAMETERS:
1937 *  msg         : the query message to be sent
1938 *  list        : the ordered list of possible next-peers
1939 *
1940 * DESCRIPTION:
1941 *  Associate a routing list with a query, and retrieve it.
1942 * If the message is freed, the list is also freed.
1943 *
1944 * RETURN VALUE:
1945 *  0     : ok
1946 *  EINVAL: a parameter is invalid
1947 */
1948int fd_msg_rt_associate( struct msg * msg, struct fd_list ** list );
1949int fd_msg_rt_get      ( struct msg * msg, struct fd_list ** list );
1950
1951/*
1952 * FUNCTION:    fd_msg_is_routable
1953 *
1954 * PARAMETERS:
1955 *  msg         : A msg object.
1956 *
1957 * DESCRIPTION:
1958 *   This function returns a boolean telling if a given message is routable in the Diameter network,
1959 *  or if it is a local link message only (ex: CER/CEA, DWR/DWA, ...).
1960 *
1961 * RETURN VALUE:
1962 *  0           : The message is not routable / an error occurred.
1963 *  1           : The message is routable.
1964 */
1965int fd_msg_is_routable ( struct msg * msg );
1966
1967/*
1968 * FUNCTION:    fd_msg_source_(g/s)et
1969 *
1970 * PARAMETERS:
1971 *  msg         : A msg object.
1972 *  diamid      : The diameter id of the peer from which this message was received.
1973 *  hash        : The hash for the diamid value.
1974 *  add_rr      : if true, a Route-Record AVP is added to the message with content diamid. In that case, dict must be supplied.
1975 *  dict        : a dictionary with definition of Route-Record AVP (if add_rr is true)
1976 *
1977 * DESCRIPTION:
1978 *   Store or retrieve the diameted id of the peer from which this message was received.
1979 * Will be used for example by the routing module to add the Route-Record AVP in forwarded requests,
1980 * or to direct answers to the appropriate peer.
1981 *
1982 * RETURN VALUE:
1983 *  0           : Operation complete.
1984 *  !0          : an error occurred.
1985 */
1986int fd_msg_source_set( struct msg * msg, char * diamid, uint32_t hash, int add_rr, struct dictionary * dict );
1987int fd_msg_source_get( struct msg * msg, char ** diamid, uint32_t *hash );
1988
1989/*
1990 * FUNCTION:    fd_msg_eteid_get
1991 *
1992 * PARAMETERS:
1993 *  -
1994 *
1995 * DESCRIPTION:
1996 *   Get a new unique end-to-end id value for the local peer.
1997 *
1998 * RETURN VALUE:
1999 *  The new assigned value. No error code is defined.
2000 */
2001uint32_t fd_msg_eteid_get ( void );
2002
2003
2004/***************************************/
2005/*   Manage AVP values                 */
2006/***************************************/
2007
2008/*
2009 * FUNCTION:    fd_msg_avp_setvalue
2010 *
2011 * PARAMETERS:
2012 *  avp         : Pointer to a valid avp object with a NULL avp_value pointer. The model must be known.
2013 *  value       : pointer to an avp_value. The content will be COPIED into the internal storage area.
2014 *               If data type is an octetstring, the data is also copied.
2015 *               If value is a NULL pointer, the previous data is erased and value is unset in the AVP.
2016 *
2017 * DESCRIPTION:
2018 *   Initialize the avp_value field of an AVP header.
2019 *
2020 * RETURN VALUE:
2021 *  0           : The avp_value pointer has been set.
2022 *  EINVAL      : A parameter is invalid.
2023 */
2024int fd_msg_avp_setvalue ( struct avp *avp, union avp_value *value );
2025
2026/*
2027 * FUNCTION:    fd_msg_avp_value_encode
2028 *
2029 * PARAMETERS:
2030 *  avp         : Pointer to a valid avp object with a NULL avp_value. The model must be known.
2031 *  data        : Pointer to the data that must be encoded as AVP value and stored in the AVP.
2032 *               This is only valid for AVPs of derived type for which type_data_encode callback is set. (ex: Address type)
2033 *
2034 * DESCRIPTION:
2035 *   Initialize the avp_value field of an AVP object from formatted data, using the AVP's type "type_data_encode" callback.
2036 *
2037 * RETURN VALUE:
2038 *  0           : The avp_value has been set.
2039 *  EINVAL      : A parameter is invalid.
2040 *  ENOTSUP     : There is no appropriate callback registered with this AVP's type.
2041 */
2042int fd_msg_avp_value_encode ( void *data, struct avp *avp );
2043
2044/*
2045 * FUNCTION:    fd_msg_avp_value_interpret
2046 *
2047 * PARAMETERS:
2048 *  avp         : Pointer to a valid avp object with a non-NULL avp_value value.
2049 *  data        : Upon success, formatted interpretation of the AVP value is stored here.
2050 *
2051 * DESCRIPTION:
2052 *   Interpret the content of an AVP of Derived type and store the result in data pointer. The structure
2053 * of the data pointer is dependent on the AVP type. This function calls the "type_data_interpret" callback
2054 * of the type.
2055 *
2056 * RETURN VALUE:
2057 *  0           : The avp_value has been set.
2058 *  EINVAL      : A parameter is invalid.
2059 *  ENOTSUP     : There is no appropriate callback registered with this AVP's type.
2060 */
2061int fd_msg_avp_value_interpret ( struct avp *avp, void *data );
2062
2063
2064/***************************************/
2065/*   Message parsing functions         */
2066/***************************************/
2067
2068/*
2069 * FUNCTION:    fd_msg_bufferize
2070 *
2071 * PARAMETERS:
2072 *  msg         : A valid msg object. All AVPs must have a value set.
2073 *  buffer      : Upon success, this points to a buffer (malloc'd) containing the message ready for network transmission (or security transformations).
2074 *               The buffer may be freed after use.
2075 *  len         : if not NULL, the size of the buffer is written here. In any case, this size is updated in the msg header.
2076 *
2077 * DESCRIPTION:
2078 *   Renders a message in memory as a buffer that can be sent over the network to the next peer.
2079 *
2080 * RETURN VALUE:
2081 *  0           : The location has been written.
2082 *  EINVAL      : The buffer does not contain a valid Diameter message.
2083 *  ENOMEM      : Unable to allocate enough memory to create the buffer object.
2084 */
2085int fd_msg_bufferize ( struct msg * msg, unsigned char ** buffer, size_t * len );
2086
2087/*
2088 * FUNCTION:    fd_msg_parse_buffer
2089 *
2090 * PARAMETERS:
2091 *  buffer      : Pointer to a buffer containing a message received from the network.
2092 *  buflen      : the size in bytes of the buffer.
2093 *  msg         : Upon success, this points to a valid msg object. No AVP value is resolved in this object, nor grouped AVP.
2094 *
2095 * DESCRIPTION:
2096 *   This function parses a buffer an creates a msg object to represent the structure of the message.
2097 *  Since no dictionary lookup is performed, the values of the AVPs are not interpreted. To interpret the values,
2098 *  the returned message object must be passed to fd_msg_parse_dict function.
2099 *  The buffer pointer is saved inside the message and will be freed when not needed anymore.
2100 *
2101 * RETURN VALUE:
2102 *  0           : The location has been written.
2103 *  ENOMEM      : Unable to allocate enough memory to create the msg object.
2104 *  EBADMSG     : The buffer does not contain a valid Diameter message (or is truncated).
2105 *  EINVAL      : A parameter is invalid.
2106 */
2107int fd_msg_parse_buffer ( unsigned char ** buffer, size_t buflen, struct msg ** msg );
2108
2109/*
2110 * FUNCTION:    fd_msg_parse_dict
2111 *
2112 * PARAMETERS:
2113 *  object      : A msg or AVP object as returned by fd_msg_parse_buffer.
2114 *  dict        : the dictionary containing the objects definitions to use for resolving all AVPs.
2115 *
2116 * DESCRIPTION:
2117 *   This function looks up for the command and each children AVP definitions in the dictionary.
2118 *  If the dictionary definition is found, avp_model is set and the value of the AVP is interpreted accordingly and:
2119 *   - for grouped AVPs, the children AVP are created and interpreted also.
2120 *   - for numerical AVPs, the value is converted to host byte order and saved in the avp_value field.
2121 *   - for octetstring AVPs, the string is copied into a new buffer and its address is saved in avp_value.
2122 *  If the dictionary definition is not found, avp_model is set to NULL and
2123 *  the content of the AVP is saved as an octetstring in an internal structure. avp_value is NULL.
2124 *  As a result, after this function has been called, there is no more dependency of the msg object to the message buffer, that is be freed.
2125 *
2126 * RETURN VALUE:
2127 *  0           : The message has been fully parsed as described.
2128 *  EINVAL      : The msg parameter is invalid for this operation.
2129 *  ENOMEM      : Unable to allocate enough memory to complete the operation.
2130 *  ENOTSUP     : No dictionary definition for the command or one of the mandatory AVP was found.
2131 */
2132int fd_msg_parse_dict ( msg_or_avp * object, struct dictionary * dict );
2133
2134/*
2135 * FUNCTION:    fd_msg_parse_rules
2136 *
2137 * PARAMETERS:
2138 *  object      : A msg or grouped avp object that must be verified.
2139 *  dict        : The dictionary containing the rules definitions.
2140 *  rule        : If not NULL, the first conflicting rule will be saved here if a conflict is found.
2141 *
2142 * DESCRIPTION:
2143 *   Check that the children of the object do not conflict with the dictionary rules (ABNF compliance).
2144 *
2145 * RETURN VALUE:
2146 *  0           : The message has been fully parsed and complies to the defined rules.
2147 *  EBADMSG     : A conflict was detected, or a mandatory AVP is unknown in the dictionary.
2148 *  EINVAL      : The msg or avp object is invalid for this operation.
2149 *  ENOMEM      : Unable to allocate enough memory to complete the operation.
2150 */
2151int fd_msg_parse_rules ( msg_or_avp * object, struct dictionary * dict, struct dict_object ** rule);
2152
2153
2154/*
2155 * FUNCTION:    fd_msg_update_length
2156 *
2157 * PARAMETERS:
2158 *  object      : Pointer to a valid msg or avp.
2159 *
2160 * DESCRIPTION:
2161 *   Update the length field of the object passed as parameter.
2162 * As a side effect, all children objects are also updated. Therefore, all avp_value fields of
2163 * the children AVPs must be set, or an error will occur.
2164 *
2165 * RETURN VALUE:
2166 *  0           : The size has been recomputed.
2167 *  EINVAL      : A parameter is invalid.
2168 */
2169int fd_msg_update_length ( msg_or_avp * object );
2170
2171
2172/*============================================================*/
2173/*                         DISPATCH                           */
2174/*============================================================*/
2175
2176/* Dispatch module (passing incoming messages to extensions registered callbacks)
2177 * is split between the library and the daemon.
2178 *
2179 * The library provides the support for associating dispatch callbacks with
2180 * dictionary objects.
2181 *
2182 * The daemon is responsible for calling the callbacks for a message when appropriate.
2183 *
2184 *
2185 * The dispatch module has two main roles:
2186 *  - help determine if a message can be handled locally (during the routing step)
2187 *        This decision involves only the application-id of the message.
2188 *  - pass the message to the callback(s) that will handle it (during the dispatch step)
2189 *
2190 * The first role is handled by the daemon.
2191 *
2192 * About the second, these are the possibilities for registering a dispatch callback:
2193 *
2194 * -> For All messages.
2195 *  This callback is called for all messages that are handled locally. This should be used only
2196 *  for debug purpose.
2197 *
2198 * -> by AVP value (constants only).
2199 *  This callback will be called when a message is received and contains an AVP with a specified enumerated value.
2200 *
2201 * -> by AVP.
2202 *  This callback will be called when the received message contains a certain AVP.
2203 *
2204 * -> by command-code.
2205 *  This callback will be called when the message is a specific command (and 'R' flag).
2206 *
2207 * -> by application.
2208 *  This callback will be called when the message has a specific application-id.
2209 *
2210 * ( by vendor: would this be useful? it may be added later)
2211 */
2212enum disp_how {
2213        DISP_HOW_ANY = 1,               /* Any message. This should be only used for debug. */
2214        DISP_HOW_APPID,                 /* Any message with the specified application-id */
2215        DISP_HOW_CC,                    /* Messages of the specified command-code (request or answer). App id may be specified. */
2216        DISP_HOW_AVP,                   /* Messages containing a specific AVP. Command-code and App id may be specified. */
2217        DISP_HOW_AVP_ENUMVAL            /* Messages containing a specific AVP with a specific enumerated value. Command-code and App id may be specified. */
2218};
2219/*
2220 * Several criteria may be selected at the same time, for example command-code AND application id.
2221 *
2222 * If several callbacks are registered for the same object, they are called in the order they were registered.
2223 * The order in which the callbacks are called is:
2224 *  DISP_HOW_ANY
2225 *  DISP_HOW_AVP_ENUMVAL & DISP_HOW_AVP
2226 *  DISP_HOW_CC
2227 *  DISP_HOW_APPID
2228 */
2229
2230/* When a callback is registered, a "when" argument is passed in addition to the disp_how value,
2231 * to specify which values the criteria must match. */
2232struct disp_when {
2233        struct dict_object *    app;
2234        struct dict_object *    command;
2235        struct dict_object *    avp;
2236        struct dict_object *    value;
2237};
2238
2239/* Note that all the dictionary objects should really belong to the same dictionary!
2240 *
2241 * Here is the details on this "when" argument, depending on the disp_how value.
2242 *
2243 * DISP_HOW_ANY.
2244 *  In this case, "when" must be NULL.
2245 *
2246 * DISP_HOW_APPID.
2247 *  Only the "app_id" field must be set, other fields are ignored. It points to a dictionary object of type DICT_APPLICATION.
2248 *
2249 * DISP_HOW_CC.
2250 *  The "command" field must be defined and point to a dictionary object of type DICT_COMMAND.
2251 *  The "app_id" may be also set. In the case it is set, it restricts the callback to be called only with this command-code and app id.
2252 *  The other fields are ignored.
2253 *
2254 * DISP_HOW_AVP.
2255 *  The "avp" field of the structure must be set and point to a dictionary object of type DICT_AVP.
2256 *  The "app_id" field may be set to restrict the messages matching to a specific app id.
2257 *  The "command" field may also be set to a valid DICT_COMMAND object.
2258 *  The content of the "value" field is ignored.
2259 *
2260 * DISP_HOW_AVP_ENUMVAL.
2261 *  All fields have the same constraints and meaning as in DISP_REG_AVP. In addition, the "value" field must be set
2262 *  and points to a valid DICT_ENUMVAL object.
2263 *
2264 * Here is a sumary of the fields: ( M : must be set; m : may be set; 0 : ignored )
2265 *  field:     app_id    command     avp    value
2266 * APPID :       M          0         0       0
2267 * CC    :       m          M         0       0
2268 * AVP   :       m          m         M       0
2269 * ENUMVA:       m          m         M       M
2270 */
2271
2272enum disp_action {
2273        DISP_ACT_CONT,  /* The next handler should be called, unless *msg == NULL. */
2274        DISP_ACT_SEND   /* The updated message must be sent. No further callback is called. */
2275};
2276/* The callbacks that are registered have the following prototype:
2277 *      int dispatch_callback( struct msg ** msg, struct avp * avp, struct session * session, enum disp_action * action );
2278 *
2279 * CALLBACK:    dispatch_callback
2280 *
2281 * PARAMETERS:
2282 *  msg         : the received message on function entry. may be updated to answer on return (see description)
2283 *  avp         : for callbacks registered with DISP_HOW_AVP or DISP_HOW_AVP_ENUMVAL, direct link to the triggering AVP.
2284 *  session     : if the message contains a Session-Id AVP, the corresponding session object, NULL otherwise.
2285 *  action      : upon return, this tells the daemon what to do next.
2286 *
2287 * DESCRIPTION:
2288 *   Called when a received message matchs the condition for which the callback was registered.
2289 * This callback may do any kind of processing on the message, including:
2290 *  - create an answer for a request.
2291 *  - proxy a request or message, add / remove the Proxy-Info AVP, then forward the message.
2292 *  - update a routing table or start a connection with a new peer, then forward the message.
2293 *  - ...
2294 *
2295 * When *action == DISP_ACT_SEND on callback return, the msg pointed by *msg is passed to the routing module for sending.
2296 * When *action == DISP_ACT_CONT, the next registered callback is called.
2297 *  When the last callback gives also DISP_ACT_CONT action value, a default handler is called. It's behavior is as follow:
2298 *   - if the message is an answer, it is discarded.
2299 *   - if the message is a request, it is passed again to the routing stack, and marked as non-local handling.
2300 *
2301 * RETURN VALUE:
2302 *  0           : The callback executed successfully and updated *action appropriately.
2303 *  !0          : standard errors. In case of error, the message is discarded.
2304 */
2305
2306/* This structure represents a handler for a registered callback, allowing its de-registration */
2307struct disp_hdl;
2308
2309/*
2310 * FUNCTION:    fd_disp_register
2311 *
2312 * PARAMETERS:
2313 *  cb            : The callback function to register (see dispatch_callback description above).
2314 *  how           : How the callback must be registered.
2315 *  when          : Values that must match, depending on the how argument.
2316 *  handle        : On success, a handler to the registered callback is stored here if not NULL.
2317 *                 This handler can be used to unregister the cb.
2318 *
2319 * DESCRIPTION:
2320 *   Register a new callback to handle messages delivered locally.
2321 *
2322 * RETURN VALUE:
2323 *  0           : The callback is registered.
2324 *  EINVAL      : A parameter is invalid.
2325 *  ENOMEM      : Not enough memory to complete the operation
2326 */
2327int fd_disp_register ( int (*cb)( struct msg **, struct avp *, struct session *, enum disp_action *), 
2328                        enum disp_how how, struct disp_when * when, struct disp_hdl ** handle );
2329
2330/*
2331 * FUNCTION:    fd_disp_unregister
2332 *
2333 * PARAMETERS:
2334 *  handle       : Location of the handle of the callback that must be unregistered.
2335 *
2336 * DESCRIPTION:
2337 *   Removes a callback previously registered by fd_disp_register.
2338 *
2339 * RETURN VALUE:
2340 *  0           : The callback is unregistered.
2341 *  EINVAL      : A parameter is invalid.
2342 */
2343int fd_disp_unregister ( struct disp_hdl ** handle );
2344
2345/*
2346 * FUNCTION:    fd_msg_dispatch
2347 *
2348 * PARAMETERS:
2349 *  msg         : A msg object that have already been fd_msg_parse_dict.
2350 *  session     : The session corresponding to this object, if any.
2351 *  action      : Upon return, the action that must be taken on the message
2352 *
2353 * DESCRIPTION:
2354 *   Call all handlers registered for a given message.
2355 *  The session must have already been resolved on entry.
2356 *  The msg pointed may be updated during this process.
2357 *  Upon return, the action parameter points to what must be done next.
2358 *
2359 * RETURN VALUE:
2360 *  0           : Success.
2361 *  EINVAL      : A parameter is invalid.
2362 *  (other errors)
2363 */
2364int fd_msg_dispatch ( struct msg ** msg, struct session * session, enum disp_action *action );
2365
2366
2367
2368/*============================================================*/
2369/*                     QUEUES                                 */
2370/*============================================================*/
2371
2372/* Management of FIFO queues of elements */
2373
2374/* A queue is an opaque object */
2375struct fifo;
2376
2377/*
2378 * FUNCTION:    fd_fifo_new
2379 *
2380 * PARAMETERS:
2381 *  queue       : Upon success, a pointer to the new queue is saved here.
2382 *
2383 * DESCRIPTION:
2384 *  Create a new empty queue.
2385 *
2386 * RETURN VALUE :
2387 *  0           : The queue has been initialized successfully.
2388 *  EINVAL      : The parameter is invalid.
2389 *  ENOMEM      : Not enough memory to complete the creation. 
2390 */
2391int fd_fifo_new ( struct fifo ** queue );
2392
2393/*
2394 * FUNCTION:    fd_fifo_del
2395 *
2396 * PARAMETERS:
2397 *  queue       : Pointer to an empty queue to delete.
2398 *
2399 * DESCRIPTION:
2400 *  Destroys a queue. This is only possible if no thread is waiting for an element,
2401 * and the queue is empty.
2402 *
2403 * RETURN VALUE:
2404 *  0           : The queue has been destroyed successfully.
2405 *  EINVAL      : The parameter is invalid.
2406 */
2407int fd_fifo_del ( struct fifo  ** queue );
2408
2409/*
2410 * FUNCTION:    fd_fifo_move
2411 *
2412 * PARAMETERS:
2413 *  old         : Location of a FIFO that is to be emptied and deleted.
2414 *  new         : A FIFO that will receive the old data.
2415 *  loc_update  : if non NULL, a place to store the pointer to new FIFO atomically with the move.
2416 *
2417 * DESCRIPTION:
2418 *  Delete a queue and move its content to another one atomically.
2419 *
2420 * RETURN VALUE:
2421 *  0           : The queue has been destroyed successfully.
2422 *  EINVAL      : A parameter is invalid.
2423 */
2424int fd_fifo_move ( struct fifo ** old, struct fifo * new, struct fifo ** loc_update );
2425
2426/*
2427 * FUNCTION:    fd_fifo_length
2428 *
2429 * PARAMETERS:
2430 *  queue       : The queue from which to retrieve the number of elements.
2431 *  length      : Upon success, the current number of elements in the queue is stored here.
2432 *
2433 * DESCRIPTION:
2434 *  Retrieve the number of elements in a queue.
2435 *
2436 * RETURN VALUE:
2437 *  0           : The length of the queue has been written.
2438 *  EINVAL      : A parameter is invalid.
2439 */
2440int fd_fifo_length ( struct fifo * queue, int * length );
2441int fd_fifo_length_noerr ( struct fifo * queue ); /* no error checking version */
2442
2443/*
2444 * FUNCTION:    fd_fifo_setthrhd
2445 *
2446 * PARAMETERS:
2447 *  queue       : The queue for which the thresholds are being set.
2448 *  data        : An opaque pointer that is passed to h_cb and l_cb callbacks.
2449 *  high        : The high-level threshold. If the number of elements in the queue increase to this value, h_cb is called.
2450 *  h_cb        : if not NULL, a callback to call when the queue lengh is bigger than "high".
2451 *  low         : The low-level threshold. Must be < high.
2452 *  l_cb        : If the number of elements decrease to low, this callback is called.
2453 *
2454 * DESCRIPTION:
2455 *  This function allows to adjust the number of producer / consumer threads of a queue.
2456 * If the consumer are slower than the producers, the number of elements in the queue increase.
2457 * By setting a "high" value, we allow a callback to be called when this number is too high.
2458 * The typical use would be to create an additional consumer thread in this callback.
2459 * If the queue continues to grow, the callback will be called again when the length is 2 * high, then 3*high, ... N * high
2460 * (the callback itself should implement a limit on the number of consumers that can be created)
2461 * When the queue starts to decrease, and the number of elements go under ((N - 1) * high + low, the l_cb callback is called
2462 * and would typially stop one of the consumer threads. If the queue continues to reduce, l_cb is again called at (N-2)*high + low,
2463 * and so on.
2464 *
2465 * Since there is no destructor for the data pointer, if cleanup operations are required, they should be performed in
2466 * l_cb when the length of the queue is becoming < low.
2467 *
2468 * Note that the callbacks are called synchronously, during fd_fifo_post or fd_fifo_get. Their operation should be quick.
2469 *
2470 * RETURN VALUE:
2471 *  0           : The thresholds have been set
2472 *  EINVAL      : A parameter is invalid.
2473 */
2474int fd_fifo_setthrhd ( struct fifo * queue, void * data, uint16_t high, void (*h_cb)(struct fifo *, void **), uint16_t low, void (*l_cb)(struct fifo *, void **) );
2475
2476/*
2477 * FUNCTION:    fd_fifo_post
2478 *
2479 * PARAMETERS:
2480 *  queue       : The queue in which the element must be posted.
2481 *  item        : The element that is put in the queue.
2482 *
2483 * DESCRIPTION:
2484 *  An element is added in a queue. Elements are retrieved from the queue in FIFO order
2485 *  with the fd_fifo_get, fd_fifo_tryget, or fd_fifo_timedget functions.
2486 *
2487 * RETURN VALUE:
2488 *  0           : The element is queued.
2489 *  EINVAL      : A parameter is invalid.
2490 *  ENOMEM      : Not enough memory to complete the operation.
2491 */
2492int fd_fifo_post_int ( struct fifo * queue, void ** item );
2493#define fd_fifo_post(queue, item) \
2494        fd_fifo_post_int((queue), (void *)(item))
2495
2496/*
2497 * FUNCTION:    fd_fifo_get
2498 *
2499 * PARAMETERS:
2500 *  queue       : The queue from which the first element must be retrieved.
2501 *  item        : On return, the first element of the queue is stored here.
2502 *
2503 * DESCRIPTION:
2504 *  This function retrieves the first element from a queue. If the queue is empty, the function will block the
2505 * thread until a new element is posted to the queue, or until the thread is canceled (in which case the
2506 * function does not return).
2507 *
2508 * RETURN VALUE:
2509 *  0           : A new element has been retrieved.
2510 *  EINVAL      : A parameter is invalid.
2511 */
2512int fd_fifo_get_int ( struct fifo * queue, void ** item );
2513#define fd_fifo_get(queue, item) \
2514        fd_fifo_get_int((queue), (void *)(item))
2515
2516/*
2517 * FUNCTION:    fd_fifo_tryget
2518 *
2519 * PARAMETERS:
2520 *  queue       : The queue from which the element must be retrieved.
2521 *  msg         : On return, the message is stored here.
2522 *
2523 * DESCRIPTION:
2524 *  This function is similar to fd_fifo_get, except that it will not block if
2525 * the queue is empty, but return EWOULDBLOCK instead.
2526 *
2527 * RETURN VALUE:
2528 *  0           : A new element has been retrieved.
2529 *  EINVAL      : A parameter is invalid.
2530 *  EWOULDBLOCK : The queue was empty.
2531 */
2532int fd_fifo_tryget_int ( struct fifo * queue, void ** item );
2533#define fd_fifo_tryget(queue, item) \
2534        fd_fifo_tryget_int((queue), (void *)(item))
2535
2536/*
2537 * FUNCTION:    fd_fifo_timedget
2538 *
2539 * PARAMETERS:
2540 *  queue       : The queue from which the element must be retrieved.
2541 *  item        : On return, the element is stored here.
2542 *  abstime     : the absolute time until which we allow waiting for an item.
2543 *
2544 * DESCRIPTION:
2545 *  This function is similar to fd_fifo_get, except that it will block if the queue is empty
2546 * only until the absolute time abstime (see pthread_cond_timedwait for + info).
2547 * If the queue is still empty when the time expires, the function returns ETIMEDOUT
2548 *
2549 * RETURN VALUE:
2550 *  0           : A new item has been retrieved.
2551 *  EINVAL      : A parameter is invalid.
2552 *  ETIMEDOUT   : The time out has passed and no item has been received.
2553 */
2554int fd_fifo_timedget_int ( struct fifo * queue, void ** item, const struct timespec *abstime );
2555#define fd_fifo_timedget(queue, item, abstime) \
2556        fd_fifo_timedget_int((queue), (void *)(item), (abstime))
2557
2558/* Dump a fifo list and optionally its inner elements -- beware of deadlocks! */
2559void fd_fifo_dump(int level, char * name, struct fifo * queue, void (*dump_item)(int level, void * item));
2560
2561#endif /* _LIBFREEDIAMETER_H */
Note: See TracBrowser for help on using the repository browser.