|
|
The following example is a listing of a kernel module that uses the XDAS API. The module provides an ioctl interface so that messages can be sent directly from a test application to the kernel driver.
/*
* EELS test driver - provides an ioctl() interface to allow the
* user to connect and submit log messages as though originating
* from a normal kernel driver
*/
#ifdef _KERNEL_HEADERS
#include <util/types.h>
#include <svc/errno.h>
#include <io/conf.h>
#include <util/debug.h>
#include <util/cmn_err.h>
#include <io/eels/sys/eels_inf.h>
#include <io/eels/eels_test/eels_drvr/eels_edt.h>
#include <io/eels/sys/xdas.h>
#include <mem/kmem.h>
#include <util/ksynch.h>
#include <util/mod/moddefs.h>
#include <io/ddi.h>
#else
#include <sys/types.h>
#include <sys/errno.h>
#include <sys/conf.h>
#include <sys/debug.h>
#include <sys/cmn_err.h>
#include <sys/eels_inf.h>
#include <sys/eels_edt.h>
#include <sys/xdas.h>
#include <sys/kmem.h>
#include <sys/ksynch.h>
#include <sys/moddefs.h>
#include <sys/ddi.h>
#endif
int edt_load(void);
int edt_unload(void);
int edtopen(dev_t *, int, int, cred_t *);
int edtclose(dev_t , int, int, cred_t *);
int edtioctl(dev_t , int, void *, int, cred_t *, int *);
extern char *edt_Initiator, *edt_Target; /* From Space.c */
int edtdevflag = D_MP;
MOD_DRV_WRAPPER(edt, edt_load, edt_unload, NULL, "eels test driver");
xdas_audit_ref_t edt_das_ref;
int edt_xdas_initialised = 0;
edt_load()
{
OM_uint32 l_status, l_ret;
/* Initialise connection with XDAS */
l_ret = xdas_initialise_session( &l_status, "edt:", NULL,
"eels test driver:", &edt_das_ref );
if ( XDAS_ERROR(l_ret) ) {
cmn_err(CE_WARN,
"edt_load: xdas_initialise_session returned %x, %x",
l_ret, l_status);
} else {
edt_xdas_initialised = 1;
}
return 0;
}
edt_unload()
{
OM_uint32 l_status, l_ret;
if ( edt_xdas_initialised ) {
l_ret = xdas_terminate_session( &l_status, &edt_das_ref );
if ( XDAS_ERROR( l_ret ) ) {
cmn_err(CE_WARN,
"edt_unload: xdas_terminate_session returned %x, %x",
l_ret, l_status );
} else {
edt_xdas_initialised = 0;
}
}
return 0;
}
/*
* Open the edt device.
*/
int
edtopen(dev_t *devp, int oflags, int otyp, cred_t *crp)
{
return 0;
}
/*
* Close the edt device.
*/
int
edtclose(dev_t dev, int oflags, int otyp, cred_t *crp)
{
return 0;
}
/*
* The main guts of the driver. Stage user supplied requests
* to the EELS driver and configure the stream as required.
*/
int
edtioctl(dev_t dev, int cmd, void *arg, int mode, cred_t *crp, int *rvalp)
{
eels_handle_t handle = 0;
edt_i_log_t log, *logp;
edt_i_connect_t con, *conp;
size_t size, init_size, targ_size;
int retval = 0;
xdas_audit_stream_t *l_audstr;
xdas_buffer_t *l_InitBuf, *l_TargBuf, *l_EventBuf;
xdas_audit_desc_t l_auddesc; /* Constructed descriptor */
OM_uint32 l_status, l_ret;
switch(cmd) {
case I_EDT_LOG:
/* Issue an eels_log() call using supplied parameters */
if (copyin(arg, &log, sizeof(log))) {
return EFAULT;
}
if (log.strlen == 0) {
return EINVAL;
}
size = log.strlen + sizeof(log);
logp = kmem_zalloc(size, KM_NOSLEEP);
if (logp == NULL) {
return EFAULT;
}
if (copyin(arg, logp, size)) {
return EFAULT;
}
l_audstr = (xdas_audit_stream_t *)logp->handle;
if ( edt_xdas_initialised == 0 ) {
kmem_free(logp, size);
return EINVAL;
}
init_size = strlen(edt_Initiator) + 1; /* NULL terminated */
l_ret = xdas_alloc_buffer( &l_status, init_size, &l_InitBuf );
if ( XDAS_ERROR( l_ret ) ) {
kmem_free(logp, size);
return EFAULT;
}
bcopy ((caddr_t )edt_Initiator, (caddr_t )((*l_InitBuf)->value),
init_size );
targ_size = strlen(edt_Target) + 1; /* NULL terminated */
l_ret = xdas_alloc_buffer( &l_status, targ_size, &l_TargBuf );
if ( XDAS_ERROR( l_ret ) ) {
kmem_free(logp, size);
xdas_release_buffer(&l_status, &edt_das_ref, l_InitBuf);
return EFAULT;
}
bcopy( (caddr_t )edt_Target, (caddr_t )((*l_TargBuf)->value),
targ_size );
l_ret = xdas_alloc_buffer(&l_status, logp->strlen, &l_EventBuf);
if ( XDAS_ERROR( l_ret ) ) {
kmem_free(logp, size);
xdas_release_buffer(&l_status, &edt_das_ref, l_TargBuf);
xdas_release_buffer(&l_status, &edt_das_ref, l_InitBuf);
return EFAULT;
}
bcopy( (caddr_t )&logp->str, (caddr_t )((*l_EventBuf)->value),
logp->strlen );
l_ret = xdas_start_record( &l_status, &edt_das_ref, &l_auddesc,
(OM_uint32 )logp->level, 0,
l_InitBuf, l_TargBuf, l_EventBuf );
if ( XDAS_ERROR( l_ret ) ) {
cmn_err(CE_WARN, "xdas_start_record: returned %x, %x",
l_ret, l_status);
kmem_free( logp, size );
xdas_release_buffer(&l_status, &edt_das_ref,l_EventBuf);
xdas_release_buffer(&l_status, &edt_das_ref, l_TargBuf);
xdas_release_buffer(&l_status, &edt_das_ref, l_InitBuf);
return EFAULT;
}
l_ret = xdas_commit_record( &l_status, &edt_das_ref,
(xdas_audit_desc_t *)&l_auddesc);
if ( XDAS_ERROR( l_ret ) ) {
cmn_err(CE_WARN, "xdas_commit_record: returned %x, %x",
l_ret, l_status);
retval = EFAULT;
}
kmem_free(logp, size);
xdas_release_buffer(&l_status, &edt_das_ref, l_EventBuf);
xdas_release_buffer(&l_status, &edt_das_ref, l_TargBuf);
xdas_release_buffer(&l_status, &edt_das_ref, l_InitBuf);
break;
case I_EDT_CONNECT:
/*
* Establish a new connection to the XDAS audit stream
*/
if ( edt_xdas_initialised == 0 ) {
return EINVAL;
}
if (copyin(arg, &con, sizeof(con))) {
return EFAULT;
}
l_ret = xdas_open_audit_stream( &l_status, &edt_das_ref,
&l_audstr );
if ( XDAS_ERROR( l_ret ) ) {
return EFAULT;
}
/*
* Return the audit-stream handle
*/
con.handle = (eels_handle_t )l_audstr;
if (copyout(&con, arg, sizeof(con))) {
return EFAULT;
}
break;
case I_EDT_TERMINATE:
/*
* Destroy the audit-stream connection associated with 'arg'
*/
l_audstr = (xdas_audit_stream_t *)arg;
if ( edt_xdas_initialised == 0 )
return EINVAL;
l_ret = xdas_close_audit_stream( &l_status, &edt_das_ref,
l_audstr );
if ( XDAS_ERROR( l_ret ) ) {
return EFAULT;
} else
return 0;
default:
return EINVAL;
}
return 0;
}