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 assemble_rmcp_pkt (fiid_obj_t obj_rmcp_hdr, fiid_obj_t obj_cmd, void *pkt, unsigned int pkt_len, unsigned int flags) { int obj_cmd_len, obj_rmcp_hdr_len; unsigned int flags_mask = 0; if (!fiid_obj_valid (obj_rmcp_hdr) || !fiid_obj_valid (obj_cmd) || !pkt || !pkt_len || (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_PACKET_VALID (obj_rmcp_hdr) < 0) { FIID_OBJECT_ERROR_TO_ERRNO (obj_rmcp_hdr); return (-1); } if (FIID_OBJ_PACKET_VALID (obj_cmd) < 0) { FIID_OBJECT_ERROR_TO_ERRNO (obj_cmd); return (-1); } if ((obj_rmcp_hdr_len = fiid_obj_len_bytes (obj_rmcp_hdr)) < 0) { FIID_OBJECT_ERROR_TO_ERRNO (obj_rmcp_hdr); return (-1); } if ((obj_cmd_len = fiid_obj_len_bytes (obj_cmd)) < 0) { FIID_OBJECT_ERROR_TO_ERRNO (obj_cmd); return (-1); } if (pkt_len < (obj_rmcp_hdr_len + obj_cmd_len)) { SET_ERRNO (EMSGSIZE); return (-1); } memset (pkt, '\0', pkt_len); if ((obj_rmcp_hdr_len = fiid_obj_get_all (obj_rmcp_hdr, pkt, pkt_len)) < 0) { FIID_OBJECT_ERROR_TO_ERRNO (obj_rmcp_hdr); return (-1); } if ((obj_cmd_len = fiid_obj_get_all (obj_cmd, pkt + obj_rmcp_hdr_len, pkt_len - obj_rmcp_hdr_len)) < 0) { FIID_OBJECT_ERROR_TO_ERRNO (obj_cmd); return (-1); } return (obj_rmcp_hdr_len + obj_cmd_len); }
static int _ipmi_lan_pkt_rq_min_size (uint8_t authentication_type, fiid_obj_t obj_cmd) { unsigned int msg_len = 0; int len; assert (IPMI_1_5_AUTHENTICATION_TYPE_VALID (authentication_type) && fiid_obj_valid (obj_cmd)); if ((len = fiid_template_len_bytes (tmpl_rmcp_hdr)) < 0) { ERRNO_TRACE (errno); return (-1); } msg_len += len; if ((len = fiid_template_len_bytes (tmpl_lan_msg_hdr_rq)) < 0) { ERRNO_TRACE (errno); return (-1); } msg_len += len; if ((len = fiid_template_len_bytes (tmpl_lan_msg_trlr)) < 0) { ERRNO_TRACE (errno); return (-1); } msg_len += len; if ((len = fiid_template_block_len_bytes (tmpl_lan_session_hdr, "authentication_type", "session_id")) < 0) { ERRNO_TRACE (errno); return (-1); } msg_len += len; if (authentication_type == IPMI_AUTHENTICATION_TYPE_MD2 || authentication_type == IPMI_AUTHENTICATION_TYPE_MD5 || authentication_type == IPMI_AUTHENTICATION_TYPE_STRAIGHT_PASSWORD_KEY || authentication_type == IPMI_AUTHENTICATION_TYPE_OEM_PROP) msg_len += IPMI_1_5_MAX_PASSWORD_LENGTH; if ((len = fiid_template_field_len_bytes (tmpl_lan_session_hdr, "ipmi_msg_len")) < 0) { ERRNO_TRACE (errno); return (-1); } msg_len += len; if ((len = fiid_obj_len_bytes (obj_cmd)) < 0) { FIID_OBJECT_ERROR_TO_ERRNO (obj_cmd); return (-1); } msg_len += len; return (msg_len); }
static int _ssif_cmd_write (ipmi_ctx_t ctx, uint8_t cmd, uint8_t group_extension, fiid_obj_t obj_cmd_rq) { uint8_t *pkt = NULL; unsigned int pkt_len; int hdr_len, cmd_len, send_len; int rv = -1; assert (ctx && ctx->magic == IPMI_CTX_MAGIC && fiid_obj_valid (obj_cmd_rq)); if ((hdr_len = fiid_template_len_bytes (tmpl_hdr_kcs)) < 0) { API_ERRNO_TO_API_ERRNUM (ctx, errno); goto cleanup; } if ((cmd_len = fiid_obj_len_bytes (obj_cmd_rq)) < 0) { API_FIID_OBJECT_ERROR_TO_API_ERRNUM (ctx, obj_cmd_rq); goto cleanup; } pkt_len = hdr_len + cmd_len; if (!(pkt = malloc (pkt_len))) { API_ERRNO_TO_API_ERRNUM (ctx, errno); goto cleanup; } memset (pkt, '\0', pkt_len); if (fill_hdr_ipmi_kcs (ctx->target.lun, ctx->target.net_fn, ctx->io.inband.rq.obj_hdr) < 0) { API_ERRNO_TO_API_ERRNUM (ctx, errno); goto cleanup; } if ((send_len = assemble_ipmi_kcs_pkt (ctx->io.inband.rq.obj_hdr, obj_cmd_rq, pkt, pkt_len, IPMI_INTERFACE_FLAGS_DEFAULT)) < 0) { API_ERRNO_TO_API_ERRNUM (ctx, errno); goto cleanup; } if (ctx->flags & IPMI_FLAGS_DEBUG_DUMP && send_len) _api_ssif_dump_rq (ctx, pkt, send_len, cmd, ctx->target.net_fn, group_extension, obj_cmd_rq); if (ipmi_ssif_write (ctx->io.inband.ssif_ctx, pkt, send_len) < 0) { API_SSIF_ERRNUM_TO_API_ERRNUM (ctx, ipmi_ssif_ctx_errnum (ctx->io.inband.ssif_ctx)); goto cleanup; } rv = 0; cleanup: free (pkt); return (rv); }
static int _ipmi_kcs_cmd_write (ipmi_kcs_ctx_t ctx, uint8_t lun, uint8_t net_fn, fiid_obj_t obj_cmd_rq) { uint8_t *pkt = NULL; unsigned int pkt_len; int hdr_len, cmd_len, rv = -1; fiid_obj_t obj_hdr = NULL; assert (ctx); assert (ctx->magic == IPMI_KCS_CTX_MAGIC); assert (IPMI_BMC_LUN_VALID (lun)); assert (IPMI_NET_FN_RQ_VALID (net_fn)); assert (fiid_obj_valid (obj_cmd_rq)); assert (fiid_obj_packet_valid (obj_cmd_rq) == 1); if ((hdr_len = fiid_template_len_bytes (tmpl_hdr_kcs)) < 0) { KCS_ERRNO_TO_KCS_ERRNUM (ctx, errno); goto cleanup; } if ((cmd_len = fiid_obj_len_bytes (obj_cmd_rq)) < 0) { KCS_FIID_OBJECT_ERROR_TO_KCS_ERRNUM (ctx, obj_cmd_rq); goto cleanup; } if (!(obj_hdr = fiid_obj_create (tmpl_hdr_kcs))) { KCS_ERRNO_TO_KCS_ERRNUM (ctx, errno); goto cleanup; } pkt_len = hdr_len + cmd_len; if (!(pkt = (uint8_t *)malloc (pkt_len))) { KCS_SET_ERRNUM (ctx, IPMI_KCS_ERR_OUT_OF_MEMORY); goto cleanup; } if (fill_hdr_ipmi_kcs (lun, net_fn, obj_hdr) < 0) { KCS_SET_ERRNUM (ctx, IPMI_KCS_ERR_INTERNAL_ERROR); goto cleanup; } if (assemble_ipmi_kcs_pkt (obj_hdr, obj_cmd_rq, pkt, pkt_len, IPMI_INTERFACE_FLAGS_DEFAULT) < 0) { KCS_SET_ERRNUM (ctx, IPMI_KCS_ERR_INTERNAL_ERROR); goto cleanup; } if (ipmi_kcs_write (ctx, pkt, pkt_len) < 0) goto cleanup; rv = 0; cleanup: fiid_obj_destroy (obj_hdr); free (pkt); return (rv); }
int assemble_ipmi_kcs_pkt (fiid_obj_t obj_kcs_hdr, fiid_obj_t obj_cmd, void *pkt, unsigned int pkt_len, unsigned int flags) { int obj_cmd_len, obj_kcs_hdr_len; unsigned int utmp; unsigned int flags_mask = 0; if (!fiid_obj_valid (obj_kcs_hdr) || !fiid_obj_valid (obj_cmd) || !pkt || (flags & ~flags_mask)) { SET_ERRNO (EINVAL); return (-1); } if (FIID_OBJ_TEMPLATE_COMPARE (obj_kcs_hdr, tmpl_hdr_kcs) < 0) { ERRNO_TRACE (errno); return (-1); } if (FIID_OBJ_PACKET_VALID (obj_kcs_hdr) < 0) { FIID_OBJECT_ERROR_TO_ERRNO (obj_kcs_hdr); return (-1); } if (FIID_OBJ_PACKET_VALID (obj_cmd) < 0) { FIID_OBJECT_ERROR_TO_ERRNO (obj_cmd); return (-1); } if ((obj_kcs_hdr_len = fiid_obj_len_bytes (obj_kcs_hdr)) < 0) { FIID_OBJECT_ERROR_TO_ERRNO (obj_kcs_hdr); return (-1); } if ((obj_cmd_len = fiid_obj_len_bytes (obj_cmd)) < 0) { FIID_OBJECT_ERROR_TO_ERRNO (obj_cmd); return (-1); } /* int overflow not possible here */ if (pkt_len < (obj_kcs_hdr_len + obj_cmd_len)) { SET_ERRNO (EMSGSIZE); return (-1); } memset (pkt, 0, pkt_len); if ((obj_kcs_hdr_len = fiid_obj_get_all (obj_kcs_hdr, pkt, pkt_len)) < 0) { FIID_OBJECT_ERROR_TO_ERRNO (obj_kcs_hdr); return (-1); } if ((obj_cmd_len = fiid_obj_get_all (obj_cmd, pkt + obj_kcs_hdr_len, pkt_len - obj_kcs_hdr_len)) < 0) { FIID_OBJECT_ERROR_TO_ERRNO (obj_cmd); return (-1); } utmp = obj_kcs_hdr_len + obj_cmd_len; if (utmp > INT_MAX) { SET_ERRNO (EMSGSIZE); return (-1); } return (obj_kcs_hdr_len + obj_cmd_len); }