Files
m241Neelima/components/ip_net2-6.9/ipmipfa/src/ipmipfa_node.h
T
2026-07-30 11:19:44 +05:30

1130 lines
24 KiB
C

/* ipmipfa_node.h - ipmipfa_node.h */
/*
******************************************************************************
* HEADER FILE
*
* Document no: @(#) $Name: VXWORKS_ITER40_2019102207 $ $RCSfile: ipmipfa_node.h,v $ $Revision: 1.26 $
* $Source: /home/interpeak/CVSRoot/ipmipfa/src/ipmipfa_node.h,v $
* $Author: jhorteli $ $Date: 2010-10-15 11:28:07 $
* $State: Exp $ $Locker: $
*
* INTERPEAK_COPYRIGHT_STRING
* Design and implementation by Joel Hortelius <joel.hortelius@interpeak.se>
******************************************************************************
*/
#ifndef IPMIPFA_NODE_H
#define IPMIPFA_NODE_H
/*
****************************************************************************
* 1 DESCRIPTION
****************************************************************************
*/
/*
DESCRIPTION
No description currently provided
*/
/*
****************************************************************************
* 2 CONFIGURATION
****************************************************************************
*/
/*
****************************************************************************
* 3 INCLUDE FILES
****************************************************************************
*/
#include "ipmipfa_h.h"
#include "ipmipfa_if.h"
#include "ipmipfa_llh.h"
#ifdef __cplusplus
extern "C" {
#endif
/*
****************************************************************************
* 4 DEFINES
****************************************************************************
*/
/*
****************************************************************************
* 5 TYPES
****************************************************************************
*/
struct Ipmipfa_fa;
struct Ipmipfa_iff;
struct Ipmipfa_data;
struct Ipmipfa_pktbuf;
struct Ipmip_proc;
struct Ipmipfa_extension;
typedef struct Ipmipfa_node_reginfo
{
Ipmip_lladdr_t *faVisitorMAC;
Ipmip_lladdr_t *faVisitorRoute;
/* Timers */
Ipmip_timer_t timer;
Ipmip_timer_t revocation_timer;
Ipmip_timer_t nat_t_timer;
Ip_u8 retransmits;
} Ipmipfa_node_reginfo_t;
/* Pending registration */
typedef struct Ipmipfa_node_pending
{
/* Current pending request */
struct Ipmipfa_pktbuf *faVisitorPendingRequest;
/* Extended information */
Ip_time_t faVisitorLastUpdated;
/* Timers */
Ipmip_timer_t timer;
} Ipmipfa_node_pending_t;
/* LLH information in the node */
typedef struct Ipmipfa_node_llh
{
Ipmipfa_llh_agent_t fa;
Ipmipfa_llh_agent_t fa_htt;
Ipmip_timer_t timer;
union Ipmipfa_llh_pending pending;
} Ipmipfa_node_llh_t;
/*
*===========================================================================
* Mobile node binding (A client may have many simultaneously)
*===========================================================================
*/
typedef struct Ipmipfa_node
{
Ipmip_timer_lock_t *lock;
Ipmip_timer_t service;
Ipmip4_msgext_uhdr_t *nai;
struct Ipmip4_auth_spi *faVisitorMobileSA;
struct Ipmip4_auth_spi *faVisitorHomeAgentSA;
struct Ipmipfa_iff *ifp;
struct Ipmipfa_mib_faVisitorEntry mib;
/**/
struct Ipmipfa_extension *handler;
Ip_u32 faVisitorIdentity;
Ip_time_t faVisitorCreationTime;
Ip_time_t faVisitorLastUpdated;
Ip_u32 faVisitorSPIMobileForeign;
Ip_u32 faVisitorSPIForeignHome;
Ip_u32 faVisitorSPIMobileAAA;
Ip_time_t faVisitorAAAVerificationTime;
Ip_u32 faVisitorRevocationTimeStamp;
Ip_u32 faVisitorInterfaceIndex;
Ip_u32 faVisitorTunnelingEndpoint;
Ip_u8 faVisitorRegType;
Ip_u8 faVisitorTunnelType;
Ip_u8 faVisitorTunnelFlags;
Ip_u8 faVisitorAccounting;
Ip_u16 faVisitorNATTraversalKeepAlive;
Ip_u32 flags;
Ip_u32 state;
/* Verified registration */
Ipmipfa_node_reginfo_t reginfo;
/* Pending registration */
Ipmipfa_node_pending_t pending;
/* Fast handover data */
Ipmipfa_node_llh_t llh;
/* Currently used challenge */
int if_challenge;
/* SPIS for this node */
struct Ipmip4_auth_spi *faLastMobileSA;
/* Pending challenge */
Ip_u8 current_challenge[IPMIPFA_CONF_CHALLENGE_LEN];
/* Challenge last unicast to node */
Ip_u8 unicast_challenge[IPMIPFA_CONF_CHALLENGE_LEN];
/* */
Ip_u32 enabled[IPMIPFA_FUNCTION_MAX];
Ip_u32 supported[IPMIPFA_FUNCTION_MAX];
void **extdata[IPMIPFA_FUNCTION_MAX];
/**/
Ip_u64 faVisitorRcvOctets;
Ip_u64 faVisitorRcvPkts;
Ip_u64 faVisitorSndOctets;
Ip_u64 faVisitorSndPkts;
}
Ipmipfa_node_t;
typedef struct Ipmipfa_node_context
{
Ipcom_mutex node_lock;
Ipcom_hash *hash_address; /* All known MN using ha/haddr address as key */
Ipcom_hash *hash_lla_nai; /* All known MN using LLA address as key */
Ipcom_hash *hash_lla_hoa; /* All known MN using LLA address as key */
Ipcom_hash *hash_pending; /* Pending registrations */
} Ipmipfa_node_context_t;
#define IPMIPFA_NODE_FLAG_DEAD 0x000002
#define IPMIPFA_NODE_FLAG_ROUTE_HAVE 0x000004
#define IPMIPFA_NODE_FLAG_TUNNEL 0x000008
#define IPMIPFA_NODE_FLAG_LLH_PREREG 0x000100
#define IPMIPFA_NODE_FLAG_LLH_POSTREG 0x000200
#define IPMIPFA_NODE_FLAG_LLH_L2_ST 0x000400
#define IPMIPFA_NODE_FLAG_LLH_L2_TT 0x000800
#define IPMIPFA_NODE_CHALLENGE_UNICAST_VALID 0x001000 /* The unicast challenge is valid */
#define IPMIPFA_NODE_CHALLENGE_UNICAST_CURRENT 0x002000 /* Current challenge is a unicast */
#define IPMIPFA_NODE_CHALLENGE_ADVERT_CURRENT 0x004000 /* Current challenge is a advert */
#define IPMIPFA_NODE_CHALLENGE_STALE_CURRENT 0x008000 /* Current challenge is stale */
#define IPMIPFA_NODE_CHALLENGE_CURRENT (IPMIPFA_NODE_CHALLENGE_UNICAST_CURRENT|\
IPMIPFA_NODE_CHALLENGE_ADVERT_CURRENT|\
IPMIPFA_NODE_CHALLENGE_STALE_CURRENT)
#define IPMIPFA_NODE_FLAG_HASH_HA_HOA 0x010000
#define IPMIPFA_NODE_FLAG_HASH_LLA_HOA 0x040000
#define IPMIPFA_NODE_FLAG_HASH_LLA_NAI 0x080000
/*
****************************************************************************
* 6 FUNCTIONS
****************************************************************************
*/
/*******************************************************************************
*
* ipmipfa_node_register_local_route - ipmipfa_node_register_local_route
*
* Register the local route
*
* Parameters:
* \is
* \i data
* Context
* \i proc
* Process
* \i node
* The node we're modifying.
* \i lladdr
* The local route
* \ie
*
* RETURNS: No return value
*
* ERRNO:
*
* \NOMANUAL
*/
IP_GLOBAL void ipmipfa_node_register_local_route
(
struct Ipmipfa_data *data,
struct Ipmip_proc *proc,
Ipmipfa_node_t *node,
Ipmip_lladdr_t *lladdr
);
/*******************************************************************************
*
* ipmipfa_node_register_home - ipmipfa_node_register_home
*
* Update the registration parameters for home address and
* agent.
*
* Parameters:
* \is
* \i data
* Context
* \i proc
* Process
* \i node
* The node we're updating
* \i home_address
* The home address in question.
* \i home_agent
* The agent we're currently using
* \i spi_mf
* The SPI used to establish this particular
*
* registration.
* \i spi_fh
* SPI used between foreign agent and home agent.
* \i spi_aaa
* AAA SPI used
* \ie
*
* RETURNS: No return value
*
* ERRNO:
*
* \NOMANUAL
*/
IP_GLOBAL void ipmipfa_node_register_home
(
struct Ipmipfa_data *data,
struct Ipmip_proc *proc,
Ipmipfa_node_t *node,
Ip_u32 home_address,
Ip_u32 home_agent,
Ip_u32 spi_mf,
Ip_u32 spi_fh,
Ip_u32 spi_aaa
);
/*******************************************************************************
*
* ipmipfa_node_set_challenge - ipmipfa_node_set_challenge
*
* Set a challenge in the node
*
* Parameters:
* \is
* \i node
* The node in question.
* \i challenge
* The challenge in question
* \i if_chawin
* The interface challenge window
* \i unicast
* IP_TRUE if unicast, IP_FALSE if advert.
* \ie
*
* RETURNS: No return value
*
* ERRNO:
*
* \NOMANUAL
*/
IP_GLOBAL void ipmipfa_node_set_challenge
(
Ipmipfa_node_t *node,
Ip_u8 *challenge,
int if_chawin,
Ip_bool unicast
);
/*******************************************************************************
*
* ipmipfa_node_clear_pending - ipmipfa_node_clear_pending
*
* Clear the pending registration values of a node.
*
* Parameters:
* \is
* \i data
* Data object
* \i proc
* Process
* \i node
* The node in question.
* \ie
*
* RETURNS: The pending packet buffer; if any
*
* ERRNO:
*
* \NOMANUAL
*/
IP_GLOBAL struct Ipmipfa_pktbuf * ipmipfa_node_clear_pending
(
struct Ipmipfa_data *data,
struct Ipmip_proc *proc,
Ipmipfa_node_t *node
);
/*******************************************************************************
*
* ipmipfa_node_create - ipmipfa_node_create
*
* Create a new node belonging with the supplied parameters.
*
* Parameters:
* \is
* \i data
* Context
* \i proc
* Process
* \i iff
* The interface on which the node has been seen.
* \i home_addr
* The home address
* \i home_agent
* Home agent
* \i nai
* NAI.
* \i lladdr
* The MAC address.
* \ie
*
* RETURNS: The node if successful.
*
* ERRNO:
*
* \NOMANUAL
*/
IP_GLOBAL Ipmipfa_node_t * ipmipfa_node_create
(
struct Ipmipfa_data *data,
struct Ipmip_proc *proc,
struct Ipmipfa_iff *iff,
Ip_u32 home_addr,
Ip_u32 home_agent,
Ipmip4_msgext_uhdr_t *nai,
Ipmip_lladdr_t *lladdr
);
/*******************************************************************************
*
* ipmipfa_node_update_pending_timeout - ipmipfa_node_update_pending_timeout
*
* Update the pending timeout of a node
*
* Parameters:
* \is
* \i data
* Context
* \i proc
* Process
* \i node
* The node
* \ie
*
* RETURNS: No return value
*
* ERRNO:
*
* \NOMANUAL
*/
IP_GLOBAL void ipmipfa_node_update_pending_timeout
(
struct Ipmipfa_data *data,
struct Ipmip_proc *proc,
Ipmipfa_node_t *node
);
/*******************************************************************************
*
* ipmipfa_node_update_pending_request - ipmipfa_node_update_pending_request
*
* Store the pending information for the outstanding request.
*
* Parameters:
* \is
* \i data
* Context
* \i proc
* Current process
* \i node
* The node
* \i pbuf
* Outstanding request
* \ie
*
* RETURNS: No return value
*
* ERRNO:
*
* \NOMANUAL
*/
IP_GLOBAL void ipmipfa_node_update_pending_request
(
struct Ipmipfa_data *data,
struct Ipmip_proc *proc,
Ipmipfa_node_t *node,
struct Ipmipfa_pktbuf *pbuf
);
/*******************************************************************************
*
* ipmipfa_node_register_tunnel - ipmipfa_node_register_tunnel
*
* Register the tunnel changes
*
* Parameters:
* \is
* \i data
* Context
* \i proc
* Process
* \i node
* The node we're modifying.
* \i reverse_endpoint
* Where to tunnel
* \i tunnel_type
* Type of the tunnel.
* \i tunnel_flags
* Tunnel flags
* \i nat_t_keepalive
* NAT-T keepalive
* \ie
*
* RETURNS: No return value
*
* ERRNO:
*
* \NOMANUAL
*/
IP_GLOBAL void ipmipfa_node_register_tunnel
(
struct Ipmipfa_data *data,
struct Ipmip_proc *proc,
Ipmipfa_node_t *node,
Ip_addr4 reverse_endpoint,
Ip_u8 tunnel_type,
Ip_u8 tunnel_flags,
Ip_u16 nat_t_keepalive
);
/*******************************************************************************
*
* ipmipfa_node_register_pending - ipmipfa_node_register_pending
*
* The pending values has been acknowledged, register it.
*
* Parameters:
* \is
* \i data
* Context
* \i proc
* Process
* \i node
* The node.
* \i pbuf
* The pending buffer
* \i lifetime
* Lifetime.
* \ie
*
* RETURNS: No return value
*
* ERRNO:
*
* \NOMANUAL
*/
IP_GLOBAL void ipmipfa_node_register_pending
(
struct Ipmipfa_data *data,
struct Ipmip_proc *proc,
Ipmipfa_node_t *node,
struct Ipmipfa_pktbuf *pbuf,
Ip_u16 lifetime
);
/*******************************************************************************
*
* ipmipfa_node_extension_data - ipmipfa_node_extension_data
*
* Return the extension data on a node for a provided, registered, extension
*
* Parameters:
* \is
* \i node
* The node
* \i ext
* The extension
* \ie
*
* RETURNS: The extension data or IP_NULL
*
* ERRNO:
*
* \NOMANUAL
*/
IP_GLOBAL void *ipmipfa_node_extension_data
(
Ipmipfa_node_t *node,
Ipmipfa_extension_t *ext
);
/*******************************************************************************
*
* ipmipfa_node_register_type - ipmipfa_node_register_type
*
* Set the current registration type
*
* Parameters:
* \is
* \i data
* Context
* \i proc
* Process
* \i node
* The node
* \i type
* Registration type
* \ie
*
* RETURNS: No return value
*
* ERRNO:
*
* \NOMANUAL
*/
IP_GLOBAL void ipmipfa_node_register_type
(
struct Ipmipfa_data *data,
struct Ipmip_proc *proc,
Ipmipfa_node_t *node,
Ip_u8 type
);
/*******************************************************************************
*
* ipmipfa_node_lifetime - ipmipfa_node_lifetime
*
* Extends the lifetime of a node
*
* Parameters:
* \is
* \i data
* Context
* \i proc
* Process
* \i node
* The node in question
* \i lifetime
* The lifetime.
* \ie
*
* RETURNS: No return value
*
* ERRNO:
*
* \NOMANUAL
*/
IP_GLOBAL void ipmipfa_node_lifetime
(
struct Ipmipfa_data *data,
struct Ipmip_proc *proc,
Ipmipfa_node_t *node,
Ip_u16 lifetime
);
/*******************************************************************************
*
* ipmipfa_node_findbykey - ipmipfa_node_findbykey
*
* Retrieve a node based on a home address.
*
* Parameters:
* \is
* \i data
* The FA data structure to look in
* \i proc
* Current process
* \i iff
* The interface this node's supposed to be located on
* \i home_addr
* The home address we're looking for.
* \i home_agent
* The home agent
* \i nai
* The nai
* \i lladdr
* The LLA
* \i timer
* Timer to use for delayed invokation
* \i func
* Callback function
* \i arg1
* First opaque argument for callback.
* \ie
*
* RETURNS: No return value
*
* ERRNO:
*
* \NOMANUAL
*/
IP_GLOBAL void ipmipfa_node_findbykey
(
struct Ipmipfa_data *data,
struct Ipmip_proc *proc,
struct Ipmipfa_iff *iff,
Ip_u32 home_addr,
Ip_u32 home_agent,
struct Ip_iovec *nai,
Ipmip_lladdr_t *lladdr,
Ipmip_timer_t *timer,
Ipmip_timer_func_t func,
void *arg1
);
/*******************************************************************************
*
* ipmipfa_node_lookup_handle - ipmipfa_node_lookup_handle
*
* Retrieve a node based on a handle
*
* Parameters:
* \is
* \i data
* The FA data structure to look in
* \i proc
* Current process
* \i handle
* The handle
* \i timer
* Timer to use for delayed invokation
* \i func
* Callback function
* \i arg1
* First opaque argument for callback.
* \ie
*
* RETURNS: No return value
*
* ERRNO:
*
* \NOMANUAL
*/
IP_GLOBAL void ipmipfa_node_lookup_handle
(
struct Ipmipfa_data *data,
struct Ipmip_proc *proc,
Ip_u32 identity,
Ipmip_timer_t *timer,
Ipmip_timer_func_t func,
void *arg1
);
/*******************************************************************************
*
* ipmipfa_node_get_pending - ipmipfa_node_get_pending
*
* Get a node with a pending registration
*
* Parameters:
* \is
* \i data
* The FA data structure to look in
* \i proc
* Process.
* \i pbuf
* The packet buffer containing the required lookup
*
* information.
* \i func
* callback function
* \ie
*
* RETURNS: IP_TRUE if there was a pending node
*
* ERRNO:
*
* \NOMANUAL
*/
IP_GLOBAL Ip_bool ipmipfa_node_get_pending
(
struct Ipmipfa_data *data,
struct Ipmip_proc *proc,
struct Ipmipfa_pktbuf *pbuf,
Ipmip_timer_func_t func
);
/*******************************************************************************
*
* ipmipfa_node_clear - ipmipfa_node_clear
*
* Clear all nodes belonging to the FA data configuration
*
* Parameters:
* \is
* \i data
* The data configuration structure.
* \i proc
* Current process.
* \ie
*
* RETURNS: No return value
*
* ERRNO:
*
* \NOMANUAL
*/
IP_GLOBAL void ipmipfa_node_clear
(
struct Ipmipfa_data *data,
struct Ipmip_proc *proc
);
/*******************************************************************************
*
* ipmipfa_node_context_destroy - ipmipfa_node_context_destroy
*
* Shutdown the node specific part of the data configuration
* structure.
*
* Parameters:
* \is
* \i data
* The data configuration structure.
* \i proc
* Current process.
* \ie
*
* RETURNS: No return value
*
* ERRNO:
*
* \NOMANUAL
*/
IP_GLOBAL void ipmipfa_node_context_destroy
(
struct Ipmipfa_data *data,
struct Ipmip_proc *proc,
Ipmipfa_node_context_t *nctx
);
/*******************************************************************************
*
* ipmipfa_node_context_alloc - ipmipfa_node_context_alloc
*
* Initialize the node specific part of the FA data structure
*
* Parameters:
* \is
* \i data
* The data structure to initialize.
* \i proc
* Current process.
* \ie
*
* RETURNS: The context
*
* ERRNO:
*
* \NOMANUAL
*/
IP_GLOBAL Ipmipfa_node_context_t *ipmipfa_node_context_alloc
(
struct Ipmipfa_data *data,
struct Ipmip_proc *proc
);
/*******************************************************************************
*
* ipmipfa_node_terminate - ipmipfa_node_terminate
*
* Terminate a node gracefully.
*
* Parameters:
* \is
* \i data
* Data
* \i proc
* Process
* \i node
* Node.
* \i inform
* Inform the node about the termination
* \ie
*
* RETURNS: A timer return value, which must be honored.
*
* ERRNO:
*
* \NOMANUAL
*/
IP_GLOBAL int ipmipfa_node_terminate
(
struct Ipmipfa_data *data,
struct Ipmip_proc *proc,
struct Ipmipfa_node *node,
Ip_bool inform
);
/*******************************************************************************
*
* ipmipfa_node_revoke - ipmipfa_node_revoke
*
* Revoke this particular node
*
* Parameters:
* \is
* \i data
* Data
* \i proc
* Process
* \i node
* Node.
* \ie
*
* RETURNS: No return value
*
* ERRNO:
*
* \NOMANUAL
*/
IP_GLOBAL void ipmipfa_node_revoke
(
struct Ipmipfa_data *data,
struct Ipmip_proc *proc,
struct Ipmipfa_node *node
);
/*******************************************************************************
*
* ipmipfa_node_enable_function - ipmipfa_node_enable_function
*
* Enable a particular function
*
* Parameters:
* \is
* \i data
* Data
* \i proc
* Process
* \i node
* Node.
* \i func
* Function
* \i mask
* Function mask
* \ie
*
* RETURNS: IP_TRUE if request is pending
*
* ERRNO:
*
* \NOMANUAL
*/
IP_GLOBAL Ip_bool ipmipfa_node_enable_function
(
struct Ipmipfa_data *ctx,
struct Ipmip_proc *proc,
Ipmipfa_node_t *node,
int func,
Ip_u32 mask
);
/*******************************************************************************
*
* ipmipfa_node_enable - ipmipfa_node_enable
*
* Enable a particular node
*
* Parameters:
* \is
* \i data
* Data
* \i proc
* Process
* \i node
* Node.
* \ie
*
* RETURNS: IP_TRUE if request is pending
*
* ERRNO:
*
* \NOMANUAL
*/
IP_GLOBAL Ip_bool ipmipfa_node_enable
(
struct Ipmipfa_data *ctx,
struct Ipmip_proc *proc,
Ipmipfa_node_t *node
);
/*******************************************************************************
*
* ipmipfa_node_disable_function - ipmipfa_node_disable_function
*
* Disable a particular function
*
* Parameters:
* \is
* \i data
* Data
* \i proc
* Process
* \i node
* Node.
* \i func
* Function
* \i mask
* Function mask
* \ie
*
* RETURNS: IP_TRUE if request is pending
*
* ERRNO:
*
* \NOMANUAL
*/
IP_GLOBAL Ip_bool ipmipfa_node_disable_function
(
struct Ipmipfa_data *ctx,
struct Ipmip_proc *proc,
Ipmipfa_node_t *node,
int func,
Ip_u32 mask
);
/*******************************************************************************
*
* ipmipfa_node_disable - ipmipfa_node_disable
*
* Disable a particular node
*
* Parameters:
* \is
* \i data
* Data
* \i proc
* Process
* \i node
* Node.
* \ie
*
* RETURNS: IP_TRUE if request is pending
*
* ERRNO:
*
* \NOMANUAL
*/
IP_GLOBAL Ip_bool ipmipfa_node_disable
(
struct Ipmipfa_data *ctx,
struct Ipmip_proc *proc,
Ipmipfa_node_t *node
);
IP_GLOBAL Ip_bool ipmipfa_node_function_reply_validate
(
struct Ipmipfa_data *ctx,
struct Ipmip_proc *proc,
Ipmipfa_node_t *node,
struct Ipmipfa_pktbuf *pbuf,
int func
);
IP_GLOBAL void ipmipfa_node_function_reply_forward
(
struct Ipmipfa_data *ctx,
struct Ipmip_proc *proc,
Ipmipfa_node_t *node,
struct Ipmipfa_pktbuf *pbuf
);
IP_GLOBAL Ip_bool ipmipfa_node_function_request_validate
(
struct Ipmipfa_data *ctx,
struct Ipmip_proc *proc,
Ipmipfa_node_t *node,
struct Ipmipfa_pktbuf *pbuf,
int func
);
IP_GLOBAL void ipmipfa_node_function_request_forward
(
struct Ipmipfa_data *ctx,
struct Ipmip_proc *proc,
Ipmipfa_node_t *node,
struct Ipmipfa_pktbuf *pbuf,
int func
);
IP_GLOBAL void ipmipfa_node_function_reqrep_accepted
(
struct Ipmipfa_data *ctx,
struct Ipmip_proc *proc,
Ipmipfa_node_t *node,
struct Ipmipfa_pktbuf *pbuf
);
IP_GLOBAL void ipmipfa_node_set_lladdr
(
struct Ipmipfa_data *ctx,
struct Ipmip_proc *proc,
Ipmipfa_node_t *node,
Ipmip_lladdr_t *lladdr
);
/*******************************************************************************
*
* ipmipfa_node_describe - ipmipfa_node_describe
*
* Describe a particular node
*
* Parameters:
* \is
* \i proc
* Process
* \i node
* Node.
* \ie
*
* RETURNS: A human readable description
*
* ERRNO:
*
* \NOMANUAL
*/
IP_GLOBAL const char *ipmipfa_node_describe
(
struct Ipmip_proc *proc,
Ipmipfa_node_t *node
);
#ifdef __cplusplus
}
#endif
#endif
/*
****************************************************************************
* END OF FILE
****************************************************************************
*/