640 lines
18 KiB
C
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
|
|
****************************************************************************
|
|
*/
|