| 
 |  | 
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;
   }