/*
 * nasd_od_dce.c
 *
 * DCE-RPC handlers for embedded NASD
 *
 * Author: Jim Zelenka
 */
/*
 * Copyright (c) of Carnegie Mellon University, 1997,1998,1999.
 *
 * Permission to reproduce, use, and prepare derivative works of
 * this software for internal use is granted provided the copyright
 * and "No Warranty" statements are included with all reproductions
 * and derivative works. This software may also be redistributed
 * without charge provided that the copyright and "No Warranty"
 * statements are included in all redistributions.
 *
 * NO WARRANTY. THIS SOFTWARE IS FURNISHED ON AN "AS IS" BASIS.
 * CARNEGIE MELLON UNIVERSITY MAKES NO WARRANTIES OF ANY KIND, EITHER
 * EXPRESSED OR IMPLIED AS TO THE MATTER INCLUDING, BUT NOT LIMITED
 * TO: WARRANTY OF FITNESS FOR PURPOSE OR MERCHANTABILITY, EXCLUSIVITY
 * OF RESULTS OR RESULTS OBTAINED FROM USE OF THIS SOFTWARE. CARNEGIE
 * MELLON UNIVERSITY DOES NOT MAKE ANY WARRANTY OF ANY KIND WITH RESPECT
 * TO FREEDOM FROM PATENT, TRADEMARK, OR COPYRIGHT INFRINGEMENT.
 */


#if defined(DEC_OSF) || (defined(OSF) && defined(MACH))
#include <sys/secdefines.h>
#if SEC_BASE > 0
#include <sys/security.h>
#include <sys/audit.h>
#include <sys/secpolicy.h>
#endif /* SEC_BASE */
#endif /* DEC_OSF || (OSF && MACH) */
#include <sys/errno.h>

#include <nasd/nasd_options.h>

#if NASD_RPC_PACKAGE == NASD_RPC_PACKAGE_DCE

#include <nasd/nasd_drive_options.h>
#undef  NASD_PTHREAD_EXC
#define NASD_PTHREAD_EXC 1
#include <nasd/nasd_types.h>
#include <nasd/nasd_freelist.h>
#include <nasd/nasd_itypes.h>
#include <nasd/nasd_mem.h>
#include <nasd/nasd_sys.h>
#include <nasd/nasd_cache.h>
#include <nasd/nasd_pdrive.h>
#include <nasd/nasd_common.h>
#include <nasd/nasd_marshall.h>
#include <nasd/nasd_keymgmt_dr.h>

#include <nasd/nasd_pipe.h>
#include <nasd/nasd_pipe_dce.h>

#include <nasd/nasd_security.h>
#include <nasd/nasd_security_dr.h>

#include <nasd/nasd_timer.h>
#include <nasd/nasd_trace_dr.h>

#include <nasd/nasd_timeout.h>

#ifndef KERNEL
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <nasd/nasd_udppipe.h>
#endif /* !KERNEL */

#include <dce/dce_error.h>

#if defined(DEC_OSF) && defined(KERNEL)
#include <dce/ker/pthread_exc.h>
#endif /* DEC_OSF && KERNEL */

#ifndef LINUX
#include <rpc/rpc.h>
#endif /* !LINUX */

#include <dce/stubbase.h>

#if defined(DEC_OSF) && defined(KERNEL)
/* I don't really want to use DCE's malloc and free */
#undef malloc
#undef free
#endif /* DEC_OSF && KERNEL */

#define NASD_OD_RPC_NASD_RET out_res.nasd_status
#include <nasd/nasd_od_rpc.h>

int nasd_pdrive_protseq_installed = 0;

int nasd_pdrive_if_registered = 0;

extern char nasd_odc_zeroblk[NASD_OD_BASIC_BLOCKSIZE];
extern char nasd_odc_bitbucket[NASD_OD_BASIC_BLOCKSIZE];

nasd_drive_opholder_t nasd_drive_fail_opholder;

unsigned_char_t *nasd_od_protseq_str = (unsigned_char_t *)"ncadg_ip_udp";

/* Don't use __FILE__ here to avoid getting kernel-mangled names */
#define NASD_OD_RPC_RETURN(_statval_) { \
  *status = _statval_; \
  return; \
}
#define DOBEGIN(_opname_) NASD_OD_RPC_DOBEGIN(_opname_,"nasd_od_dce.c")
#define DORETURN(_opname_) NASD_OD_RPC_DORETURN(_opname_,"nasd_od_dce.c")

#define NASD_OD_DCE_EXCEPTION_CAUGHT() { \
}

#define NASD_DCE_SEC_OP_DECL \
  nasd_security_param_t in_sec_param; \
  nasd_capability_t in_capability; \
  nasd_key_t op_key; \
  nasd_key_t integrity_key; \
  nasd_key_t privacy_key; \
  nasd_iv_t icv;

#if NASD_TRACE_DR > 0
#define NASD_DCE_TRACE_OP_DECL \
  nasd_trace_seq_t trace_seq;
#else /* NASD_TRACE_DR > 0 */
#define NASD_DCE_TRACE_OP_DECL
#endif /* NASD_TRACE_DR > 0 */

#define NASD_DCE_OP_DECL \
  NASD_DCE_SEC_OP_DECL \
  NASD_DCE_TRACE_OP_DECL \
  NASD_OD_RPC_OP_STATS_DECL

#define NASD_DCE_NOSEC_OP_DECL \
  NASD_DCE_TRACE_OP_DECL \
  NASD_OD_RPC_OP_STATS_DECL


/*
 * No-op
 */
void
nasd_sp_null_dr(
  handle_t         client_handle, 
  nasd_res_otw_t   out_res_otw,
  error_status_t  *status)
{
  nasd_res_t out_res;
  NASD_DCE_NOSEC_OP_DECL

  DOBEGIN(null);
  nasd_dt_noop_args(&trace_seq);

  out_res.nasd_status = NASD_SUCCESS;
  nasd_res_t_marshall(&out_res, out_res_otw);

  nasd_dt_noop_res(trace_seq);
  DORETURN(null);
}

/*
 * Sync
 */
void
nasd_sp_sync_dr(
  handle_t         client_handle, 
  nasd_res_otw_t   out_res_otw,
  error_status_t  *status)
{
  nasd_res_t out_res;
  NASD_DCE_NOSEC_OP_DECL

  DOBEGIN(sync);
  nasd_dt_sync_args(&trace_seq);

  TRY {
    out_res.nasd_status = nasd_odc_flush_dirty(1);
  }
  CATCH_ALL {
    NASD_OD_DCE_EXCEPTION_CAUGHT();
    out_res.nasd_status = NASD_REMOTE_TRAP;
#if NASD_OD_RPC_DEBUG_DCE_EXCEPTION > 0
    nasd_printf("sync caught DCE exception\n");
#endif /* NASD_OD_RPC_DEBUG_DCE_EXCEPTION > 0 */
  } ENDTRY

  nasd_res_t_marshall(&out_res, out_res_otw);

  nasd_dt_sync_res(trace_seq);
  DORETURN(sync);
}

/*
 * Create partition
 */
void
nasd_sp_part_creat_otw_dr(
  handle_t                          client_handle, 
  nasd_security_param_otw_t         in_sec_param_otw,
  nasd_capability_otw_t             in_capability_otw,
  nasd_digest_nonce_otw_t           in_digest_otw,
  nasd_p_part_creat_dr_args_otw_t   in_args_otw,
  nasd_p_part_creat_dr_res_otw_t    out_res_otw,
  nasd_digest_nonce_otw_t           out_digest_otw,
  error_status_t                   *status)
{
  nasd_p_part_creat_dr_args_t in_args;
  nasd_p_part_creat_dr_res_t out_res;
  nasd_identifier_t nid;
  NASD_DCE_OP_DECL

  DOBEGIN(part_creat);
  nasd_dt_part_creat_args(in_args_otw, &trace_seq);

  TRY {
    out_res.nasd_status =
      nasd_unpack_args(in_sec_param_otw, in_capability_otw, in_digest_otw,
                       in_args_otw, sizeof(nasd_p_part_creat_dr_args_otw_t),
                       &in_sec_param, &in_capability, &in_args,
                       nasd_p_part_creat_dr_args_t_unmarshall,
                       icv, op_key, integrity_key, privacy_key, NULL);
    if(!out_res.nasd_status) {
      NASD_SEC_POLICY_PART_CREAT(in_sec_param, in_capability, in_args,
                                 out_res.nasd_status);
      if(!out_res.nasd_status) {
        out_res.nasd_status =
          nasd_od_create_partition((int) in_args.in_partnum,
                                   (nasd_blkcnt_t)in_args.in_blkcnt,
                                   in_args.in_min_protection,
                                   in_args.in_partition_key,
                                   in_args.in_red_key,
                                   in_args.in_black_key,
                                   &nid);
      }
    }
  }
  CATCH_ALL {
    NASD_OD_DCE_EXCEPTION_CAUGHT();
    out_res.nasd_status = NASD_REMOTE_TRAP;
#if NASD_OD_RPC_DEBUG_DCE_EXCEPTION > 0
    nasd_printf("part_creat caught DCE exception\n");
#endif /* NASD_OD_RPC_DEBUG_DCE_EXCEPTION > 0 */
  } ENDTRY

  nasd_pack_res(&in_sec_param, &out_res, out_res_otw,
                sizeof(nasd_p_part_creat_dr_res_otw_t),
                out_digest_otw,
                nasd_p_part_creat_dr_res_t_marshall,
                icv, op_key, integrity_key, privacy_key, NULL);

  nasd_dt_part_creat_res(out_res_otw, trace_seq);
  DORETURN(part_creat);

}

/*
 * Create object
 */
void
nasd_sp_create_otw_dr(
  handle_t                      client_handle, 
  nasd_security_param_otw_t     in_sec_param_otw,
  nasd_capability_otw_t         in_capability_otw,
  nasd_digest_nonce_otw_t       in_digest_otw,
  nasd_p_create_dr_args_otw_t   in_args_otw,
  nasd_p_create_dr_res_otw_t    out_res_otw,
  nasd_digest_nonce_otw_t       out_digest_otw,
  error_status_t               *status)
{
  nasd_drive_opholder_t *cr_opholder;
  nasd_res_t out_res;
  NASD_DCE_OP_DECL

  DOBEGIN(create);
  nasd_dt_create_args(in_args_otw, &trace_seq);

  NASD_DRIVE_GET_OPHOLDER(cr_opholder);
  if (cr_opholder == NULL) {
    /* we don't care about the status of nasd_unpack_args here; all we
       really want is the security information so we can send a
       properly-encrypted/digested NASD_NO_MEM.  if there's an error,
       the client is screwed (and, really, so are we).  oh well. */
    nasd_unpack_args(in_sec_param_otw, in_capability_otw, in_digest_otw,
                     in_args_otw, sizeof(nasd_p_create_dr_args_otw_t),
                     &in_sec_param, &in_capability,
                     &nasd_drive_fail_opholder.opholder_create.in_args,
                     nasd_p_create_dr_args_t_unmarshall,
                     icv, op_key, integrity_key, privacy_key, NULL);
    goto done_create;
  }

  TRY {
    out_res.nasd_status =
      cr_opholder->opholder_create.out_res.nasd_status
      = nasd_unpack_args(in_sec_param_otw, in_capability_otw, in_digest_otw,
                         in_args_otw, sizeof(nasd_p_create_dr_args_otw_t),
                         &in_sec_param, &in_capability,
                         &cr_opholder->opholder_create.in_args,
                         nasd_p_create_dr_args_t_unmarshall,
                         icv, op_key, integrity_key, privacy_key, NULL);
    if(!out_res.nasd_status)
      NASD_SEC_POLICY_CREATE(in_sec_param, in_capability,
                             cr_opholder->opholder_create.in_args,
                             out_res.nasd_status);
    if(out_res.nasd_status) {
      cr_opholder->opholder_create.out_res.nasd_status = out_res.nasd_status;
    } else {
      out_res.nasd_status =
        cr_opholder->opholder_create.out_res.nasd_status =
        nasd_obj_create((int)cr_opholder->opholder_create.in_args.in_partnum,
                        &cr_opholder->opholder_create.in_args.in_attribute,
                        cr_opholder->opholder_create.in_args.in_fieldmask,
                        &cr_opholder->opholder_create.out_res.out_identifier,
                        &cr_opholder->opholder_create.out_res.out_attribute, 0);
    }
  }
  CATCH_ALL {
    NASD_OD_DCE_EXCEPTION_CAUGHT();
    out_res.nasd_status = cr_opholder->opholder_create.out_res.nasd_status = NASD_REMOTE_TRAP;
#if NASD_OD_RPC_DEBUG_DCE_EXCEPTION > 0
    nasd_printf("create caught DCE exception\n");
#endif /* NASD_OD_RPC_DEBUG_DCE_EXCEPTION > 0 */
  } ENDTRY

done_create:
  if (cr_opholder) {
    nasd_pack_res(&in_sec_param, &cr_opholder->opholder_create.out_res,
                  out_res_otw,
                  sizeof(nasd_p_create_dr_res_otw_t),
                  out_digest_otw,
                  nasd_p_create_dr_res_t_marshall, icv, op_key,
                  integrity_key, privacy_key, NULL);
  }
  else {
    nasd_pack_res(&in_sec_param,
                  &nasd_drive_fail_opholder.opholder_create.out_res,
                  out_res_otw,
                  sizeof(nasd_p_create_dr_res_otw_t), out_digest_otw,
                  nasd_p_create_dr_res_t_marshall, icv, op_key,
                  integrity_key, privacy_key, NULL);
  }


  if (cr_opholder) {
    NASD_DRIVE_FREE_OPHOLDER(cr_opholder);
  }

  nasd_dt_create_res(out_res_otw, trace_seq);
  DORETURN(create);
}

/*
 * Get object attributes
 */
void
nasd_sp_getattr_otw_dr(
  handle_t                       client_handle, 
  nasd_security_param_otw_t      in_sec_param_otw,
  nasd_capability_otw_t          in_capability_otw,
  nasd_digest_nonce_otw_t        in_digest_otw,
  nasd_p_getattr_dr_args_otw_t   in_args_otw,
  nasd_p_getattr_dr_res_otw_t    out_res_otw,
  nasd_digest_nonce_otw_t        out_digest_otw,
  error_status_t                *status)
{
  nasd_p_getattr_dr_args_t in_args;
  nasd_p_getattr_dr_res_t out_res;
  NASD_DCE_OP_DECL

  DOBEGIN(getattr);
  nasd_dt_getattr_args(in_args_otw, &trace_seq);

  TRY {
    out_res.nasd_status =
      nasd_unpack_args(in_sec_param_otw, in_capability_otw, in_digest_otw,
                       in_args_otw, sizeof(nasd_p_getattr_dr_args_otw_t),
                       &in_sec_param, &in_capability, &in_args,
                       nasd_p_getattr_dr_args_t_unmarshall,
                       icv, op_key, integrity_key, privacy_key, NULL);
    if(!out_res.nasd_status) {
      NASD_SEC_POLICY_GETATTR(in_sec_param, in_capability, in_args,
                              out_res.nasd_status);
      if(!out_res.nasd_status)
        out_res.nasd_status = nasd_obj_getattr(in_args.in_partnum,
                                               in_args.in_identifier,
                                               &out_res.out_attribute);
    }
  }
  CATCH_ALL {
    NASD_OD_DCE_EXCEPTION_CAUGHT();
    out_res.nasd_status = NASD_REMOTE_TRAP;
#if NASD_OD_RPC_DEBUG_DCE_EXCEPTION > 0
    nasd_printf("getattr caught DCE exception\n");
#endif /* NASD_OD_RPC_DEBUG_DCE_EXCEPTION > 0 */
  } ENDTRY

  nasd_pack_res(&in_sec_param, &out_res, out_res_otw,
                sizeof(nasd_p_getattr_dr_res_otw_t),
                out_digest_otw,
                nasd_p_getattr_dr_res_t_marshall,
                icv, op_key, integrity_key, privacy_key, NULL);

  nasd_dt_getattr_res(out_res_otw, trace_seq);
  DORETURN(getattr);
}

/*
 * Read single byterange in object - internal
 * function (does read and read2, which are only
 * different for stats-gathering).
 */
void
nasd_sp_read_simple_otw_dr_internal(
  handle_t                       client_handle, 
  nasd_security_param_otw_t      in_sec_param_otw,
  nasd_capability_otw_t          in_capability_otw,
  nasd_digest_nonce_otw_t        in_digest_otw,
  nasd_p_smpl_op_dr_args_otw_t   in_args_otw,
  nasd_byte_pipe_t               byte_pipe,
  nasd_p_fastread_dr_res_otw_t   out_res_otw,
  nasd_digest_nonce_otw_t        out_digest_otw,
  error_status_t                *status,
  int                            is_read2,
  nasd_od_rpc_basic_t           *out_res_basic_p)
{
  nasd_security_context_t security_context;
  nasd_procpipe_t procpipe;
  nasd_net_pipe_state_t pipe_state;
  nasd_p_smpl_op_dr_args_t in_args;
  nasd_p_fastread_dr_res_t out_res;
  nasd_len_t out_len, len, l;
  nasd_byte_t *sendp;
  nasd_status_t rc;
  NASD_DCE_OP_DECL

  TRY {
    out_res.nasd_status =
      nasd_unpack_args(in_sec_param_otw, in_capability_otw, in_digest_otw,
                       in_args_otw, sizeof(nasd_p_smpl_op_dr_args_otw_t),
                       &in_sec_param, &in_capability, &in_args,
                       nasd_p_smpl_op_dr_args_t_unmarshall,
                       icv, op_key, integrity_key, privacy_key, &security_context);

    if(!out_res.nasd_status) {
      NASD_SEC_POLICY_READ_SIMPLE(in_sec_param, in_capability, in_args,
                                  out_res.nasd_status);
      if(!out_res.nasd_status) {
        security_context.cur_off = in_args.in_offset;
        security_context.remain = in_args.in_len;

        out_len = 0;
        pipe_state.rpc_state = &byte_pipe;
        pipe_state.push = nasd_dcepipe_push;
        pipe_state.pull = NULL;
        pipe_state.context = &security_context;
        procpipe.state = &pipe_state;
        procpipe.push = nasd_pipe_push;
        procpipe.pull = NULL;

        out_res.nasd_status =
          nasd_obj_read_simple(in_args.in_partnum, in_args.in_identifier,
                               in_args.in_offset, in_args.in_len, NULL,
                               is_read2, &procpipe, &out_len,
                               &security_context);
        NASD_ASSERT(in_args.in_len >= out_len);
        out_res.out_datalen = out_len;

        if (out_res.nasd_status != NASD_RPC_TRAP) {
          /* 
           * Must send correct number of bytes to avoid angering DCE
           * gods. Grrn.
           */

          len = in_args.in_len - out_len;

          sendp=(nasd_byte_t *)nasd_odc_zeroblk;

          while(len) {
            l = NASD_MIN(len, NASD_OD_BASIC_BLOCKSIZE);
            rc = nasd_pipe_push(&pipe_state, sendp, l, NULL, NULL, NULL);
            if (rc) {
              out_res.nasd_status = NASD_RPC_TRAP;
              break;
            }
            len -= l;
          }

          /* terminate DCE pipe */
          if (out_res.nasd_status != NASD_RPC_TRAP) {
            nasd_pipe_push(&pipe_state, (nasd_byte_t *)nasd_odc_zeroblk, 0,
                           NULL, NULL, NULL);
          }
        }
      }
      else {
        /* terminate DCE pipe */
        if (out_res.nasd_status != NASD_RPC_TRAP) {
          nasd_dcepipe_push((void *)&byte_pipe, nasd_odc_zeroblk, 0);
        }
      }
    }
    else {
      /* terminate DCE pipe */
      if (out_res.nasd_status != NASD_RPC_TRAP) {
        nasd_dcepipe_push((void *)&byte_pipe, nasd_odc_zeroblk, 0);
      }
    }
  }
  CATCH_ALL {
    NASD_OD_DCE_EXCEPTION_CAUGHT();
    out_res.nasd_status = NASD_REMOTE_TRAP;
#if NASD_OD_RPC_DEBUG_DCE_EXCEPTION > 0
    nasd_printf("read_simple caught DCE exception\n");
#endif /* NASD_OD_RPC_DEBUG_DCE_EXCEPTION > 0 */
  } ENDTRY

  nasd_pack_res(&in_sec_param, &out_res, out_res_otw,
                sizeof(nasd_p_fastread_dr_res_otw_t),
                out_digest_otw,
                nasd_p_fastread_dr_res_t_marshall,
                icv, op_key, integrity_key, privacy_key, &security_context);

  return;
}

/*
 * Read single byterange in object
 */
void
nasd_sp_read_simple_otw_dr(
  handle_t                       client_handle, 
  nasd_security_param_otw_t      in_sec_param_otw,
  nasd_capability_otw_t          in_capability_otw,
  nasd_digest_nonce_otw_t        in_digest_otw,
  nasd_p_smpl_op_dr_args_otw_t   in_args_otw,
  nasd_byte_pipe_t               byte_pipe,
  nasd_p_fastread_dr_res_otw_t   out_res_otw,
  nasd_digest_nonce_otw_t        out_digest_otw,
  error_status_t                *status)
{
  nasd_od_rpc_basic_t out_res;
  NASD_DCE_NOSEC_OP_DECL

  DOBEGIN(read_simple);
  nasd_dt_read_simple_args(in_args_otw, &trace_seq);
  nasd_sp_read_simple_otw_dr_internal(client_handle, in_sec_param_otw,
    in_capability_otw, in_digest_otw,
    in_args_otw, byte_pipe, out_res_otw, out_digest_otw, status, 0, &out_res);
  nasd_dt_read_simple_res(out_res_otw, trace_seq);
  DORETURN(read_simple);
}

/*
 * Read single byterange in object
 */
void
nasd_sp_read2_simple_otw_dr(
  handle_t                       client_handle, 
  nasd_security_param_otw_t      in_sec_param_otw,
  nasd_capability_otw_t          in_capability_otw,
  nasd_digest_nonce_otw_t        in_digest_otw,
  nasd_p_smpl_op_dr_args_otw_t   in_args_otw,
  nasd_byte_pipe_t               byte_pipe,
  nasd_p_fastread_dr_res_otw_t   out_res_otw,
  nasd_digest_nonce_otw_t        out_digest_otw,
  error_status_t                *status)
{
  nasd_od_rpc_basic_t out_res;
  NASD_DCE_NOSEC_OP_DECL

  DOBEGIN(read2_simple);
  nasd_dt_read2_simple_args(in_args_otw, &trace_seq);
  nasd_sp_read_simple_otw_dr_internal(client_handle, in_sec_param_otw,
    in_capability_otw, in_digest_otw,
    in_args_otw, byte_pipe, out_res_otw, out_digest_otw, status, 1,
    &out_res);
  nasd_dt_read2_simple_res(out_res_otw, trace_seq);
  DORETURN(read2_simple);
}

/*
 * Throttled read single byterange in object
 */
void
nasd_sp_tread_simple_otw_dr(
  handle_t                        client_handle, 
  nasd_security_param_otw_t       in_sec_param_otw,
  nasd_capability_otw_t           in_capability_otw,
  nasd_digest_nonce_otw_t         in_digest_otw,
  nasd_p_thrtl_op_dr_args_otw_t   in_args_otw,
  nasd_byte_pipe_t                byte_pipe,
  nasd_p_fastread_dr_res_otw_t    out_res_otw,
  nasd_digest_nonce_otw_t         out_digest_otw,
  error_status_t                 *status)
{
  nasd_security_context_t security_context;
  nasd_procpipe_t procpipe;
  nasd_net_pipe_state_t pipe_state;
  nasd_p_thrtl_op_dr_args_t in_args;
  nasd_p_fastread_dr_res_t out_res;
  nasd_len_t out_len, len, l;
  nasd_byte_t *sendp;
  nasd_status_t rc;
  NASD_DCE_OP_DECL

  DOBEGIN(tread_simple);
  nasd_dt_tread_simple_args(in_args_otw, &trace_seq);

  TRY {
    out_res.nasd_status =
      nasd_unpack_args(in_sec_param_otw, in_capability_otw, in_digest_otw,
                       in_args_otw, sizeof(nasd_p_thrtl_op_dr_args_otw_t),
                       &in_sec_param, &in_capability, &in_args,
                       nasd_p_thrtl_op_dr_args_t_unmarshall,
                       icv, op_key, integrity_key, privacy_key, &security_context);

    if(!out_res.nasd_status) {
      NASD_SEC_POLICY_READ_SIMPLE(in_sec_param, in_capability, in_args,
                                  out_res.nasd_status);
      if(!out_res.nasd_status) {
        security_context.cur_off = in_args.in_offset;
        security_context.remain = in_args.in_len;

        out_len = 0;
        pipe_state.rpc_state = &byte_pipe;
        pipe_state.push = nasd_dcepipe_push;
        pipe_state.pull = NULL;
        pipe_state.context = &security_context;
        procpipe.state = &pipe_state;
        procpipe.push = nasd_pipe_push;
        procpipe.pull = NULL;

        out_res.nasd_status =
          nasd_obj_read_simple(in_args.in_partnum, in_args.in_identifier,
                               in_args.in_offset, in_args.in_len,
                               &in_args.in_bms_targ, 0, &procpipe, &out_len,
                               &security_context);
        NASD_ASSERT(in_args.in_len >= out_len);
        out_res.out_datalen = out_len;

        if (out_res.nasd_status != NASD_RPC_TRAP) {
          /* 
           * Must send correct number of bytes to avoid angering DCE
           * gods. Grrn.
           */

          len = in_args.in_len - out_len;

          sendp=(nasd_byte_t *)nasd_odc_zeroblk;

          while(len) {
            l = NASD_MIN(len, NASD_OD_BASIC_BLOCKSIZE);
            rc = nasd_dcepipe_push(&byte_pipe, sendp, l);
            if (rc) {
              out_res.nasd_status = NASD_RPC_TRAP;
              break;
            }
            len -= l;
          }

          /* terminate DCE pipe */
          if (out_res.nasd_status != NASD_RPC_TRAP) {
            nasd_dcepipe_push(&byte_pipe, (nasd_byte_t *)nasd_odc_zeroblk, 0);
          }
        }
      }
    }
  }
  CATCH_ALL {
    NASD_OD_DCE_EXCEPTION_CAUGHT();
    out_res.nasd_status = NASD_REMOTE_TRAP;
#if NASD_OD_RPC_DEBUG_DCE_EXCEPTION > 0
    nasd_printf("read_simple caught DCE exception\n");
#endif /* NASD_OD_RPC_DEBUG_DCE_EXCEPTION > 0 */
  } ENDTRY

  nasd_pack_res(&in_sec_param, &out_res, out_res_otw,
                sizeof(nasd_p_fastread_dr_res_otw_t),
                out_digest_otw,
                nasd_p_fastread_dr_res_t_marshall,
                icv, op_key, integrity_key, privacy_key, &security_context);

  nasd_dt_tread_simple_res(out_res_otw, trace_seq);
  DORETURN(tread_simple);
}

/*
 * Write single byterange in object
 */
void
nasd_sp_write_simple_otw_dr(
  handle_t                        client_handle, 
  nasd_security_param_otw_t       in_sec_param_otw,
  nasd_capability_otw_t           in_capability_otw,
  nasd_digest_nonce_otw_t         in_digest_otw,
  nasd_p_smpl_op_dr_args_otw_t    in_args_otw,
  nasd_byte_pipe_t                byte_pipe,
  nasd_p_fastwrite_dr_res_otw_t   out_res_otw,
  nasd_digest_nonce_otw_t         out_digest_otw,
  error_status_t                 *status)
{
  nasd_security_context_t security_context;
  nasd_procpipe_t procpipe;
  nasd_net_pipe_state_t pipe_state;
  nasd_p_smpl_op_dr_args_t in_args;
  nasd_p_fastwrite_dr_res_t out_res;
  nasd_status_t rc;
  nasd_len_t tcount;
  nasd_len_t len, l;
  NASD_DCE_OP_DECL

  DOBEGIN(write_simple);
  nasd_dt_write_simple_args(in_args_otw, &trace_seq);

  TRY {
    rc = NASD_SUCCESS;

    bzero(&security_context, sizeof(nasd_security_context_t));
    out_res.nasd_status =
      nasd_unpack_args(in_sec_param_otw, in_capability_otw, in_digest_otw,
                       in_args_otw, sizeof(nasd_p_smpl_op_dr_args_otw_t),
                       &in_sec_param, &in_capability, &in_args,
                       nasd_p_smpl_op_dr_args_t_unmarshall,
                       icv, op_key, integrity_key, privacy_key, &security_context);
    if(!out_res.nasd_status) {
      NASD_SEC_POLICY_WRITE_SIMPLE(in_sec_param, in_capability, in_args,
                                   out_res.nasd_status);
      if(!out_res.nasd_status) {
        security_context.cur_off = in_args.in_offset;
        security_context.remain = in_args.in_len;
        security_context.last_commit_off = in_args.in_offset;

        out_res.out_datalen = 0;
        pipe_state.rpc_state = &byte_pipe;
        pipe_state.push = NULL;
        pipe_state.pull = nasd_dcepipe_pull;
        pipe_state.context = &security_context;
        procpipe.state = &pipe_state;
        procpipe.push = NULL;
        procpipe.pull = nasd_pipe_pull;

        rc = nasd_obj_write_simple(in_args.in_partnum, in_args.in_identifier,
                                   in_args.in_offset, in_args.in_len, &procpipe,
                                   &security_context, &out_res.out_datalen);
        out_res.nasd_status = rc;
        NASD_ASSERT(in_args.in_len >= out_res.out_datalen);

        if(out_res.nasd_status != NASD_RPC_TRAP) {
          /*
           * Must recv correct number of bytes to avoid angering DCE
           * gods. Grrn.
           */
          len = in_args.in_len - out_res.out_datalen;
          while(len) {
            l = NASD_MIN(len, NASD_OD_BASIC_BLOCKSIZE);
            nasd_dcepipe_pull(&byte_pipe, (nasd_byte_t *)nasd_odc_bitbucket,
                              l, &tcount);
            len -= tcount;      
            if (tcount == 0)
              break;
          }

          /* terminate DCE pipe */
          rc = nasd_dcepipe_pull(&byte_pipe,
                                 (nasd_byte_t *)nasd_odc_bitbucket, 0,
                                 &tcount);
          if (rc) {
            if (out_res.nasd_status == NASD_SUCCESS)
              out_res.nasd_status = NASD_RPC_TRAP;
          }
        }
      }
      else {
        nasd_dcepipe_pull(&byte_pipe,
          (nasd_byte_t *)nasd_odc_bitbucket, 0,
          &tcount);
      }
    }
    else {
      nasd_dcepipe_pull(&byte_pipe,
        (nasd_byte_t *)nasd_odc_bitbucket, 0,
        &tcount);
    }
  }
  CATCH_ALL {
    NASD_OD_DCE_EXCEPTION_CAUGHT();
    out_res.nasd_status = NASD_REMOTE_TRAP;
#if NASD_OD_RPC_DEBUG_DCE_EXCEPTION > 0
    nasd_printf("write_simple caught DCE exception\n");
#endif /* NASD_OD_RPC_DEBUG_DCE_EXCEPTION > 0 */
  } ENDTRY

  nasd_pack_res(&in_sec_param, &out_res, out_res_otw,
                sizeof(nasd_p_fastwrite_dr_res_otw_t),
                out_digest_otw,
                nasd_p_fastwrite_dr_res_t_marshall,
                icv, op_key, integrity_key, privacy_key, &security_context);

  nasd_dt_write_simple_res(out_res_otw, trace_seq);
  DORETURN(write_simple);
}

/*
 * Set object attributes
 */
void
nasd_sp_setattr_otw_dr(
  handle_t                       client_handle, 
  nasd_security_param_otw_t      in_sec_param_otw,
  nasd_capability_otw_t          in_capability_otw,
  nasd_digest_nonce_otw_t        in_digest_otw,
  nasd_p_setattr_dr_args_otw_t   in_args_otw,
  nasd_p_setattr_dr_res_otw_t    out_res_otw,
  nasd_digest_nonce_otw_t        out_digest_otw,
  error_status_t                *status)
{
  nasd_p_setattr_dr_args_t in_args;
  nasd_p_setattr_dr_res_t out_res;
  NASD_DCE_OP_DECL  

  DOBEGIN(setattr);
  nasd_dt_setattr_args(in_args_otw, &trace_seq);
  TRY {
    out_res.nasd_status =
      nasd_unpack_args(in_sec_param_otw, in_capability_otw, in_digest_otw,
                       in_args_otw, sizeof(nasd_p_setattr_dr_args_otw_t),
                       &in_sec_param, &in_capability, &in_args,
                       nasd_p_setattr_dr_args_t_unmarshall,
                       icv, op_key, integrity_key, privacy_key, NULL);
    if(!out_res.nasd_status) {
      NASD_SEC_POLICY_SETATTR(in_sec_param, in_capability, in_args,
                              out_res.nasd_status);
      if(!out_res.nasd_status) {

        out_res.nasd_status =
          nasd_obj_setattr(in_args.in_partnum, in_args.in_identifier,
                           &in_args.in_attribute, in_args.in_fieldmask,
                           &out_res.out_attribute);
      }
    }
  } CATCH_ALL {
    NASD_OD_DCE_EXCEPTION_CAUGHT();
    out_res.nasd_status = NASD_REMOTE_TRAP;
#if NASD_OD_RPC_DEBUG_DCE_EXCEPTION > 0
    nasd_printf("setattr caught DCE exception\n");
#endif /* NASD_OD_RPC_DEBUG_DCE_EXCEPTION > 0 */
  } ENDTRY

  nasd_pack_res(&in_sec_param, &out_res, out_res_otw,
                sizeof(nasd_p_setattr_dr_res_otw_t),
                out_digest_otw,
                nasd_p_setattr_dr_res_t_marshall,
                icv, op_key, integrity_key, privacy_key, NULL);

  nasd_dt_setattr_res(out_res_otw, trace_seq);
  DORETURN(setattr);
}

void
nasd_sp_flush_obj_otw_dr(
  handle_t                         client_handle, 
  nasd_security_param_otw_t        in_sec_param_otw,
  nasd_capability_otw_t            in_capability_otw,
  nasd_digest_nonce_otw_t          in_digest_otw,
  nasd_p_flush_obj_dr_args_otw_t   in_args_otw,
  nasd_p_flush_obj_dr_res_otw_t    out_res_otw,
  nasd_digest_nonce_otw_t          out_digest_otw,
  error_status_t                  *status)
{
  nasd_p_flush_obj_dr_args_t in_args;
  nasd_p_flush_obj_dr_res_t out_res;
  NASD_DCE_OP_DECL

  DOBEGIN(flush_obj);
  nasd_dt_flush_obj_args(in_args_otw, &trace_seq);
  TRY {
    out_res.nasd_status =
      nasd_unpack_args(in_sec_param_otw, in_capability_otw, in_digest_otw,
                       in_args_otw, sizeof(nasd_p_flush_obj_dr_args_otw_t),
                       &in_sec_param, &in_capability, &in_args,
                       nasd_p_flush_obj_dr_args_t_unmarshall,
                       icv, op_key, integrity_key, privacy_key, NULL);
    if(!out_res.nasd_status) {
      NASD_SEC_POLICY_FLUSH_OBJ(in_sec_param, in_capability, in_args,
                                out_res.nasd_status);
      if(!out_res.nasd_status) {

        out_res.nasd_status = nasd_obj_flush(in_args.in_partnum,
                                             in_args.in_identifier);
      }
    }
  }
  CATCH_ALL {
    NASD_OD_DCE_EXCEPTION_CAUGHT();
    out_res.nasd_status = NASD_REMOTE_TRAP;
#if NASD_OD_RPC_DEBUG_DCE_EXCEPTION > 0
    nasd_printf("flush caught DCE exception\n");
#endif /* NASD_OD_RPC_DEBUG_DCE_EXCEPTION > 0 */
  } ENDTRY

  nasd_pack_res(&in_sec_param, &out_res, out_res_otw,
                sizeof(nasd_p_flush_obj_dr_res_otw_t),
                out_digest_otw,
                nasd_p_flush_obj_dr_res_t_marshall,
                icv, op_key, integrity_key, privacy_key, NULL);

  nasd_dt_flush_obj_res(out_res_otw, trace_seq);
  DORETURN(flush_obj);
}


void
nasd_sp_remove_otw_dr(
  handle_t                      client_handle, 
  nasd_security_param_otw_t     in_sec_param_otw,
  nasd_capability_otw_t         in_capability_otw,
  nasd_digest_nonce_otw_t       in_digest_otw,
  nasd_p_remove_dr_args_otw_t   in_args_otw,
  nasd_p_remove_dr_res_otw_t    out_res_otw,
  nasd_digest_nonce_otw_t       out_digest_otw,
  error_status_t               *status)
{
  nasd_p_remove_dr_args_t in_args;
  nasd_p_remove_dr_res_t out_res;
  NASD_DCE_OP_DECL

  DOBEGIN(remove);
  nasd_dt_remove_args(in_args_otw, &trace_seq);

  TRY {
    out_res.nasd_status =
      nasd_unpack_args(in_sec_param_otw, in_capability_otw, in_digest_otw,
                       in_args_otw, sizeof(nasd_p_remove_dr_args_otw_t),
                       &in_sec_param, &in_capability, &in_args,
                       nasd_p_remove_dr_args_t_unmarshall,
                       icv, op_key, integrity_key, privacy_key, NULL);
    if(!out_res.nasd_status) {
      NASD_SEC_POLICY_REMOVE(in_sec_param, in_capability, in_args,
                             out_res.nasd_status);
      if(!out_res.nasd_status) {
        out_res.nasd_status = nasd_obj_remove(in_args.in_partnum,
                                              in_args.in_identifier);
      }
    }
  }
  CATCH_ALL {
    NASD_OD_DCE_EXCEPTION_CAUGHT();
    out_res.nasd_status = NASD_REMOTE_TRAP;
#if NASD_OD_RPC_DEBUG_DCE_EXCEPTION > 0
    nasd_printf("obj_remove caught DCE exception\n");
#endif /* NASD_OD_RPC_DEBUG_DCE_EXCEPTION > 0 */
  } ENDTRY

  nasd_pack_res(&in_sec_param, &out_res, out_res_otw,
                sizeof(nasd_p_remove_dr_res_otw_t),
                out_digest_otw,
                nasd_p_remove_dr_res_t_marshall,
                icv, op_key, integrity_key, privacy_key, NULL);

  nasd_dt_remove_res(out_res_otw, trace_seq);
  DORETURN(remove);
}



void
nasd_sp_initialize_otw_dr(
  handle_t                          client_handle, 
  nasd_p_initialize_dr_args_otw_t   in_args_otw,
  nasd_p_initialize_dr_res_otw_t    out_res_otw,
  error_status_t                   *status)
{
  nasd_p_initialize_dr_args_t in_args;
  nasd_p_initialize_dr_res_t out_res;
  NASD_DCE_NOSEC_OP_DECL
    
  DOBEGIN(initialize);

  TRY {
    nasd_p_initialize_dr_args_t_unmarshall(in_args_otw, &in_args);
  
    out_res.nasd_status = nasd_sec_initialize_drive(in_args.in_master_key,
                                                    in_args.in_drive_key);
  }
  CATCH_ALL {
    NASD_OD_DCE_EXCEPTION_CAUGHT();
    out_res.nasd_status = NASD_REMOTE_TRAP;
#if NASD_OD_RPC_DEBUG_DCE_EXCEPTION > 0
    nasd_printf("initialize caught DCE exception\n");
#endif /* NASD_OD_RPC_DEBUG_DCE_EXCEPTION > 0 */
  } ENDTRY

  nasd_p_initialize_dr_res_t_marshall(&out_res, out_res_otw);
  DORETURN(initialize);
}



void
nasd_sp_change_key_otw_dr(
  handle_t                          client_handle, 
  nasd_security_param_otw_t         in_sec_param_otw,
  nasd_capability_otw_t             in_capability_otw,
  nasd_digest_nonce_otw_t           in_digest_otw,
  nasd_p_change_key_dr_args_otw_t   in_args_otw,
  nasd_p_change_key_dr_res_otw_t    out_res_otw,
  nasd_digest_nonce_otw_t           out_digest_otw,
  error_status_t                   *status)
{
  nasd_p_change_key_dr_args_t in_args;
  nasd_p_change_key_dr_res_t out_res;
  NASD_DCE_OP_DECL

  DOBEGIN(change_key);
  TRY {
    out_res.nasd_status =
      nasd_unpack_args(in_sec_param_otw, in_capability_otw, in_digest_otw,
                       in_args_otw, sizeof(nasd_p_change_key_dr_args_otw_t),
                       &in_sec_param, &in_capability, &in_args,
                       nasd_p_change_key_dr_args_t_unmarshall,
                       icv, op_key, integrity_key, privacy_key, NULL);
    if(!out_res.nasd_status) {
      NASD_SEC_POLICY_CHANGE_KEY(in_sec_param, in_capability, in_args,
                                 out_res.nasd_status);
      if(!out_res.nasd_status) {
        out_res.nasd_status = nasd_sec_setkey(in_args.in_partnum,
                                              in_args.in_type,
                                              in_args.in_new_key);
      }
    }
  }
  CATCH_ALL {
    NASD_OD_DCE_EXCEPTION_CAUGHT();
    out_res.nasd_status = NASD_REMOTE_TRAP;
#if NASD_OD_RPC_DEBUG_DCE_EXCEPTION > 0
    nasd_printf("change_key caught DCE exception\n");
#endif /* NASD_OD_RPC_DEBUG_DCE_EXCEPTION > 0 */
  } ENDTRY

  nasd_pack_res(&in_sec_param, &out_res, out_res_otw,
                sizeof(nasd_p_change_key_dr_res_otw_t),
                out_digest_otw,
                nasd_p_change_key_dr_res_t_marshall,
                icv, op_key, integrity_key, privacy_key, NULL);

  DORETURN(change_key);
}


void
nasd_sp_eject_obj_otw_dr(
  handle_t                         client_handle, 
  nasd_security_param_otw_t        in_sec_param_otw,
  nasd_capability_otw_t            in_capability_otw,
  nasd_digest_nonce_otw_t          in_digest_otw,
  nasd_p_eject_obj_dr_args_otw_t   in_args_otw,
  nasd_p_eject_obj_dr_res_otw_t    out_res_otw,
  nasd_digest_nonce_otw_t          out_digest_otw,
  error_status_t                  *status)
{
  nasd_p_eject_obj_dr_args_t in_args;
  nasd_p_eject_obj_dr_res_t out_res;
  NASD_DCE_OP_DECL

  DOBEGIN(eject_obj);
  nasd_dt_eject_obj_args(in_args_otw, &trace_seq);
  TRY {
    out_res.nasd_status =
      nasd_unpack_args(in_sec_param_otw, in_capability_otw, in_digest_otw,
                       in_args_otw, sizeof(nasd_p_eject_obj_dr_args_otw_t),
                       &in_sec_param, &in_capability, &in_args,
                       nasd_p_eject_obj_dr_args_t_unmarshall,
                       icv, op_key, integrity_key, privacy_key, NULL);
    if(!out_res.nasd_status) {
      NASD_SEC_POLICY_EJECT_OBJ(in_sec_param, in_capability, in_args,
                                out_res.nasd_status);
      if(!out_res.nasd_status) {
        out_res.nasd_status = nasd_obj_eject(in_args.in_partnum,
                                             in_args.in_identifier);
      }
    }
  }
  CATCH_ALL {
    NASD_OD_DCE_EXCEPTION_CAUGHT();
    out_res.nasd_status = NASD_REMOTE_TRAP;
#if NASD_OD_RPC_DEBUG_DCE_EXCEPTION > 0
    nasd_printf("eject caught DCE exception\n");
#endif /* NASD_OD_RPC_DEBUG_DCE_EXCEPTION > 0 */
  } ENDTRY

  nasd_pack_res(&in_sec_param, &out_res, out_res_otw,
                sizeof(nasd_p_eject_obj_dr_res_otw_t),
                out_digest_otw,
                nasd_p_eject_obj_dr_res_t_marshall,
                icv, op_key, integrity_key, privacy_key, NULL);

  nasd_dt_eject_obj_res(out_res_otw, trace_seq);
  DORETURN(eject_obj);
}

void
nasd_sp_strt_iread_otw_dr(
  handle_t                         client_handle, 
  nasd_security_param_otw_t        in_sec_param_otw,
  nasd_capability_otw_t            in_capability_otw,
  nasd_digest_nonce_otw_t          in_digest_otw,
  nasd_p_strt_iread_dr_args_otw_t  in_args_otw,
  nasd_p_strt_iread_dr_res_otw_t   out_res_otw,
  nasd_digest_nonce_otw_t          out_digest_otw,
  error_status_t                  *status)
{
  nasd_p_strt_iread_dr_args_t in_args;
  nasd_p_strt_iread_dr_res_t out_res;
  NASD_DCE_OP_DECL

  DOBEGIN(strt_iread);
#if KERNEL
  /* no code for socket ops in the kernel yet. */
  *status = NASD_OP_NOT_SUPPORTED;
  DORETURN(strt_iread);
#else /* KERNEL */
  nasd_dt_strt_iread_args(in_args_otw, &trace_seq);

  TRY {
    out_res.nasd_status =
      nasd_unpack_args(in_sec_param_otw, in_capability_otw, in_digest_otw,
                       in_args_otw, sizeof(nasd_p_strt_iread_dr_args_otw_t),
                       &in_sec_param, &in_capability, &in_args,
                       nasd_p_strt_iread_dr_args_t_unmarshall,
                       icv, op_key, integrity_key, privacy_key, NULL);
    if(!out_res.nasd_status) {
      NASD_SEC_POLICY_STRT_IREAD(in_sec_param, in_capability, in_args,
                                 out_res.nasd_status);
      if(!out_res.nasd_status) {

        out_res.nasd_status = nasd_obj_start_iread(in_args.in_partnum,
                                                   in_args.in_index_identifier,
                                                   in_args.in_data_identifier,
                                                   in_args.in_interval,
                                                   in_args.in_offset,
                                                   in_args.in_flownum,
                                                   in_args.in_earliest_start,
                                                   in_args.in_latest_start,
                                                   in_args.in_client_addr,
                                                   &out_res.out_stream_id);
      }
    }
  }
  CATCH_ALL {
    NASD_OD_DCE_EXCEPTION_CAUGHT();
    out_res.nasd_status = NASD_REMOTE_TRAP;
#if NASD_OD_RPC_DEBUG_DCE_EXCEPTION > 0
    nasd_printf("strt_iread caught DCE exception\n");
#endif /* NASD_OD_RPC_DEBUG_DCE_EXCEPTION > 0 */
  } ENDTRY

  nasd_pack_res(&in_sec_param, &out_res, out_res_otw,
                sizeof(nasd_p_strt_iread_dr_res_otw_t),
                out_digest_otw,
                nasd_p_strt_iread_dr_res_t_marshall,
                icv, op_key, integrity_key, privacy_key, NULL);

  nasd_dt_strt_iread_res(out_res_otw, trace_seq);
  DORETURN(strt_iread);
#endif /* KERNEL */
}

void
nasd_sp_stop_iread_otw_dr(
  handle_t                         client_handle, 
  nasd_security_param_otw_t        in_sec_param_otw,
  nasd_capability_otw_t            in_capability_otw,
  nasd_digest_nonce_otw_t          in_digest_otw,
  nasd_p_stop_iread_dr_args_otw_t  in_args_otw,
  nasd_p_stop_iread_dr_res_otw_t   out_res_otw,
  nasd_digest_nonce_otw_t          out_digest_otw,
  error_status_t                  *status)
{
  nasd_p_stop_iread_dr_args_t in_args;
  nasd_p_stop_iread_dr_res_t out_res;
  NASD_DCE_OP_DECL

  DOBEGIN(stop_iread);
#if KERNEL
  /* no code for socket ops in the kernel yet. */
  *status = NASD_OP_NOT_SUPPORTED;
  DORETURN(stop_iread);
#else /* KERNEL */
  nasd_dt_stop_iread_args(in_args_otw, &trace_seq);

  TRY {
    out_res.nasd_status =
      nasd_unpack_args(in_sec_param_otw, in_capability_otw, in_digest_otw,
                       in_args_otw, sizeof(nasd_p_stop_iread_dr_args_otw_t),
                       &in_sec_param, &in_capability, &in_args,
                       nasd_p_stop_iread_dr_args_t_unmarshall,
                       icv, op_key, integrity_key, privacy_key, NULL);
    if(!out_res.nasd_status) {
      NASD_SEC_POLICY_STOP_IREAD(in_sec_param, in_capability, in_args,
                                 out_res.nasd_status);
      if(!out_res.nasd_status) {
        out_res.nasd_status = nasd_obj_stop_iread(in_args.in_stream_id);
      }
    }
  }
  CATCH_ALL {
    NASD_OD_DCE_EXCEPTION_CAUGHT();
    out_res.nasd_status = NASD_REMOTE_TRAP;
#if NASD_OD_RPC_DEBUG_DCE_EXCEPTION > 0
    nasd_printf("stop_iread caught DCE exception\n");
#endif /* NASD_OD_RPC_DEBUG_DCE_EXCEPTION > 0 */
  } ENDTRY

  nasd_pack_res(&in_sec_param, &out_res, out_res_otw,
                sizeof(nasd_p_stop_iread_dr_res_otw_t),
                out_digest_otw,
                nasd_p_stop_iread_dr_res_t_marshall,
                icv, op_key, integrity_key, privacy_key, NULL);

  nasd_dt_stop_iread_res(out_res_otw, trace_seq);
  DORETURN(stop_iread);
#endif /* KERNEL */
}

void
nasd_sp_rshutdown_otw_dr(
  handle_t                         client_handle, 
  nasd_security_param_otw_t         in_sec_param_otw,
  nasd_capability_otw_t             in_capability_otw,
  nasd_digest_nonce_otw_t           in_digest_otw,
  nasd_p_rshutdown_dr_args_otw_t   in_args_otw,
  nasd_p_rshutdown_dr_res_otw_t    out_res_otw,
  nasd_digest_nonce_otw_t        out_digest_otw,
  error_status_t                  *status)
{
  nasd_p_rshutdown_dr_args_t in_args;
  nasd_p_rshutdown_dr_res_t out_res;
  NASD_DCE_OP_DECL

  DOBEGIN(rshutdown);

  nasd_dt_rshutdown_args(in_args_otw, &trace_seq);
  TRY {
    out_res.nasd_status =
      nasd_unpack_args(in_sec_param_otw, in_capability_otw, in_digest_otw,
                       in_args_otw, sizeof(nasd_p_rshutdown_dr_args_otw_t),
                       &in_sec_param, &in_capability, &in_args,
                       nasd_p_rshutdown_dr_args_t_unmarshall,
                       icv, op_key, integrity_key, privacy_key, NULL);
    if(!out_res.nasd_status) {
      NASD_SEC_POLICY_RSHUTDOWN(in_sec_param, in_capability, in_args,
                                out_res.nasd_status);
      if(!out_res.nasd_status) {
        out_res.nasd_status = nasd_drive_rshutdown(in_args.in_flags);
      }
    }  
  }
  CATCH_ALL {
    NASD_OD_DCE_EXCEPTION_CAUGHT();
    out_res.nasd_status = NASD_REMOTE_TRAP;
#if NASD_OD_RPC_DEBUG_DCE_EXCEPTION > 0
    nasd_printf("rshutdown caught DCE exception\n");
#endif /* NASD_OD_RPC_DEBUG_DCE_EXCEPTION > 0 */
  } ENDTRY

  nasd_pack_res(&in_sec_param, &out_res, out_res_otw,
                sizeof(nasd_p_rshutdown_dr_res_otw_t),
                out_digest_otw,
                nasd_p_rshutdown_dr_res_t_marshall,
                icv, op_key, integrity_key, privacy_key, NULL);

  nasd_dt_rshutdown_res(out_res_otw, trace_seq);
  DORETURN(rshutdown);

}

void
nasd_sp_getinfo_otw_dr(
  handle_t                      client_handle, 
  nasd_p_getinfo_dr_res_otw_t   out_res_otw,
  error_status_t               *status)
{
  nasd_p_getinfo_dr_res_t out_res;
  NASD_DCE_NOSEC_OP_DECL

  DOBEGIN(getinfo);

  /*
   * GETINFO is special; we do no security on this because it is
   * used to retrieve the drive's current time so clients can
   * synchronize their nonces to it. Any information that should
   * be protected belongs in a control object, not here.
   */

  out_res.nasd_status = nasd_drive_getinfo(&out_res.info);

  nasd_p_getinfo_dr_res_t_marshall(&out_res, out_res_otw);

  DORETURN(getinfo);
}


/*
 * !!! Do not hand-modify! Generate this stanza with "make mepv"
 */
static nasd_pdrive_v0_1_epv_t nasd_pdrive_epv = {
  nasd_sp_null_dr
  ,nasd_sp_sync_dr
  ,nasd_sp_part_creat_otw_dr
  ,nasd_sp_create_otw_dr
  ,nasd_sp_getattr_otw_dr
  ,nasd_sp_read_simple_otw_dr
  ,nasd_sp_read2_simple_otw_dr
  ,nasd_sp_tread_simple_otw_dr
  ,nasd_sp_write_simple_otw_dr
  ,nasd_sp_setattr_otw_dr
  ,nasd_sp_flush_obj_otw_dr
  ,nasd_sp_remove_otw_dr
  ,nasd_sp_initialize_otw_dr
  ,nasd_sp_change_key_otw_dr
  ,nasd_sp_eject_obj_otw_dr
  ,nasd_sp_strt_iread_otw_dr
  ,nasd_sp_stop_iread_otw_dr
  ,nasd_sp_rshutdown_otw_dr
  ,nasd_sp_getinfo_otw_dr
};


void
nasd_drive_dce_setup_tcp()
{
  rpc_if_rep_t *rep;

  nasd_od_protseq_str = (unsigned_char_t *)"ncacn_ip_tcp";
  rep = (rpc_if_rep_t *)nasd_pdrive_v0_1_s_ifspec;
  rep->endpoint_vector.endpoint_vector_elt[0].rpc_protseq = nasd_od_protseq_str;
}

void
nasd_drive_dce_setup_udp()
{
  rpc_if_rep_t *rep;

  nasd_od_protseq_str = (unsigned_char_t *)"ncadg_ip_udp";
  rep = (rpc_if_rep_t *)nasd_pdrive_v0_1_s_ifspec;
  rep->endpoint_vector.endpoint_vector_elt[0].rpc_protseq = nasd_od_protseq_str;
}

nasd_status_t
nasd_drive_rpc_specific_init()
{
  nasd_status_t rc;

  bzero((char *)&nasd_drive_fail_opholder, sizeof(nasd_drive_fail_opholder));
  nasd_drive_fail_opholder.opholder_create.out_res.nasd_status = NASD_NO_MEM;

  rc = nasd_dcepipe_init(nasd_odc_shutdown);
  if (rc) {
    return(rc);
  }

  return(NASD_SUCCESS);
}

nasd_status_t
nasd_drive_rpc_specific_startup()
{
  rpc_binding_vector_p_t binding_vector;
  rpc_if_handle_t nasd_pdrive_ifspec;
  rpc_if_rep_p_t nasd_pdrive_ifrep;
  dce_error_string_t err_str;
  error_status_t status, ps;

  nasd_pdrive_ifrep = (rpc_if_rep_p_t)nasd_pdrive_v0_1_s_ifspec;
  nasd_pdrive_ifrep->manager_epv = (rpc_mgr_epv_t)&nasd_pdrive_epv;
  nasd_pdrive_ifspec = nasd_pdrive_v0_1_s_ifspec;

  if (nasd_pdrive_protseq_installed == 0) {
    rpc_server_use_protseq_if(nasd_od_protseq_str,
      rpc_c_protseq_max_reqs_default, nasd_pdrive_ifspec, &status);
    if (status != rpc_s_ok) {
      dce_error_inq_text(status, err_str, (int *) &ps);
      if (ps)
        strcpy(err_str, "unknown");
      nasd_printf("ERROR: cannot register protocol sequence status=0x%x (%s)\n",
        status, err_str);
      return(NASD_FAIL);
    }
    nasd_pdrive_protseq_installed = 1;
  }

  if (nasd_pdrive_if_registered) {
    nasd_printf("ERROR: nasd_pdrive_if_registered already has value %d"
           " in nasd_startup_rpc()\n",
           nasd_pdrive_if_registered);
    return(NASD_FAIL);
  }

  rpc_server_register_if(nasd_pdrive_ifspec, NULL, NULL, &status);
  if (status != rpc_s_ok) {
    dce_error_inq_text(status, err_str, (int *) &ps);
    if (ps)
      strcpy(err_str, "unknown");
    nasd_printf("ERROR: cannot register interface status=0x%x (%s)\n",
      status, err_str);
    return(NASD_FAIL);
  }
  nasd_pdrive_if_registered = 1;

  rpc_server_inq_bindings(&binding_vector, &status);
  if (status != rpc_s_ok) {
    dce_error_inq_text(status, err_str, (int *) &ps);
    if (ps)
      strcpy(err_str, "unknown");
    nasd_printf("ERROR: cannot retrieve binding information status=0x%x (%s)\n",
      status, err_str);
    return(NASD_FAIL);
  }

  return(NASD_SUCCESS);
}

void
nasd_drive_rpc_specific_stop()
{
  rpc_if_handle_t nasd_pdrive_ifspec;
  dce_error_string_t err_str;
  error_status_t status, ps;

  nasd_pdrive_ifspec = nasd_pdrive_v0_1_s_ifspec;

#if 0
  /*
   * This just doesn't work. Hurray DCE.
   */
  rpc_mgmt_stop_server_listening(NULL, &status);
  if (status) {
    dce_error_inq_text(status, err_str, &ps);
    if (ps)
      strcpy(err_str, "unknown");
    nasd_printf("DRIVE: cannot stop server listener status %d (%s)\n",
      status, err_str);
  }
#endif

  if (nasd_pdrive_if_registered) {
    rpc_server_unregister_if(nasd_pdrive_ifspec, NULL, &status);
    if (status) {
      dce_error_inq_text(status, err_str, (int *) &ps);
      nasd_printf("DRIVE: cannot unregister server_if status %d (%s)\n",
        status, err_str);
    }
    nasd_pdrive_if_registered = 0;
  }
}

nasd_status_t
nasd_drive_rpc_specific_listen(
  int          service_threads,
  nasd_uint16  ipport /* !!! ignored !!! */)
{
  char err_str[dce_c_error_string_len];
  error_status_t status;
  int dce_ps;

  rpc_server_listen(service_threads, &status);

  if (status) {
#ifdef KERNEL
    if (status == rpc_s_already_listening)
      return(NASD_SUCCESS);
#endif /* KERNEL */

    dce_error_inq_text(status, err_str, &dce_ps);

    if (dce_ps) {
      strcpy(err_str, "unknown");
    }

    nasd_printf("DRIVE ERROR: DCE listener aborted! status=0x%x (%s)\n",
      status, err_str);

    return(NASD_FAIL);
  }

  return(NASD_SUCCESS);
}

nasd_status_t
nasd_drive_rpc_specific_set_stacksize(
  int  stacksize)
{
#if defined(DEC_OSF) && defined(KERNEL)
  return(NASD_OP_NOT_SUPPORTED);
#else /* defined(DEC_OSF) && defined(KERNEL) */
  error_status_t status;

  /* XXX better error handling */

  rpc_mgmt_set_server_stack_size(stacksize, &status);
  if (status)
    return(NASD_FAIL);

  return(NASD_SUCCESS);
#endif /* defined(DEC_OSF) && defined(KERNEL) */
}

#endif /* NASD_RPC_PACKAGE == NASD_RPC_PACKAGE_DCE */

/* Local Variables:  */
/* indent-tabs-mode: nil */
/* tab-width: 2 */
/* End: */
