Navigation


source: freeDiameter/include/freeDiameter/libfdcore.h @ 658:f198d16fa7f4

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

Initial commit for 1.1.0:

  • Restructuring:
    • libfreeDiameter:
      • renamed folder & binary into libfdproto
      • renamed libfD.h into fdproto-internal.h
      • removed signals management (replaced by triggers in libfdcore)
  • freeDiameter split into:
    • libfdcore (most contents)
      • renamed fD.h into fdcore-internal.h
      • added core.c for framework init/shutdown.
      • new triggers mechanism in events.c.
  • freeDiameterd (main, command line parsing, signals management)
  • tests:
    • now in top-level directory tests.
  • other changes:
    • fd_dict_new now returns 0 on duplicate identical entries.
    • fixes in dict_legacy_xml
    • fixes in some dictionaries
    • moved FD_DEFAULT_CONF_FILENAME definition to freeDiameter-host.h
File size: 36.6 KB
Line 
1/*********************************************************************************************************
2* Software License Agreement (BSD License)                                                               *
3* Author: Sebastien Decugis <sdecugis@nict.go.jp>                                                        *
4*                                                                                                        *
5* Copyright (c) 2011, 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#ifndef _LIBFDCORE_H
37#define _LIBFDCORE_H
38
39
40#include <freeDiameter/libfdproto.h>
41#include <gnutls/gnutls.h>
42#include <gnutls/x509.h>
43
44/* GNUTLS version */
45#ifndef GNUTLS_VERSION
46#define GNUTLS_VERSION LIBGNUTLS_VERSION
47#endif /* GNUTLS_VERSION */
48
49/* GNUTLS calls debug level */
50#ifndef GNUTLS_DBG_LEVEL
51#define GNUTLS_DBG_LEVEL ANNOYING
52#endif /* GNUTLS_DBG_LEVEL */
53
54/* Check the return value of a GNUTLS function, log and propagate */
55#define CHECK_GNUTLS_DO( __call__, __fallback__ ) {                                             \
56        int __ret__;                                                                            \
57        TRACE_DEBUG(GNUTLS_DBG_LEVEL, "GNUTLS call: " #__call__ );                              \
58        __ret__ = (__call__);                                                                   \
59        if (__ret__ < 0) {                                                                      \
60                TRACE_DEBUG(INFO, "Error in '" #__call__ "':\t%s", gnutls_strerror(__ret__));   \
61                __fallback__;                                                                   \
62        }                                                                                       \
63}
64
65/* For GNUTLS routines that do not return a value */
66#define GNUTLS_TRACE( __call__) {                                       \
67        TRACE_DEBUG(GNUTLS_DBG_LEVEL, "GNUTLS call: " #__call__ );      \
68        (__call__);                                                     \
69}
70
71
72/*============================================================*/
73/*                      INITIALIZATION                        */
74/*============================================================*/
75
76
77/* Initialize the libfdcore internals. This also initializes libfdproto */
78int fd_core_initialize(void);
79
80/* Return a string describing the version of the library */
81const char *fd_core_version(void);
82
83/* Parse the freeDiameter.conf configuration file, load the extensions */
84int fd_core_parseconf(char * conffile);
85
86/* Start the server & client threads */
87int fd_core_start(void);
88
89/* Block until the framework has completed its initialization -- useful for extensions */
90int fd_core_waitstartcomplete(void);
91
92/* Initialize shutdown of the framework */
93int fd_core_shutdown(void);
94
95/* Wait for the shutdown to be complete -- this should always be called after fd_core_shutdown */
96int fd_core_wait_shutdown_complete(void);
97
98
99/*============================================================*/
100/*                          CONFIG                            */
101/*============================================================*/
102
103/* Structure to hold the configuration of the freeDiameter daemon */
104#define EYEC_CONFIG     0xC011F16
105struct fd_config {
106        int              cnf_eyec;      /* Eye catcher: EYEC_CONFIG */
107       
108        char            *cnf_file;      /* Configuration file to parse, default is DEFAULT_CONF_FILE */
109       
110        char            *cnf_diamid;    /* Diameter Identity of the local peer (FQDN -- UTF-8) */
111        size_t           cnf_diamid_len;        /* length of the previous string */
112        char            *cnf_diamrlm;   /* Diameter realm of the local peer, default to realm part of diam_id */
113        size_t           cnf_diamrlm_len;/* length of the previous string */
114       
115        unsigned int     cnf_timer_tc;  /* The value in seconds of the default Tc timer */
116        unsigned int     cnf_timer_tw;  /* The value in seconds of the default Tw timer */
117       
118        uint16_t         cnf_port;      /* the local port for legacy Diameter (default: 3868) in host byte order */
119        uint16_t         cnf_port_tls;  /* the local port for Diameter/TLS (default: 3869) in host byte order */
120        uint16_t         cnf_sctp_str;  /* default max number of streams for SCTP associations (def: 30) */
121        struct fd_list   cnf_endpoints; /* the local endpoints to bind the server to. list of struct fd_endpoint. default is empty (bind all) */
122        struct fd_list   cnf_apps;      /* Applications locally supported (except relay, see flags). Use fd_disp_app_support to add one. list of struct fd_app. */
123        uint16_t         cnf_dispthr;   /* Number of dispatch threads to create */
124        struct {
125                unsigned no_fwd : 1;    /* the peer does not relay messages (0xffffff app id) */
126                unsigned no_ip4 : 1;    /* disable IP */
127                unsigned no_ip6 : 1;    /* disable IPv6 */
128                unsigned no_tcp : 1;    /* disable use of TCP */
129                unsigned no_sctp: 1;    /* disable the use of SCTP */
130                unsigned pr_tcp : 1;    /* prefer TCP over SCTP */
131                unsigned tls_alg: 1;    /* TLS algorithm for initiated cnx. 0: separate port. 1: inband-security (old) */
132        }                cnf_flags;
133       
134        struct {
135                /* Credentials parameters (backup) */
136                char *                           cert_file;
137                char *                           key_file;
138               
139                char *                           ca_file;
140                int                              ca_file_nr;
141                char *                           crl_file;
142               
143                char *                           prio_string;
144                unsigned int                     dh_bits;
145                char *                           dh_file;
146               
147                /* GNUTLS parameters */
148                gnutls_priority_t                prio_cache;
149                gnutls_dh_params_t               dh_cache;
150               
151                /* GNUTLS server credential(s) */
152                gnutls_certificate_credentials_t credentials;
153               
154        }                cnf_sec_data;
155       
156        uint32_t         cnf_orstateid; /* The value to use in Origin-State-Id, default to random value */
157        struct dictionary *cnf_dict;    /* pointer to the global dictionary */
158        struct fifo       *cnf_main_ev; /* events for the daemon's main (struct fd_event items) */
159};
160extern struct fd_config *fd_g_config; /* The pointer to access the global configuration, initalized in main */
161
162
163
164/*============================================================*/
165/*                         PEERS                              */
166/*============================================================*/
167
168/* States of a peer */
169enum peer_state {
170        /* Stable states */
171        STATE_NEW = 0,          /* The peer has been just been created, PSM thread not started yet */
172        STATE_OPEN,             /* Connexion established */
173       
174        /* Peer state machine */
175        STATE_CLOSED,           /* No connection established, will re-attempt after TcTimer. */
176        STATE_CLOSING,          /* the connection is being shutdown (DPR/DPA in progress) */
177        STATE_WAITCNXACK,       /* Attempting to establish transport-level connection */
178        STATE_WAITCNXACK_ELEC,  /* Received a CER from this same peer on an incoming connection (other peer object), while we were waiting for cnx ack */
179        STATE_WAITCEA,          /* Connection established, CER sent, waiting for CEA */
180        /* STATE_WAITRETURNS_ELEC, */   /* This state is not stable and therefore deprecated:
181                                   We have sent a CER on our initiated connection, and received a CER from the remote peer on another connection. Election.
182                                   If we win the election, we must disconnect the initiated connection and send a CEA on the other => we go to OPEN state.
183                                   If we lose, we disconnect the other connection (receiver) and fallback to WAITCEA state. */
184        STATE_OPEN_HANDSHAKE,   /* TLS Handshake and validation are in progress in open state -- we use it only for debug purpose, it is never displayed */
185       
186        /* Failover state machine */
187        STATE_SUSPECT,          /* A DWR was sent and not answered within TwTime. Failover in progress. */
188        STATE_REOPEN,           /* Connection has been re-established, waiting for 3 DWR/DWA exchanges before putting back to service */
189       
190        /* Error state */
191        STATE_ZOMBIE            /* The PSM thread is not running anymore; it must be re-started or peer should be deleted. */
192#define STATE_MAX STATE_ZOMBIE
193};
194/* The following macro is called in freeDiameter/p_psm.c */
195#define DECLARE_STATE_STR()             \
196const char *peer_state_str[] = {        \
197          "STATE_NEW"                   \
198        , "STATE_OPEN"                  \
199        , "STATE_CLOSED"                \
200        , "STATE_CLOSING"               \
201        , "STATE_WAITCNXACK"            \
202        , "STATE_WAITCNXACK_ELEC"       \
203        , "STATE_WAITCEA"               \
204        , "STATE_OPEN_HANDSHAKE"        \
205        , "STATE_SUSPECT"               \
206        , "STATE_REOPEN"                \
207        , "STATE_ZOMBIE"                \
208        };
209extern const char *peer_state_str[];
210#define STATE_STR(state) \
211        (((unsigned)(state)) <= STATE_MAX ? peer_state_str[((unsigned)(state)) ] : "<Invalid>")
212
213/* Constants for the peer_info structure bellow */
214#define PI_P3_DEFAULT   0       /* Use any available protocol */
215#define PI_P3_IP        1       /* Use only IP to connect to this peer */
216#define PI_P3_IPv6      2       /* resp, IPv6 */
217
218#define PI_P4_DEFAULT   0       /* Attempt any available protocol */
219#define PI_P4_TCP       1       /* Only use TCP */
220#define PI_P4_SCTP      2       /* Only use SCTP */
221
222#define PI_ALGPREF_SCTP 0       /* SCTP is  attempted first (default) */
223#define PI_ALGPREF_TCP  1       /* TCP is attempted first */
224
225#define PI_SEC_DEFAULT  0       /* New TLS security (handshake after connection, protecting also CER/CEA) */
226#define PI_SEC_NONE     1       /* Transparent security with this peer (IPsec) */
227#define PI_SEC_TLS_OLD  2       /* Old TLS security (use Inband-Security-Id AVP during CER/CEA) */
228                                /* Set sec = 3 to authorize use of (Inband-Security-Id == NONE) with this peer, sec = 2 only authorizing TLS */
229
230#define PI_EXP_NONE     0       /* the peer entry does not expire */
231#define PI_EXP_INACTIVE 1       /* the peer entry expires (i.e. is deleted) after pi_lft seconds without activity */
232
233#define PI_PRST_NONE    0       /* the peer entry is deleted after disconnection / error */
234#define PI_PRST_ALWAYS  1       /* the peer entry is persistant (will be kept as ZOMBIE in case of error) */
235                       
236/* Information about a remote peer */
237struct peer_info {
238       
239        char *          pi_diamid;      /* UTF-8, \0 terminated. The Diameter Identity of the remote peer. */
240       
241        struct {
242                struct {
243                        unsigned        pro3 :2;        /* PI_P3_* */
244                        unsigned        pro4 :2;        /* PI_P4_* */
245                        unsigned        alg :1;         /* PI_ALGPREF_* */
246                        unsigned        sec :2;         /* PI_SEC_* */
247                        unsigned        exp :1;         /* PI_EXP_* */
248                        unsigned        persist :1;     /* PI_PRST_* */
249                       
250                }               pic_flags;      /* Flags influencing the connection to the remote peer */
251               
252                char *          pic_realm;      /* If configured, the daemon will match the received realm in CER/CEA matches this. */
253                uint16_t        pic_port;       /* port to connect to. 0: default. */
254               
255                uint32_t        pic_lft;        /* lifetime of this peer when inactive (see pic_flags.exp definition) */
256                int             pic_tctimer;    /* use this value for TcTimer instead of global, if != 0 */
257                int             pic_twtimer;    /* use this value for TwTimer instead of global, if != 0 */
258               
259                char *          pic_priority;   /* Priority string for GnuTLS if we don't use the default */
260               
261        } config;       /* Configured data (static for this peer entry) */
262       
263        struct {
264               
265                enum peer_state pir_state;      /* Current state of the peer in the state machine. fd_cpu_flush_cache() might be useful before reading. */
266               
267                char *          pir_realm;      /* The received realm in CER/CEA. */
268               
269                uint32_t        pir_vendorid;   /* Content of the Vendor-Id AVP, or 0 by default */
270                uint32_t        pir_orstate;    /* Origin-State-Id value */
271                char *          pir_prodname;   /* copy of UTF-8 Product-Name AVP (\0 terminated) */
272                uint32_t        pir_firmrev;    /* Content of the Firmware-Revision AVP */
273                int             pir_relay;      /* The remote peer advertized the relay application */
274                struct fd_list  pir_apps;       /* applications advertised by the remote peer, except relay (pi_flags.relay) */
275                int             pir_isi;        /* Inband-Security-Id advertised (PI_SEC_* bits) */
276               
277                uint32_t        pir_lastDC;     /* The last Disconnect-Cause value received */
278               
279                int             pir_proto;      /* The L4 protocol currently used with the peer (IPPROTO_TCP or IPPROTO_SCTP) */
280                const gnutls_datum_t    *pir_cert_list;         /* The (valid) credentials that the peer has presented, or NULL if TLS is not used */
281                                                                /* This is inspired from http://www.gnu.org/software/gnutls/manual/gnutls.html#ex_003ax509_002dinfo
282                                                                   see there for example of using this data */
283                unsigned int    pir_cert_list_size;             /* Number of certificates in the list */
284               
285        } runtime;      /* Data populated after connection, may change between 2 connections -- not used by fd_peer_add */
286       
287        struct fd_list  pi_endpoints;   /* Endpoint(s) of the remote peer (configured, discovered, or advertized). list of struct fd_endpoint. DNS resolved if empty. */
288};
289
290
291struct peer_hdr {
292        struct fd_list   chain; /* List of all the peers, ordered by their Diameter Id */
293        struct peer_info info;  /* The public data */
294       
295        /* This header is followed by more data in the private peer structure definition */
296};
297
298/* the global list of peers.
299  Since we are not expecting so many connections, we don't use a hash, but it might be changed.
300  The list items are peer_hdr structures (actually, fd_peer, but the cast is OK) */
301extern struct fd_list fd_g_peers;
302extern pthread_rwlock_t fd_g_peers_rw; /* protect the list */
303
304/*
305 * FUNCTION:    fd_peer_add
306 *
307 * PARAMETERS:
308 *  info        : Information to create the peer.
309 *  orig_dbg    : A string indicating the origin of the peer information, for debug (ex: conf, redirect, ...)
310 *  cb          : optional, a callback to call (once) when the peer connection is established or failed
311 *  cb_data     : opaque data to pass to the callback.
312 *
313 * DESCRIPTION:
314 *  Add a peer to the list of peers to which the daemon must maintain a connexion.
315 *
316 *  The content of info parameter is copied, except for the list of endpoints if
317 * not empty, which is simply moved into the created object. It means that the list
318 * items must have been malloc'd, so that they can be freed.
319 *
320 *  If cb is not null, the callback is called when the connection is in OPEN state or
321 * when an error has occurred. The callback should use the pi_state information to
322 * determine which one it is. If the first parameter of the called callback is NULL, it
323 * means that the peer is being destroyed before attempt success / failure.
324 * cb is called to allow freeing cb_data in  * this case.
325 *
326 *  The orig_dbg string is only useful for easing debug, and can be left to NULL.
327 *
328 * RETURN VALUE:
329 *  0           : The peer is added.
330 *  EINVAL      : A parameter is invalid.
331 *  EEXIST      : A peer with the same Diameter-Id is already in the list.
332 *  (other standard errors may be returned, too, with their standard meaning. Example:
333 *    ENOMEM    : Memory allocation for the new object element failed.)
334 */
335int fd_peer_add ( struct peer_info * info, char * orig_dbg, void (*cb)(struct peer_info *, void *), void * cb_data );
336
337/*
338 * FUNCTION:    fd_peer_getbyid
339 *
340 * PARAMETERS:
341 *  diamid      : A \0 terminated string.
342 *  peer        : The peer is stored here if it exists.
343 *
344 * DESCRIPTION:
345 *   Search a peer by its Diameter-Id.
346 *
347 * RETURN VALUE:
348 *  0   : *peer has been updated (to NULL if the peer is not found).
349 * !0   : An error occurred.
350 */
351int fd_peer_getbyid( char * diamid, struct peer_hdr ** peer );
352
353/*
354 * FUNCTION:    fd_peer_validate_register
355 *
356 * PARAMETERS:
357 *  peer_validate       : Callback as defined bellow.
358 *
359 * DESCRIPTION:
360 *  Add a callback to authorize / reject incoming peer connections.
361 * All registered callbacks are called until a callback sets auth = -1 or auth = 1.
362 * If no callback returns a clear decision, the default behavior is applied (reject unknown connections)
363 * The callbacks are called in FILO order of their registration.
364 *
365 * RETURN VALUE:
366 *  0   : The callback is added.
367 * !0   : An error occurred.
368 */
369int fd_peer_validate_register ( int (*peer_validate)(struct peer_info * /* info */, int * /* auth */, int (**cb2)(struct peer_info *)) );
370/*
371 * CALLBACK:    peer_validate
372 *
373 * PARAMETERS:
374 *   info     : Structure containing information about the peer attempting the connection.
375 *   auth     : Store there the result if the peer is accepted (1), rejected (-1), or unknown (0).
376 *   cb2      : If != NULL and in case of PI_SEC_TLS_OLD, another callback to call after handshake (if auth = 1).
377 *
378 * DESCRIPTION:
379 *   This callback is called when a new connection is being established from an unknown peer,
380 * after the CER is received. An extension must register such callback with peer_validate_register.
381 *
382 *   The callback can learn if the peer has sent Inband-Security-Id AVPs in runtime.pir_isi fields.
383 * It can also learn if a handshake has already been performed in runtime.pir_cert_list field.
384 * The callback must set the value of config.pic_flags.sec appropriately to allow a connection without TLS.
385 *
386 *   If the old TLS mechanism is used,
387 * the extension may also need to check the credentials provided during the TLS
388 * exchange (remote certificate). For this purpose, it may set the address of a new callback
389 * to be called once the handshake is completed. This new callback receives the information
390 * structure as parameter (with pir_cert_list set) and returns 0 if the credentials are correct,
391 * or an error code otherwise. If the error code is received, the connection is closed and the
392 * peer is destroyed.
393 * Note that freeDiameter already achieves some usual checks. The callback may be used to enforce
394 * additional restrictions.
395 *
396 * RETURN VALUE:
397 *  0           : The authorization decision has been written in the location pointed by auth.
398 *  !0          : An error occurred.
399 */
400
401
402
403/*============================================================*/
404/*                         MESSAGES                           */
405/*============================================================*/
406
407/*
408 * FUNCTION:    fd_msg_send, fd_msg_send_timeout 
409 *
410 * PARAMETERS:
411 *  pmsg        : Location of the message to be sent on the network (set to NULL on function return to avoid double deletion).
412 *  anscb       : A callback to be called when answer is received, if msg is a request (optional for fd_msg_send)
413 *  anscb_data  : opaque data to be passed back to the anscb when it is called.
414 *  timeout     : (only for fd_msg_send_timeout) sets the absolute time until when to wait for an answer. Past this time,
415 *                the anscb is called with the request as parameter and the answer will be discarded when received.
416 *
417 * DESCRIPTION:
418 *   Sends a message on the network. (actually simply queues it in a global queue, to be picked by a daemon's thread)
419 * For requests, the end-to-end id must be set (see fd_msg_get_eteid / MSGFL_ALLOC_ETEID).
420 * For answers, the message must be created with function fd_msg_new_answ.
421 *
422 * The routing module will handle sending to the correct peer, usually based on the Destination-Realm / Destination-Host AVP.
423 *
424 * If the msg is a request, there are two ways of receiving the answer:
425 *  - either having registered a callback in the dispatch module (see fd_disp_register)
426 *  - or provide a callback as parameter here. If such callback is provided, it is called before the dispatch callbacks.
427 *    The prototype for this callback function is:
428 *     void anscb(void * data, struct msg ** answer)
429 *      where:
430 *              data   : opaque data that was registered along with the callback.
431 *              answer : location of the pointer to the answer.
432 *      note1: on function return, if *answer is not NULL, the message is passed to the dispatch module for regular callbacks.
433 *             otherwise, the callback must take care of freeing the message (fd_msg_free).
434 *      note2: the opaque data is not freed by the daemon in any case, extensions should ensure clean handling in fd_ext_fini.
435 *
436 * If no callback is registered to handle an answer, the message is discarded and an error is logged.
437 *
438 *  fd_msg_send_timeout is similar to fd_msg_send, except that it takes an additional argument "timeout" and can be called
439 * only with requests as parameters, and an anscb callback.
440 * If the matching answer or error is received before the timeout date passes, everything occurs as with fd_msg_send. Otherwise,
441 * the request is removed from the queue (meaning the matching answer will be discarded upon reception) and passed to the answcb
442 * function. This function can easily distinguish between timeout case and answer case by checking if the message received is
443 * a request. Upon return, if the *msg parameter is not NULL, it is freed (not passed to other callbacks).
444 *
445 * RETURN VALUE:
446 *  0           : The message has been queued for sending (sending may fail asynchronously).
447 *  EINVAL      : A parameter is invalid (ex: anscb provided but message is not a request).
448 *  ...
449 */
450int fd_msg_send ( struct msg ** pmsg, void (*anscb)(void *, struct msg **), void * data );
451int fd_msg_send_timeout ( struct msg ** pmsg, void (*anscb)(void *, struct msg **), void * data, const struct timespec *timeout );
452
453/*
454 * FUNCTION:    fd_msg_rescode_set
455 *
456 * PARAMETERS:
457 *  msg         : A msg object -- it must be an answer.
458 *  rescode     : The name of the returned error code (ex: "DIAMETER_INVALID_AVP")
459 *  errormsg    : (optional) human-readable error message to put in Error-Message AVP
460 *  optavp      : (optional) If provided, the content will be put inside a Failed-AVP
461 *  type_id     : 0 => nothing; 1 => adds Origin-Host and Origin-Realm with local info. 2=> adds Error-Reporting-Host.
462 *
463 * DESCRIPTION:
464 *   This function adds a Result-Code AVP to a message, and optionally
465 *  - sets the 'E' error flag in the header,
466 *  - adds Error-Message, Error-Reporting-Host and Failed-AVP AVPs.
467 *
468 * RETURN VALUE:
469 *  0           : Operation complete.
470 *  !0          : an error occurred.
471 */
472int fd_msg_rescode_set( struct msg * msg, char * rescode, char * errormsg, struct avp * optavp, int type_id );
473
474/* Add Origin-Host, Origin-Realm, (if osi) Origin-State-Id AVPS at the end of the message */
475int fd_msg_add_origin ( struct msg * msg, int osi ); 
476
477/* Parse a message against our dictionary, and in case of error log and eventually build the error reply (on return and EBADMSG, *msg == NULL or *msg is the error message ready to send) */
478int fd_msg_parse_or_error( struct msg ** msg );
479
480
481
482
483/*============================================================*/
484/*                         DISPATCH                           */
485/*============================================================*/
486
487/*
488 * FUNCTION:    fd_disp_app_support
489 *
490 * PARAMETERS:
491 *  app         : The dictionary object corresponding to the Application.
492 *  vendor      : (Optional) the dictionary object of a Vendor to claim support in Vendor-Specific-Application-Id
493 *  auth        : Support auth app part.
494 *  acct        : Support acct app part.
495 *
496 * DESCRIPTION:
497 *   Registers an application to be advertized in CER/CEA exchanges.
498 *  Messages with an application-id matching a registered value are passed to the dispatch module,
499 * while other messages are simply relayed or an error is returned (if local node does not relay)
500 *
501 * RETURN VALUE:
502 *  0           : The application support is registered.
503 *  EINVAL      : A parameter is invalid.
504 */
505int fd_disp_app_support ( struct dict_object * app, struct dict_object * vendor, int auth, int acct );
506
507/* Note: if we want to support capabilities updates, we'll have to add possibility to remove an app as well... */
508
509
510/*============================================================*/
511/*                         ROUTING                            */
512/*============================================================*/
513
514/* This file contains the definitions of types and functions involved in the routing decisions in freeDiameter,
515 * and that can be called by extensions.
516 *
517 * Three different type of messages must be distinguished:
518 *  - Messages received, and the peer is final recipient (IN messages)
519 *  - Messages received, and the peer is not final recipient (FWD messages)
520 *  - Message is locally generated (OUT messages)
521 *
522 * There are three global message queues (in queues.c) and also peers-specific queues (in struct fd_peer).
523 *
524 * (*) IN messages processing details:
525 *   - the message is received from the remote peer, a FDEVP_CNX_MSG_RECV event is generated for the peer.
526 *   - the PSM thread parses the buffer, does some verifications, handles non routable messages (fd_msg_is_routable)
527 *   - routable messages are queued in the fd_g_incoming global queue.
528 *   - a thread (routing-in) picks the message and takes the decision if it is handled locally or forwarded,
529 *       based on local capabilities (registered by extensions with fd_disp_app_support).
530 *   - If the message is handled locally, it is queued in fd_g_local.
531 *   - Another thread (dispatch.c) will handle this message and pass it to registered callbacks (see fd_disp_register in libfreeDiameter.h).
532 *
533 * (*) FWD messages details:
534 *   - The process is the same as for IN messages, until the routing-in threads makes its decision that the message is not handled locally.
535 *   - If the local peer does not relay message, an error DIAMETER_APPLICATION_UNSUPPORTED is returned.
536 *   - All callbacks registered with fd_rt_fwd_register are called for the message (see bellow).
537 *     - these callbacks will typically do proxying work. Note that adding the route-record is handled by the daemon.
538 *   - Once all callbacks have been called, the message is queued in the global fd_g_outgoing queue.
539 *   - The remaining processing is the same as for OUT messages, as described bellow.
540 *
541 * (*) OUT messages details:
542 *   - The message are picked from fd_g_outgoing (they are queued there as result of forwarding process or call to fd_msg_send.)
543 *   - The (routing-out) thread builds a list of possible destinations for the message, as follow:
544 *      - create a list of all known peers in the "OPEN" state.
545 *      - remove from that list all peers that are in a Route-Record AVP of the message, to avoid routing loops.
546 *      - remove also all peers that have previously replied an error message for this message.
547 *   - If the list is empty, create an error UNABLE_TO_DELIVER (note: should we trig dynamic discovery here???) and reply.
548 *   - Otherwise, call all callbacks registered by function fd_rt_out_register, with the list of peers and the message.
549 *   - Order the resulting list of peers by score (see bellow), and sent the message to the peer with highest (positive) score.
550 *    - in case the peer is no longer in the "OPEN" state, send the message to the second peer in the list.
551 *      - if no peer is in OPEN state anymore, restart the process of creating the list.
552 *   - Once a peer has been selected, the message is queued into that peer's outgoing queue.
553 *
554 * The following functions allow an extension to register or remove a callback as described above.
555 */
556
557/********** Forwarding callbacks: for Proxy operations ***********/
558
559/* Handle to registered callback */
560struct fd_rt_fwd_hdl;
561
562/* Message direction for the callback */
563enum fd_rt_fwd_dir {
564        RT_FWD_REQ = 1, /* The callback will be called on forwarded requests only */
565        RT_FWD_ALL = 2, /* The callback will be called on all forwarded messages (requests and answers )*/
566        RT_FWD_ANS = 3  /* The callback will be called on answers and errors only */
567};     
568
569/*
570 * FUNCTION:    fd_rt_fwd_register
571 *
572 * PARAMETERS:
573 *  rt_fwd_cb     : The callback function to register (see prototype bellow).
574 *  cbdata        : Pointer to pass to the callback when it is called. The data is opaque to the daemon.
575 *  dir           : One of the RT_FWD_* directions defined above.
576 *  handler       : On success, a handler to the registered callback is stored here.
577 *                 This handler will be used to unregister the cb.
578 *
579 * DESCRIPTION:
580 *   Register a new callback for forwarded messages. See explanations above.
581 * Note that there is no guaranteed order for the callbacks calls.
582 *
583 * RETURN VALUE:
584 *  0           : The callback is registered.
585 *  EINVAL      : A parameter is invalid.
586 *  ENOMEM      : Not enough memory to complete the operation
587 */
588int fd_rt_fwd_register ( int (*rt_fwd_cb)(void * cbdata, struct msg ** msg), void * cbdata, enum fd_rt_fwd_dir dir, struct fd_rt_fwd_hdl ** handler );
589/*
590 * CALLBACK:    rt_fwd_cb
591 *
592 * PARAMETERS:
593 *  data        : pointer to some data that was passed when the callback was registered (optional).
594 *  msg         : The message that is being forwarded.
595 *
596 * DESCRIPTION:
597 *   This callback is called when a message is forwarded to another peer. It may for example add a Proxy-Info AVP.
598 *  The callback may also choose to handle the message in a more complex form. In that case, it must set *msg = NULL
599 *  and handle it differently. In such case, the forwarding thread will stop processing this message.
600 *
601 * RETURN VALUE:
602 *  0           : Operation complete.
603 *  !0          : An error occurred -- will result in daemon's termination.
604 */
605
606/*
607 * FUNCTION:    fd_rt_fwd_unregister
608 *
609 * PARAMETERS:
610 *  handler     : The handler of the callback that must be unregistered.
611 *  cbdata      : Will receive the data registered with the callback, that can be freed if needed.
612 *
613 * DESCRIPTION:
614 *   Removes a callback from the list of registered callbacks.
615 *
616 * RETURN VALUE:
617 *  0           : The callback is unregistered.
618 *  EINVAL      : A parameter is invalid.
619 */
620int fd_rt_fwd_unregister ( struct fd_rt_fwd_hdl * handler, void ** cbdata );
621
622
623/********** Out callbacks: for next hop routing decision operations ***********/
624
625/* Handle to registered callback */
626struct fd_rt_out_hdl;
627
628enum fd_rt_out_score {
629        FD_SCORE_NO_DELIVERY     = -70, /* We should not send this message to this candidate */
630        FD_SCORE_INI             =  -2, /* All candidates are initialized with this value */
631        FD_SCORE_LOAD_BALANCE    =   1, /* Use this to differentiate between several peers with the same score */
632        FD_SCORE_DEFAULT         =   5, /* The peer is a default route for all messages */
633        FD_SCORE_DEFAULT_REALM   =  10, /* The peer is a default route for this realm */
634        FD_SCORE_REALM           =  15, /* The peer belongs to Destination-Realm of the message */
635        FD_SCORE_REDIR_HOST      =  25, /* If there is a redirect rule with ALL_HOST for these message and peer */
636        FD_SCORE_REDIR_APP       =  30, /* If there is a redirect rule with ALL_APPLICATION for these message and peer */
637        FD_SCORE_REDIR_REALM     =  35, /* If there is a redirect rule with ALL_REALM for these message and peer */
638        FD_SCORE_REDIR_REALM_APP =  40, /* If there is a redirect rule with REALM_AND_APPLICATION for these message and peer */
639        FD_SCORE_REDIR_USER      =  45, /* If there is a redirect rule with ALL_USER for these message and peer */
640        FD_SCORE_REDIR_SESSION   =  50, /* If there is a redirect rule with ALL_SESSION for these message and peer */
641        FD_SCORE_FINALDEST       = 100  /* If the peer is the final recipient of the message (i.e. matching Destination-Host), it receives a big score. */
642};
643
644/*
645 * FUNCTION:    fd_rt_out_register
646 *
647 * PARAMETERS:
648 *  rt_out_cb     : The callback function to register (see prototype bellow).
649 *  cbdata        : Pointer to pass to the callback when it is called. The data is opaque to the daemon.
650 *  priority      : Order for calling this callback. The callbacks are called in reverse priority order (higher priority = called sooner).
651 *  handler       : On success, a handler to the registered callback is stored here.
652 *                 This handler will be used to unregister the cb.
653 *
654 * DESCRIPTION:
655 *   Register a new callback to handle OUT routing decisions. See explanations above.
656 *
657 * RETURN VALUE:
658 *  0           : The callback is registered.
659 *  EINVAL      : A parameter is invalid.
660 *  ENOMEM      : Not enough memory to complete the operation
661 */
662int fd_rt_out_register ( int (*rt_out_cb)(void * cbdata, struct msg * msg, struct fd_list * candidates), void * cbdata, int priority, struct fd_rt_out_hdl ** handler );
663/*
664 * CALLBACK:    rt_out_cb
665 *
666 * PARAMETERS:
667 *  cbdata      : pointer to some data that was registered with the callback.
668 *  msg         : The message that must be sent.
669 *  list        : The list of peers to which the message may be sent to, as returned by fd_rtd_candidate_extract
670 *
671 * DESCRIPTION:
672 *   This callback must attribute a score (preferably from FD_SCORE_*) to each candidate peer in the list.
673 *  Once all registered callbacks have been called, the message is sent to the candidate with the highest score.
674 *  Note that each callback must *add* its locally-attributed score to the candidate current "score" parameter, not replace it!
675 *  Note also that this callback must be re-entrant since it may be called by several threads at the same time
676 *  (for different messages)
677 *
678 * RETURN VALUE:
679 *  0           : Operation complete.
680 *  !0          : An error occurred.
681 */
682
683/*
684 * FUNCTION:    fd_rt_out_unregister
685 *
686 * PARAMETERS:
687 *  handler     : The handler of the callback that must be unregistered.
688 *  cbdata      : Will receive the data registered with the callback, that can be freed if needed.
689 *
690 * DESCRIPTION:
691 *   Removes a callback from the list of registered callbacks.
692 *
693 * RETURN VALUE:
694 *  0           : The callback is unregistered.
695 *  EINVAL      : A parameter is invalid.
696 */
697int fd_rt_out_unregister ( struct fd_rt_out_hdl * handler, void ** cbdata );
698
699
700/*============================================================*/
701/*                         EVENTS                             */
702/*============================================================*/
703
704struct fd_event {
705        int      code; /* codespace depends on the queue */
706        size_t   size;
707        void    *data;
708};
709
710/* Daemon's codespace: 1000->1999 (1500->1999 defined in fdcore-internal.h) */
711enum {
712         FDEV_TERMINATE = 1000  /* request to terminate */
713        ,FDEV_DUMP_DICT         /* Dump the content of the dictionary */
714        ,FDEV_DUMP_EXT          /* Dump state of extensions */
715        ,FDEV_DUMP_SERV         /* Dump the server socket status */
716        ,FDEV_DUMP_QUEUES       /* Dump the message queues */
717        ,FDEV_DUMP_CONFIG       /* Dump the configuration */
718        ,FDEV_DUMP_PEERS        /* Dump the list of peers */
719        ,FDEV_TRIGGER           /* Trigger available for extensions. size is sizeof(int), data is int * */
720};
721
722int fd_event_send(struct fifo *queue, int code, size_t datasz, void * data);
723int fd_event_get(struct fifo *queue, int * code, size_t * datasz, void ** data);
724int fd_event_timedget(struct fifo *queue, struct timespec * timeout, int timeoutcode, int * code, size_t * datasz, void ** data);
725void fd_event_destroy(struct fifo **queue, void (*free_cb)(void * data));
726const char * fd_ev_str(int event);
727
728/* for extensions */
729int fd_event_trig_regcb(int trigger_val, const char * module, void (*cb)(void));
730void fd_event_trig_dump();
731
732
733/*============================================================*/
734/*                         ENDPOINTS                          */
735/*============================================================*/
736
737struct fd_endpoint {
738        struct fd_list  chain;  /* link in cnf_endpoints list */
739       
740        union {
741                sSS             ss;     /* the socket information. List is always ordered by ss value (memcmp) -- see fd_ep_add_merge */
742                sSA4            sin;
743                sSA6            sin6;
744                sSA             sa;
745        }
746#ifdef SWIG /* nested anonymous unions are not supported yet */
747                        s
748#endif /* SWIG */
749        ;
750       
751#define EP_FL_CONF      (1 << 0)        /* This endpoint is statically configured in a configuration file */
752#define EP_FL_DISC      (1 << 1)        /* This endpoint was resolved from the Diameter Identity or other DNS query */
753#define EP_FL_ADV       (1 << 2)        /* This endpoint was advertized in Diameter CER/CEA exchange */
754#define EP_FL_LL        (1 << 3)        /* Lower layer mechanism provided this endpoint */
755#define EP_FL_PRIMARY   (1 << 4)        /* This endpoint is primary in a multihomed SCTP association */
756#define EP_ACCEPTALL    (1 << 15)       /* This flag allows bypassing the address filter in fd_ep_add_merge. */
757        uint32_t        flags;          /* Additional information about the endpoint */
758               
759        /* To add: a validity timestamp for DNS records ? How do we retrieve this lifetime from DNS ? */
760};
761
762int fd_ep_add_merge( struct fd_list * list, sSA * sa, socklen_t sl, uint32_t flags );
763int fd_ep_filter( struct fd_list * list, uint32_t flags );
764int fd_ep_filter_family( struct fd_list * list, int af );
765int fd_ep_filter_list( struct fd_list * list, struct fd_list * exclude_list );
766int fd_ep_clearflags( struct fd_list * list, uint32_t flags );
767void fd_ep_dump_one( char * prefix, struct fd_endpoint * ep, char * suffix );
768void fd_ep_dump( int indent, struct fd_list * eps );
769
770
771/*============================================================*/
772/*                         APPLICATIONS IDs                   */
773/*============================================================*/
774
775struct fd_app {
776        struct fd_list   chain; /* link in cnf_apps list. List ordered by appid. */
777        struct {
778                unsigned auth   : 1;
779                unsigned acct   : 1;
780        }                flags;
781        vendor_id_t      vndid; /* if not 0, Vendor-Specific-App-Id AVP will be used */
782        application_id_t appid; /* The identifier of the application */
783};
784       
785int fd_app_merge(struct fd_list * list, application_id_t aid, vendor_id_t vid, int auth, int acct);
786int fd_app_check(struct fd_list * list, application_id_t aid, struct fd_app **detail);
787int fd_app_check_common(struct fd_list * list1, struct fd_list * list2, int * common_found);
788int fd_app_empty(struct fd_list * list);
789
790#endif /* _LIBFDCORE_H */
Note: See TracBrowser for help on using the repository browser.