int fill_ipmb_msg_hdr (uint8_t rs_addr, uint8_t net_fn, uint8_t rs_lun, uint8_t rq_addr, uint8_t rq_lun, uint8_t rq_seq, fiid_obj_t obj_ipmb_msg_hdr) { uint8_t checksum_buf[1024]; int checksum_len; uint8_t checksum; if (!IPMI_NET_FN_VALID (net_fn) || !IPMI_BMC_LUN_VALID (rs_lun) || !IPMI_BMC_LUN_VALID (rq_lun) || (rq_seq > IPMI_IPMB_REQUESTER_SEQUENCE_NUMBER_MAX) || !fiid_obj_valid (obj_ipmb_msg_hdr)) { 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); } FILL_FIID_OBJ_CLEAR (obj_ipmb_msg_hdr); FILL_FIID_OBJ_SET (obj_ipmb_msg_hdr, "rs_addr", rs_addr); FILL_FIID_OBJ_SET (obj_ipmb_msg_hdr, "net_fn", net_fn); FILL_FIID_OBJ_SET (obj_ipmb_msg_hdr, "rs_lun", rs_lun); if ((checksum_len = fiid_obj_get_block (obj_ipmb_msg_hdr, "rs_addr", "net_fn", checksum_buf, 1024)) < 0) { FIID_OBJECT_ERROR_TO_ERRNO (obj_ipmb_msg_hdr); return (-1); } checksum = ipmi_checksum (checksum_buf, checksum_len); FILL_FIID_OBJ_SET (obj_ipmb_msg_hdr, "checksum1", checksum); FILL_FIID_OBJ_SET (obj_ipmb_msg_hdr, "rq_addr", rq_addr); FILL_FIID_OBJ_SET (obj_ipmb_msg_hdr, "rq_lun", rq_lun); FILL_FIID_OBJ_SET (obj_ipmb_msg_hdr, "rq_seq", rq_seq); 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 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); }
int ipmi_sdr_cache_open (ipmi_sdr_ctx_t ctx, ipmi_ctx_t ipmi_ctx, const char *filename) { uint8_t sdr_version; uint16_t record_count; uint32_t most_recent_addition_timestamp, most_recent_erase_timestamp; char sdr_version_buf; char sdr_cache_magic_buf[4]; char sdr_cache_version_buf[4]; char record_count_buf[2]; char most_recent_addition_timestamp_buf[4]; char most_recent_erase_timestamp_buf[4]; struct stat stat_buf; if (!ctx || ctx->magic != IPMI_SDR_CTX_MAGIC) { ERR_TRACE (ipmi_sdr_ctx_errormsg (ctx), ipmi_sdr_ctx_errnum (ctx)); return (-1); } if (!filename) { SDR_SET_ERRNUM (ctx, IPMI_SDR_ERR_PARAMETERS); return (-1); } if (ctx->operation != IPMI_SDR_OPERATION_UNINITIALIZED) { if (ctx->operation == IPMI_SDR_OPERATION_READ_CACHE) SDR_SET_ERRNUM (ctx, IPMI_SDR_ERR_CACHE_READ_ALREADY_INITIALIZED); else SDR_SET_ERRNUM (ctx, IPMI_SDR_ERR_INTERNAL_ERROR); return (-1); } if (stat (filename, &stat_buf) < 0) { SDR_ERRNO_TO_SDR_ERRNUM (ctx, errno); goto cleanup; } /* File Size must be atleast magic_buf + file_version_buf + * sdr_version_buf + record_count_buf + * most_recent_addition_timestamp_buf + * most_recent_erase_timestamp-buf in size. */ ctx->file_size = stat_buf.st_size; if (ctx->file_size < (4 + 4 + 1 + 2 + 4 + 4)) { SDR_SET_ERRNUM (ctx, IPMI_SDR_ERR_CACHE_INVALID); goto cleanup; } if ((ctx->fd = open (filename, O_RDONLY)) < 0) { SDR_ERRNO_TO_SDR_ERRNUM (ctx, errno); goto cleanup; } ctx->sdr_cache = (uint8_t *)mmap (NULL, ctx->file_size, PROT_READ, MAP_PRIVATE, ctx->fd, 0); if (!ctx->sdr_cache || ctx->sdr_cache == ((void *) -1)) { ERRNO_TRACE (errno); SDR_SET_ERRNUM (ctx, IPMI_SDR_ERR_SYSTEM_ERROR); goto cleanup; } memcpy (sdr_cache_magic_buf, ctx->sdr_cache + ctx->records_start_offset, 4); ctx->records_start_offset += 4; memcpy (sdr_cache_version_buf, ctx->sdr_cache + ctx->records_start_offset, 4); ctx->records_start_offset += 4; memcpy (&sdr_version_buf, ctx->sdr_cache + ctx->records_start_offset, 1); ctx->records_start_offset += 1; memcpy (record_count_buf, ctx->sdr_cache + ctx->records_start_offset, 2); ctx->records_start_offset += 2; memcpy (most_recent_addition_timestamp_buf, ctx->sdr_cache + ctx->records_start_offset, 4); ctx->records_start_offset += 4; memcpy (most_recent_erase_timestamp_buf, ctx->sdr_cache + ctx->records_start_offset, 4); ctx->records_start_offset += 4; if ((uint8_t)sdr_cache_magic_buf[0] != IPMI_SDR_CACHE_FILE_MAGIC_0 || (uint8_t)sdr_cache_magic_buf[1] != IPMI_SDR_CACHE_FILE_MAGIC_1 || (uint8_t)sdr_cache_magic_buf[2] != IPMI_SDR_CACHE_FILE_MAGIC_2 || (uint8_t)sdr_cache_magic_buf[3] != IPMI_SDR_CACHE_FILE_MAGIC_3) { SDR_SET_ERRNUM (ctx, IPMI_SDR_ERR_CACHE_INVALID); goto cleanup; } if (((uint8_t)sdr_cache_version_buf[0] != IPMI_SDR_CACHE_FILE_VERSION_1_0 || (uint8_t)sdr_cache_version_buf[1] != IPMI_SDR_CACHE_FILE_VERSION_1_1 || (uint8_t)sdr_cache_version_buf[2] != IPMI_SDR_CACHE_FILE_VERSION_1_2 || (uint8_t)sdr_cache_version_buf[3] != IPMI_SDR_CACHE_FILE_VERSION_1_3) && ((uint8_t)sdr_cache_version_buf[0] != IPMI_SDR_CACHE_FILE_VERSION_1_2_0 || (uint8_t)sdr_cache_version_buf[1] != IPMI_SDR_CACHE_FILE_VERSION_1_2_1 || (uint8_t)sdr_cache_version_buf[2] != IPMI_SDR_CACHE_FILE_VERSION_1_2_2 || (uint8_t)sdr_cache_version_buf[3] != IPMI_SDR_CACHE_FILE_VERSION_1_2_3)) { SDR_SET_ERRNUM (ctx, IPMI_SDR_ERR_CACHE_INVALID); goto cleanup; } ctx->sdr_version = (uint8_t)sdr_version_buf; ctx->record_count = ((uint16_t)record_count_buf[0] & 0xFF); ctx->record_count |= ((uint16_t)record_count_buf[1] & 0xFF) << 8; ctx->most_recent_addition_timestamp = ((uint32_t)most_recent_addition_timestamp_buf[0] & 0xFF); ctx->most_recent_addition_timestamp |= ((uint32_t)most_recent_addition_timestamp_buf[1] & 0xFF) << 8; ctx->most_recent_addition_timestamp |= ((uint32_t)most_recent_addition_timestamp_buf[2] & 0xFF) << 16; ctx->most_recent_addition_timestamp |= ((uint32_t)most_recent_addition_timestamp_buf[3] & 0xFF) << 24; ctx->most_recent_erase_timestamp = ((uint32_t)most_recent_erase_timestamp_buf[0] & 0xFF); ctx->most_recent_erase_timestamp |= ((uint32_t)most_recent_erase_timestamp_buf[1] & 0xFF) << 8; ctx->most_recent_erase_timestamp |= ((uint32_t)most_recent_erase_timestamp_buf[2] & 0xFF) << 16; ctx->most_recent_erase_timestamp |= ((uint32_t)most_recent_erase_timestamp_buf[3] & 0xFF) << 24; if (ipmi_ctx) { if (sdr_info (ctx, ipmi_ctx, &sdr_version, &record_count, &most_recent_addition_timestamp, &most_recent_erase_timestamp) < 0) goto cleanup; if (ctx->sdr_version != sdr_version || ctx->most_recent_addition_timestamp != most_recent_addition_timestamp || ctx->most_recent_erase_timestamp != most_recent_erase_timestamp) { SDR_SET_ERRNUM (ctx, IPMI_SDR_ERR_CACHE_OUT_OF_DATE); goto cleanup; } } if ((uint8_t)sdr_cache_version_buf[0] == IPMI_SDR_CACHE_FILE_VERSION_1_2_0 && (uint8_t)sdr_cache_version_buf[1] == IPMI_SDR_CACHE_FILE_VERSION_1_2_1 && (uint8_t)sdr_cache_version_buf[2] == IPMI_SDR_CACHE_FILE_VERSION_1_2_2 && (uint8_t)sdr_cache_version_buf[3] == IPMI_SDR_CACHE_FILE_VERSION_1_2_3) { uint8_t header_checksum_buf[512]; unsigned int header_checksum_buf_len = 0; uint8_t header_checksum, header_checksum_cache; uint8_t trailer_checksum, trailer_checksum_cache; char total_bytes_written_buf[4]; unsigned int total_bytes_written; unsigned int header_bytes_len; unsigned int trailer_bytes_len; /* File Size must be atleast magic_buf + file_version_buf + * sdr_version_buf + record_count_buf + * most_recent_addition_timestamp_buf + * most_recent_erase_timestamp-buf + header_checksum + trailer * bytes written + trailer records checksum. */ header_bytes_len = 4 + 4 + 1 + 2 + 4 + 4 + 1; trailer_bytes_len = 4 + 1; if (ctx->file_size < (header_bytes_len + trailer_bytes_len)) { SDR_SET_ERRNUM (ctx, IPMI_SDR_ERR_CACHE_INVALID); goto cleanup; } memcpy (&header_checksum_cache, ctx->sdr_cache + ctx->records_start_offset, 1); ctx->records_start_offset += 1; memcpy(&header_checksum_buf[header_checksum_buf_len], sdr_cache_magic_buf, 4); header_checksum_buf_len += 4; memcpy(&header_checksum_buf[header_checksum_buf_len], sdr_cache_version_buf, 4); header_checksum_buf_len += 4; memcpy(&header_checksum_buf[header_checksum_buf_len], &sdr_version_buf, 1); header_checksum_buf_len += 1; memcpy(&header_checksum_buf[header_checksum_buf_len], record_count_buf, 2); header_checksum_buf_len += 2; memcpy(&header_checksum_buf[header_checksum_buf_len], most_recent_addition_timestamp_buf, 4); header_checksum_buf_len += 4; memcpy(&header_checksum_buf[header_checksum_buf_len], most_recent_erase_timestamp_buf, 4); header_checksum_buf_len += 4; header_checksum = ipmi_checksum (header_checksum_buf, header_checksum_buf_len); if (header_checksum != header_checksum_cache) { SDR_SET_ERRNUM (ctx, IPMI_SDR_ERR_CACHE_INVALID); goto cleanup; } /* total_bytes_written is written before checksum */ /* checksum of records is last byte written */ memcpy (total_bytes_written_buf, ctx->sdr_cache + ctx->file_size - 5, 4); memcpy (&trailer_checksum_cache, ctx->sdr_cache + ctx->file_size - 1, 1); total_bytes_written = ((uint32_t)total_bytes_written_buf[0] & 0xFF); total_bytes_written |= ((uint32_t)total_bytes_written_buf[1] & 0xFF) << 8; total_bytes_written |= ((uint32_t)total_bytes_written_buf[2] & 0xFF) << 16; total_bytes_written |= ((uint32_t)total_bytes_written_buf[3] & 0xFF) << 24; if (total_bytes_written != ctx->file_size) { SDR_SET_ERRNUM (ctx, IPMI_SDR_ERR_CACHE_INVALID); goto cleanup; } /* -1 for checksum */ trailer_checksum = ipmi_checksum (ctx->sdr_cache + ctx->records_start_offset, total_bytes_written - ctx->records_start_offset - 1); if (trailer_checksum != trailer_checksum_cache) { SDR_SET_ERRNUM (ctx, IPMI_SDR_ERR_CACHE_INVALID); goto cleanup; } ctx->records_end_offset = ctx->file_size - trailer_bytes_len; } else /* (uint8_t)sdr_cache_version_buf[0] == IPMI_SDR_CACHE_FILE_VERSION_1_0 && (uint8_t)sdr_cache_version_buf[1] == IPMI_SDR_CACHE_FILE_VERSION_1_1 && (uint8_t)sdr_cache_version_buf[2] == IPMI_SDR_CACHE_FILE_VERSION_1_2 && (uint8_t)sdr_cache_version_buf[3] == IPMI_SDR_CACHE_FILE_VERSION_1_3 */ ctx->records_end_offset = ctx->file_size; _sdr_set_current_offset (ctx, ctx->records_start_offset); ctx->operation = IPMI_SDR_OPERATION_READ_CACHE; ctx->errnum = IPMI_SDR_ERR_SUCCESS; return (0); cleanup: /* ignore potential error, cleanup path */ if (ctx->fd >= 0) close (ctx->fd); /* ignore potential error, cleanup path */ if (ctx->sdr_cache) munmap ((void *)ctx->sdr_cache, ctx->file_size); sdr_init_ctx (ctx); return (-1); }
static int _sdr_cache_header_write (ipmi_sdr_ctx_t ctx, ipmi_ctx_t ipmi_ctx, int fd, unsigned int *total_bytes_written, uint8_t sdr_version, uint16_t record_count, uint32_t most_recent_addition_timestamp, uint32_t most_recent_erase_timestamp) { char sdr_cache_magic_buf[4]; char sdr_cache_version_buf[4]; char record_count_buf[2]; char most_recent_addition_timestamp_buf[4]; char most_recent_erase_timestamp_buf[4]; uint8_t header_checksum_buf[512]; unsigned int header_checksum_buf_len = 0; uint8_t header_checksum; ssize_t n; assert (ctx); assert (ctx->magic == IPMI_SDR_CTX_MAGIC); assert (ipmi_ctx); assert (fd); assert (total_bytes_written); sdr_cache_magic_buf[0] = IPMI_SDR_CACHE_FILE_MAGIC_0; sdr_cache_magic_buf[1] = IPMI_SDR_CACHE_FILE_MAGIC_1; sdr_cache_magic_buf[2] = IPMI_SDR_CACHE_FILE_MAGIC_2; sdr_cache_magic_buf[3] = IPMI_SDR_CACHE_FILE_MAGIC_3; if ((n = fd_write_n (fd, sdr_cache_magic_buf, 4)) < 0) { SDR_ERRNO_TO_SDR_ERRNUM (ctx, errno); return (-1); } if (n != 4) { SDR_SET_ERRNUM (ctx, IPMI_SDR_ERR_SYSTEM_ERROR); return (-1); } (*total_bytes_written) += 4; memcpy(&header_checksum_buf[header_checksum_buf_len], sdr_cache_magic_buf, 4); header_checksum_buf_len += 4; sdr_cache_version_buf[0] = IPMI_SDR_CACHE_FILE_VERSION_1_2_0; sdr_cache_version_buf[1] = IPMI_SDR_CACHE_FILE_VERSION_1_2_1; sdr_cache_version_buf[2] = IPMI_SDR_CACHE_FILE_VERSION_1_2_2; sdr_cache_version_buf[3] = IPMI_SDR_CACHE_FILE_VERSION_1_2_3; if ((n = fd_write_n (fd, sdr_cache_version_buf, 4)) < 0) { SDR_ERRNO_TO_SDR_ERRNUM (ctx, errno); return (-1); } if (n != 4) { SDR_SET_ERRNUM (ctx, IPMI_SDR_ERR_SYSTEM_ERROR); return (-1); } (*total_bytes_written) += 4; memcpy(&header_checksum_buf[header_checksum_buf_len], sdr_cache_version_buf, 4); header_checksum_buf_len += 4; if ((n = fd_write_n (fd, (char *)&sdr_version, 1)) < 0) { SDR_ERRNO_TO_SDR_ERRNUM (ctx, errno); return (-1); } if (n != 1) { SDR_SET_ERRNUM (ctx, IPMI_SDR_ERR_SYSTEM_ERROR); return (-1); } (*total_bytes_written) += 1; memcpy(&header_checksum_buf[header_checksum_buf_len], &sdr_version, 1); header_checksum_buf_len += 1; /* Store record count little-endian */ record_count_buf[0] = (record_count & 0x00FF); record_count_buf[1] = (record_count & 0xFF00) >> 8; if ((n = fd_write_n (fd, record_count_buf, 2)) < 0) { SDR_ERRNO_TO_SDR_ERRNUM (ctx, errno); return (-1); } if (n != 2) { SDR_SET_ERRNUM (ctx, IPMI_SDR_ERR_SYSTEM_ERROR); return (-1); } (*total_bytes_written) += 2; memcpy(&header_checksum_buf[header_checksum_buf_len], record_count_buf, 2); header_checksum_buf_len += 2; /* Store most recent addition timestamp little-endian */ most_recent_addition_timestamp_buf[0] = (most_recent_addition_timestamp & 0x000000FF); most_recent_addition_timestamp_buf[1] = (most_recent_addition_timestamp & 0x0000FF00) >> 8; most_recent_addition_timestamp_buf[2] = (most_recent_addition_timestamp & 0x00FF0000) >> 16; most_recent_addition_timestamp_buf[3] = (most_recent_addition_timestamp & 0xFF000000) >> 24; if ((n = fd_write_n (fd, most_recent_addition_timestamp_buf, 4)) < 0) { SDR_ERRNO_TO_SDR_ERRNUM (ctx, errno); return (-1); } if (n != 4) { SDR_SET_ERRNUM (ctx, IPMI_SDR_ERR_SYSTEM_ERROR); return (-1); } (*total_bytes_written) += 4; memcpy(&header_checksum_buf[header_checksum_buf_len], most_recent_addition_timestamp_buf, 4); header_checksum_buf_len += 4; /* Store most recent erase timestamp little-endian */ most_recent_erase_timestamp_buf[0] = (most_recent_erase_timestamp & 0x000000FF); most_recent_erase_timestamp_buf[1] = (most_recent_erase_timestamp & 0x0000FF00) >> 8; most_recent_erase_timestamp_buf[2] = (most_recent_erase_timestamp & 0x00FF0000) >> 16; most_recent_erase_timestamp_buf[3] = (most_recent_erase_timestamp & 0xFF000000) >> 24; if ((n = fd_write_n (fd, most_recent_erase_timestamp_buf, 4)) < 0) { SDR_ERRNO_TO_SDR_ERRNUM (ctx, errno); return (-1); } if (n != 4) { SDR_SET_ERRNUM (ctx, IPMI_SDR_ERR_SYSTEM_ERROR); return (-1); } (*total_bytes_written) += 4; memcpy(&header_checksum_buf[header_checksum_buf_len], most_recent_erase_timestamp_buf, 4); header_checksum_buf_len += 4; header_checksum = ipmi_checksum (header_checksum_buf, header_checksum_buf_len); if ((n = fd_write_n (fd, (char *)&header_checksum, 1)) < 0) { SDR_ERRNO_TO_SDR_ERRNUM (ctx, errno); return (-1); } if (n != 1) { SDR_SET_ERRNUM (ctx, IPMI_SDR_ERR_SYSTEM_ERROR); return (-1); } (*total_bytes_written) += 1; return (0); }