Files
m241Neelima/components/ip_net2-6.9/ipike/src/ipike_event_server.c
T
2026-07-30 11:19:44 +05:30

640 lines
18 KiB
C

/*
******************************************************************************
* SOURCE FILE
*
* Document no: @(#) $Name: VXWORKS_ITER40_2019102207 $ $RCSfile: ipike_event_server.c,v $ $Revision: 1.5.2.4 $
* $Source: /home/interpeak/CVSRoot/ipike/src/ipike_event_server.c,v $
* $Author: zan $ $Date: 2013-07-31 08:17:04 $
* $State: Exp $ $Locker: $
*
* INTERPEAK_COPYRIGHT_STRING
* Design and implementation by Erik Dahlberg <erik.dahlberg@windriver.com>
******************************************************************************
*/
/*
****************************************************************************
* 1 DESCRIPTION
****************************************************************************
*/
/* IKE event receiver (client) and server implementation. The event server
* will send event messages to each registered receiver. All communication
* relies on IKE channels */
/*
****************************************************************************
* 2 CONFIGURATION
****************************************************************************
*/
#define IPCOM_USE_CLIB_PROTO
#include "ipike_config.h"
#ifdef IPIKE_USE_EVENT_LOG
/*
****************************************************************************
* 3 INCLUDE FILES
****************************************************************************
*/
#include "ipike_h.h"
#include "ipike_event.h"
#include "ipike_event_server.h"
#include "ipike_event_receiver.h"
#include "ipike_channel.h"
/*
****************************************************************************
* 4 EXTERN PROTOTYPES
****************************************************************************
*/
/*
****************************************************************************
* 5 DEFINES
****************************************************************************
*/
/* Retry time period for an IKE event receiver */
#define IPIKE_EVENT_RECEIVER_RETRY_TIME_SEC 1
/* Process name */
#define IPIKE_EVENT_RECEIVER_PROC_NAME "tIKEEventReceiver"
/* Channel address */
#if defined(IPCOM_USE_INET)
#define IPIKE_EVENT_CHANNEL_IP "127.0.0.1"
#else
#define IPIKE_EVENT_CHANNEL_IP "::1"
#endif
/* Channel port */
#define IPIKE_EVENT_CHANNEL_PORT "50150"
/* Full channel address */
#define IPIKE_EVENT_CHANNEL_ADDRESS \
IPIKE_EVENT_CHANNEL_IP "@" IPIKE_EVENT_CHANNEL_PORT
/*
****************************************************************************
* 6 TYPES
****************************************************************************
*/
/* Event receiver context */
typedef struct Ipike_event_receiver_ctx_struct
{
/* Semaphore for synchronized termination */
Ipcom_sem sem;
Ipcom_mutex mutex;
/* Variables protected by mutex - start */
Ipike_event_receiver_cb event_cb;
Ipike_channel *channel;
/* variables protected by mutex - end */
} Ipike_event_receiver_ctx;
/*
****************************************************************************
* 7 LOCAL PROTOTYPES
****************************************************************************
*/
/*
****************************************************************************
* 8 DATA
****************************************************************************
*/
/* Event receiver context, use one static global for now */
IP_STATIC Ipike_event_receiver_ctx ctx_store;
IP_STATIC Ipike_event_receiver_ctx * libctx;
/* String representation of events, must be aligned with the event table */
IP_STATIC const char * Ipike_event_strings[] =
{
"SOFT_LIFE_SIZE_EXPIRED",
"SOFT_LIFE_TIME_EXPIRED",
"HARD_LIFE_SIZE_EXPIRED",
"HARD_LIFE_TIME_EXPIRED",
"IKE_PACKET_DISCARD",
"IKE_PHASE_I_FAIL",
"IKE_PHASE_I_SUCCESS",
"IKE_PHASE_II_FAIL",
"IKE_PHASE_II_SUCCESS",
"IPSEC_PACKET_DISCARD",
"SEQUENCE_NUM_OVERFLOW",
"SPD_PACKET_DISCARD"
};
/* String representation of event reasons, must be aligned with
* the event reason table */
IP_STATIC const char * Ipike_event_reason_strings[] =
{
"UNDEFINED",
"AUTHENTICATION_ERROR",
"DECRYPTION_ERROR",
"ENCRYPTION_ERROR",
"EXPLICIT_DISCARD_POLICY",
"INVALID_SPI_ERROR",
"NEGOTIATION_TIMEOUT",
"NO_POLICY",
"NO_PROTECTION_SUITE",
"POLICY_ERROR",
"REPLAY_ERROR",
"INTERNAL_ERROR",
"ISAKMP_PACKET_ERROR",
"PROPOSAL_MISMATCH",
"PSK_MISMATCH",
"FLOW_MISMATCH",
"IKE_INTERNAL_ERROR",
"IKE_SA_OVERFLOW",
"IPSEC_SA_OVERFLOW"
};
/*
****************************************************************************
* 9 LOCAL FUNCTIONS
****************************************************************************
*/
/*
*===========================================================================
* ipike_event_receiver_callback_set
*===========================================================================
*/
IP_STATIC void
ipike_event_receiver_callback_set(
Ipike_event_receiver_ctx * ctx,
Ipike_event_receiver_cb event_cb)
{
ip_assert(ctx != IP_NULL);
ipcom_mutex_lock(ctx->mutex);
ctx->event_cb = event_cb;
ipcom_mutex_unlock(ctx->mutex);
}
/*
*===========================================================================
* ipike_event_receiver_callback_get
*===========================================================================
*/
IP_STATIC Ipike_event_receiver_cb
ipike_event_receiver_callback_get(
Ipike_event_receiver_ctx * ctx)
{
Ipike_event_receiver_cb cb;
ip_assert(ctx != IP_NULL);
ipcom_mutex_lock(ctx->mutex);
cb = ctx->event_cb;
ipcom_mutex_unlock(ctx->mutex);
return cb;
}
/*
*===========================================================================
* ipike_event_receiver_process_msg
*===========================================================================
*/
IP_STATIC int
ipike_event_receiver_process_msg(
Ipike_event_receiver_ctx * ctx,
Ipike_channel_msg * msg)
{
Ipike_event_msg * emsg = (Ipike_event_msg *) msg;
Ipike_event_receiver_cb cb = IP_NULL;
cb = ipike_event_receiver_callback_get(ctx);
emsg->event.spi = ip_ntohl(emsg->event.spi);
emsg->event.reason = ip_ntohs(emsg->event.reason);
emsg->event.type = ip_ntohs(emsg->event.type);
emsg->event.src_port = ip_ntohs(emsg->event.src_port);
emsg->event.dst_port = ip_ntohs(emsg->event.dst_port);
if ( cb )
return cb(&emsg->event);
return -1;
}
/*
*===========================================================================
* ipike_event_receiver_proc
*===========================================================================
*/
IP_STATIC
IPCOM_PROCESS(ipike_event_receiver_proc)
{
Ipike_channel_addr * caddr = IP_NULL;
Ipike_channel_msg * msg = IP_NULL;
Ipike_channel * channel = IP_NULL;
Ipike_event_msg emsg;
Ipike_channel_status ret;
ip_assert(libctx != IP_NULL);
/* Register process */
ipcom_proc_init();
/* Register log in ipike facility */
ipcom_openlog("ipike", 0, IPCOM_LOG_IPIKE);
/* Get IKE daemon's channel address */
caddr = ipike_channel_addr_create(IPIKE_EVENT_CHANNEL_ADDRESS);
if ( caddr == IP_NULL )
{
IPCOM_LOG0(ERR, "ipike_event_receiver_proc() :: "\
"failed to create address");
goto errout;
}
/* Try keep us connected as long we have callback */
while ( ipike_event_receiver_callback_get(libctx) )
{
IPCOM_LOG1(DEBUG2, "ipike_event_receiver_proc() ::"\
" opening channel, retrying in %d seconds",
IPIKE_EVENT_RECEIVER_RETRY_TIME_SEC);
/* We are reestablishing an existing channel */
if ( channel != IP_NULL )
{
ipcom_mutex_lock(libctx->mutex);
libctx->channel = IP_NULL;
ipcom_mutex_unlock(libctx->mutex);
/* Destroy channel */
ipike_channel_destroy(channel);
}
/* Open channel to IKE daemon */
channel = ipike_channel_open(caddr);
if ( channel == IP_NULL )
{
IPCOM_LOG1(DEBUG2, "ipike_event_receiver_proc() :: failed to"\
" open channel, retrying in %d seconds",
IPIKE_EVENT_RECEIVER_RETRY_TIME_SEC);
ipcom_sleep(IPIKE_EVENT_RECEIVER_RETRY_TIME_SEC);
continue;
}
ipcom_mutex_lock(libctx->mutex);
libctx->channel = channel;
ipcom_mutex_unlock(libctx->mutex);
/* Loop forever and process channel messages */
for (;;)
{
IPIKE_CHANNEL_MSG_INIT_STATIC(msg, emsg);
/* Block until we get a message */
ret = ipike_channel_receive_msg(channel, &msg);
if ( ret != IPIKE_CHANNEL_OK )
{
IPCOM_LOG0(DEBUG, "ipike_event_receiver_proc() :: "\
"closing channel");
/* Something is wrong with the channel, break and
* reestablish the channel */
break;
}
/* We got a message, process it */
if ( ipike_event_receiver_process_msg(libctx, msg) < 0 )
{
IPCOM_LOG0(DEBUG, "ipike_event_receiver_proc() :: "\
"user callback signaled stop");
goto errout;
}
}
}
errout:
IPCOM_LOG0(DEBUG, "ipike_event_receiver_proc() :: cleaning up before exit");
ipcom_mutex_lock(libctx->mutex);
if (libctx->channel)
{
ipike_channel_destroy(libctx->channel);
libctx->channel = IP_NULL;
}
ipcom_mutex_unlock(libctx->mutex);
if (caddr)
ipike_channel_addr_destroy(caddr);
ipcom_closelog();
/* Notify exit */
ipcom_sem_post(libctx->sem);
/* Not allowed to reference libctx from now */
ipcom_proc_exit();
}
/*
****************************************************************************
* 10 PUBLIC FUNCTIONS
****************************************************************************
*/
/*
*===========================================================================
* ipike_event_server_log
*===========================================================================
*/
IP_GLOBAL void
ipike_event_server_log(
int type,
int reason,
union Ip_sockaddr_union * src_ip,
union Ip_sockaddr_union * dst_ip,
int protocol,
Ip_u8 spi[4])
{
Ipike_event_msg emsg;
Ipike_channel_msg * msg;
Ipike_event * event;
event = &emsg.event;
if ( ipike.event_server != IP_NULL )
{
/* Set channel message header */
IPIKE_CHANNEL_MSG_INIT_STATIC(msg, emsg);
/* Set event data */
event->type = ip_htons((Ip_u16) type);
event->reason = ip_htons((Ip_u16) reason);
event->protocol = (Ip_u8) protocol;
if ( src_ip != IP_NULL )
(void)ipike_addr_copy(&event->src_ip, src_ip);
if ( dst_ip != IP_NULL )
(void)ipike_addr_copy(&event->dst_ip, dst_ip);
if ( spi != IP_NULL )
ipcom_memcpy(&event->spi, spi, 4);
IPCOM_LOG1(DEBUG2, "ipike_event_server_log() :: broadcasting event (%s) "\
"on all channels", ipike_event_type_str((Ip_u16) type));
ipike_channel_server_broadcast_msg(ipike.event_server,
(Ipike_channel_msg *) &emsg);
}
}
/*
*===========================================================================
* ipike_event_server_relay
*===========================================================================
*/
IP_GLOBAL void
ipike_event_server_relay(Ipike_event_msg *emsg)
{
if ( ipike.event_server )
{
IPCOM_LOG0(DEBUG2, "ipike_event_relay() :: relaying event "\
"message on all channels");
ipike_channel_server_broadcast_msg(ipike.event_server,
(Ipike_channel_msg *) emsg);
}
}
/*
*===========================================================================
* ipike_event_server_startup
*===========================================================================
*/
IP_GLOBAL Ipike_error
ipike_event_server_startup(void)
{
Ipike_channel_addr * caddr;
/* Create IKE daemon's channel address */
caddr = ipike_channel_addr_create(IPIKE_EVENT_CHANNEL_ADDRESS);
if ( caddr == IP_NULL )
return IPIKE_FAILED;
/* Create a channel server */
ipike.event_server = ipike_channel_server_create(caddr,
IP_NULL,
IP_NULL,
IP_NULL);
/* We only needed the channel address to create the channel server */
ipike_channel_addr_destroy(caddr);
if ( ipike.event_server == IP_NULL )
{
IPCOM_LOG0(ERR, "ipike_event_server_startup() :: "\
"failed to create event server");
return IPIKE_FAILED;
}
IPCOM_LOG0(DEBUG2, "ipike_event_server_startup() :: "\
"event channel server is running started");
return IPIKE_SUCCESS;
}
/*
*===========================================================================
* ipike_event_server_shutdown
*===========================================================================
*/
IP_GLOBAL void
ipike_event_server_shutdown(void)
{
if ( ipike.event_server != IP_NULL )
{
ipike_channel_server_destroy(ipike.event_server);
ipike.event_server = IP_NULL;
}
}
/*
*===========================================================================
* ipike_event_server_add_fds
*===========================================================================
*/
IP_GLOBAL int
ipike_event_server_add_fds(
Ip_fd_set * read_fds,
Ip_fd_set * write_fds)
{
return ipike_channel_server_add_fds(ipike.event_server,
read_fds,
write_fds);
}
/*
*===========================================================================
* ipike_event_server_process
*===========================================================================
*/
IP_GLOBAL int
ipike_event_server_process(
Ip_fd_set * read_fds,
Ip_fd_set * write_fds)
{
return ipike_channel_server_process(ipike.event_server,
read_fds,
write_fds);
}
/*
*===========================================================================
* ipike_event_type_str
*===========================================================================
*/
IP_GLOBAL const char *
ipike_event_type_str(
Ip_u16 type)
{
if ( type >= IPIKE_EVENT_MAX )
return "TYPE_UNKNOWN";
return Ipike_event_strings[type];
}
/*
*===========================================================================
* ipike_event_type_str
*===========================================================================
*/
IP_GLOBAL const char *
ipike_event_reason_str(
Ip_u16 type)
{
if ( type >= IPIKE_REASON_MAX )
return "REASON_UNKNOWN";
return Ipike_event_reason_strings[type];
}
/*
****************************************************************************
* Event receiver (client) functionality
****************************************************************************
*/
/*
*===========================================================================
* ipike_event_receiver_init
*===========================================================================
*/
IP_PUBLIC int
ipike_event_receiver_init(
Ipike_event_receiver_cb event_cb)
{
Ipcom_proc_attr proc_attr;
Ip_err err;
/* Make sure that library isn't initialized yet */
if ( libctx != IP_NULL )
return -1;
/* Get context, (replace with malloc to allow multiple instances */
libctx = &ctx_store;
ipcom_memset(libctx, 0, sizeof(Ipike_event_receiver_ctx));
/* Create mutex */
if ( ipcom_mutex_create(&libctx->mutex) != IPCOM_SUCCESS )
goto errout;
/* Create mutex */
if ( ipcom_sem_create(&libctx->sem, 0) != IPCOM_SUCCESS )
{
ipcom_mutex_delete(&libctx->mutex);
goto errout;
}
ipike_event_receiver_callback_set(libctx, event_cb);
ipcom_proc_attr_init(&proc_attr);
proc_attr.flags |= IPCOM_PROC_FLAG_FP;
proc_attr.stacksize = IPCOM_PROC_STACK_DEFAULT;
/* Spawn a new task/thread for handling events */
err = ipcom_proc_acreate(IPIKE_EVENT_RECEIVER_PROC_NAME,
(Ipcom_proc_func) ipike_event_receiver_proc,
&proc_attr,
IP_NULL);
if ( err != IPCOM_SUCCESS )
{
ipcom_mutex_delete(&libctx->mutex);
ipcom_sem_delete(&libctx->sem);
goto errout;
}
return 0;
errout:
libctx = IP_NULL;
return -1;
}
/*
*===========================================================================
* ipike_event_receiver_destroy
*===========================================================================
*/
IP_PUBLIC void
ipike_event_receiver_destroy(void)
{
/* Make sure we are initialized */
if ( libctx == IP_NULL )
return;
/* Protect shared data */
ipcom_mutex_lock(libctx->mutex);
libctx->event_cb = IP_NULL;
if ( libctx->channel != IP_NULL )
{
/* This will wake up the receiver task/thread */
ipike_channel_close(libctx->channel);
}
ipcom_mutex_unlock(libctx->mutex);
/* Wait for the receiver thread to finish */
ipcom_sem_wait(libctx->sem);
/* Receiver thread has finished, do clean up */
ipcom_mutex_delete(&libctx->mutex);
ipcom_sem_delete(&libctx->sem);
ipcom_memset(libctx, 0, sizeof(Ipike_event_receiver_ctx));
libctx = IP_NULL;
}
#else
int ipike_channel_empty_file = 0;
#endif /* IPIKE_USE_EVENT_LOG */
/*
****************************************************************************
* END OF FILE
****************************************************************************
*/