int
api_inteldcmi_cmd_raw_ipmb (ipmi_ctx_t ctx,
                            const void *buf_rq,
                            unsigned int buf_rq_len,
                            void *buf_rs,
                            unsigned int buf_rs_len)
{
  fiid_obj_t obj_cmd_rq = NULL;
  fiid_obj_t obj_cmd_rs = NULL;
  int len, rv = -1;

  assert (ctx
          && ctx->magic == IPMI_CTX_MAGIC
          && ctx->type == IPMI_DEVICE_INTELDCMI
          && buf_rq
          && buf_rq_len
          && buf_rs
          && buf_rs_len);

  if (!(obj_cmd_rq = fiid_obj_create (tmpl_inteldcmi_raw)))
    {
      API_ERRNO_TO_API_ERRNUM (ctx, errno);
      goto cleanup;
    }
  if (!(obj_cmd_rs = fiid_obj_create (tmpl_inteldcmi_raw)))
    {
      API_ERRNO_TO_API_ERRNUM (ctx, errno);
      goto cleanup;
    }

  if (fiid_obj_set_all (obj_cmd_rq,
                        buf_rq,
                        buf_rq_len) < 0)
    {
      API_FIID_OBJECT_ERROR_TO_API_ERRNUM (ctx, obj_cmd_rq);
      goto cleanup;
    }

  if (api_inteldcmi_cmd_ipmb (ctx,
                              obj_cmd_rq,
                              obj_cmd_rs) < 0)
    goto cleanup;

  if ((len = fiid_obj_get_all (obj_cmd_rs,
                               buf_rs,
                               buf_rs_len)) < 0)
    {
      API_FIID_OBJECT_ERROR_TO_API_ERRNUM (ctx, obj_cmd_rs);
      goto cleanup;
    }

  rv = len;
 cleanup:
  fiid_obj_destroy (obj_cmd_rq);
  fiid_obj_destroy (obj_cmd_rs);
  return (rv);
}
int32_t 
Fiid_obj_set_all(fiid_obj_t obj, uint8_t *data, uint32_t data_len)
{
  int32_t rv;

  assert(fiid_obj_valid(obj) && data && data_len);

  if ((rv = fiid_obj_set_all(obj, data, data_len)) < 0)
    ierr_exit("Fiid_obj_set_all: %s", fiid_strerror(fiid_obj_errnum(obj)));

  return rv;
}
int
ipmi_sunbmc_cmd (ipmi_sunbmc_ctx_t ctx,
                 uint8_t lun,
                 uint8_t net_fn,
                 fiid_obj_t obj_cmd_rq,
                 fiid_obj_t obj_cmd_rs)
{
  if (!ctx || ctx->magic != IPMI_SUNBMC_CTX_MAGIC)
    {
      ERR_TRACE (ipmi_sunbmc_ctx_errormsg (ctx), ipmi_sunbmc_ctx_errnum (ctx));
      return (-1);
    }

  if (!IPMI_BMC_LUN_VALID (lun)
      || !IPMI_NET_FN_RQ_VALID (net_fn)
      || !fiid_obj_valid (obj_cmd_rq)
      || !fiid_obj_valid (obj_cmd_rs)
      || fiid_obj_packet_valid (obj_cmd_rq) <= 0)
    {
      SUNBMC_SET_ERRNUM (ctx, IPMI_SUNBMC_ERR_PARAMETERS);
      return (-1);
    }

  if (!ctx->io_init)
    {
      SUNBMC_SET_ERRNUM (ctx, IPMI_SUNBMC_ERR_IO_NOT_INITIALIZED);
      return (-1);
    }

  if (ctx->putmsg_intf)
    {
      if (_sunbmc_write (ctx,
                         lun,
                         net_fn,
                         obj_cmd_rq) < 0)
        return (-1);

      if (_sunbmc_read (ctx,
                        obj_cmd_rs) < 0)
        return (-1);
    }
  else
    {
#if defined(HAVE_SYS_STROPTS_H)
      struct strioctl istr;
      bmc_reqrsp_t reqrsp;
      uint8_t rq_buf_temp[IPMI_SUNBMC_BUFLEN];
      uint8_t rq_buf[IPMI_SUNBMC_BUFLEN];
      uint8_t rq_cmd;
      unsigned int rq_buf_len;
      uint8_t rs_buf[IPMI_SUNBMC_BUFLEN];
      int len;

      memset (&istr, '\0', sizeof (struct strioctl));
      memset (&reqrsp, '\0', sizeof (bmc_reqrsp_t));

      /* Due to API differences, we need to extract the cmd out of the
       * request.
       */
      memset (rq_buf_temp, '\0', IPMI_SUNBMC_BUFLEN);

      if ((len = fiid_obj_get_all (obj_cmd_rq,
                                   rq_buf_temp,
                                   IPMI_SUNBMC_BUFLEN)) <= 0)
        {
          SUNBMC_SET_ERRNUM (ctx, IPMI_SUNBMC_ERR_INTERNAL_ERROR);
          return (-1);
        }

      rq_cmd = rq_buf_temp[0];
      if (len > 1)
        {
          /* -1 b/c of cmd */
          memcpy (rq_buf, &rq_buf_temp[1], len - 1);
          rq_buf_len = len - 1;
        }
      else
        rq_buf_len = 0;

      reqrsp.req.fn = net_fn;
      reqrsp.req.lun = lun;
      reqrsp.req.cmd = rq_cmd;

      istr.ic_cmd = IOCTL_IPMI_KCS_ACTION;
      istr.ic_timout = 0;       /* spelled 'timout', not a typo */
      istr.ic_len = sizeof (struct bmc_reqrsp);
      istr.ic_dp = (char *)&reqrsp;

      if (ioctl (ctx->device_fd,
                 I_STR,
                 &istr) < 0)
        {
          SUNBMC_ERRNO_TO_SUNBMC_ERRNUM (ctx, errno);
          return (-1);
        }

      rs_buf[0] = reqrsp.rsp.cmd;
      rs_buf[1] = reqrsp.rsp.ccode;
      /* -2 b/c of cmd and ccode */
#if 0
      /* achu: to remove warnings, IPMI_SUNBMC_BUFLEN > amount uint8_t can hold */
      if (reqrsp.rsp.datalength >= (IPMI_SUNBMC_BUFLEN - 2))
        reqrsp.rsp.datalength = IPMI_SUNBMC_BUFLEN - 2;
#endif
      /* remove header data stuff in front we don't care about */
      if (reqrsp.rsp.datalength > 3)
        reqrsp.rsp.datalength -= 3;
      else
        reqrsp.rsp.datalength = 0;
      memcpy (rs_buf + 2, reqrsp.rsp.data, reqrsp.rsp.datalength);

      if (fiid_obj_set_all (obj_cmd_rs,
                            rs_buf,
                            reqrsp.rsp.datalength + 2) < 0)
        {
          SUNBMC_SET_ERRNUM (ctx, IPMI_SUNBMC_ERR_INTERNAL_ERROR);
          return (-1);
        }
#else /* !defined(HAVE_SYS_STROPTS_H) */
      /* otherwise, device is not supported */
      SUNBMC_SET_ERRNUM (ctx, IPMI_SUNBMC_ERR_DEVICE_NOT_SUPPORTED);
      return (-1);
#endif /* !defined(HAVE_SYS_STROPTS_H) */
    }

  return (0);
}
static int
_sunbmc_read (ipmi_sunbmc_ctx_t ctx,
              fiid_obj_t obj_cmd_rs)
{
#if defined(HAVE_SYS_STROPTS_H)
  struct strbuf sbuf;
  bmc_msg_t *msg = NULL;
  bmc_rsp_t *rsp = NULL;
  int flags = 0;
  uint8_t rs_buf_temp[IPMI_SUNBMC_BUFLEN];
  uint8_t rs_buf[IPMI_SUNBMC_BUFLEN];
  unsigned int rs_buf_len = 0;
#endif /* !defined(HAVE_SYS_STROPTS_H) */
  fd_set read_fds;
  struct timeval tv;
  int n;

  assert (ctx);
  assert (ctx->magic == IPMI_SUNBMC_CTX_MAGIC);
  assert (ctx->io_init);
  assert (ctx->putmsg_intf);
  assert (fiid_obj_valid (obj_cmd_rs));

#if defined(HAVE_SYS_STROPTS_H)
  memset (&sbuf, '\0', sizeof (struct strbuf));

  sbuf.maxlen = IPMI_SUNBMC_BUFLEN;
  sbuf.buf = (char *)rs_buf_temp;
#else /* !defined(HAVE_SYS_STROPTS_H) */
  /* otherwise, device is not supported */
  SUNBMC_SET_ERRNUM (ctx, IPMI_SUNBMC_ERR_DEVICE_NOT_SUPPORTED);
  return (-1);
#endif /* !defined(HAVE_SYS_STROPTS_H) */

  FD_ZERO (&read_fds);
  FD_SET (ctx->device_fd, &read_fds);

  tv.tv_sec = IPMI_SUNBMC_TIMEOUT;
  tv.tv_usec = 0;

  if ((n = select (ctx->device_fd + 1,
                   &read_fds,
                   NULL,
                   NULL,
                   &tv)) < 0)
    {
      SUNBMC_ERRNO_TO_SUNBMC_ERRNUM (ctx, errno);
      return (-1);
    }

  if (!n)
    {
      /* Could be due to a different error, but we assume a timeout */
      SUNBMC_SET_ERRNUM (ctx, IPMI_SUNBMC_ERR_DRIVER_TIMEOUT);
      return (-1);
    }

#if defined(HAVE_SYS_STROPTS_H)
  if (getmsg (ctx->device_fd, NULL, &sbuf, &flags) < 0)
    {
      SUNBMC_ERRNO_TO_SUNBMC_ERRNUM (ctx, errno);
      return (-1);
    }
  msg = (bmc_msg_t *)&(sbuf.buf[0]);

  if (msg->m_type == BMC_MSG_ERROR)
    {
      errno = msg->msg[0];
      SUNBMC_ERRNO_TO_SUNBMC_ERRNUM (ctx, errno);
      return (-1);
    }
  if (msg->m_type != BMC_MSG_RESPONSE)
    {
      SUNBMC_SET_ERRNUM (ctx, IPMI_SUNBMC_ERR_SYSTEM_ERROR);
      return (-1);
    }
  if (msg->m_id != ctx->putmsg_intf_msg_id)
    {
      SUNBMC_SET_ERRNUM (ctx, IPMI_SUNBMC_ERR_SYSTEM_ERROR);
      return (-1);
    }

  rsp = (bmc_rsp_t *)&(msg->msg[0]);

  /* Due to API differences, we need to put the cmd/ccode back into
   * the buffer.
   */
  rs_buf[0] = rsp->cmd;
  rs_buf_len++;
  rs_buf[1] = rsp->ccode;
  rs_buf_len++;
  memcpy (&(rs_buf[2]), rsp->data, rsp->datalength);
  rs_buf_len += rsp->datalength;

  if (fiid_obj_set_all (obj_cmd_rs,
                        rs_buf,
                        rs_buf_len) < 0)
    {
      SUNBMC_SET_ERRNUM (ctx, IPMI_SUNBMC_ERR_INTERNAL_ERROR);
      return (-1);
    }

#else /* !defined(HAVE_SYS_STROPTS_H) */
  /* otherwise, device is not supported */
  SUNBMC_SET_ERRNUM (ctx, IPMI_SUNBMC_ERR_DEVICE_NOT_SUPPORTED);
  return (-1);
#endif /* !defined(HAVE_SYS_STROPTS_H) */

  return (0);
}
int
assemble_ipmi_ipmb_msg (fiid_obj_t obj_ipmb_msg_hdr,
                        fiid_obj_t obj_cmd,
                        fiid_obj_t obj_ipmb_msg,
			unsigned int flags)
{
  uint8_t buf[IPMB_MAX_LEN+1];
  unsigned int indx = 0;
  uint8_t *checksum_data_ptr = NULL;
  unsigned int checksum_data_count = 0;
  unsigned int required_len = 0;
  fiid_obj_t obj_ipmb_msg_trlr = NULL;
  uint8_t checksum;
  int len, rv = -1;
  unsigned int flags_mask = 0;

  if (!fiid_obj_valid (obj_ipmb_msg_hdr)
      || !fiid_obj_valid (obj_cmd)
      || !fiid_obj_valid (obj_ipmb_msg)
      || (flags & ~flags_mask))
    {
      SET_ERRNO (EINVAL);
      return (-1);
    }

  if (FIID_OBJ_TEMPLATE_COMPARE (obj_ipmb_msg_hdr, tmpl_ipmb_msg_hdr_rq) < 0)
    {
      ERRNO_TRACE (errno);
      return (-1);
    }
  if (FIID_OBJ_TEMPLATE_COMPARE (obj_ipmb_msg, tmpl_ipmb_msg) < 0)
    {
      ERRNO_TRACE (errno);
      return (-1);
    }

  if (FIID_OBJ_PACKET_VALID (obj_ipmb_msg_hdr) < 0)
    {
      FIID_OBJECT_ERROR_TO_ERRNO (obj_ipmb_msg_hdr);
      return (-1);
    }
  if (FIID_OBJ_PACKET_VALID (obj_cmd) < 0)
    {
      FIID_OBJECT_ERROR_TO_ERRNO (obj_cmd);
      return (-1);
    }

  if ((len = fiid_template_len_bytes (tmpl_ipmb_msg_hdr_rq)) < 0)
    {
      ERRNO_TRACE (errno);
      return (-1);
    }
  required_len += len;

  if ((len = fiid_obj_len_bytes (obj_cmd)) < 0)
    {
      FIID_OBJECT_ERROR_TO_ERRNO (obj_cmd);
      return (-1);
    }
  required_len += len;

  if ((len = fiid_template_len_bytes (tmpl_ipmb_msg_trlr)) < 0)
    {
      ERRNO_TRACE (errno);
      return (-1);
    }
  required_len += len;

  if (IPMB_MAX_LEN < required_len)
    {
      SET_ERRNO (EMSGSIZE);
      return (-1);
    }

  memset (buf, '\0', IPMB_MAX_LEN+1);

  if ((len = fiid_obj_get_block (obj_ipmb_msg_hdr,
                                 "rs_addr",
                                 "checksum1",
                                 buf + indx,
                                 IPMB_MAX_LEN - indx)) < 0)
    {
      FIID_OBJECT_ERROR_TO_ERRNO (obj_ipmb_msg_hdr);
      goto cleanup;
    }
  indx += len;

  checksum_data_ptr = (buf + indx);

  if ((len = fiid_obj_get_block (obj_ipmb_msg_hdr,
                                 "rq_addr",
                                 "rq_seq",
                                 buf + indx,
                                 IPMB_MAX_LEN - indx)) < 0)
    {
      FIID_OBJECT_ERROR_TO_ERRNO (obj_ipmb_msg_hdr);
      goto cleanup;
    }
  indx += len;
  checksum_data_count += len;

  if ((len = fiid_obj_get_all (obj_cmd, buf + indx, IPMB_MAX_LEN - indx)) < 0)
    {
      FIID_OBJECT_ERROR_TO_ERRNO (obj_cmd);
      goto cleanup;
    }
  indx += len;
  checksum_data_count += len;

  if (!(obj_ipmb_msg_trlr = fiid_obj_create (tmpl_ipmb_msg_trlr)))
    {
      ERRNO_TRACE (errno);
      goto cleanup;
    }

  checksum = ipmi_checksum (checksum_data_ptr, checksum_data_count);

  if (fiid_obj_set_all (obj_ipmb_msg_trlr, &checksum, sizeof (checksum)) < 0)
    {
      FIID_OBJECT_ERROR_TO_ERRNO (obj_ipmb_msg_trlr);
      goto cleanup;
    }

  if ((len = fiid_obj_get_all (obj_ipmb_msg_trlr, buf + indx, IPMB_MAX_LEN - indx)) < 0)
    {
      FIID_OBJECT_ERROR_TO_ERRNO (obj_ipmb_msg_trlr);
      goto cleanup;
    }
  indx += len;

  if ((len = fiid_obj_set_all (obj_ipmb_msg, buf, indx)) < 0)
    {
      FIID_OBJECT_ERROR_TO_ERRNO (obj_ipmb_msg);
      goto cleanup;
    }

  rv = len;
 cleanup:
  fiid_obj_destroy (obj_ipmb_msg_trlr);
  return (rv);
}
int
unassemble_ipmi_ipmb_msg (fiid_obj_t obj_ipmb_msg,
                          fiid_obj_t obj_ipmb_msg_hdr,
                          fiid_obj_t obj_cmd,
                          fiid_obj_t obj_ipmb_msg_trlr,
			  unsigned int flags)
{
  uint8_t buf[IPMB_MAX_LEN+1];
  int buf_len, obj_ipmb_msg_trlr_len, len;
  unsigned int indx = 0;
  unsigned int ipmb_msg_len;
  unsigned int flags_mask = (IPMI_INTERFACE_FLAGS_NO_LEGAL_CHECK);

  if (!fiid_obj_valid (obj_ipmb_msg)
      || !fiid_obj_valid (obj_ipmb_msg_hdr)
      || !fiid_obj_valid (obj_cmd)
      || !fiid_obj_valid (obj_ipmb_msg_trlr)
      || (flags & ~flags_mask))
    {
      SET_ERRNO (EINVAL);
      return (-1);
    }

  if (FIID_OBJ_TEMPLATE_COMPARE (obj_ipmb_msg_hdr, tmpl_ipmb_msg_hdr_rs) < 0)
    {
      ERRNO_TRACE (errno);
      return (-1);
    }
  if (FIID_OBJ_TEMPLATE_COMPARE (obj_ipmb_msg_trlr, tmpl_ipmb_msg_trlr) < 0)
    {
      ERRNO_TRACE (errno);
      return (-1);
    }

  memset (buf, '\0', IPMB_MAX_LEN+1);

  if ((buf_len = fiid_obj_get_all (obj_ipmb_msg, buf, IPMB_MAX_LEN)) < 0)
    {
      FIID_OBJECT_ERROR_TO_ERRNO (obj_ipmb_msg);
      return (-1);
    }

  if (fiid_obj_clear (obj_ipmb_msg_hdr) < 0)
    {
      FIID_OBJECT_ERROR_TO_ERRNO (obj_ipmb_msg_hdr);
      return (-1);
    }

  if (fiid_obj_clear (obj_cmd) < 0)
    {
      FIID_OBJECT_ERROR_TO_ERRNO (obj_cmd);
      return (-1);
    }
  
  if (fiid_obj_clear (obj_ipmb_msg_trlr) < 0)
    {
      FIID_OBJECT_ERROR_TO_ERRNO (obj_ipmb_msg_trlr);
      return (-1);
    }

  if ((len = fiid_obj_set_all (obj_ipmb_msg_hdr, buf + indx, buf_len - indx)) < 0)
    {
      FIID_OBJECT_ERROR_TO_ERRNO (obj_ipmb_msg_hdr);
      return (-1);
    }
  indx += len;
  
  if (buf_len <= indx)
    {
      /* cannot parse packet */
      ERR_TRACE ("malformed packet", EINVAL);
      return (0);
    }
  
  if ((obj_ipmb_msg_trlr_len = fiid_template_len_bytes (tmpl_ipmb_msg_trlr)) < 0)
    {
      ERRNO_TRACE (errno);
      return (-1);
    }
  
  if ((buf_len - indx) <= obj_ipmb_msg_trlr_len)
    {
      /* cannot parse packet */
      ERR_TRACE ("malformed packet", EINVAL);
      return (0);
    }

  ipmb_msg_len = (buf_len - indx) - obj_ipmb_msg_trlr_len;

  if ((len = fiid_obj_set_all (obj_cmd, buf + indx, ipmb_msg_len)) < 0)
    {
      FIID_OBJECT_ERROR_TO_ERRNO (obj_cmd);
      return (-1);
    }
  indx += len;
      
  if (buf_len <= indx)
    {
      /* cannot parse packet */
      ERR_TRACE ("malformed packet", EINVAL);
      return (0);
    }

  if ((len = fiid_obj_set_all (obj_ipmb_msg_trlr, buf + indx, buf_len - indx)) < 0)
    {
      FIID_OBJECT_ERROR_TO_ERRNO (obj_ipmb_msg_trlr);
      return (-1);
    }
  indx += len;
  
  if (FIID_OBJ_PACKET_VALID (obj_ipmb_msg_hdr) == 1
      && ((flags & IPMI_INTERFACE_FLAGS_NO_LEGAL_CHECK) || FIID_OBJ_PACKET_SUFFICIENT (obj_cmd) == 1)
      && FIID_OBJ_PACKET_VALID (obj_ipmb_msg_trlr) == 1)
    return (1);

  return (0);
}
static int
_openipmi_read (ipmi_openipmi_ctx_t ctx,
                fiid_obj_t obj_cmd_rs)
{
  uint8_t rs_buf_temp[IPMI_OPENIPMI_BUFLEN];
  uint8_t rs_buf[IPMI_OPENIPMI_BUFLEN];
  struct ipmi_system_interface_addr rs_addr;
  struct ipmi_recv rs_packet;
  fd_set read_fds;
  struct timeval tv;
  int n;

  assert (ctx);
  assert (ctx->magic == IPMI_OPENIPMI_CTX_MAGIC);
  assert (fiid_obj_valid (obj_cmd_rs));

  rs_packet.addr = (unsigned char *)&rs_addr;
  rs_packet.addr_len = sizeof (struct ipmi_system_interface_addr);
  rs_packet.msg.data = rs_buf_temp;
  rs_packet.msg.data_len = IPMI_OPENIPMI_BUFLEN;

  FD_ZERO (&read_fds);
  FD_SET (ctx->device_fd, &read_fds);

  tv.tv_sec = IPMI_OPENIPMI_TIMEOUT;
  tv.tv_usec = 0;

  if ((n = select (ctx->device_fd + 1,
                   &read_fds,
                   NULL,
                   NULL,
                   &tv)) < 0)
    {
      OPENIPMI_ERRNO_TO_OPENIPMI_ERRNUM (ctx, errno);
      return (-1);
    }

  if (!n)
    {
      /* Could be due to a different error, but we assume a timeout */
      OPENIPMI_SET_ERRNUM (ctx, IPMI_OPENIPMI_ERR_DRIVER_TIMEOUT);
      return (-1);
    }

  if (ioctl (ctx->device_fd,
             IPMICTL_RECEIVE_MSG_TRUNC,
             &rs_packet) < 0)
    {
      OPENIPMI_ERRNO_TO_OPENIPMI_ERRNUM (ctx, errno);
      return (-1);
    }

  /* achu: atleast the completion code should be returned */
  if (!rs_packet.msg.data_len)
    {
      OPENIPMI_SET_ERRNUM (ctx, IPMI_OPENIPMI_ERR_SYSTEM_ERROR);
      return (-1);
    }

  rs_buf[0] = rs_packet.msg.cmd;
  /* -1 b/c of cmd */
  if (rs_packet.msg.data_len >= (IPMI_OPENIPMI_BUFLEN - 1))
    rs_packet.msg.data_len = IPMI_OPENIPMI_BUFLEN - 1;
  memcpy (rs_buf + 1, rs_buf_temp, rs_packet.msg.data_len);

  if (fiid_obj_set_all (obj_cmd_rs,
                        rs_buf,
                        rs_packet.msg.data_len + 1) < 0)
    {
      OPENIPMI_SET_ERRNUM (ctx, IPMI_OPENIPMI_ERR_INTERNAL_ERROR);
      return (-1);
    }

  return (0);
}
int
ipmi_dump_rmcp_packet (int fd,
                       const char *prefix,
                       const char *hdr,
                       const char *trlr,
                       const void *pkt,
                       unsigned int pkt_len,
                       fiid_template_t tmpl_cmd)
{
  unsigned int indx = 0;
  char prefix_buf[IPMI_DEBUG_MAX_PREFIX_LEN];
  char *rmcp_hdr =
    "RMCP Header:\n"
    "------------";
  char *rmcp_cmd =
    "RMCP Command Data:\n"
    "------------------";
  char *unexpected_hdr =
    "Unexpected Data:\n"
    "----------------";
  fiid_obj_t obj_rmcp_hdr = NULL;
  fiid_obj_t obj_cmd = NULL;
  fiid_obj_t obj_unexpected_data = NULL;
  int len, rv = -1;

  if (!pkt || !tmpl_cmd)
    {
      SET_ERRNO (EINVAL);
      return (-1);
    }

  if (debug_set_prefix (prefix_buf, IPMI_DEBUG_MAX_PREFIX_LEN, prefix) < 0)
    {
      ERRNO_TRACE (errno);
      return (-1);
    }

  if (debug_output_str (fd, prefix_buf, hdr) < 0)
    {
      ERRNO_TRACE (errno);
      return (-1);
    }

  /* Dump rmcp header */

  if (!(obj_rmcp_hdr = fiid_obj_create (tmpl_rmcp_hdr)))
    {
      ERRNO_TRACE (errno);
      goto cleanup;
    }

  if ((len = fiid_obj_set_all (obj_rmcp_hdr, pkt + indx, pkt_len - indx)) < 0)
    {
      FIID_OBJECT_ERROR_TO_ERRNO (obj_rmcp_hdr);
      goto cleanup;
    }
  indx += len;

  if (ipmi_obj_dump (fd, prefix, rmcp_hdr, NULL, obj_rmcp_hdr) < 0)
    {
      ERRNO_TRACE (errno);
      goto cleanup;
    }

  if (pkt_len <= indx)
    {
      rv = 0;
      goto cleanup;
    }

  /* Dump command data */

  if (!(obj_cmd = fiid_obj_create (tmpl_cmd)))
    {
      ERRNO_TRACE (errno);
      goto cleanup;
    }

  if ((len = fiid_obj_set_all (obj_cmd, pkt + indx, pkt_len - indx)) < 0)
    {
      FIID_OBJECT_ERROR_TO_ERRNO (obj_cmd);
      goto cleanup;
    }
  indx += len;

  if (ipmi_obj_dump (fd, prefix, rmcp_cmd, NULL, obj_cmd) < 0)
    {
      ERRNO_TRACE (errno);
      goto cleanup;
    }

  /* Dump unexpected stuff */

  if ((pkt_len - indx) > 0)
    {
      if (!(obj_unexpected_data = fiid_obj_create (tmpl_unexpected_data)))
        {
          ERRNO_TRACE (errno);
          goto cleanup;
        }
      
      if ((len = fiid_obj_set_all (obj_unexpected_data, pkt + indx, pkt_len - indx)) < 0)
        {
          FIID_OBJECT_ERROR_TO_ERRNO (obj_unexpected_data);
          goto cleanup;
        }
      indx += len;
      
      if (ipmi_obj_dump (fd, prefix, unexpected_hdr, NULL, obj_unexpected_data) < 0)
        {
          ERRNO_TRACE (errno);
          goto cleanup;
        }
    }

  if (debug_output_str (fd, prefix_buf, trlr) < 0)
    {
      ERRNO_TRACE (errno);
      goto cleanup;
    }


#if WITH_RAWDUMPS
  /* For those vendors that get confused when they see the nice output
   * and want the hex output
   */
  if (ipmi_dump_hex (fd,
                     prefix,
                     hdr,
                     trlr,
                     pkt,
                     pkt_len) < 0)
    {
      ERRNO_TRACE (errno);
      goto cleanup;
    }
#endif
  
  rv = 0;
 cleanup:
  fiid_obj_destroy (obj_rmcp_hdr);
  fiid_obj_destroy (obj_cmd);
  fiid_obj_destroy (obj_unexpected_data);
  return (rv);
}
/* return (1) - is oem intel node manager, fully parsed                                                                                     
 * return (0) - is not oem intel node manager                                                                                               
 * return (-1) - error                                                                                                                      
 */
int
ipmi_sdr_oem_parse_intel_node_manager (ipmi_sdr_ctx_t ctx,
                                       const void *sdr_record,
                                       unsigned int sdr_record_len,
                                       uint8_t *nm_device_slave_address,
                                       uint8_t *sensor_owner_lun,
                                       uint8_t *channel_number,
                                       uint8_t *nm_health_event_sensor_number,
                                       uint8_t *nm_exception_event_sensor_number,
                                       uint8_t *nm_operational_capabilities_sensor_number,
                                       uint8_t *nm_alert_threshold_exceeded_sensor_number)
{
  uint8_t sdr_record_buf[IPMI_SDR_MAX_RECORD_LENGTH];
  int sdr_record_buf_len;
  fiid_obj_t obj_oem_record = NULL;
  int expected_record_len;
  void *sdr_record_to_use;
  unsigned int sdr_record_len_to_use;
  uint64_t val;
  int rv = -1;

  if (!ctx || ctx->magic != IPMI_SDR_CTX_MAGIC)
    {
      ERR_TRACE (ipmi_sdr_ctx_errormsg (ctx), ipmi_sdr_ctx_errnum (ctx));
      return (-1);
    }

  if (!sdr_record || !sdr_record_len)
    {
      if (ctx->operation == IPMI_SDR_OPERATION_READ_CACHE
          && !sdr_record
          && !sdr_record_len)
        {
          if ((sdr_record_buf_len = ipmi_sdr_cache_record_read (ctx,
                                                                sdr_record_buf,
                                                                IPMI_SDR_MAX_RECORD_LENGTH)) < 0)
            {
              SDR_SET_INTERNAL_ERRNUM (ctx);
              return (-1);
            }
          sdr_record_to_use = sdr_record_buf;
          sdr_record_len_to_use = sdr_record_buf_len;
        }
      else
        {
          SDR_SET_ERRNUM (ctx, IPMI_SDR_ERR_PARAMETERS);
          return (-1);
        }
    }
  else
    {
      sdr_record_to_use = (void *)sdr_record;
      sdr_record_len_to_use = sdr_record_len;
    }

  if ((expected_record_len = fiid_template_len_bytes (tmpl_sdr_oem_intel_node_manager_record)) < 0)
    {
      SDR_ERRNO_TO_SDR_ERRNUM (ctx, errno);
      goto cleanup;
    }
  
  if (sdr_record_len_to_use < expected_record_len)
    {
      rv = 0;
      goto cleanup;
    }

  if (!(obj_oem_record = fiid_obj_create (tmpl_sdr_oem_intel_node_manager_record)))
    {
      SDR_ERRNO_TO_SDR_ERRNUM (ctx, errno);
      goto cleanup;
    }

  if (fiid_obj_set_all (obj_oem_record,
                        sdr_record_to_use,
                        expected_record_len) < 0)
    {
      SDR_FIID_OBJECT_ERROR_TO_SDR_ERRNUM (ctx, obj_oem_record);
      goto cleanup;
    }

  /* achu: Node Manager documentation states that OEM ID in the
   * SDR record should be Intel's, but I've seen motherboards w/o
   * it, so don't bother checking.
   */

  if (FIID_OBJ_GET (obj_oem_record,
                    "record_subtype",
                    &val) < 0)
    {
      SDR_FIID_OBJECT_ERROR_TO_SDR_ERRNUM (ctx, obj_oem_record);
      goto cleanup;
    }
  
  if (val != IPMI_SDR_OEM_INTEL_NODE_MANAGER_RECORD_SUBTYPE_NM_DISCOVERY)
    {
      rv = 0;
      goto cleanup;
    }

  if (FIID_OBJ_GET (obj_oem_record,
                    "version_number",
                    &val) < 0)
    {
      SDR_FIID_OBJECT_ERROR_TO_SDR_ERRNUM (ctx, obj_oem_record);
      goto cleanup;
    }

  if (val != IPMI_SDR_OEM_INTEL_NODE_MANAGER_DISCOVERY_VERSION)
    {
      rv = 0;
      goto cleanup;
    }
     
  if (nm_device_slave_address)
    {
      if (FIID_OBJ_GET (obj_oem_record,
                        "nm_device_slave_address",
                        &val) < 0)
        {
          SDR_FIID_OBJECT_ERROR_TO_SDR_ERRNUM (ctx, obj_oem_record);
          goto cleanup;
        }
      (*nm_device_slave_address) = val;
    }

  if (sensor_owner_lun)
    {
      if (FIID_OBJ_GET (obj_oem_record,
                        "sensor_owner_lun",
                        &val) < 0)
        {
          SDR_FIID_OBJECT_ERROR_TO_SDR_ERRNUM (ctx, obj_oem_record);
          goto cleanup;
        }
      (*sensor_owner_lun) = val;
    }

  if (channel_number)
    {
      if (FIID_OBJ_GET (obj_oem_record,
                        "channel_number",
                        &val) < 0)
        {
          SDR_FIID_OBJECT_ERROR_TO_SDR_ERRNUM (ctx, obj_oem_record);
          goto cleanup;
        }
      (*channel_number) = val;
    }

  if (nm_health_event_sensor_number)
    {
      if (FIID_OBJ_GET (obj_oem_record,
                        "nm_health_event_sensor_number",
                        &val) < 0)
        {
          SDR_FIID_OBJECT_ERROR_TO_SDR_ERRNUM (ctx, obj_oem_record);
          goto cleanup;
        }
      (*nm_health_event_sensor_number) = val;
    }

  if (nm_exception_event_sensor_number)
    {
      if (FIID_OBJ_GET (obj_oem_record,
                        "nm_exception_event_sensor_number",
                        &val) < 0)
        {
          SDR_FIID_OBJECT_ERROR_TO_SDR_ERRNUM (ctx, obj_oem_record);
          goto cleanup;
        }
      (*nm_exception_event_sensor_number) = val;
    }

  if (nm_operational_capabilities_sensor_number)
    {
      if (FIID_OBJ_GET (obj_oem_record,
                        "nm_operational_capabilities_sensor_number",
                        &val) < 0)
        {
          SDR_FIID_OBJECT_ERROR_TO_SDR_ERRNUM (ctx, obj_oem_record);
          goto cleanup;
        }
      (*nm_operational_capabilities_sensor_number) = val;
    }
  
  if (nm_alert_threshold_exceeded_sensor_number)
    {
      if (FIID_OBJ_GET (obj_oem_record,
                        "nm_alert_threshold_exceeded_sensor_number",
                        &val) < 0)
        {
          SDR_FIID_OBJECT_ERROR_TO_SDR_ERRNUM (ctx, obj_oem_record);
          goto cleanup;
        }
      (*nm_alert_threshold_exceeded_sensor_number) = val;
    }

  sdr_check_read_status (ctx);

  rv = 1;
  ctx->errnum = IPMI_SDR_ERR_SUCCESS;
 cleanup:
  fiid_obj_destroy (obj_oem_record);
  return (rv);
}
Beispiel #10
0
int
unassemble_rmcp_pkt (const void *pkt,
                     unsigned int pkt_len,
                     fiid_obj_t obj_rmcp_hdr,
                     fiid_obj_t obj_cmd,
		     unsigned int flags)
{
  unsigned int indx = 0;
  int len;
  unsigned int flags_mask = (IPMI_INTERFACE_FLAGS_NO_LEGAL_CHECK);

  if (!pkt
      || !fiid_obj_valid (obj_rmcp_hdr)
      || !fiid_obj_valid (obj_cmd)
      || (flags & ~flags_mask))
    {
      SET_ERRNO (EINVAL);
      return (-1);
    }

  if (FIID_OBJ_TEMPLATE_COMPARE (obj_rmcp_hdr, tmpl_rmcp_hdr) < 0)
    {
      ERRNO_TRACE (errno);
      return (-1);
    }

  if (fiid_obj_clear (obj_rmcp_hdr) < 0)
    {
      FIID_OBJECT_ERROR_TO_ERRNO (obj_rmcp_hdr);
      return (-1);
    }

  if (fiid_obj_clear (obj_cmd) < 0)
    {
      FIID_OBJECT_ERROR_TO_ERRNO (obj_cmd);
      return (-1);
    }

  if ((len = fiid_obj_set_all (obj_rmcp_hdr, pkt + indx, pkt_len - indx)) < 0)
    {
      FIID_OBJECT_ERROR_TO_ERRNO (obj_rmcp_hdr);
      return (-1);
    }
  indx += len;

  if (pkt_len <= indx)
    {
      /* trace, but don't error out, cannot parse packet */
      ERR_TRACE ("malformed packet", EINVAL);
      return (0);
    }

  if ((len = fiid_obj_set_all (obj_cmd, pkt + indx, pkt_len - indx)) < 0)
    {
      FIID_OBJECT_ERROR_TO_ERRNO (obj_cmd);
      return (-1);
    }
  indx += len;

  if (FIID_OBJ_PACKET_VALID (obj_rmcp_hdr) == 1
      && ((flags & IPMI_INTERFACE_FLAGS_NO_LEGAL_CHECK) || FIID_OBJ_PACKET_SUFFICIENT (obj_cmd) == 1))
    return (1);

  return (0);
}
Beispiel #11
0
int
unassemble_ipmi_lan_pkt (const void *pkt,
                         unsigned int pkt_len,
                         fiid_obj_t obj_rmcp_hdr,
                         fiid_obj_t obj_lan_session_hdr,
                         fiid_obj_t obj_lan_msg_hdr,
                         fiid_obj_t obj_cmd,
                         fiid_obj_t obj_lan_msg_trlr,
			 unsigned int flags)
{
  uint8_t authentication_type;
  unsigned int indx = 0;
  unsigned int obj_cmd_len;
  int obj_lan_msg_trlr_len, len;
  uint64_t val;
  unsigned int flags_mask = (IPMI_INTERFACE_FLAGS_NO_LEGAL_CHECK);

  if (!pkt
      || !fiid_obj_valid (obj_rmcp_hdr)
      || !fiid_obj_valid (obj_lan_session_hdr)
      || !fiid_obj_valid (obj_lan_msg_hdr)
      || !fiid_obj_valid (obj_cmd)
      || !fiid_obj_valid (obj_lan_msg_trlr)
      || (flags & ~flags_mask))
    {
      SET_ERRNO (EINVAL);
      return (-1);
    }

  if (FIID_OBJ_TEMPLATE_COMPARE (obj_rmcp_hdr, tmpl_rmcp_hdr) < 0)
    {
      ERRNO_TRACE (errno);
      return (-1);
    }
  if (FIID_OBJ_TEMPLATE_COMPARE (obj_lan_session_hdr, tmpl_lan_session_hdr) < 0)
    {
      ERRNO_TRACE (errno);
      return (-1);
    }
  if (FIID_OBJ_TEMPLATE_COMPARE (obj_lan_msg_hdr, tmpl_lan_msg_hdr_rs) < 0)
    {
      ERRNO_TRACE (errno);
      return (-1);
    }
  if (FIID_OBJ_TEMPLATE_COMPARE (obj_lan_msg_trlr, tmpl_lan_msg_trlr) < 0)
    {
      ERRNO_TRACE (errno);
      return (-1);
    }

  indx = 0;
  if (fiid_obj_clear (obj_rmcp_hdr) < 0)
    {
      FIID_OBJECT_ERROR_TO_ERRNO (obj_rmcp_hdr);
      return (-1);
    }

  if (fiid_obj_clear (obj_lan_session_hdr) < 0)
    {
      FIID_OBJECT_ERROR_TO_ERRNO (obj_lan_session_hdr);
      return (-1);
    }

  if (fiid_obj_clear (obj_lan_msg_hdr) < 0)
    {
      FIID_OBJECT_ERROR_TO_ERRNO (obj_lan_msg_hdr);
      return (-1);
    }
  
  if (fiid_obj_clear (obj_cmd) < 0)
    {
      FIID_OBJECT_ERROR_TO_ERRNO (obj_cmd);
      return (-1);
    }

  if (fiid_obj_clear (obj_lan_msg_trlr) < 0)
    {
      FIID_OBJECT_ERROR_TO_ERRNO (obj_lan_msg_trlr);
      return (-1);
    }

  if ((len = fiid_obj_set_all (obj_rmcp_hdr, pkt + indx, pkt_len - indx)) < 0)
    {
      FIID_OBJECT_ERROR_TO_ERRNO (obj_rmcp_hdr);
      return (-1);
    }
  indx += len;

  if (pkt_len <= indx)
    {
      /* cannot parse packet */
      ERR_TRACE ("malformed packet", EINVAL);
      return (0);
    }

  if ((len = fiid_obj_set_block (obj_lan_session_hdr,
                                 "authentication_type",
                                 "session_id",
                                 pkt + indx,
                                 pkt_len - indx)) < 0)
    {
      FIID_OBJECT_ERROR_TO_ERRNO (obj_lan_session_hdr);
      return (-1);
    }
  indx += len;

  if (FIID_OBJ_GET (obj_lan_session_hdr,
                    "authentication_type",
                    &val) < 0)
    {
      FIID_OBJECT_ERROR_TO_ERRNO (obj_lan_session_hdr);
      return (-1);
    }
  authentication_type = val;

  if (!IPMI_1_5_AUTHENTICATION_TYPE_VALID (authentication_type))
    {
      /* cannot parse packet */
      ERR_TRACE ("malformed packet", EINVAL);
      return (0);
    }

  if (authentication_type != IPMI_AUTHENTICATION_TYPE_NONE)
    {
      if ((len = fiid_obj_set_data (obj_lan_session_hdr,
                                    "authentication_code",
                                    pkt + indx,
                                    pkt_len - indx)) < 0)
        {
          FIID_OBJECT_ERROR_TO_ERRNO (obj_lan_session_hdr);
          return (-1);
        }
      indx += len;

      if (pkt_len <= indx)
        {
          /* cannot parse packet */
          ERR_TRACE ("malformed packet", EINVAL);
          return (0);
        }
    }

  if ((len = fiid_obj_set_data (obj_lan_session_hdr,
                                "ipmi_msg_len",
                                pkt + indx,
                                pkt_len - indx)) < 0)
    {
      FIID_OBJECT_ERROR_TO_ERRNO (obj_lan_session_hdr);
      return (-1);
    }
  indx += len;

  if (pkt_len <= indx)
    {
      /* cannot parse packet */
      ERR_TRACE ("malformed packet", EINVAL);
      return (0);
    }

  if ((len = fiid_obj_set_all (obj_lan_msg_hdr, pkt + indx, pkt_len - indx)) < 0)
    {
      FIID_OBJECT_ERROR_TO_ERRNO (obj_lan_msg_hdr);
      return (-1);
    }
  indx += len;

  if (pkt_len <= indx)
    {
      /* cannot parse packet */
      ERR_TRACE ("malformed packet", EINVAL);
      return (0);
    }

  if ((obj_lan_msg_trlr_len = fiid_template_len_bytes (tmpl_lan_msg_trlr)) < 0)
    {
      ERRNO_TRACE (errno);
      return (-1);
    }

  if ((pkt_len - indx) <= obj_lan_msg_trlr_len)
    {
      /* cannot parse packet */
      ERR_TRACE ("malformed packet", EINVAL);
      return (0);
    }

  obj_cmd_len = (pkt_len - indx) - obj_lan_msg_trlr_len;

  if ((len = fiid_obj_set_all (obj_cmd, pkt + indx, obj_cmd_len)) < 0)
    {
      FIID_OBJECT_ERROR_TO_ERRNO (obj_cmd);
      return (-1);
    }
  indx += len;

  if (pkt_len <= indx)
    {
      /* cannot parse packet */
      ERR_TRACE ("malformed packet", EINVAL);
      return (0);
    }

  if ((len = fiid_obj_set_all (obj_lan_msg_trlr, pkt + indx, pkt_len - indx)) < 0)
    {
      FIID_OBJECT_ERROR_TO_ERRNO (obj_lan_msg_trlr);
      return (-1);
    }
  indx += len;
  
  if (FIID_OBJ_PACKET_VALID (obj_rmcp_hdr) == 1
      && FIID_OBJ_PACKET_VALID (obj_lan_session_hdr) == 1
      && FIID_OBJ_PACKET_VALID (obj_lan_msg_hdr) == 1
      && ((flags & IPMI_INTERFACE_FLAGS_NO_LEGAL_CHECK) || FIID_OBJ_PACKET_SUFFICIENT (obj_cmd) == 1)
      && FIID_OBJ_PACKET_VALID (obj_lan_msg_trlr) == 1)
    return (1);

  return (0);
}
Beispiel #12
0
int
assemble_ipmi_lan_pkt (fiid_obj_t obj_rmcp_hdr,
                       fiid_obj_t obj_lan_session_hdr,
                       fiid_obj_t obj_lan_msg_hdr,
                       fiid_obj_t obj_cmd,
                       const void *authentication_code_data,
                       unsigned int authentication_code_data_len,
                       void *pkt,
                       unsigned int pkt_len,
		       unsigned int flags)
{
  uint8_t authentication_type;
  uint64_t val;
  unsigned int indx = 0;
  int required_len;
  void *authentication_code_field_ptr = NULL;
  void *checksum_data_ptr = NULL;
  void *msg_data_ptr = NULL;
  void *ipmi_msg_len_ptr = NULL;
  unsigned int msg_data_count = 0;
  unsigned int checksum_data_count = 0;
  uint8_t ipmi_msg_len;
  fiid_obj_t obj_lan_msg_trlr = NULL;
  uint8_t pwbuf[IPMI_1_5_MAX_PASSWORD_LENGTH];
  uint8_t checksum;
  int len, rv = -1;
  unsigned int flags_mask = 0;

  if (!fiid_obj_valid (obj_rmcp_hdr)
      || !fiid_obj_valid (obj_lan_session_hdr)
      || !fiid_obj_valid (obj_lan_msg_hdr)
      || !fiid_obj_valid (obj_cmd)
      || (authentication_code_data && authentication_code_data_len > IPMI_1_5_MAX_PASSWORD_LENGTH)
      || !pkt
      || (flags & ~flags_mask))
    {
      SET_ERRNO (EINVAL);
      return (-1);
    }

  if (FIID_OBJ_TEMPLATE_COMPARE (obj_rmcp_hdr, tmpl_rmcp_hdr) < 0)
    {
      ERRNO_TRACE (errno);
      return (-1);
    }
  if (FIID_OBJ_TEMPLATE_COMPARE (obj_lan_session_hdr, tmpl_lan_session_hdr) < 0)
    {
      ERRNO_TRACE (errno);
      return (-1);
    }
  if (FIID_OBJ_TEMPLATE_COMPARE (obj_lan_msg_hdr, tmpl_lan_msg_hdr_rq) < 0)
    {
      ERRNO_TRACE (errno);
      return (-1);
    }

  if (FIID_OBJ_PACKET_VALID (obj_rmcp_hdr) < 0)
    {
      FIID_OBJECT_ERROR_TO_ERRNO (obj_rmcp_hdr);
      return (-1);
    }

  /*
   * ipmi_msg_len is calculated in this function, so we can't use
   * fiid_obj_packet_valid() on obj_lan_session_hdr b/c ipmi_msg_len
   * is probably not set yet.
   */

  if (FIID_OBJ_PACKET_VALID (obj_lan_msg_hdr) < 0)
    {
      FIID_OBJECT_ERROR_TO_ERRNO (obj_lan_msg_hdr);
      return (-1);
    }
  if (FIID_OBJ_PACKET_VALID (obj_cmd) < 0)
    {
      FIID_OBJECT_ERROR_TO_ERRNO (obj_cmd);
      return (-1);
    }

  if (FIID_OBJ_GET (obj_lan_session_hdr,
                    "authentication_type",
                    &val) < 0)
    {
      ERRNO_TRACE (errno);
      return (-1);
    }
  authentication_type = val;

  if (authentication_type != IPMI_AUTHENTICATION_TYPE_NONE
      && authentication_type != IPMI_AUTHENTICATION_TYPE_MD2
      && authentication_type != IPMI_AUTHENTICATION_TYPE_MD5
      && authentication_type != IPMI_AUTHENTICATION_TYPE_STRAIGHT_PASSWORD_KEY)
    {
      SET_ERRNO (EINVAL);
      return (-1);
    }

  /* no need for overflow checks, handled w/ _ipmi_lan_pkt_rq_min_size check */

  required_len = _ipmi_lan_pkt_rq_min_size (authentication_type, obj_cmd);
  if (pkt_len < required_len)
    {
      SET_ERRNO (EMSGSIZE);
      return (-1);
    }

  memset (pkt, 0, pkt_len);

  if ((len = fiid_obj_get_all (obj_rmcp_hdr, pkt + indx, pkt_len - indx)) < 0)
    {
      FIID_OBJECT_ERROR_TO_ERRNO (obj_rmcp_hdr);
      goto cleanup;
    }
  indx += len;

  if ((len = fiid_obj_get_block (obj_lan_session_hdr,
                                 "authentication_type",
                                 "session_id",
                                 pkt + indx,
                                 pkt_len - indx)) < 0)
    {
      FIID_OBJECT_ERROR_TO_ERRNO (obj_lan_session_hdr);
      goto cleanup;
    }

  indx += len;

  /* authentication_code generated last.  Save pointers for later calculation */
  if (authentication_type != IPMI_AUTHENTICATION_TYPE_NONE)
    {
      authentication_code_field_ptr = (pkt + indx);
      indx += IPMI_1_5_MAX_PASSWORD_LENGTH;
    }

  ipmi_msg_len_ptr = (pkt + indx);
  if ((len = fiid_template_field_len_bytes (tmpl_lan_session_hdr, "ipmi_msg_len")) < 0)
    {
      ERRNO_TRACE (errno);
      goto cleanup;
    }
  if (len != 1)
    {
      SET_ERRNO (EINVAL);
      goto cleanup;
    }
  indx += len;

  msg_data_ptr = (pkt + indx);

  if ((len = fiid_obj_get_block (obj_lan_msg_hdr,
                                 "rs_addr",
                                 "checksum1",
                                 pkt + indx,
                                 pkt_len - indx)) < 0)
    {
      FIID_OBJECT_ERROR_TO_ERRNO (obj_lan_msg_hdr);
      goto cleanup;
    }
  indx += len;
  msg_data_count += len;

  checksum_data_ptr = (pkt + indx);

  if ((len = fiid_obj_get_block (obj_lan_msg_hdr,
                                 "rq_addr",
                                 "rq_seq",
                                 pkt + indx,
                                 pkt_len - indx)) < 0)
    {
      FIID_OBJECT_ERROR_TO_ERRNO (obj_lan_msg_hdr);
      goto cleanup;
    }
  indx += len;
  msg_data_count += len;
  checksum_data_count += len;

  if ((len = fiid_obj_get_all (obj_cmd, pkt + indx, pkt_len - indx)) < 0)
    {
      FIID_OBJECT_ERROR_TO_ERRNO (obj_cmd);
      goto cleanup;
    }
  indx += len;
  msg_data_count += len;
  checksum_data_count += len;

  if (!(obj_lan_msg_trlr = fiid_obj_create (tmpl_lan_msg_trlr)))
    {
      ERRNO_TRACE (errno);
      goto cleanup;
    }

  checksum = ipmi_checksum (checksum_data_ptr, checksum_data_count);

  if (fiid_obj_set_all (obj_lan_msg_trlr, &checksum, sizeof (checksum)) < 0)
    {
      FIID_OBJECT_ERROR_TO_ERRNO (obj_lan_msg_trlr);
      goto cleanup;
    }

  if ((len = fiid_obj_get_all (obj_lan_msg_trlr, pkt + indx, pkt_len - indx)) < 0)
    {
      FIID_OBJECT_ERROR_TO_ERRNO (obj_lan_msg_trlr);
      goto cleanup;
    }
  indx += len;
  msg_data_count += len;

  /* ipmi_msg_len done after message length is computed */
  ipmi_msg_len = msg_data_count;
  memcpy (ipmi_msg_len_ptr,
          &ipmi_msg_len,
          sizeof (ipmi_msg_len));

  /* Auth code must be done last, some authentication like md2 and md5
   * require all fields, including checksums, to be calculated
   * beforehand
   */
  if (authentication_type != IPMI_AUTHENTICATION_TYPE_NONE)
    {
      int authentication_len;

      memset (pwbuf, '\0', IPMI_1_5_MAX_PASSWORD_LENGTH);

      if ((authentication_len = fiid_obj_field_len_bytes (obj_lan_session_hdr,
                                                          "authentication_code")) < 0)
        {
          FIID_OBJECT_ERROR_TO_ERRNO (obj_lan_session_hdr);
          goto cleanup;
        }

      if (authentication_len)
        {
          if (fiid_obj_get_data (obj_lan_session_hdr,
                                 "authentication_code",
                                 pwbuf,
                                 IPMI_1_5_MAX_PASSWORD_LENGTH) < 0)
            {
              FIID_OBJECT_ERROR_TO_ERRNO (obj_lan_session_hdr);
              goto cleanup;
            }

          memcpy (authentication_code_field_ptr,
                  pwbuf,
                  IPMI_1_5_MAX_PASSWORD_LENGTH);
        }
      else
        {
          if (authentication_code_data)
            memcpy (pwbuf,
                    authentication_code_data,
                    authentication_code_data_len);

          if (authentication_type == IPMI_AUTHENTICATION_TYPE_STRAIGHT_PASSWORD_KEY)
            {
              memcpy (authentication_code_field_ptr,
                      pwbuf,
                      IPMI_1_5_MAX_PASSWORD_LENGTH);
            }
          else /* IPMI_AUTHENTICATION_TYPE_MD2 || IPMI_AUTHENTICATION_TYPE_MD5 */
            {
              uint8_t session_id_buf[1024];
              uint8_t session_sequence_number_buf[1024];
              int session_id_len, session_sequence_number_len;

              if ((session_id_len = fiid_obj_get_data (obj_lan_session_hdr,
                                                       "session_id",
                                                       session_id_buf,
                                                       1024)) < 0)
                {
                  FIID_OBJECT_ERROR_TO_ERRNO (obj_lan_session_hdr);
                  goto cleanup;
                }

              if ((session_sequence_number_len = fiid_obj_get_data (obj_lan_session_hdr,
                                                                    "session_sequence_number",
                                                                    session_sequence_number_buf,
                                                                    1024)) < 0)
                {
                  FIID_OBJECT_ERROR_TO_ERRNO (obj_lan_session_hdr);
                  goto cleanup;
                }

              if (authentication_type == IPMI_AUTHENTICATION_TYPE_MD2)
                {
                  md2_t ctx;
                  uint8_t digest[MD2_DIGEST_LENGTH];

                  assert (IPMI_1_5_MAX_PASSWORD_LENGTH == MD2_DIGEST_LENGTH);

                  md2_init (&ctx);
                  md2_update_data (&ctx, pwbuf, IPMI_1_5_MAX_PASSWORD_LENGTH);
                  md2_update_data (&ctx, session_id_buf, session_id_len);
                  md2_update_data (&ctx, msg_data_ptr, msg_data_count);
                  md2_update_data (&ctx, session_sequence_number_buf, session_sequence_number_len);
                  md2_update_data (&ctx, pwbuf, IPMI_1_5_MAX_PASSWORD_LENGTH);
                  md2_finish (&ctx, digest, MD2_DIGEST_LENGTH);
                  md2_init (&ctx);

                  memcpy (authentication_code_field_ptr, digest, IPMI_1_5_MAX_PASSWORD_LENGTH);
                  secure_memset (digest, '\0', MD2_DIGEST_LENGTH);
                }
              else if (authentication_type == IPMI_AUTHENTICATION_TYPE_MD5)
                {
                  md5_t ctx;
                  uint8_t digest[MD5_DIGEST_LENGTH];

                  assert (IPMI_1_5_MAX_PASSWORD_LENGTH == MD5_DIGEST_LENGTH);

                  md5_init (&ctx);
                  md5_update_data (&ctx, pwbuf, IPMI_1_5_MAX_PASSWORD_LENGTH);
                  md5_update_data (&ctx, session_id_buf, session_id_len);
                  md5_update_data (&ctx, msg_data_ptr, msg_data_count);
                  md5_update_data (&ctx, session_sequence_number_buf, session_sequence_number_len);
                  md5_update_data (&ctx, pwbuf, IPMI_1_5_MAX_PASSWORD_LENGTH);
                  md5_finish (&ctx, digest, MD5_DIGEST_LENGTH);
                  md5_init (&ctx);

                  memcpy (authentication_code_field_ptr, digest, IPMI_1_5_MAX_PASSWORD_LENGTH);
                  secure_memset (digest, '\0', MD5_DIGEST_LENGTH);
                }
            }
        }
    }

  if (indx > INT_MAX)
    {
      SET_ERRNO (EMSGSIZE);
      goto cleanup;
    }

  rv = indx;
 cleanup:
  if (rv < 0)
    secure_memset (pkt, '\0', pkt_len);
  fiid_obj_destroy (obj_lan_msg_trlr);
  secure_memset (pwbuf, '\0', IPMI_1_5_MAX_PASSWORD_LENGTH);
  return (rv);
}
static int
_sdr_cache_get_record (ipmi_sdr_ctx_t ctx,
                       ipmi_ctx_t ipmi_ctx,
                       uint16_t record_id,
                       void *record_buf,
                       unsigned int record_buf_len,
                       uint16_t *reservation_id,
                       uint16_t *next_record_id)
{
    fiid_obj_t obj_cmd_rs = NULL;
    fiid_obj_t obj_sdr_record_header = NULL;
    int sdr_record_header_length = 0;
    int sdr_record_len = 0;
    unsigned int record_length = 0;
    int rv = -1;
    unsigned int bytes_to_read = IPMI_SDR_CACHE_BYTES_TO_READ_START;
    unsigned int offset_into_record = 0;
    unsigned int reservation_id_retry_count = 0;
    uint8_t temp_record_buf[IPMI_SDR_MAX_RECORD_LENGTH];
    uint64_t val;

    assert (ctx);
    assert (ctx->magic == IPMI_SDR_CTX_MAGIC);
    assert (ipmi_ctx);
    assert (record_buf);
    assert (record_buf_len);
    assert (reservation_id);
    assert (next_record_id);

    if (!(obj_cmd_rs = fiid_obj_create (tmpl_cmd_get_sdr_rs)))
    {
        SDR_ERRNO_TO_SDR_ERRNUM (ctx, errno);
        goto cleanup;
    }

    if (!(obj_sdr_record_header = fiid_obj_create (tmpl_sdr_record_header)))
    {
        SDR_ERRNO_TO_SDR_ERRNUM (ctx, errno);
        goto cleanup;
    }

    if ((sdr_record_header_length = fiid_template_len_bytes (tmpl_sdr_record_header)) < 0)
    {
        SDR_ERRNO_TO_SDR_ERRNUM (ctx, errno);
        goto cleanup;
    }

    /* achu:
     *
     * Many motherboards now allow you to read the full SDR record, try
     * that first.  If it fails for any reason, bail and try to read via
     * partial reads.
     */

    reservation_id_retry_count = 0;
    while (!offset_into_record)
    {
        if (ipmi_cmd_get_sdr (ipmi_ctx,
                              *reservation_id,
                              record_id,
                              0,
                              IPMI_SDR_READ_ENTIRE_RECORD_BYTES_TO_READ,
                              obj_cmd_rs) < 0)
        {
            if (ipmi_ctx_errnum (ipmi_ctx) == IPMI_ERR_BAD_COMPLETION_CODE)
            {
                uint8_t comp_code;

                if (FIID_OBJ_GET (obj_cmd_rs,
                                  "comp_code",
                                  &val) < 0)
                {
                    SDR_FIID_OBJECT_ERROR_TO_SDR_ERRNUM (ctx, obj_cmd_rs);
                    goto cleanup;
                }
                comp_code = val;

                if (comp_code == IPMI_COMP_CODE_RESERVATION_CANCELLED
                        && (reservation_id_retry_count < IPMI_SDR_CACHE_MAX_RESERVATION_ID_RETRY))
                {
                    if (_sdr_cache_reservation_id (ctx,
                                                   ipmi_ctx,
                                                   reservation_id) < 0)
                        goto cleanup;
                    reservation_id_retry_count++;
                    continue;
                }
            }

            goto partial_read;
        }

        if ((sdr_record_len = fiid_obj_get_data (obj_cmd_rs,
                              "record_data",
                              temp_record_buf,
                              IPMI_SDR_MAX_RECORD_LENGTH)) < 0)
        {
            SDR_FIID_OBJECT_ERROR_TO_SDR_ERRNUM (ctx, obj_cmd_rs);
            goto cleanup;
        }

        /* Assume this is an "IPMI Error", fall through to partial reads */
        if (sdr_record_len < sdr_record_header_length)
            goto partial_read;

        /*
         * IPMI Workaround (achu)
         *
         * Discovered on Xyratex HB-F8-SRAY
         *
         * For some reason reading the entire SDR record (with
         * IPMI_SDR_READ_ENTIRE_RECORD_BYTES_TO_READ) the response
         * returns fewer bytes than the actual length of the record.
         * However, when reading with partial reads things ultimately
         * succeed.  If we notice the length is off, we fall out and do
         * a partial read.
         */
        if ((((uint8_t)temp_record_buf[IPMI_SDR_RECORD_LENGTH_INDEX]) + IPMI_SDR_RECORD_HEADER_LENGTH) > sdr_record_len)
            goto partial_read;

        if (sdr_record_len > record_buf_len)
        {
            SDR_SET_ERRNUM (ctx, IPMI_SDR_ERR_INTERNAL_ERROR);
            goto cleanup;
        }

        if (FIID_OBJ_GET (obj_cmd_rs,
                          "next_record_id",
                          &val) < 0)
        {
            SDR_FIID_OBJECT_ERROR_TO_SDR_ERRNUM (ctx, obj_cmd_rs);
            goto cleanup;
        }
        *next_record_id = val;

        memcpy (record_buf, temp_record_buf, sdr_record_len);
        offset_into_record += sdr_record_len;
        goto out;
    }

partial_read:

    reservation_id_retry_count = 0;
    while (!record_length)
    {
        uint8_t record_header_buf[IPMI_SDR_MAX_RECORD_LENGTH];
        int sdr_record_header_len;

        if (ipmi_cmd_get_sdr (ipmi_ctx,
                              *reservation_id,
                              record_id,
                              0,
                              sdr_record_header_length,
                              obj_cmd_rs) < 0)
        {
            if (ipmi_ctx_errnum (ipmi_ctx) != IPMI_ERR_BAD_COMPLETION_CODE)
            {
                SDR_SET_ERRNUM (ctx, IPMI_SDR_ERR_IPMI_ERROR);
                goto cleanup;
            }
            else
            {
                uint8_t comp_code;

                if (FIID_OBJ_GET (obj_cmd_rs,
                                  "comp_code",
                                  &val) < 0)
                {
                    SDR_FIID_OBJECT_ERROR_TO_SDR_ERRNUM (ctx, obj_cmd_rs);
                    goto cleanup;
                }
                comp_code = val;

                if (comp_code == IPMI_COMP_CODE_RESERVATION_CANCELLED
                        && (reservation_id_retry_count < IPMI_SDR_CACHE_MAX_RESERVATION_ID_RETRY))
                {
                    if (_sdr_cache_reservation_id (ctx,
                                                   ipmi_ctx,
                                                   reservation_id) < 0)
                        goto cleanup;
                    reservation_id_retry_count++;
                    continue;
                }

                SDR_SET_ERRNUM (ctx, IPMI_SDR_ERR_IPMI_ERROR);
                goto cleanup;
            }
        }

        if ((sdr_record_header_len = fiid_obj_get_data (obj_cmd_rs,
                                     "record_data",
                                     record_header_buf,
                                     IPMI_SDR_MAX_RECORD_LENGTH)) < 0)
        {
            SDR_FIID_OBJECT_ERROR_TO_SDR_ERRNUM (ctx, obj_cmd_rs);
            goto cleanup;
        }

        if (sdr_record_header_len < sdr_record_header_length)
        {
            SDR_SET_ERRNUM (ctx, IPMI_SDR_ERR_IPMI_ERROR);
            goto cleanup;
        }

        if (fiid_obj_set_all (obj_sdr_record_header,
                              record_header_buf,
                              sdr_record_header_len) < 0)
        {
            SDR_FIID_OBJECT_ERROR_TO_SDR_ERRNUM (ctx, obj_sdr_record_header);
            goto cleanup;
        }

        if (FIID_OBJ_GET (obj_sdr_record_header,
                          "record_length",
                          &val) < 0)
        {
            SDR_FIID_OBJECT_ERROR_TO_SDR_ERRNUM (ctx, obj_sdr_record_header);
            goto cleanup;
        }

        if (sdr_record_header_len > record_buf_len)
        {
            SDR_SET_ERRNUM (ctx, IPMI_SDR_ERR_INTERNAL_ERROR);
            goto cleanup;
        }

        /* copy header into buf */
        memcpy (record_buf, record_header_buf, sdr_record_header_len);
        offset_into_record += sdr_record_header_len;
        record_length = val + sdr_record_header_length;
    }

    if (record_length > record_buf_len)
    {
        SDR_SET_ERRNUM (ctx, IPMI_SDR_ERR_INTERNAL_ERROR);
        goto cleanup;
    }

    if (FIID_OBJ_GET (obj_cmd_rs,
                      "next_record_id",
                      &val) < 0)
    {
        SDR_FIID_OBJECT_ERROR_TO_SDR_ERRNUM (ctx, obj_cmd_rs);
        goto cleanup;
    }
    *next_record_id = val;

    reservation_id_retry_count = 0;
    while (offset_into_record < record_length)
    {
        int record_data_len;

        if ((record_length - offset_into_record) < bytes_to_read)
            bytes_to_read = record_length - offset_into_record;

        if (ipmi_cmd_get_sdr (ipmi_ctx,
                              *reservation_id,
                              record_id,
                              offset_into_record,
                              bytes_to_read,
                              obj_cmd_rs) < 0)
        {
            if (ipmi_ctx_errnum (ipmi_ctx) != IPMI_ERR_BAD_COMPLETION_CODE)
            {
                SDR_SET_ERRNUM (ctx, IPMI_SDR_ERR_IPMI_ERROR);
                goto cleanup;
            }
            else
            {
                uint8_t comp_code;

                if (FIID_OBJ_GET (obj_cmd_rs,
                                  "comp_code",
                                  &val) < 0)
                {
                    SDR_FIID_OBJECT_ERROR_TO_SDR_ERRNUM (ctx, obj_cmd_rs);
                    goto cleanup;
                }
                comp_code = val;

                if (comp_code == IPMI_COMP_CODE_RESERVATION_CANCELLED
                        && (reservation_id_retry_count < IPMI_SDR_CACHE_MAX_RESERVATION_ID_RETRY))
                {
                    if (_sdr_cache_reservation_id (ctx,
                                                   ipmi_ctx,
                                                   reservation_id) < 0)
                        goto cleanup;
                    reservation_id_retry_count++;
                    continue;
                }
                else if  ((comp_code == IPMI_COMP_CODE_CANNOT_RETURN_REQUESTED_NUMBER_OF_BYTES
                           || comp_code == IPMI_COMP_CODE_UNSPECIFIED_ERROR)
                          && bytes_to_read > sdr_record_header_length)
                {
                    bytes_to_read -= IPMI_SDR_CACHE_BYTES_TO_READ_DECREMENT;
                    if (bytes_to_read < sdr_record_header_length)
                        bytes_to_read = sdr_record_header_length;
                    continue;
                }

                SDR_SET_ERRNUM (ctx, IPMI_SDR_ERR_IPMI_ERROR);
                goto cleanup;
            }
        }

        if ((record_data_len = fiid_obj_get_data (obj_cmd_rs,
                               "record_data",
                               record_buf + offset_into_record,
                               record_buf_len - offset_into_record)) < 0)
        {
            SDR_FIID_OBJECT_ERROR_TO_SDR_ERRNUM (ctx, obj_cmd_rs);
            goto cleanup;
        }

        offset_into_record += record_data_len;
    }

out:
    rv = offset_into_record;
cleanup:
    fiid_obj_destroy (obj_cmd_rs);
    fiid_obj_destroy (obj_sdr_record_header);
    return (rv);
}
Beispiel #14
0
static int
_api_ssif_ipmb_recv (ipmi_ctx_t ctx,
		     fiid_obj_t obj_ipmb_msg_hdr_rs,
		     fiid_obj_t obj_ipmb_msg_trlr,
		     fiid_obj_t obj_cmd_rs)
{
  struct ipmi_ctx_target target_save;
  uint8_t buf[IPMI_MAX_PKT_LEN];
  fiid_obj_t obj_ipmb_msg_rs = NULL;
  fiid_obj_t obj_get_cmd_rs = NULL;
  int len, ret, rv = -1;
  unsigned int intf_flags = IPMI_INTERFACE_FLAGS_DEFAULT;

  assert (ctx
          && ctx->magic == IPMI_CTX_MAGIC
          && ctx->type == IPMI_DEVICE_SSIF
          && fiid_obj_valid (obj_ipmb_msg_hdr_rs)
          && fiid_obj_valid (obj_ipmb_msg_trlr)
          && fiid_obj_valid (obj_cmd_rs));

  if (ctx->flags & IPMI_FLAGS_NO_LEGAL_CHECK)
    intf_flags |= IPMI_INTERFACE_FLAGS_NO_LEGAL_CHECK;

  if (!(obj_ipmb_msg_rs = fiid_obj_create (tmpl_ipmb_msg)))
    {
      API_ERRNO_TO_API_ERRNUM (ctx, errno);
      goto cleanup;
    }
  if (!(obj_get_cmd_rs = fiid_obj_create (tmpl_cmd_get_message_rs)))
    {
      API_ERRNO_TO_API_ERRNUM (ctx, errno);
      goto cleanup;
    }
  
  /* get_message will send to the BMC, so clear out target information */
  memcpy (&target_save, &ctx->target, sizeof (target_save));
  ctx->target.channel_number_is_set = 0;
  ctx->target.rs_addr_is_set = 0;
  
  ret = ipmi_cmd_get_message (ctx, obj_get_cmd_rs);

  /* restore target info */
  memcpy (&ctx->target, &target_save, sizeof (target_save));

  if (ret < 0)
    {
      if (ipmi_check_completion_code (obj_get_cmd_rs, IPMI_COMP_CODE_GET_MESSAGE_DATA_NOT_AVAILABLE) == 1)
        API_SET_ERRNUM (ctx, IPMI_ERR_MESSAGE_TIMEOUT);
      else
        API_BAD_RESPONSE_TO_API_ERRNUM (ctx, obj_get_cmd_rs);
      goto cleanup;
    }

  if ((len = fiid_obj_get_data (obj_get_cmd_rs,
                                "message_data",
                                buf,
                                IPMI_MAX_PKT_LEN)) < 0)
    {
      API_FIID_OBJECT_ERROR_TO_API_ERRNUM (ctx, obj_get_cmd_rs);
      goto cleanup;
    }

  if (fiid_obj_set_all (obj_ipmb_msg_rs,
                        buf,
                        len) < 0)
    {
      API_FIID_OBJECT_ERROR_TO_API_ERRNUM (ctx, obj_ipmb_msg_rs);
      goto cleanup;
    }

  if (unassemble_ipmi_ipmb_msg (obj_ipmb_msg_rs,
                                obj_ipmb_msg_hdr_rs,
                                obj_cmd_rs,
                                obj_ipmb_msg_trlr,
				intf_flags) < 0)
    {
      API_ERRNO_TO_API_ERRNUM (ctx, errno);
      goto cleanup;
    }

  rv = 0;
 cleanup:
  fiid_obj_destroy (obj_ipmb_msg_rs);
  fiid_obj_destroy (obj_get_cmd_rs);
  return (rv);
}
Beispiel #15
0
int
debug_dump_ipmb (int fd,
		 const char *prefix,
		 const uint8_t *ipmb_buf,
		 unsigned int ipmb_buf_len,
		 fiid_template_t tmpl_ipmb_msg_hdr,
		 fiid_template_t tmpl_ipmb_cmd)
{
  char *ipmb_msg_hdr =
    "IPMB Message Header:\n"
    "--------------------";
  char *ipmb_cmd_hdr =
    "IPMB Message Data:\n"
    "------------------";
  char *ipmb_msg_trlr_hdr =
    "IPMB Message Trailer:\n"
    "---------------------";
  char *ipmb_unexpected_hdr =
    "IPMB Unexpected Data:\n"
    "---------------------";
  fiid_obj_t obj_ipmb_msg_hdr = NULL;
  fiid_obj_t obj_ipmb_cmd = NULL;
  fiid_obj_t obj_ipmb_msg_trlr = NULL;
  fiid_obj_t obj_ipmb_unexpected_data = NULL;
  int obj_ipmb_msg_trlr_len = 0;
  unsigned int obj_ipmb_cmd_len = 0;
  int ipmb_hdr_len = 0;
  int ipmb_cmd_len = 0;
  int ipmb_trlr_len = 0;
  int len;
  unsigned int ipmb_indx = 0;
  int rv = -1;

  assert (ipmb_buf);
  assert (ipmb_buf_len);
  assert (tmpl_ipmb_msg_hdr);
  assert (tmpl_ipmb_cmd);

  if (!(obj_ipmb_msg_hdr = fiid_obj_create (tmpl_ipmb_msg_hdr)))
    {
      ERRNO_TRACE (errno);
      goto cleanup;
    }
  if (!(obj_ipmb_cmd = fiid_obj_create (tmpl_ipmb_cmd)))
    {
      ERRNO_TRACE (errno);
      goto cleanup;
    }
  if (!(obj_ipmb_msg_trlr = fiid_obj_create (tmpl_ipmb_msg_trlr)))
    {
      ERRNO_TRACE (errno);
      goto cleanup;
    }

  if ((obj_ipmb_msg_trlr_len = fiid_template_len_bytes (tmpl_ipmb_msg_trlr)) < 0)
    {
      ERRNO_TRACE (errno);
      goto cleanup;
    }

  if ((ipmb_hdr_len = fiid_obj_set_all (obj_ipmb_msg_hdr,
                                        ipmb_buf,
                                        ipmb_buf_len)) < 0)
    {
      FIID_OBJECT_ERROR_TO_ERRNO (obj_ipmb_msg_hdr);
      goto cleanup;
    }
  ipmb_indx += ipmb_hdr_len;

  if (ipmi_obj_dump (fd,
                     prefix,
                     ipmb_msg_hdr,
                     NULL,
                     obj_ipmb_msg_hdr) < 0)
    {
      ERRNO_TRACE (errno);
      goto cleanup;
    }

  if (ipmb_buf_len <= ipmb_indx)
    {
      rv = 0;
      goto cleanup;
    }

  if ((ipmb_buf_len - ipmb_hdr_len) <= obj_ipmb_msg_trlr_len)
    goto dump_ipmb_extra;

  obj_ipmb_cmd_len = (ipmb_buf_len - ipmb_hdr_len) - obj_ipmb_msg_trlr_len;

  if ((ipmb_cmd_len = fiid_obj_set_all (obj_ipmb_cmd,
                                        ipmb_buf + ipmb_hdr_len,
                                        obj_ipmb_cmd_len)) < 0)
    {
      FIID_OBJECT_ERROR_TO_ERRNO (obj_ipmb_cmd);
      goto cleanup;
    }
  ipmb_indx += ipmb_cmd_len;

  if (ipmi_obj_dump (fd,
                     prefix,
                     ipmb_cmd_hdr,
                     NULL,
                     obj_ipmb_cmd) < 0)
    {
      ERRNO_TRACE (errno);
      goto cleanup;
    }

  if (ipmb_buf_len <= ipmb_indx)
    {
      rv = 0;
      goto cleanup;
    }

  if ((ipmb_trlr_len = fiid_obj_set_all (obj_ipmb_msg_trlr,
                                         ipmb_buf + ipmb_hdr_len + ipmb_cmd_len,
                                         (ipmb_buf_len - ipmb_hdr_len - ipmb_cmd_len))) < 0)
    {
      FIID_OBJECT_ERROR_TO_ERRNO (obj_ipmb_msg_trlr);
      goto cleanup;
    }
  ipmb_indx += ipmb_trlr_len;

  if (ipmi_obj_dump (fd,
                     prefix,
                     ipmb_msg_trlr_hdr,
                     NULL,
                     obj_ipmb_msg_trlr) < 0)
    {
      ERRNO_TRACE (errno);
      goto cleanup;
    }
  
  /* Dump IPMB unexpected stuff */
  
 dump_ipmb_extra:
  
  if ((ipmb_buf_len - ipmb_indx) > 0)
    {
      if (!(obj_ipmb_unexpected_data = fiid_obj_create (tmpl_unexpected_data)))
        {
          ERRNO_TRACE (errno);
          goto cleanup;
        }
      
      if ((len = fiid_obj_set_all (obj_ipmb_unexpected_data,
                                   ipmb_buf + ipmb_indx,
                                   ipmb_buf_len - ipmb_indx)) < 0)
        {
          FIID_OBJECT_ERROR_TO_ERRNO (obj_ipmb_unexpected_data);
          goto cleanup;
        }
      ipmb_indx += len;
      
      if (ipmi_obj_dump (fd,
                         prefix,
                         ipmb_unexpected_hdr,
                         NULL,
                         obj_ipmb_unexpected_data) < 0)
        {
          ERRNO_TRACE (errno);
          goto cleanup;
        }
    }
  
  rv = 0;
 cleanup:
  fiid_obj_destroy (obj_ipmb_msg_hdr);
  fiid_obj_destroy (obj_ipmb_cmd);
  fiid_obj_destroy (obj_ipmb_msg_trlr);
  fiid_obj_destroy (obj_ipmb_unexpected_data);
  return (rv);

}